lonnen / astragalus

a utility for Cult of the Lamb's minigame Knucklebones
MIT License
0 stars 0 forks source link

LON could be less ambiguous or at least match the game #1

Open lonnen opened 1 year ago

lonnen commented 1 year ago

Lonnen-Otis Notation (LON) is a trivial encoding of the game boards into an array. The game boards accepts all three of the following as different, valid states:

1.

| 0 | 2 | 0 |
| 0 | 3 | 0 |
| 0 | 0 | 0 |

2.

| 0 | 2 | 0 |
| 0 | 0 | 0 |
| 0 | 3 | 0 |

3.

| 0 | 0 | 0 |
| 0 | 2 | 0 |
| 0 | 3 | 0 |

While they all sum the same, only [1] would appear in the game Cult of the Lamb (CotL) because 0's are always pushed to the end of the row.

For the sake of memory over many positions, and writing an AI to leverage that, it would be an improvement if we always reduced these to a canonical form. Perhaps:

4.

| 0 | 3 | 0 |
| 0 | 2 | 0 |
| 0 | 0 | 0 |

Where each column is sorted largest to smallest. This makes it easier to detect 0s (legal moves), and ensures that all 4 of these boards are treated as equivalent.

I think astragalus should accept any board state that might appear in CotL, but store and output a canonical form. This wouldn't change any output advice since a good or bad move is agnostic to the ordering or items in the same column.

lonnen commented 11 months ago

Here are some further optimizations that could be made for the game-state-tree:

The ordering of columns matters only relative to the same column on the other board. The following are all equivalent:

| 1 | 4 | 7 |
| 2 | 5 | 8 |
| 3 | 6 | 9 |

| 1 | 2 | 3 |
| 1 | 2 | 3 |
| 1 | 2 | 3 |
| 4 | 7 | 1 |
| 5 | 8 | 2 |
| 6 | 9 | 3 |

| 2 | 3 | 1 | 
| 2 | 3 | 1 |
| 2 | 3 | 1 |
| 7 | 1 | 4 |
| 8 | 2 | 5 |
| 9 | 3 | 6 |

| 3 | 1 | 2 |
| 3 | 1 | 2 |
| 3 | 1 | 2 |

... the other permutations are left as an exercise for the reader. Thus the game state space could be further reduced if columns were not only sorted internally, but also we sorted all columns by largest starting value, moving down the column as a tie breaker and ultimately into the corresponding column on the opponent's board. Thus the board above would become:

| 9 | 6 | 3 |
| 8 | 5 | 2 | 
| 7 | 4 | 1 | 

| 3 | 2 | 1 |
| 3 | 2 | 1 |
| 3 | 2 | 1 |
lonnen commented 11 months ago

As a further step for reducing the game-state-space, we can address the problem of symmetry across boards. While implementing the game requires an absolute sense of which player has the turn, answering the question of "what move to play next" can always assume the perspective of the active player, relatively. Consider the following position:

*
| 6 | 6 | 3 |
| 6 | 5 | 2 | 
| 0 | 0 | 0 | 

| 3 | 2 | 1 |
| 3 | 2 | 1 |
| 0 | 0 | 0 |

If we assume the top board is the active player (*), the die is rolled a 2, and they place it so as to cancel the opponent's column the board becomes:

| 6 | 6 | 3 |
| 6 | 5 | 2 | 
| 0 | 2 | 0 | 

*
| 3 | 0 | 1 |
| 3 | 0 | 1 |
| 0 | 0 | 0 |

But from the perspective of the now active player, the board position is equivalent to:

*
| 3 | 1 | 0 |
| 3 | 1 | 0 |
| 0 | 0 | 0 |

| 6 | 3 | 6 |
| 6 | 2 | 5 |
| 0 | 0 | 2 |

The challenge then becomes how does the implementer map an answer about this board back to the current, absolute game state so that it applies to the correct board and column, when one or both have shifted place. Concretely - if the roll is a 1, and the oracle answers that the correct placement is board 0, column 1 (0-ordered), how do we translate that back to the actual game state where that needs to be board 1, column 2?