Update design document
This commit is contained in:
parent
1f25e9109c
commit
851c1f6fc6
2 changed files with 79 additions and 19 deletions
86
DESIGN.md
86
DESIGN.md

@ 1,33 +1,99 @@


# Design




[tabula](https://code.rocket9labs.com/tslocum/tabula) is a multithreaded backgammon analysis engine.


To find the best move, the engine performs a series of simulations and scores the resulting game states.


The result with the lowest score is the best move.


[tabula](https://code.rocket9labs.com/tslocum/tabula) is a multithreaded


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.




## Scoring




### Space value


The score of each game state is comprised of weighted calculations.




Space value is defined as what the term 'pips' would normally refer to. The


value of a space is the same as the space number as it would appear to the


player being scored.


Each game state is initially scored as follows:




### Pseudopips


```


score = pips*pipsWeight + blots*blotsWeight + hits*hitsWeight


```




All scoring calculations use pseudopips.


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


```




All scoring calculations use pseudopips. Space value is defined as what the


term 'pips' would normally refer to. The value of a space is the same as the


space number as it would appear to the player being scored.




A pseudopip value is assigned to each board space as follows:




 Each space is worth 6 pseudopips plus **double the space value**.


 Each space is worth 6 pseudopips plus double the space value.


 Spaces outside of the player's home board are worth an additional 6 pseudopips.




Space 2 (from the perspective of the player being scored) is therefore worth 10


pseudopips, space 6 is worth 18, space 7 is worth 26 and the bar space is worth 62.




The base value of 6 incentivizes bearing pieces off instead of moving them


when possible. Adding double the space value incentivizes prioritizing moving


checkers that are further away from home.




Adding an additional 6 pseudopips to checkers outside of the player's home board


incentivizes moving all checkers into the home board before moving any checkers


within the home board.




### 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.




## Analysis




Analysis is performed in parallel, utilizing all available CPU cores.




### Step 1: Simulate all legal move available to the player




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.




### Step 2: Simulate all opponent dice rolls and opponent moves that may follow the above simulations




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.




### Step 3: Sort simulation results by score




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.




12
board.go
12
board.go

@ 8,9 +8,9 @@ import (


)




var (


WeightBlot = 1.5


WeightHit = 1.5


WeightOppScore = 0.25


WeightBlot = 0.25


WeightHit = 0.225


WeightOppScore = 0.55


)




const (



@ 315,12 +315,6 @@ func (b Board) Blots(player int) int {


return pips


}




func (b Board) Score(player int, hitScore int) float64 {


pips := b.Pips(player)


blots := b.Blots(player)


return float64(pips) + float64(blots)*WeightBlot + float64(hitScore)*WeightHit


}




func (b Board) evaluate(player int, hitScore int, a *Analysis) {


pips := b.Pips(player)


score := float64(pips)




Loading…
Reference in a new issue