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-04 06:19:23 +00:00
|
|
|
The pips weight is positive. The blots and hits weights are negative.
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
The following table lists pseudopip value of each space. Space 25 is the bar.
|
|
|
|
|
|
|
|
| Space | Pseudopips |
|
|
|
|
| --- | --- |
|
|
|
|
| 1 | 15 |
|
|
|
|
| 2 | 16 |
|
|
|
|
| 3 | 17 |
|
|
|
|
| 4 | 20 |
|
|
|
|
| 5 | 21 |
|
|
|
|
| 6 | 24 |
|
|
|
|
| 7 | 51 |
|
|
|
|
| 8 | 52 |
|
|
|
|
| 9 | 57 |
|
|
|
|
| 10 | 60 |
|
|
|
|
| 11 | 65 |
|
|
|
|
| 12 | 70 |
|
|
|
|
| 13 | 75 |
|
|
|
|
| 14 | 82 |
|
|
|
|
| 15 | 91 |
|
|
|
|
| 16 | 100 |
|
|
|
|
| 17 | 111 |
|
|
|
|
| 18 | 126 |
|
|
|
|
| 19 | 143 |
|
|
|
|
| 20 | 164 |
|
|
|
|
| 21 | 189 |
|
|
|
|
| 22 | 220 |
|
|
|
|
| 23 | 257 |
|
|
|
|
| 24 | 302 |
|
|
|
|
| 25 | 357 |
|