diff --git a/DESIGN.md b/DESIGN.md index 345ed25..cba6c8c 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -24,25 +24,22 @@ 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. +All scoring calculations use pseudopips. -A pseudopip value is assigned to each board space as follows: +Space value is defined as what the term 'pips' would normally refer to for a +given space. The value of a space isthe same as the space number as it would +appear to the player being scored. -- 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. +Base value is 12 for spaces within the home board of the player being scored. +All other spaces have a base value of 36. The base values incentivize +prioritizing moving all checkers into the player's home board, and subsequently +bearing checkers off instead of moving them. -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 pseudopip value of each space is calculated as follows: -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. +``` +pseudoPips = baseValue(space) + spaceValue(space) + exp(spaceValue(space)*0.2)*2 +``` ### Pips @@ -70,7 +67,7 @@ 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 +### Step 2: Simulate all possible opponent dice rolls and opponent moves following the above simulations Copy each resulting gamestate from step one and simulate all 21 possible dice roll combinations and resulting legal moves. @@ -97,3 +94,35 @@ score = playerScore Each combination is sorted by its overall score. The combination with the lowest overall score is the best move. + +## 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 | diff --git a/board.go b/board.go index 2fda790..60a6c37 100644 --- a/board.go +++ b/board.go @@ -8,9 +8,9 @@ import ( ) var ( - WeightBlot = 0.25 - WeightHit = -0.225 - WeightOppScore = -0.55 + WeightBlot = 0.6 + WeightHit = -0.3 + WeightOppScore = -3.5 ) const ( @@ -292,9 +292,9 @@ func (b Board) Past(player int) bool { func (b Board) Pips(player int) int { var pips int if player == 1 { - pips += int(b.Checkers(player, SpaceBarPlayer)) * (50 + 12) + pips += int(b.Checkers(player, SpaceBarPlayer)) * pseudoPips(player, SpaceBarPlayer) } else { - pips += int(b.Checkers(player, SpaceBarOpponent)) * (50 + 12) + pips += int(b.Checkers(player, SpaceBarOpponent)) * pseudoPips(player, SpaceBarOpponent) } for space := 1; space < 25; space++ { pips += int(b.Checkers(player, space)) * pseudoPips(player, space) @@ -430,8 +430,7 @@ func (b Board) Analyze(player int, available [][]int) []*Analysis { j := j go func() { check := rollProbabilities[j] - bc := Board{} - bc = result[i].Board + bc := result[i].Board bc[SpaceRoll1], bc[SpaceRoll2] = int8(check.Roll1), int8(check.Roll2) if int8(check.Roll1) == int8(check.Roll2) { bc[SpaceRoll3], bc[SpaceRoll4] = int8(check.Roll1), int8(check.Roll2) @@ -440,6 +439,7 @@ func (b Board) Analyze(player int, available [][]int) []*Analysis { a := &Analysis{ Past: a.Past, } + bc.evaluate(player, 0, a) w.Add(len(available)) queueAnalysis(a, w, bc, 2, available, nil, &[][][]int{}, &oppResults[i], oppResultMutex) w.Done() @@ -505,9 +505,9 @@ func spaceValue(player int, space int) int { } func pseudoPips(player int, space int) int { - v := spaceValue(player, space)*2 + 6 - if (player == 1 && space > 6) || (player == 2 && space < 19) { - v += 6 + v := 12 + spaceValue(player, space) + int(math.Exp(float64(spaceValue(player, space))*0.2))*2 + if (player == 1 && (space > 6 || space == SpaceBarPlayer)) || (player == 2 && (space < 19 || space == SpaceBarOpponent)) { + v += 24 } return v } diff --git a/board_test.go b/board_test.go index 63d4bdc..9a6e571 100644 --- a/board_test.go +++ b/board_test.go @@ -82,33 +82,33 @@ func TestBlots(t *testing.T) { b := NewBoard() got, expected := b.Blots(1), 0 if got != expected { - t.Errorf("unexpected past value: expected %v: got %v", expected, got) + t.Errorf("unexpected blots value: expected %v: got %v", expected, got) } got, expected = b.Blots(2), 0 if got != expected { - t.Errorf("unexpected past value: expected %v: got %v", expected, got) + t.Errorf("unexpected blots value: expected %v: got %v", expected, got) } b = b.Move(24, 23, 1) - got, expected = b.Blots(1), 3 + got, expected = b.Blots(1), 31 if got != expected { - t.Errorf("unexpected past value: expected %v: got %v", expected, got) + t.Errorf("unexpected blots value: expected %v: got %v", expected, got) } got, expected = b.Blots(2), 0 if got != expected { - t.Errorf("unexpected past value: expected %v: got %v", expected, got) + t.Errorf("unexpected blots value: expected %v: got %v", expected, got) } b = b.Move(1, 2, 2) - got, expected = b.Blots(1), 3 + got, expected = b.Blots(1), 31 if got != expected { - t.Errorf("unexpected past value: expected %v: got %v", expected, got) + t.Errorf("unexpected blots value: expected %v: got %v", expected, got) } - got, expected = b.Blots(2), 3 + got, expected = b.Blots(2), 31 if got != expected { - t.Errorf("unexpected past value: expected %v: got %v", expected, got) + t.Errorf("unexpected blots value: expected %v: got %v", expected, got) } }