--- /dev/null
+{
+ "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": [
+ "{<Player.player1: 1>: [[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",
+ " <Player.player2: 2>: [[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': <Player.player1: 1>}"
+ ]
+ },
+ "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": [
+ "[<Player.player1: 1>, <Player.player2: 2>]"
+ ]
+ },
+ "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": [
+ "<Player.player2: 2>"
+ ]
+ },
+ "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": [
+ "{<Player.player1: 1>: [[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': [(<Player.player1: 1>, 3),\n",
+ " (<Player.player2: 2>, 3),\n",
+ " (<Player.player1: 1>, 1),\n",
+ " (<Player.player2: 2>, 2)],\n",
+ " <Player.player2: 2>: [[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': <Player.player1: 1>}"
+ ]
+ },
+ "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": [
+ "{<Player.player1: 1>: [[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': [(<Player.player1: 1>, 3),\n",
+ " (<Player.player2: 2>, 3),\n",
+ " (<Player.player1: 1>, 1),\n",
+ " (<Player.player2: 2>, 2)],\n",
+ " <Player.player2: 2>: [[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': <Player.player1: 1>}"
+ ]
+ },
+ "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
+}