Added renamed previous cipher to autokey stream cipher; added non-autokeyed version
[computing-unplugged-book.git] / nim-menace-learning.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# MENACE for Nim\n",
8 "http://shorttermmemoryloss.com/menace/\n",
9 "\n",
10 "https://en.wikipedia.org/wiki/Donald_Michie\n",
11 "\n",
12 "https://en.wikipedia.org/wiki/Nim\n"
13 ]
14 },
15 {
16 "cell_type": "markdown",
17 "metadata": {},
18 "source": [
19 "# Data structures\n",
20 "\n",
21 "* Menace state: a `list` of boxes, one for each number of starting stones. 1-based indexing.\n",
22 "* Menace box: a `list` of beads\n",
23 "* Game: a `dict`, containing a `list` of moves taken, a count of stones left, player names, and current player.\n",
24 "* Move: a `dict` of player, number\n",
25 "\n",
26 "# Operations\n",
27 "* Pick a random bead from a box\n",
28 "* Apply a move to a game\n",
29 "* Update Menace depending on win or loss"
30 ]
31 },
32 {
33 "cell_type": "code",
34 "execution_count": 159,
35 "metadata": {
36 "collapsed": true
37 },
38 "outputs": [],
39 "source": [
40 "import enum\n",
41 "import random\n",
42 "import collections"
43 ]
44 },
45 {
46 "cell_type": "code",
47 "execution_count": 133,
48 "metadata": {
49 "collapsed": true
50 },
51 "outputs": [],
52 "source": [
53 "STARTING_STONES = 9\n",
54 "MAX_STONES_PER_MOVE = 3\n",
55 "INITIAL_BEADS_PER_MOVE = 4\n",
56 "PLAYER_POOL_SIZE = 10\n",
57 "TOURNAMENT_ROUNDS = 100"
58 ]
59 },
60 {
61 "cell_type": "code",
62 "execution_count": 17,
63 "metadata": {
64 "collapsed": true
65 },
66 "outputs": [],
67 "source": [
68 "Players = enum.Enum('Player', 'player1 player2')"
69 ]
70 },
71 {
72 "cell_type": "code",
73 "execution_count": 41,
74 "metadata": {
75 "collapsed": true
76 },
77 "outputs": [],
78 "source": [
79 "def new_menace(beads_per_move=INITIAL_BEADS_PER_MOVE, starting_stones=STARTING_STONES):\n",
80 " return [[bead \n",
81 " for beadset in [[m] * beads_per_move for m in range(1, MAX_STONES_PER_MOVE+1)]\n",
82 " for bead in beadset\n",
83 " ] for _ in range(starting_stones+1)]"
84 ]
85 },
86 {
87 "cell_type": "code",
88 "execution_count": 42,
89 "metadata": {
90 "collapsed": false
91 },
92 "outputs": [
93 {
94 "data": {
95 "text/plain": [
96 "[[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
97 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
98 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
99 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
100 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
101 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
102 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
103 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
104 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
105 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]]"
106 ]
107 },
108 "execution_count": 42,
109 "metadata": {},
110 "output_type": "execute_result"
111 }
112 ],
113 "source": [
114 "new_menace()"
115 ]
116 },
117 {
118 "cell_type": "code",
119 "execution_count": 45,
120 "metadata": {
121 "collapsed": true
122 },
123 "outputs": [],
124 "source": [
125 "player1 = new_menace()\n",
126 "player2 = new_menace()"
127 ]
128 },
129 {
130 "cell_type": "code",
131 "execution_count": 39,
132 "metadata": {
133 "collapsed": true
134 },
135 "outputs": [],
136 "source": [
137 "def new_game(first_player, second_player, stones=STARTING_STONES):\n",
138 " return {'moves': [],\n",
139 " 'stones': stones,\n",
140 " 'current_player': Players.player1,\n",
141 " Players.player1: first_player,\n",
142 " Players.player2: second_player}"
143 ]
144 },
145 {
146 "cell_type": "code",
147 "execution_count": 46,
148 "metadata": {
149 "collapsed": false
150 },
151 "outputs": [
152 {
153 "data": {
154 "text/plain": [
155 "{<Player.player1: 1>: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
156 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
157 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
158 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
159 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
160 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
161 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
162 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
163 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
164 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n",
165 " 'stones': 9,\n",
166 " 'moves': [],\n",
167 " <Player.player2: 2>: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
168 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
169 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
170 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
171 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
172 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
173 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
174 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
175 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
176 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n",
177 " 'current_player': <Player.player1: 1>}"
178 ]
179 },
180 "execution_count": 46,
181 "metadata": {},
182 "output_type": "execute_result"
183 }
184 ],
185 "source": [
186 "game = new_game(player1, player2)\n",
187 "game"
188 ]
189 },
190 {
191 "cell_type": "code",
192 "execution_count": 96,
193 "metadata": {
194 "collapsed": true
195 },
196 "outputs": [],
197 "source": [
198 "def next_player(player):\n",
199 " if player == Players.player1:\n",
200 " return Players.player2\n",
201 " else:\n",
202 " return Players.player1"
203 ]
204 },
205 {
206 "cell_type": "code",
207 "execution_count": 97,
208 "metadata": {
209 "collapsed": false
210 },
211 "outputs": [
212 {
213 "data": {
214 "text/plain": [
215 "[<Player.player1: 1>, <Player.player2: 2>]"
216 ]
217 },
218 "execution_count": 97,
219 "metadata": {},
220 "output_type": "execute_result"
221 }
222 ],
223 "source": [
224 "[p for p in Players]"
225 ]
226 },
227 {
228 "cell_type": "code",
229 "execution_count": 98,
230 "metadata": {
231 "collapsed": false
232 },
233 "outputs": [
234 {
235 "data": {
236 "text/plain": [
237 "<Player.player2: 2>"
238 ]
239 },
240 "execution_count": 98,
241 "metadata": {},
242 "output_type": "execute_result"
243 }
244 ],
245 "source": [
246 "next_player(Players.player1)"
247 ]
248 },
249 {
250 "cell_type": "code",
251 "execution_count": 64,
252 "metadata": {
253 "collapsed": true
254 },
255 "outputs": [],
256 "source": [
257 "def pick_move(player, stones):\n",
258 " move = stones + 1\n",
259 " while move > stones:\n",
260 " move = random.choice(player[stones])\n",
261 " return move"
262 ]
263 },
264 {
265 "cell_type": "code",
266 "execution_count": 70,
267 "metadata": {
268 "collapsed": false
269 },
270 "outputs": [
271 {
272 "data": {
273 "text/plain": [
274 "1"
275 ]
276 },
277 "execution_count": 70,
278 "metadata": {},
279 "output_type": "execute_result"
280 }
281 ],
282 "source": [
283 "pick_move(player1, 9)"
284 ]
285 },
286 {
287 "cell_type": "code",
288 "execution_count": 85,
289 "metadata": {
290 "collapsed": false
291 },
292 "outputs": [
293 {
294 "data": {
295 "text/plain": [
296 "1"
297 ]
298 },
299 "execution_count": 85,
300 "metadata": {},
301 "output_type": "execute_result"
302 }
303 ],
304 "source": [
305 "pick_move(player1, 2)"
306 ]
307 },
308 {
309 "cell_type": "code",
310 "execution_count": 114,
311 "metadata": {
312 "collapsed": true
313 },
314 "outputs": [],
315 "source": [
316 "def apply_move(game, move):\n",
317 " if move > game['stones']:\n",
318 " raise Exception('Too many stones removed')\n",
319 " game['stones'] -= move\n",
320 " game['moves'].append((game['current_player'], move))"
321 ]
322 },
323 {
324 "cell_type": "code",
325 "execution_count": 90,
326 "metadata": {
327 "collapsed": true
328 },
329 "outputs": [],
330 "source": [
331 "def game_finished(game):\n",
332 " return game['stones'] == 0"
333 ]
334 },
335 {
336 "cell_type": "code",
337 "execution_count": 102,
338 "metadata": {
339 "collapsed": true
340 },
341 "outputs": [],
342 "source": [
343 "def play_game(game):\n",
344 " while not game_finished(game):\n",
345 " move = pick_move(game[game['current_player']], game['stones'])\n",
346 " apply_move(game, move)\n",
347 " game['current_player'] = next_player(game['current_player'])\n",
348 " return game"
349 ]
350 },
351 {
352 "cell_type": "code",
353 "execution_count": 126,
354 "metadata": {
355 "collapsed": false
356 },
357 "outputs": [
358 {
359 "data": {
360 "text/plain": [
361 "{<Player.player1: 1>: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
362 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
363 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
364 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
365 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
366 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
367 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
368 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
369 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
370 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n",
371 " 'stones': 0,\n",
372 " 'moves': [(<Player.player1: 1>, 3),\n",
373 " (<Player.player2: 2>, 3),\n",
374 " (<Player.player1: 1>, 1),\n",
375 " (<Player.player2: 2>, 2)],\n",
376 " <Player.player2: 2>: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
377 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
378 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
379 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
380 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
381 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
382 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
383 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
384 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
385 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n",
386 " 'current_player': <Player.player1: 1>}"
387 ]
388 },
389 "execution_count": 126,
390 "metadata": {},
391 "output_type": "execute_result"
392 }
393 ],
394 "source": [
395 "player1 = new_menace()\n",
396 "player2 = new_menace()\n",
397 "game = new_game(player1, player2)\n",
398 "play_game(game)"
399 ]
400 },
401 {
402 "cell_type": "code",
403 "execution_count": 151,
404 "metadata": {
405 "collapsed": false
406 },
407 "outputs": [],
408 "source": [
409 "def update_players(game):\n",
410 " stones = 0\n",
411 " loser = game['moves'][-1][0]\n",
412 " winner = next_player(loser)\n",
413 " updating = loser\n",
414 " for move in reversed(game['moves']):\n",
415 " stones += move[1]\n",
416 " if updating == loser:\n",
417 " game[loser][stones].remove(move[1])\n",
418 " if game[loser][stones].count(1) == 0:\n",
419 " game[loser][stones].append(1)\n",
420 " updating = winner\n",
421 " else:\n",
422 " game[winner][stones].append(move[1])\n",
423 " updating = loser \n",
424 " return game[winner], game[loser]"
425 ]
426 },
427 {
428 "cell_type": "code",
429 "execution_count": 127,
430 "metadata": {
431 "collapsed": false
432 },
433 "outputs": [
434 {
435 "data": {
436 "text/plain": [
437 "([[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
438 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
439 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
440 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
441 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
442 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
443 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
444 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
445 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
446 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n",
447 " [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
448 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
449 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
450 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
451 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
452 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
453 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
454 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
455 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
456 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]])"
457 ]
458 },
459 "execution_count": 127,
460 "metadata": {},
461 "output_type": "execute_result"
462 }
463 ],
464 "source": [
465 "player1, player2"
466 ]
467 },
468 {
469 "cell_type": "code",
470 "execution_count": 128,
471 "metadata": {
472 "collapsed": false
473 },
474 "outputs": [
475 {
476 "data": {
477 "text/plain": [
478 "([[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
479 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
480 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
481 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 1],\n",
482 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
483 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
484 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
485 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
486 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
487 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3]],\n",
488 " [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
489 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
490 " [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3],\n",
491 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
492 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
493 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
494 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3],\n",
495 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
496 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
497 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]])"
498 ]
499 },
500 "execution_count": 128,
501 "metadata": {},
502 "output_type": "execute_result"
503 }
504 ],
505 "source": [
506 "update_players(game)"
507 ]
508 },
509 {
510 "cell_type": "code",
511 "execution_count": 129,
512 "metadata": {
513 "collapsed": false
514 },
515 "outputs": [
516 {
517 "data": {
518 "text/plain": [
519 "{<Player.player1: 1>: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
520 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
521 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
522 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 1],\n",
523 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
524 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
525 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
526 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
527 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
528 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3]],\n",
529 " 'stones': 0,\n",
530 " 'moves': [(<Player.player1: 1>, 3),\n",
531 " (<Player.player2: 2>, 3),\n",
532 " (<Player.player1: 1>, 1),\n",
533 " (<Player.player2: 2>, 2)],\n",
534 " <Player.player2: 2>: [[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
535 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
536 " [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3],\n",
537 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
538 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
539 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
540 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3],\n",
541 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
542 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
543 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]],\n",
544 " 'current_player': <Player.player1: 1>}"
545 ]
546 },
547 "execution_count": 129,
548 "metadata": {},
549 "output_type": "execute_result"
550 }
551 ],
552 "source": [
553 "game"
554 ]
555 },
556 {
557 "cell_type": "code",
558 "execution_count": 152,
559 "metadata": {
560 "collapsed": false
561 },
562 "outputs": [
563 {
564 "data": {
565 "text/plain": [
566 "10"
567 ]
568 },
569 "execution_count": 152,
570 "metadata": {},
571 "output_type": "execute_result"
572 }
573 ],
574 "source": [
575 "player_pool = [new_menace() for _ in range(PLAYER_POOL_SIZE)]\n",
576 "len(player_pool)"
577 ]
578 },
579 {
580 "cell_type": "code",
581 "execution_count": 153,
582 "metadata": {
583 "collapsed": false
584 },
585 "outputs": [
586 {
587 "data": {
588 "text/plain": [
589 "[[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
590 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
591 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
592 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
593 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
594 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
595 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
596 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
597 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],\n",
598 " [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]]"
599 ]
600 },
601 "execution_count": 153,
602 "metadata": {},
603 "output_type": "execute_result"
604 }
605 ],
606 "source": [
607 "player_pool[0]"
608 ]
609 },
610 {
611 "cell_type": "code",
612 "execution_count": 165,
613 "metadata": {
614 "collapsed": true
615 },
616 "outputs": [],
617 "source": [
618 "def show_player(player):\n",
619 " show = ''\n",
620 " for i, s in enumerate(player):\n",
621 " show += \"{}: {}\\n\".format(i, collections.Counter(s))\n",
622 " return show"
623 ]
624 },
625 {
626 "cell_type": "code",
627 "execution_count": 167,
628 "metadata": {
629 "collapsed": false
630 },
631 "outputs": [
632 {
633 "name": "stdout",
634 "output_type": "stream",
635 "text": [
636 "0: Counter({1: 4, 2: 4, 3: 4})\n",
637 "1: Counter({2: 4, 3: 4, 1: 1})\n",
638 "2: Counter({1: 15, 3: 4})\n",
639 "3: Counter({2: 22, 3: 2, 1: 1})\n",
640 "4: Counter({3: 79, 1: 1, 2: 1})\n",
641 "5: Counter({1: 1})\n",
642 "6: Counter({1: 15, 3: 5})\n",
643 "7: Counter({2: 14, 3: 3, 1: 1})\n",
644 "8: Counter({3: 54, 1: 1})\n",
645 "9: Counter({1: 1})\n",
646 "\n"
647 ]
648 }
649 ],
650 "source": [
651 "print(show_player(player_pool[0]))"
652 ]
653 },
654 {
655 "cell_type": "code",
656 "execution_count": 169,
657 "metadata": {
658 "collapsed": false,
659 "scrolled": true
660 },
661 "outputs": [
662 {
663 "name": "stdout",
664 "output_type": "stream",
665 "text": [
666 "0: Counter({1: 4, 2: 4, 3: 4})\n",
667 "1: Counter({2: 4, 3: 4, 1: 1})\n",
668 "2: Counter({1: 15, 3: 4})\n",
669 "3: Counter({2: 22, 3: 2, 1: 1})\n",
670 "4: Counter({3: 79, 1: 1, 2: 1})\n",
671 "5: Counter({1: 1})\n",
672 "6: Counter({1: 15, 3: 5})\n",
673 "7: Counter({2: 14, 3: 3, 1: 1})\n",
674 "8: Counter({3: 54, 1: 1})\n",
675 "9: Counter({1: 1})\n",
676 "\n",
677 "0: Counter({1: 4, 2: 4, 3: 4})\n",
678 "1: Counter({2: 4, 3: 4, 1: 1})\n",
679 "2: Counter({1: 19, 3: 4, 2: 1})\n",
680 "3: Counter({2: 17, 1: 1})\n",
681 "4: Counter({3: 93, 1: 1})\n",
682 "5: Counter({1: 1})\n",
683 "6: Counter({1: 21})\n",
684 "7: Counter({2: 21, 1: 3})\n",
685 "8: Counter({3: 65, 1: 4})\n",
686 "9: Counter({1: 1})\n",
687 "\n",
688 "0: Counter({1: 4, 2: 4, 3: 4})\n",
689 "1: Counter({2: 4, 3: 4, 1: 1})\n",
690 "2: Counter({1: 17, 3: 4, 2: 2})\n",
691 "3: Counter({2: 21, 3: 2, 1: 1})\n",
692 "4: Counter({3: 55, 1: 2})\n",
693 "5: Counter({1: 1})\n",
694 "6: Counter({1: 20, 3: 3, 2: 1})\n",
695 "7: Counter({2: 10, 1: 1})\n",
696 "8: Counter({3: 15, 1: 7})\n",
697 "9: Counter({1: 1})\n",
698 "\n",
699 "0: Counter({1: 4, 2: 4, 3: 4})\n",
700 "1: Counter({2: 4, 3: 4, 1: 1})\n",
701 "2: Counter({1: 24, 3: 4, 2: 1})\n",
702 "3: Counter({2: 8, 3: 3, 1: 2})\n",
703 "4: Counter({3: 79, 1: 1, 2: 1})\n",
704 "5: Counter({1: 1})\n",
705 "6: Counter({1: 22, 2: 3})\n",
706 "7: Counter({2: 19, 1: 1, 3: 1})\n",
707 "8: Counter({3: 49, 2: 2, 1: 1})\n",
708 "9: Counter({1: 1})\n",
709 "\n",
710 "0: Counter({1: 4, 2: 4, 3: 4})\n",
711 "1: Counter({2: 4, 3: 4, 1: 1})\n",
712 "2: Counter({1: 19, 3: 4})\n",
713 "3: Counter({2: 17, 1: 2, 3: 1})\n",
714 "4: Counter({3: 91, 1: 1})\n",
715 "5: Counter({1: 1})\n",
716 "6: Counter({1: 25, 3: 3, 2: 1})\n",
717 "7: Counter({2: 10, 1: 1})\n",
718 "8: Counter({3: 57, 1: 2, 2: 2})\n",
719 "9: Counter({1: 1})\n",
720 "\n",
721 "0: Counter({1: 4, 2: 4, 3: 4})\n",
722 "1: Counter({2: 4, 3: 4, 1: 1})\n",
723 "2: Counter({1: 12, 3: 4, 2: 1})\n",
724 "3: Counter({2: 14, 1: 1, 3: 1})\n",
725 "4: Counter({3: 88, 1: 1})\n",
726 "5: Counter({1: 1})\n",
727 "6: Counter({1: 7, 3: 2})\n",
728 "7: Counter({2: 8, 1: 1, 3: 1})\n",
729 "8: Counter({3: 57, 1: 1})\n",
730 "9: Counter({1: 1})\n",
731 "\n",
732 "0: Counter({1: 4, 2: 4, 3: 4})\n",
733 "1: Counter({2: 4, 3: 4, 1: 1})\n",
734 "2: Counter({1: 13, 3: 4, 2: 2})\n",
735 "3: Counter({2: 33, 1: 1})\n",
736 "4: Counter({3: 90, 1: 1, 2: 1})\n",
737 "5: Counter({1: 1})\n",
738 "6: Counter({1: 31})\n",
739 "7: Counter({2: 28, 1: 2, 3: 1})\n",
740 "8: Counter({3: 48, 1: 6, 2: 2})\n",
741 "9: Counter({1: 1})\n",
742 "\n",
743 "0: Counter({1: 4, 2: 4, 3: 4})\n",
744 "1: Counter({2: 4, 3: 4, 1: 1})\n",
745 "2: Counter({1: 15, 3: 4, 2: 1})\n",
746 "3: Counter({2: 21, 1: 1, 3: 1})\n",
747 "4: Counter({3: 75, 1: 1})\n",
748 "5: Counter({1: 1})\n",
749 "6: Counter({1: 14, 3: 2})\n",
750 "7: Counter({2: 18, 1: 7, 3: 1})\n",
751 "8: Counter({3: 39, 1: 3, 2: 1})\n",
752 "9: Counter({1: 1})\n",
753 "\n",
754 "0: Counter({1: 4, 2: 4, 3: 4})\n",
755 "1: Counter({2: 4, 3: 4, 1: 1})\n",
756 "2: Counter({1: 21, 3: 4})\n",
757 "3: Counter({2: 21, 1: 2})\n",
758 "4: Counter({3: 64, 1: 2, 2: 1})\n",
759 "5: Counter({1: 1})\n",
760 "6: Counter({1: 18, 2: 1})\n",
761 "7: Counter({2: 7, 1: 5})\n",
762 "8: Counter({3: 39, 1: 1})\n",
763 "9: Counter({1: 1})\n",
764 "\n",
765 "0: Counter({1: 4, 2: 4, 3: 4})\n",
766 "1: Counter({2: 4, 3: 4, 1: 1})\n",
767 "2: Counter({1: 24, 3: 4, 2: 1})\n",
768 "3: Counter({2: 29, 1: 1})\n",
769 "4: Counter({3: 63, 1: 1})\n",
770 "5: Counter({1: 1})\n",
771 "6: Counter({1: 17, 2: 1})\n",
772 "7: Counter({2: 16, 1: 2})\n",
773 "8: Counter({3: 35, 1: 1, 2: 1})\n",
774 "9: Counter({1: 2})\n",
775 "\n"
776 ]
777 }
778 ],
779 "source": [
780 "for p in player_pool:\n",
781 " print(show_player(p))"
782 ]
783 },
784 {
785 "cell_type": "code",
786 "execution_count": 197,
787 "metadata": {
788 "collapsed": true
789 },
790 "outputs": [],
791 "source": [
792 "def play_tournament(no_of_players=PLAYER_POOL_SIZE, rounds=TOURNAMENT_ROUNDS, stones=STARTING_STONES):\n",
793 " players = [new_menace(starting_stones=stones) for _ in range(no_of_players)]\n",
794 " for r in range(rounds):\n",
795 " random.shuffle(players)\n",
796 " game = new_game(players[0], players[1], stones)\n",
797 " play_game(game)\n",
798 " update_players(game)\n",
799 " return players"
800 ]
801 },
802 {
803 "cell_type": "code",
804 "execution_count": 200,
805 "metadata": {
806 "collapsed": false,
807 "scrolled": true
808 },
809 "outputs": [
810 {
811 "name": "stdout",
812 "output_type": "stream",
813 "text": [
814 "0: Counter({1: 4, 2: 4, 3: 4})\n",
815 "1: Counter({2: 4, 3: 4, 1: 1})\n",
816 "2: Counter({1: 7, 3: 4, 2: 1})\n",
817 "3: Counter({2: 5, 1: 3, 3: 2})\n",
818 "4: Counter({3: 6, 1: 5, 2: 3})\n",
819 "5: Counter({1: 5, 2: 4, 3: 3})\n",
820 "6: Counter({1: 6, 3: 3, 2: 1})\n",
821 "7: Counter({1: 5, 3: 4, 2: 3})\n",
822 "8: Counter({1: 5, 2: 5, 3: 4})\n",
823 "9: Counter({2: 7, 1: 3, 3: 2})\n",
824 "\n",
825 "0: Counter({1: 4, 2: 4, 3: 4})\n",
826 "1: Counter({2: 4, 3: 4, 1: 1})\n",
827 "2: Counter({1: 13, 3: 4, 2: 1})\n",
828 "3: Counter({2: 6, 1: 4, 3: 3})\n",
829 "4: Counter({3: 6, 1: 4, 2: 3})\n",
830 "5: Counter({2: 7, 1: 4, 3: 4})\n",
831 "6: Counter({1: 5, 3: 5, 2: 3})\n",
832 "7: Counter({1: 2, 2: 2, 3: 2})\n",
833 "8: Counter({3: 6, 1: 4, 2: 4})\n",
834 "9: Counter({2: 7, 3: 7, 1: 2})\n",
835 "\n",
836 "0: Counter({1: 4, 2: 4, 3: 4})\n",
837 "1: Counter({2: 4, 3: 4, 1: 1})\n",
838 "2: Counter({1: 6, 3: 4, 2: 2})\n",
839 "3: Counter({2: 5, 3: 4, 1: 3})\n",
840 "4: Counter({2: 5, 3: 5, 1: 3})\n",
841 "5: Counter({1: 4, 2: 4, 3: 1})\n",
842 "6: Counter({1: 4, 2: 3, 3: 2})\n",
843 "7: Counter({1: 6, 2: 5, 3: 3})\n",
844 "8: Counter({2: 5, 3: 4, 1: 3})\n",
845 "9: Counter({2: 4, 1: 3, 3: 2})\n",
846 "\n",
847 "0: Counter({1: 4, 2: 4, 3: 4})\n",
848 "1: Counter({2: 4, 3: 4, 1: 1})\n",
849 "2: Counter({1: 7, 3: 4, 2: 3})\n",
850 "3: Counter({2: 6, 3: 3, 1: 1})\n",
851 "4: Counter({3: 7, 1: 3, 2: 2})\n",
852 "5: Counter({2: 7, 3: 4, 1: 3})\n",
853 "6: Counter({2: 4, 3: 4, 1: 3})\n",
854 "7: Counter({3: 5, 1: 3, 2: 2})\n",
855 "8: Counter({1: 6, 3: 4, 2: 3})\n",
856 "9: Counter({1: 5, 3: 5, 2: 4})\n",
857 "\n",
858 "0: Counter({1: 4, 2: 4, 3: 4})\n",
859 "1: Counter({2: 4, 3: 4, 1: 1})\n",
860 "2: Counter({1: 7, 3: 4, 2: 3})\n",
861 "3: Counter({2: 5, 1: 4, 3: 3})\n",
862 "4: Counter({1: 4, 3: 4, 2: 3})\n",
863 "5: Counter({2: 5, 1: 4, 3: 3})\n",
864 "6: Counter({3: 5, 1: 4, 2: 3})\n",
865 "7: Counter({1: 4, 2: 3, 3: 3})\n",
866 "8: Counter({3: 5, 1: 4, 2: 4})\n",
867 "9: Counter({3: 4, 2: 3, 1: 1})\n",
868 "\n",
869 "0: Counter({1: 4, 2: 4, 3: 4})\n",
870 "1: Counter({2: 4, 3: 4, 1: 1})\n",
871 "2: Counter({1: 5, 3: 4, 2: 2})\n",
872 "3: Counter({2: 5, 1: 4, 3: 1})\n",
873 "4: Counter({1: 5, 3: 5, 2: 3})\n",
874 "5: Counter({1: 5, 2: 4, 3: 4})\n",
875 "6: Counter({1: 5, 2: 2, 3: 2})\n",
876 "7: Counter({1: 6, 3: 2, 2: 1})\n",
877 "8: Counter({2: 5, 3: 5, 1: 4})\n",
878 "9: Counter({2: 4, 3: 4, 1: 2})\n",
879 "\n",
880 "0: Counter({1: 4, 2: 4, 3: 4})\n",
881 "1: Counter({2: 4, 3: 4, 1: 1})\n",
882 "2: Counter({1: 7, 3: 4, 2: 1})\n",
883 "3: Counter({2: 6, 1: 5, 3: 3})\n",
884 "4: Counter({1: 5, 2: 5, 3: 5})\n",
885 "5: Counter({1: 4, 2: 3, 3: 2})\n",
886 "6: Counter({1: 5, 3: 4, 2: 2})\n",
887 "7: Counter({3: 5, 1: 4, 2: 2})\n",
888 "8: Counter({2: 4, 3: 4, 1: 2})\n",
889 "9: Counter({3: 10, 2: 3, 1: 2})\n",
890 "\n",
891 "0: Counter({1: 4, 2: 4, 3: 4})\n",
892 "1: Counter({2: 4, 3: 4, 1: 1})\n",
893 "2: Counter({1: 8, 3: 4, 2: 3})\n",
894 "3: Counter({2: 6, 1: 5, 3: 1})\n",
895 "4: Counter({3: 6, 1: 5, 2: 4})\n",
896 "5: Counter({3: 5, 1: 4, 2: 3})\n",
897 "6: Counter({3: 5, 1: 3, 2: 3})\n",
898 "7: Counter({1: 4, 2: 4, 3: 4})\n",
899 "8: Counter({2: 5, 3: 4, 1: 2})\n",
900 "9: Counter({2: 6, 3: 6, 1: 3})\n",
901 "\n",
902 "0: Counter({1: 4, 2: 4, 3: 4})\n",
903 "1: Counter({2: 4, 3: 4, 1: 1})\n",
904 "2: Counter({1: 10, 3: 4, 2: 2})\n",
905 "3: Counter({2: 5, 1: 3, 3: 3})\n",
906 "4: Counter({3: 7, 1: 4, 2: 4})\n",
907 "5: Counter({2: 6, 1: 5, 3: 4})\n",
908 "6: Counter({1: 4, 2: 4, 3: 4})\n",
909 "7: Counter({3: 5, 1: 4, 2: 3})\n",
910 "8: Counter({1: 7, 3: 6, 2: 4})\n",
911 "9: Counter({2: 7, 1: 3, 3: 3})\n",
912 "\n",
913 "0: Counter({1: 4, 2: 4, 3: 4})\n",
914 "1: Counter({2: 4, 3: 4, 1: 1})\n",
915 "2: Counter({1: 5, 3: 4, 2: 3})\n",
916 "3: Counter({2: 6, 3: 3, 1: 1})\n",
917 "4: Counter({3: 6, 2: 4, 1: 3})\n",
918 "5: Counter({3: 5, 1: 4, 2: 4})\n",
919 "6: Counter({3: 4, 1: 2, 2: 2})\n",
920 "7: Counter({1: 7, 2: 4, 3: 4})\n",
921 "8: Counter({1: 4, 2: 4, 3: 4})\n",
922 "9: Counter({1: 6, 2: 3, 3: 3})\n",
923 "\n"
924 ]
925 }
926 ],
927 "source": [
928 "players = play_tournament()\n",
929 "for p in players:\n",
930 " print(show_player(p))"
931 ]
932 },
933 {
934 "cell_type": "code",
935 "execution_count": 201,
936 "metadata": {
937 "collapsed": false,
938 "scrolled": true
939 },
940 "outputs": [
941 {
942 "name": "stdout",
943 "output_type": "stream",
944 "text": [
945 "0: Counter({1: 4, 2: 4, 3: 4})\n",
946 "1: Counter({2: 4, 3: 4, 1: 1})\n",
947 "2: Counter({1: 19, 3: 4, 2: 2})\n",
948 "3: Counter({2: 22, 1: 1})\n",
949 "4: Counter({3: 50082, 1: 1})\n",
950 "5: Counter({1: 1})\n",
951 "6: Counter({1: 20, 2: 1, 3: 1})\n",
952 "7: Counter({2: 27, 1: 1, 3: 1})\n",
953 "8: Counter({3: 50026, 1: 2})\n",
954 "9: Counter({1: 1})\n",
955 "\n",
956 "0: Counter({1: 4, 2: 4, 3: 4})\n",
957 "1: Counter({2: 4, 3: 4, 1: 1})\n",
958 "2: Counter({1: 16, 3: 4, 2: 3})\n",
959 "3: Counter({2: 32, 1: 1, 3: 1})\n",
960 "4: Counter({3: 49843, 1: 1})\n",
961 "5: Counter({1: 1})\n",
962 "6: Counter({1: 24})\n",
963 "7: Counter({2: 23, 1: 2})\n",
964 "8: Counter({3: 49799, 1: 1})\n",
965 "9: Counter({1: 1})\n",
966 "\n"
967 ]
968 }
969 ],
970 "source": [
971 "players = play_tournament(no_of_players=2, rounds=100000)\n",
972 "for p in players:\n",
973 " print(show_player(p))"
974 ]
975 },
976 {
977 "cell_type": "code",
978 "execution_count": null,
979 "metadata": {
980 "collapsed": true
981 },
982 "outputs": [],
983 "source": []
984 }
985 ],
986 "metadata": {
987 "kernelspec": {
988 "display_name": "Python 3",
989 "language": "python",
990 "name": "python3"
991 },
992 "language_info": {
993 "codemirror_mode": {
994 "name": "ipython",
995 "version": 3
996 },
997 "file_extension": ".py",
998 "mimetype": "text/x-python",
999 "name": "python",
1000 "nbconvert_exporter": "python",
1001 "pygments_lexer": "ipython3",
1002 "version": "3.4.2"
1003 }
1004 },
1005 "nbformat": 4,
1006 "nbformat_minor": 0
1007 }