2023-12-03 18:23:07 +00:00
|
|
|
# Design
|
|
|
|
|
2023-12-04 06:19:23 +00:00
|
|
|
[tabula](https://code.rocket9labs.com/tslocum/tabula) is a multi-threaded
|
|
|
|
backgammon analysis engine. To find the best move, the engine performs a series
|
|
|
|
of simulations and scores the resulting game states. The combination that
|
|
|
|
results in the lowest scoring game state is the best move.
|
2023-12-03 18:23:07 +00:00
|
|
|
|
|
|
|
## Scoring
|
|
|
|
|
2023-12-04 06:19:23 +00:00
|
|
|
The score of each game state is comprised of weighted calculations.
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-04 06:19:23 +00:00
|
|
|
Each game state is initially scored as follows:
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-04 06:19:23 +00:00
|
|
|
```
|
|
|
|
score = pips*pipsWeight + blots*blotsWeight + hits*hitsWeight
|
|
|
|
```
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-12 19:08:31 +00:00
|
|
|
The pips and blots weights are positive. The hits weight is negative.
|
2023-12-04 06:19:23 +00:00
|
|
|
|
|
|
|
When past the opponent (there is no longer any chance of hitting the opponent)
|
|
|
|
the game state is scored as follows:
|
|
|
|
|
|
|
|
```
|
|
|
|
score = pips*pipsWeight
|
|
|
|
```
|
|
|
|
|
2023-12-05 08:27:41 +00:00
|
|
|
All scoring calculations use pseudopips.
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-05 08:27:41 +00:00
|
|
|
Space value is defined as what the term 'pips' would normally refer to for a
|
2023-12-05 20:42:54 +00:00
|
|
|
given space. The value of a space is the same as the space number as it appears
|
|
|
|
to the player being scored.
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-06 22:02:04 +00:00
|
|
|
Base value is 6 for spaces within the home board of the player being scored.
|
|
|
|
All other spaces have a base value of 42. The base values incentivize
|
2023-12-05 08:27:41 +00:00
|
|
|
prioritizing moving all checkers into the player's home board, and subsequently
|
|
|
|
bearing checkers off instead of moving them.
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-05 08:27:41 +00:00
|
|
|
The pseudopip value of each space is calculated as follows:
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-05 08:27:41 +00:00
|
|
|
```
|
|
|
|
pseudoPips = baseValue(space) + spaceValue(space) + exp(spaceValue(space)*0.2)*2
|
|
|
|
```
|
2023-12-04 06:19:23 +00:00
|
|
|
|
|
|
|
### Pips
|
|
|
|
|
|
|
|
Pips are any player checkers that are on the board.
|
|
|
|
|
|
|
|
### Blots
|
|
|
|
|
|
|
|
Blots are single checkers that could be hit by the opponent during this turn or
|
|
|
|
any other turn.
|
|
|
|
|
|
|
|
### Hits
|
|
|
|
|
|
|
|
Hits are single checkers that may be hit by the player during this turn using
|
|
|
|
the available dice rolls.
|
|
|
|
|
2023-12-03 18:23:07 +00:00
|
|
|
## Analysis
|
|
|
|
|
2023-12-04 06:19:23 +00:00
|
|
|
Analysis is performed in parallel, utilizing all available CPU cores.
|
|
|
|
|
2023-12-03 18:23:07 +00:00
|
|
|
### Step 1: Simulate all legal move available to the player
|
|
|
|
|
2023-12-04 06:19:23 +00:00
|
|
|
Copy the current gamestate and simulate each available combination of legal moves.
|
|
|
|
Combinations that are logically equal are skipped.
|
|
|
|
|
|
|
|
Score the resulting gamestate after making each combination of legal moves.
|
|
|
|
This is the player score.
|
|
|
|
|
2023-12-05 08:27:41 +00:00
|
|
|
### Step 2: Simulate all possible opponent dice rolls and opponent moves following the above simulations
|
2023-12-03 18:23:07 +00:00
|
|
|
|
2023-12-04 06:19:23 +00:00
|
|
|
Copy each resulting gamestate from step one and simulate all 21 possible dice
|
|
|
|
roll combinations and resulting legal moves.
|
|
|
|
|
|
|
|
Score the resulting gamestate after making each combination of legal moves.
|
|
|
|
Average out all of the scores. This is the opponent score.
|
|
|
|
|
2023-12-03 18:23:07 +00:00
|
|
|
### Step 3: Sort simulation results by score
|
2023-12-04 06:19:23 +00:00
|
|
|
|
|
|
|
For each legal player move combination, the overall score is calculated as follows:
|
|
|
|
|
|
|
|
```
|
|
|
|
score = playerScore + opponentScore*opponentScoreWeight
|
|
|
|
```
|
|
|
|
|
|
|
|
The opponent score weight is negative.
|
|
|
|
|
|
|
|
When past the opponent (there is no longer any chance of hitting the opponent)
|
|
|
|
the overall score is calculated as follows:
|
|
|
|
|
|
|
|
```
|
|
|
|
score = playerScore
|
|
|
|
```
|
|
|
|
|
|
|
|
Each combination is sorted by its overall score. The combination with the
|
|
|
|
lowest overall score is the best move.
|
2023-12-05 08:27:41 +00:00
|
|
|
|
|
|
|
## Pseudopip values
|
|
|
|
|
2023-12-07 01:45:24 +00:00
|
|
|
The following table lists the pseudopip value of each space. Space 25 is the bar.
|
2023-12-05 08:27:41 +00:00
|
|
|
|
|
|
|
| Space | Pseudopips |
|
|
|
|
| --- | --- |
|
2023-12-07 01:45:24 +00:00
|
|
|
| 1 | 9 |
|
|
|
|
| 2 | 10 |
|
|
|
|
| 3 | 11 |
|
|
|
|
| 4 | 14 |
|
|
|
|
| 5 | 15 |
|
|
|
|
| 6 | 18 |
|
|
|
|
| 7 | 57 |
|
|
|
|
| 8 | 58 |
|
|
|
|
| 9 | 63 |
|
|
|
|
| 10 | 66 |
|
|
|
|
| 11 | 71 |
|
|
|
|
| 12 | 76 |
|
|
|
|
| 13 | 81 |
|
|
|
|
| 14 | 88 |
|
|
|
|
| 15 | 97 |
|
|
|
|
| 16 | 106 |
|
|
|
|
| 17 | 117 |
|
|
|
|
| 18 | 132 |
|
|
|
|
| 19 | 149 |
|
|
|
|
| 20 | 170 |
|
|
|
|
| 21 | 195 |
|
|
|
|
| 22 | 226 |
|
|
|
|
| 23 | 263 |
|
|
|
|
| 24 | 308 |
|
|
|
|
| 25 | 363 |
|