From: Neil Smith Date: Mon, 27 Jul 2015 15:50:04 +0000 (+0100) Subject: Added MENACE learning game for Nim X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=41a19b0744e04270472eb78aa8a7a96c8be3659c;p=computing-unplugged-book.git Added MENACE learning game for Nim --- 41a19b0744e04270472eb78aa8a7a96c8be3659c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0546add --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +*.py[cod] + +# C extensions +*.so + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +lib +lib64 +__pycache__ + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# IPython +.ipynb* + +# Sublime text +*.sublime-workspace + +# Logs +*.log diff --git a/SIGNED.md b/SIGNED.md new file mode 100644 index 0000000..7b81393 --- /dev/null +++ b/SIGNED.md @@ -0,0 +1,71 @@ +##### Signed by https://keybase.io/neilnjae +``` +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 + +iQIcBAABAgAGBQJVtlMvAAoJEJPB2e07Pgbqi4QQAKLPu4LQCCX4SCSBMRqbmeUt +zEn5Epz0RUjSBvfcwo44tbpNt/zHQKG3nff7xTQ9IgL2FX218fuGOkWALPgy94UU +kYNdx00ZoaD/q7LLJyvXIaT+NVHIVqNvkD1Knjigoa0s7LgvmsfLfKJ+1ncU1ici +OLSMBWPYZ9wIc3QSho57WMIr1j2Y6PPwgh8Cy+roB976kzph2Jzy/uF+ih0+S5fe +9uy1ZHP7RM5VrRt9hxCCj8SeUVfC+J+UvTDYT2Bx8VVgJjLhpo1clXWtCO6Yn0OK +62ZGtmu0lf4Bp2QYRzFc42kbuIVhxM00ZgP2MluQq31yuLJ2gE/tFYd3uib2m56E +mONhXvdS5CjllHAf5VnjpbTBj3goTQ9VG4liA+AkzJCjx1RKkpnKb9IR50HURpMA +hkmD8Nr1zmhzRo0OMFX95AotPRnhl3vPvLm8KYLWJflXFE+3ohefmEor/m06JYsd +KagzwLUCsmz3E3OvrRSSR+O8PYbeLENEnf8uHFSWua5z3eUh9FQRCC8bYKhOfGb3 +PFuNkoNdSEwES2PTdcHQPtbqD408XfUoarIUfNr8dsjmDzAqNa1xxblcI7c/o+PH +A1aln1HIbyPh3VqRX20XC/5BOsDYG5cL9Nk/ELrnhwV4KmFxlV89qP5M5o3G6RTj +hFZVracXKEeZqwFEE3ks +=94iF +-----END PGP SIGNATURE----- + +``` + + + +### Begin signed statement + +#### Expect + +``` +size exec file contents + ./ +384 .gitignore a93de2ae5c2a47a38599751d1f914566569dfa09dd1778e207117db6c71421dd +28564 nim-menace-learning.ipynb e13cd187b5785516ade802d71674ff682da7315da1a5ef82d2fe66d3ff8675bf +``` + +#### Ignore + +``` +/SIGNED.md +``` + +#### Presets + +``` +git # ignore .git and anything as described by .gitignore files +``` + + + +### End signed statement + +
+ +#### Notes + +With keybase you can sign any directory's contents, whether it's a git repo, +source code distribution, or a personal documents folder. It aims to replace the drudgery of: + + 1. comparing a zipped file to a detached statement + 2. downloading a public key + 3. confirming it is in fact the author's by reviewing public statements they've made, using it + +All in one simple command: + +```bash +keybase dir verify +``` + +There are lots of options, including assertions for automating your checks. + +For more info, check out https://keybase.io/docs/command_line/code_signing \ No newline at end of file diff --git a/nim-menace-learning.ipynb b/nim-menace-learning.ipynb new file mode 100644 index 0000000..a400301 --- /dev/null +++ b/nim-menace-learning.ipynb @@ -0,0 +1,1007 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# MENACE for Nim\n", + "http://shorttermmemoryloss.com/menace/\n", + "\n", + "https://en.wikipedia.org/wiki/Donald_Michie\n", + "\n", + "https://en.wikipedia.org/wiki/Nim\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data structures\n", + "\n", + "* Menace state: a `list` of boxes, one for each number of starting stones. 1-based indexing.\n", + "* Menace box: a `list` of beads\n", + "* Game: a `dict`, containing a `list` of moves taken, a count of stones left, player names, and current player.\n", + "* Move: a `dict` of player, number\n", + "\n", + "# Operations\n", + "* Pick a random bead from a box\n", + "* Apply a move to a game\n", + "* Update Menace depending on win or loss" + ] + }, + { + "cell_type": "code", + "execution_count": 159, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import enum\n", + "import random\n", + "import collections" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "STARTING_STONES = 9\n", + "MAX_STONES_PER_MOVE = 3\n", + "INITIAL_BEADS_PER_MOVE = 4\n", + "PLAYER_POOL_SIZE = 10\n", + "TOURNAMENT_ROUNDS = 100" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "Players = enum.Enum('Player', 'player1 player2')" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def new_menace(beads_per_move=INITIAL_BEADS_PER_MOVE, starting_stones=STARTING_STONES):\n", + " return [[bead \n", + " for beadset in [[m] * beads_per_move for m in range(1, MAX_STONES_PER_MOVE+1)]\n", + " for bead in beadset\n", + " ] for _ in range(starting_stones+1)]" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]]" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_menace()" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "player1 = new_menace()\n", + "player2 = new_menace()" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def new_game(first_player, second_player, stones=STARTING_STONES):\n", + " return {'moves': [],\n", + " 'stones': stones,\n", + " 'current_player': Players.player1,\n", + " Players.player1: first_player,\n", + " Players.player2: second_player}" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n", + " 'stones': 9,\n", + " 'moves': [],\n", + " : [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n", + " 'current_player': }" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "game = new_game(player1, player2)\n", + "game" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def next_player(player):\n", + " if player == Players.player1:\n", + " return Players.player2\n", + " else:\n", + " return Players.player1" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[, ]" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[p for p in Players]" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "next_player(Players.player1)" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def pick_move(player, stones):\n", + " move = stones + 1\n", + " while move > stones:\n", + " move = random.choice(player[stones])\n", + " return move" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 70, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pick_move(player1, 9)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pick_move(player1, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def apply_move(game, move):\n", + " if move > game['stones']:\n", + " raise Exception('Too many stones removed')\n", + " game['stones'] -= move\n", + " game['moves'].append((game['current_player'], move))" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def game_finished(game):\n", + " return game['stones'] == 0" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def play_game(game):\n", + " while not game_finished(game):\n", + " move = pick_move(game[game['current_player']], game['stones'])\n", + " apply_move(game, move)\n", + " game['current_player'] = next_player(game['current_player'])\n", + " return game" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n", + " 'stones': 0,\n", + " 'moves': [(, 3),\n", + " (, 3),\n", + " (, 1),\n", + " (, 2)],\n", + " : [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n", + " 'current_player': }" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "player1 = new_menace()\n", + "player2 = new_menace()\n", + "game = new_game(player1, player2)\n", + "play_game(game)" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def update_players(game):\n", + " stones = 0\n", + " loser = game['moves'][-1][0]\n", + " winner = next_player(loser)\n", + " updating = loser\n", + " for move in reversed(game['moves']):\n", + " stones += move[1]\n", + " if updating == loser:\n", + " game[loser][stones].remove(move[1])\n", + " if game[loser][stones].count(1) == 0:\n", + " game[loser][stones].append(1)\n", + " updating = winner\n", + " else:\n", + " game[winner][stones].append(move[1])\n", + " updating = loser \n", + " return game[winner], game[loser]" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "([[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n", + " [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]])" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "player1, player2" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "([[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 1],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3]],\n", + " [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]])" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "update_players(game)" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 1],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3]],\n", + " 'stones': 0,\n", + " 'moves': [(, 3),\n", + " (, 3),\n", + " (, 1),\n", + " (, 2)],\n", + " : [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n", + " 'current_player': }" + ] + }, + "execution_count": 129, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "game" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 152, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "player_pool = [new_menace() for _ in range(PLAYER_POOL_SIZE)]\n", + "len(player_pool)" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n", + " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]]" + ] + }, + "execution_count": 153, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "player_pool[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def show_player(player):\n", + " show = ''\n", + " for i, s in enumerate(player):\n", + " show += \"{}: {}\\n\".format(i, collections.Counter(s))\n", + " return show" + ] + }, + { + "cell_type": "code", + "execution_count": 167, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 15, 3: 4})\n", + "3: Counter({2: 22, 3: 2, 1: 1})\n", + "4: Counter({3: 79, 1: 1, 2: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 15, 3: 5})\n", + "7: Counter({2: 14, 3: 3, 1: 1})\n", + "8: Counter({3: 54, 1: 1})\n", + "9: Counter({1: 1})\n", + "\n" + ] + } + ], + "source": [ + "print(show_player(player_pool[0]))" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 15, 3: 4})\n", + "3: Counter({2: 22, 3: 2, 1: 1})\n", + "4: Counter({3: 79, 1: 1, 2: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 15, 3: 5})\n", + "7: Counter({2: 14, 3: 3, 1: 1})\n", + "8: Counter({3: 54, 1: 1})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 19, 3: 4, 2: 1})\n", + "3: Counter({2: 17, 1: 1})\n", + "4: Counter({3: 93, 1: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 21})\n", + "7: Counter({2: 21, 1: 3})\n", + "8: Counter({3: 65, 1: 4})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 17, 3: 4, 2: 2})\n", + "3: Counter({2: 21, 3: 2, 1: 1})\n", + "4: Counter({3: 55, 1: 2})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 20, 3: 3, 2: 1})\n", + "7: Counter({2: 10, 1: 1})\n", + "8: Counter({3: 15, 1: 7})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 24, 3: 4, 2: 1})\n", + "3: Counter({2: 8, 3: 3, 1: 2})\n", + "4: Counter({3: 79, 1: 1, 2: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 22, 2: 3})\n", + "7: Counter({2: 19, 1: 1, 3: 1})\n", + "8: Counter({3: 49, 2: 2, 1: 1})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 19, 3: 4})\n", + "3: Counter({2: 17, 1: 2, 3: 1})\n", + "4: Counter({3: 91, 1: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 25, 3: 3, 2: 1})\n", + "7: Counter({2: 10, 1: 1})\n", + "8: Counter({3: 57, 1: 2, 2: 2})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 12, 3: 4, 2: 1})\n", + "3: Counter({2: 14, 1: 1, 3: 1})\n", + "4: Counter({3: 88, 1: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 7, 3: 2})\n", + "7: Counter({2: 8, 1: 1, 3: 1})\n", + "8: Counter({3: 57, 1: 1})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 13, 3: 4, 2: 2})\n", + "3: Counter({2: 33, 1: 1})\n", + "4: Counter({3: 90, 1: 1, 2: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 31})\n", + "7: Counter({2: 28, 1: 2, 3: 1})\n", + "8: Counter({3: 48, 1: 6, 2: 2})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 15, 3: 4, 2: 1})\n", + "3: Counter({2: 21, 1: 1, 3: 1})\n", + "4: Counter({3: 75, 1: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 14, 3: 2})\n", + "7: Counter({2: 18, 1: 7, 3: 1})\n", + "8: Counter({3: 39, 1: 3, 2: 1})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 21, 3: 4})\n", + "3: Counter({2: 21, 1: 2})\n", + "4: Counter({3: 64, 1: 2, 2: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 18, 2: 1})\n", + "7: Counter({2: 7, 1: 5})\n", + "8: Counter({3: 39, 1: 1})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 24, 3: 4, 2: 1})\n", + "3: Counter({2: 29, 1: 1})\n", + "4: Counter({3: 63, 1: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 17, 2: 1})\n", + "7: Counter({2: 16, 1: 2})\n", + "8: Counter({3: 35, 1: 1, 2: 1})\n", + "9: Counter({1: 2})\n", + "\n" + ] + } + ], + "source": [ + "for p in player_pool:\n", + " print(show_player(p))" + ] + }, + { + "cell_type": "code", + "execution_count": 197, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def play_tournament(no_of_players=PLAYER_POOL_SIZE, rounds=TOURNAMENT_ROUNDS, stones=STARTING_STONES):\n", + " players = [new_menace(starting_stones=stones) for _ in range(no_of_players)]\n", + " for r in range(rounds):\n", + " random.shuffle(players)\n", + " game = new_game(players[0], players[1], stones)\n", + " play_game(game)\n", + " update_players(game)\n", + " return players" + ] + }, + { + "cell_type": "code", + "execution_count": 200, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 7, 3: 4, 2: 1})\n", + "3: Counter({2: 5, 1: 3, 3: 2})\n", + "4: Counter({3: 6, 1: 5, 2: 3})\n", + "5: Counter({1: 5, 2: 4, 3: 3})\n", + "6: Counter({1: 6, 3: 3, 2: 1})\n", + "7: Counter({1: 5, 3: 4, 2: 3})\n", + "8: Counter({1: 5, 2: 5, 3: 4})\n", + "9: Counter({2: 7, 1: 3, 3: 2})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 13, 3: 4, 2: 1})\n", + "3: Counter({2: 6, 1: 4, 3: 3})\n", + "4: Counter({3: 6, 1: 4, 2: 3})\n", + "5: Counter({2: 7, 1: 4, 3: 4})\n", + "6: Counter({1: 5, 3: 5, 2: 3})\n", + "7: Counter({1: 2, 2: 2, 3: 2})\n", + "8: Counter({3: 6, 1: 4, 2: 4})\n", + "9: Counter({2: 7, 3: 7, 1: 2})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 6, 3: 4, 2: 2})\n", + "3: Counter({2: 5, 3: 4, 1: 3})\n", + "4: Counter({2: 5, 3: 5, 1: 3})\n", + "5: Counter({1: 4, 2: 4, 3: 1})\n", + "6: Counter({1: 4, 2: 3, 3: 2})\n", + "7: Counter({1: 6, 2: 5, 3: 3})\n", + "8: Counter({2: 5, 3: 4, 1: 3})\n", + "9: Counter({2: 4, 1: 3, 3: 2})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 7, 3: 4, 2: 3})\n", + "3: Counter({2: 6, 3: 3, 1: 1})\n", + "4: Counter({3: 7, 1: 3, 2: 2})\n", + "5: Counter({2: 7, 3: 4, 1: 3})\n", + "6: Counter({2: 4, 3: 4, 1: 3})\n", + "7: Counter({3: 5, 1: 3, 2: 2})\n", + "8: Counter({1: 6, 3: 4, 2: 3})\n", + "9: Counter({1: 5, 3: 5, 2: 4})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 7, 3: 4, 2: 3})\n", + "3: Counter({2: 5, 1: 4, 3: 3})\n", + "4: Counter({1: 4, 3: 4, 2: 3})\n", + "5: Counter({2: 5, 1: 4, 3: 3})\n", + "6: Counter({3: 5, 1: 4, 2: 3})\n", + "7: Counter({1: 4, 2: 3, 3: 3})\n", + "8: Counter({3: 5, 1: 4, 2: 4})\n", + "9: Counter({3: 4, 2: 3, 1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 5, 3: 4, 2: 2})\n", + "3: Counter({2: 5, 1: 4, 3: 1})\n", + "4: Counter({1: 5, 3: 5, 2: 3})\n", + "5: Counter({1: 5, 2: 4, 3: 4})\n", + "6: Counter({1: 5, 2: 2, 3: 2})\n", + "7: Counter({1: 6, 3: 2, 2: 1})\n", + "8: Counter({2: 5, 3: 5, 1: 4})\n", + "9: Counter({2: 4, 3: 4, 1: 2})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 7, 3: 4, 2: 1})\n", + "3: Counter({2: 6, 1: 5, 3: 3})\n", + "4: Counter({1: 5, 2: 5, 3: 5})\n", + "5: Counter({1: 4, 2: 3, 3: 2})\n", + "6: Counter({1: 5, 3: 4, 2: 2})\n", + "7: Counter({3: 5, 1: 4, 2: 2})\n", + "8: Counter({2: 4, 3: 4, 1: 2})\n", + "9: Counter({3: 10, 2: 3, 1: 2})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 8, 3: 4, 2: 3})\n", + "3: Counter({2: 6, 1: 5, 3: 1})\n", + "4: Counter({3: 6, 1: 5, 2: 4})\n", + "5: Counter({3: 5, 1: 4, 2: 3})\n", + "6: Counter({3: 5, 1: 3, 2: 3})\n", + "7: Counter({1: 4, 2: 4, 3: 4})\n", + "8: Counter({2: 5, 3: 4, 1: 2})\n", + "9: Counter({2: 6, 3: 6, 1: 3})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 10, 3: 4, 2: 2})\n", + "3: Counter({2: 5, 1: 3, 3: 3})\n", + "4: Counter({3: 7, 1: 4, 2: 4})\n", + "5: Counter({2: 6, 1: 5, 3: 4})\n", + "6: Counter({1: 4, 2: 4, 3: 4})\n", + "7: Counter({3: 5, 1: 4, 2: 3})\n", + "8: Counter({1: 7, 3: 6, 2: 4})\n", + "9: Counter({2: 7, 1: 3, 3: 3})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 5, 3: 4, 2: 3})\n", + "3: Counter({2: 6, 3: 3, 1: 1})\n", + "4: Counter({3: 6, 2: 4, 1: 3})\n", + "5: Counter({3: 5, 1: 4, 2: 4})\n", + "6: Counter({3: 4, 1: 2, 2: 2})\n", + "7: Counter({1: 7, 2: 4, 3: 4})\n", + "8: Counter({1: 4, 2: 4, 3: 4})\n", + "9: Counter({1: 6, 2: 3, 3: 3})\n", + "\n" + ] + } + ], + "source": [ + "players = play_tournament()\n", + "for p in players:\n", + " print(show_player(p))" + ] + }, + { + "cell_type": "code", + "execution_count": 201, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 19, 3: 4, 2: 2})\n", + "3: Counter({2: 22, 1: 1})\n", + "4: Counter({3: 50082, 1: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 20, 2: 1, 3: 1})\n", + "7: Counter({2: 27, 1: 1, 3: 1})\n", + "8: Counter({3: 50026, 1: 2})\n", + "9: Counter({1: 1})\n", + "\n", + "0: Counter({1: 4, 2: 4, 3: 4})\n", + "1: Counter({2: 4, 3: 4, 1: 1})\n", + "2: Counter({1: 16, 3: 4, 2: 3})\n", + "3: Counter({2: 32, 1: 1, 3: 1})\n", + "4: Counter({3: 49843, 1: 1})\n", + "5: Counter({1: 1})\n", + "6: Counter({1: 24})\n", + "7: Counter({2: 23, 1: 2})\n", + "8: Counter({3: 49799, 1: 1})\n", + "9: Counter({1: 1})\n", + "\n" + ] + } + ], + "source": [ + "players = play_tournament(no_of_players=2, rounds=100000)\n", + "for p in players:\n", + " print(show_player(p))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.4.2" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}