Tic-tac-toe in Erlang — full game space
This is part of an Erlang tutorial built around a tic-tac-toe program. The program is stuffed into one file, called tic.erl and available here.
There are also smaller Erlang modules for analyzing game-spaces called tic_count.erl and tic_game_space.erl.
The tutorial is organized as follows:
- Introduction
- Top-level loop
- User input
- Board display
- Board abstraction
- Game abstraction
- Next move calculations and predictions
- Predicted outcome abstraction
- Utilities to introduce randomness
- Macros for testing and debugging
Full game space
In my last post (Tic-tac-toe in Erlang — game space symmetries) I talk about how many tic-tac-toe boards there are in the entire tic-tac-toe game space. Using the Erlang function tic_count:report() in tic_count.erl, I put together the following table of all the possible boards in the tic-tac-toe game space.
| Number of marks on board | Number of winning boards | Number of continuing boards | Total number of boards | Potential number of boards |
|---|---|---|---|---|
| 0 (0+0) | 0 | 1 | 1 | 1 |
| 1 (1+0) | 0 | 3 | 3 | 9 |
| 2 (1+1) | 0 | 12 | 12 | 72 |
| 3 (2+1) | 0 | 38 | 38 | 252 |
| 4 (2+2) | 0 | 108 | 108 | 756 |
| 5 (3+2) | 21 | 153 | 174 | 1260 |
| 6 (3+3) | 21 | 183 | 204 | 1680 |
| 7 (4+3) | 58 | 95 | 153 | 1260 |
| 8 (4+4) | 23 | 34 | 57 | 630 |
| 9 (5+4) | 12 | (ties) 3 | 15 | 126 |
| Totals | 135 | 630 | 765 | 6,055 |
This table treats all rotated and reflected boards as equivalent. The last-column calculation is explained in original post, where this table first appeared.
The last column shows how many possible boards there are at each ply, not treating rotated and reflected boards as equivalent and NOT PRUNING boards that don’t appear in the game space. A board with three-in-a-rows for both X and O is not in the tic-tac-toe game space but is still counted in the last column.
So what are the actual board counts for the game space when you don’t factor out rotations and reflections? The last column above was meant as an estimate, but really it’s an upper bound. I assumed it wouldn’t be too far wrong, but I wasn’t sure.
To find out I wrote a simple program. It’s in tic_game_space.erl if you want to see it. It reports the un-rotated/un-reflected board counts as follows.
| Number of marks on board | Number of winning boards | Number of continuing boards | Total number of boards | Potential number of boards |
|---|---|---|---|---|
| 0 (0+0) | 0 | 1 | 1 | 1 |
| 1 (1+0) | 0 | 9 | 9 | 9 |
| 2 (1+1) | 0 | 72 | 72 | 72 |
| 3 (2+1) | 0 | 252 | 252 | 252 |
| 4 (2+2) | 0 | 756 | 756 | 756 |
| 5 (3+2) | 120 | 1140 | 1260 | 1260 |
| 6 (3+3) | 148 | 1372 | 1520 | 1680 |
| 7 (4+3) | 444 | 696 | 1140 | 1260 |
| 8 (4+4) | 168 | 222 | 390 | 630 |
| 9 (5+4) | 62 | (ties) 16 | 78 | 126 |
| Totals | 942 | 4,536 | 5,478 | 6,055 |
The 9-mark row tells us there are 16 tied (cat) boards possible, including all rotations and reflections as separate boards. Which means there are 958 final boards (942 winning boards and 16 ties).
The 4536 in the last row counts all continuing boards, including the initial blank board, and the 16 ties. Subtracting out the ties tells us there are 4520 boards that are not finished games.
Since there are 6055 possible boards and only 5478 boards in the actual game space, there must be 577 boards with the right number of Xs and Os that you’ll never see in a legal game of tic-tac-toe. All have at least 3 Xs and 3 Os. 48 (126 – 78) have no empty spots.
The reports from tic_game_space.erl provide a little more detail, so I’ll list them here. First we instruct the program to treat rotations and reflections as different.
Eshell V5.6.5 (abort with ^G)
1> c( 'c:/src/erlang/tic_game_space',
1> {d, no_rotation_relection_collapse}).
{ok,tic_game_space}
2> tic_game_space:report0( ).
Full tic-tac-toe game space:
Player 1: all moves
Player 2: all moves
Total number of game paths: 255168
Total number of boards: 5478
Player 1 winning boards : 626
Player 2 winning boards : 316
Player 1 must respond to: 2423
Player 2 must respond to: 2097
Tie boards : 16
Total number of boards can also be broken down as:
Initial board count : 1
Boards produced by player 1: 2739
Boards produced by player 2: 2738
ok
3> tic_game_space:report0( ply_overview).
Full tic-tac-toe game space:
Player 1: all moves
Player 2: all moves
Player 1 moves, leading to ply 1
9 boards (all continue to ties)
Player 2 moves, leading to ply 2
72 boards (all continue)
24 boards lead to ties
48 boards lead to a win by player 1
Player 1 moves, leading to ply 3
252 boards (all continue)
138 boards lead to ties
64 boards lead to a win by player 1
50 boards lead to a win by player 2
Player 2 moves, leading to ply 4
756 boards (all continue)
136 boards lead to ties
36 boards lead to a win by player 2
584 boards lead to a win by player 1
Player 1 moves, leading to ply 5
1260 boards (1140 continuing)
120 boards won by player 1
264 boards lead to ties
336 boards lead to a win by player 1
540 boards lead to a win by player 2
Player 2 moves, leading to ply 6
1520 boards (1372 continuing)
148 boards won by player 2
200 boards lead to ties
116 boards lead to a win by player 2
1056 boards lead to a win by player 1
Player 1 moves, leading to ply 7
1140 boards (696 continuing)
444 boards won by player 1
200 boards lead to ties
80 boards lead to a win by player 1
416 boards lead to a win by player 2
Player 2 moves, leading to ply 8
390 boards (222 continuing)
168 boards won by player 2
80 boards lead to ties
142 boards lead to a win by player 1
Player 1 moves (last move)
16 tie boards
62 boards won by player 1
ok
These break up board counts between between the first and second player, and report predictions as well as final board totals.
Here is the same report, but treating rotations and reflections the same. These numbers agree with the first table above, and with the counts reported in the last post.
Eshell V5.6.5 (abort with ^G)
1> c( 'c:/src/erlang/tic_game_space').
{ok,tic_game_space}
2> tic_game_space:report0( ).
Full tic-tac-toe game space:
Player 1: all moves
Player 2: all moves
Total number of game paths: 26830
Total number of boards: 765
Player 1 winning boards : 91
Player 2 winning boards : 44
Player 1 must respond to: 338
Player 2 must respond to: 289
Tie boards : 3
Total number of boards can also be broken down as:
Initial board count : 1
Boards produced by player 1: 383
Boards produced by player 2: 381
ok
3> tic_game_space:report0( ply_overview).
Full tic-tac-toe game space:
Player 1: all moves
Player 2: all moves
Player 1 moves, leading to ply 1
3 boards (all continue to ties)
Player 2 moves, leading to ply 2
12 boards (all continue)
5 boards lead to ties
7 boards lead to a win by player 1
Player 1 moves, leading to ply 3
38 boards (all continue)
21 boards lead to ties
9 boards lead to a win by player 1
8 boards lead to a win by player 2
Player 2 moves, leading to ply 4
108 boards (all continue)
18 boards lead to ties
5 boards lead to a win by player 2
85 boards lead to a win by player 1
Player 1 moves, leading to ply 5
174 boards (153 continuing)
21 boards won by player 1
35 boards lead to ties
46 boards lead to a win by player 1
72 boards lead to a win by player 2
Player 2 moves, leading to ply 6
204 boards (183 continuing)
21 boards won by player 2
27 boards lead to ties
17 boards lead to a win by player 2
139 boards lead to a win by player 1
Player 1 moves, leading to ply 7
153 boards (95 continuing)
58 boards won by player 1
27 boards lead to ties
12 boards lead to a win by player 1
56 boards lead to a win by player 2
Player 2 moves, leading to ply 8
57 boards (34 continuing)
23 boards won by player 2
11 boards lead to ties
23 boards lead to a win by player 1
Player 1 moves (last move)
3 tie boards
12 boards won by player 1
ok
These board counts describe the entire tic-tac-toe game space, and include plenty of unlikely and perverse games. But what if you remove some of these unusual games? How much do you reduce the game space? I’ll report on that in the next post.
Comments
Leave a Reply