Store moves as [4][2]int instead of [][]int
This commit is contained in:
parent
b2e8b5ed5b
commit
de39467643
3 changed files with 191 additions and 211 deletions
|
@ -53,7 +53,7 @@ func init() {
|
|||
|
||||
type Analysis struct {
|
||||
Board Board
|
||||
Moves [][]int
|
||||
Moves [4][2]int
|
||||
Past bool
|
||||
Score float64
|
||||
|
||||
|
@ -79,9 +79,12 @@ type Analysis struct {
|
|||
func (a *Analysis) _analyze() {
|
||||
var hs int
|
||||
o := opponent(a.player)
|
||||
for i := 0; i < len(a.Moves); i++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
move := a.Moves[i]
|
||||
checkers := a.Board.Checkers(o, move[1])
|
||||
if move[0] == 0 && move[1] == 0 {
|
||||
break
|
||||
}
|
||||
checkers := checkers(o, a.Board[move[1]])
|
||||
if checkers == 1 {
|
||||
hs += PseudoPips(o, move[1])
|
||||
}
|
||||
|
|
379
board.go
379
board.go
|
@ -1,6 +1,7 @@
|
|||
package tabula
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"sort"
|
||||
|
@ -42,10 +43,6 @@ func NewBoard(acey bool) Board {
|
|||
return Board{0, -2, 0, 0, 0, 0, 5, 0, 3, 0, 0, 0, -5, 5, 0, 0, 0, -3, 0, -5, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}
|
||||
}
|
||||
|
||||
func (b Board) Acey() bool {
|
||||
return b[SpaceAcey] == 1
|
||||
}
|
||||
|
||||
func (b Board) SetValue(space int, value int8) Board {
|
||||
b[space] = value
|
||||
return b
|
||||
|
@ -76,37 +73,38 @@ func (b Board) Move(from int, to int, player int) Board {
|
|||
return b
|
||||
}
|
||||
|
||||
// Checkers returns the number of checkers at a space. It always returns a positive number.
|
||||
func (b Board) Checkers(player int, space int) int {
|
||||
v := b[space]
|
||||
// checkers returns the number of checkers that belong to the spcified player at the provided space.
|
||||
func checkers(player int, v int8) int8 {
|
||||
if player == 1 && v > 0 {
|
||||
return int(v)
|
||||
return v
|
||||
} else if player == 2 && v < 0 {
|
||||
return int(v * -1)
|
||||
return v * -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (b Board) MayBearOff(player int) bool {
|
||||
if b.Acey() && ((player == 1 && b[SpaceEnteredPlayer] == 0) || (player == 2 && b[SpaceEnteredOpponent] == 0)) {
|
||||
if b[SpaceAcey] == 1 && ((player == 1 && b[SpaceEnteredPlayer] == 0) || (player == 2 && b[SpaceEnteredOpponent] == 0)) {
|
||||
return false
|
||||
}
|
||||
homeStart := 1
|
||||
homeEnd := 6
|
||||
barSpace := SpaceBarPlayer
|
||||
if player == 2 {
|
||||
homeStart = 19
|
||||
homeEnd = 24
|
||||
barSpace = SpaceBarOpponent
|
||||
}
|
||||
if b.Checkers(player, barSpace) != 0 {
|
||||
if checkers(player, b[barSpace]) != 0 {
|
||||
return false
|
||||
}
|
||||
for space := 1; space < 25; space++ {
|
||||
if space >= homeStart && space <= homeEnd {
|
||||
continue
|
||||
} else if b.Checkers(player, space) != 0 {
|
||||
return false
|
||||
if player == 1 {
|
||||
for space := 24; space > 6; space-- {
|
||||
if checkers(player, b[space]) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for space := 1; space < 19; space++ {
|
||||
if checkers(player, b[space]) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
@ -125,7 +123,7 @@ func (b Board) spaceDiff(player int, from int, to int) int {
|
|||
case to == SpaceHomeOpponent:
|
||||
return 25 - from
|
||||
case from == SpaceHomePlayer || from == SpaceHomeOpponent:
|
||||
if b.Acey() {
|
||||
if b[SpaceAcey] == 1 {
|
||||
if player == 1 && from == SpaceHomePlayer && b[SpaceEnteredPlayer] == 0 {
|
||||
return 25 - to
|
||||
} else if player == 2 && from == SpaceHomeOpponent && b[SpaceEnteredOpponent] == 0 {
|
||||
|
@ -160,16 +158,21 @@ func (b Board) HaveRoll(from int, to int, player int) bool {
|
|||
if delta == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if b[SpaceRoll1] == delta || b[SpaceRoll2] == delta || b[SpaceRoll3] == delta || b[SpaceRoll4] == delta {
|
||||
return true
|
||||
}
|
||||
|
||||
playerDelta := -1
|
||||
playerHomeEnd := 6
|
||||
if player == 2 {
|
||||
playerDelta = 1
|
||||
playerHomeEnd = 19
|
||||
}
|
||||
if b.MayBearOff(player) && !b.Acey() {
|
||||
if b.MayBearOff(player) && b[SpaceAcey] == 0 {
|
||||
allowGreater := true
|
||||
for checkSpace := int8(0); checkSpace < 6-delta; checkSpace++ {
|
||||
if b.Checkers(player, playerHomeEnd+int(checkSpace)*playerDelta) != 0 {
|
||||
for checkSpace := 0; checkSpace < 6-int(delta); checkSpace++ {
|
||||
if checkers(player, b[playerHomeEnd+checkSpace*playerDelta]) != 0 {
|
||||
allowGreater = false
|
||||
break
|
||||
}
|
||||
|
@ -178,7 +181,7 @@ func (b Board) HaveRoll(from int, to int, player int) bool {
|
|||
return (b[SpaceRoll1] >= delta || b[SpaceRoll2] >= delta || b[SpaceRoll3] >= delta || b[SpaceRoll4] >= delta)
|
||||
}
|
||||
}
|
||||
return (b[SpaceRoll1] == delta || b[SpaceRoll2] == delta || b[SpaceRoll3] == delta || b[SpaceRoll4] == delta)
|
||||
return false
|
||||
}
|
||||
|
||||
// UseRoll uses a die roll.
|
||||
|
@ -188,6 +191,22 @@ func (b Board) UseRoll(from int, to int, player int) Board {
|
|||
b.Print()
|
||||
log.Panic("unknown space diff", from, to, player)
|
||||
}
|
||||
|
||||
switch {
|
||||
case b[SpaceRoll1] == delta:
|
||||
b[SpaceRoll1] = 0
|
||||
return b
|
||||
case b[SpaceRoll2] == delta:
|
||||
b[SpaceRoll2] = 0
|
||||
return b
|
||||
case b[SpaceRoll3] == delta:
|
||||
b[SpaceRoll3] = 0
|
||||
return b
|
||||
case b[SpaceRoll4] == delta:
|
||||
b[SpaceRoll4] = 0
|
||||
return b
|
||||
}
|
||||
|
||||
playerDelta := -1
|
||||
playerHomeEnd := 6
|
||||
if player == 2 {
|
||||
|
@ -195,48 +214,37 @@ func (b Board) UseRoll(from int, to int, player int) Board {
|
|||
playerHomeEnd = 19
|
||||
}
|
||||
var allowGreater bool
|
||||
if b.MayBearOff(player) && !b.Acey() {
|
||||
if b.MayBearOff(player) && b[SpaceAcey] == 0 {
|
||||
allowGreater = true
|
||||
for checkSpace := int8(0); checkSpace < 6-delta; checkSpace++ {
|
||||
if b.Checkers(player, playerHomeEnd+int(checkSpace)*playerDelta) != 0 {
|
||||
if checkers(player, b[playerHomeEnd+int(checkSpace)*playerDelta]) != 0 {
|
||||
allowGreater = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if allowGreater {
|
||||
switch {
|
||||
case b[SpaceRoll1] >= delta:
|
||||
b[SpaceRoll1] = 0
|
||||
case b[SpaceRoll2] >= delta:
|
||||
b[SpaceRoll2] = 0
|
||||
case b[SpaceRoll3] >= delta:
|
||||
b[SpaceRoll3] = 0
|
||||
case b[SpaceRoll4] >= delta:
|
||||
b[SpaceRoll4] = 0
|
||||
default:
|
||||
b.Print()
|
||||
log.Panic("no available roll for move", from, to, player, delta)
|
||||
}
|
||||
} else {
|
||||
switch {
|
||||
case b[SpaceRoll1] == delta:
|
||||
b[SpaceRoll1] = 0
|
||||
case b[SpaceRoll2] == delta:
|
||||
b[SpaceRoll2] = 0
|
||||
case b[SpaceRoll3] == delta:
|
||||
b[SpaceRoll3] = 0
|
||||
case b[SpaceRoll4] == delta:
|
||||
b[SpaceRoll4] = 0
|
||||
default:
|
||||
b.Print()
|
||||
log.Panic("no available roll for move", from, to, player, delta)
|
||||
}
|
||||
if !allowGreater {
|
||||
b.Print()
|
||||
log.Panic(fmt.Sprint(b), "no available roll for move", from, to, player, delta)
|
||||
}
|
||||
|
||||
switch {
|
||||
case b[SpaceRoll1] >= delta:
|
||||
b[SpaceRoll1] = 0
|
||||
case b[SpaceRoll2] >= delta:
|
||||
b[SpaceRoll2] = 0
|
||||
case b[SpaceRoll3] >= delta:
|
||||
b[SpaceRoll3] = 0
|
||||
case b[SpaceRoll4] >= delta:
|
||||
b[SpaceRoll4] = 0
|
||||
default:
|
||||
b.Print()
|
||||
log.Panic(fmt.Sprint(b), "no available roll for move", from, to, player, delta)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b Board) _available(player int) [][]int {
|
||||
func (b Board) _available(player int) [][2]int {
|
||||
homeSpace := SpaceHomePlayer
|
||||
barSpace := SpaceBarPlayer
|
||||
opponentBarSpace := SpaceBarOpponent
|
||||
|
@ -248,19 +256,19 @@ func (b Board) _available(player int) [][]int {
|
|||
mayBearOff := b.MayBearOff(player)
|
||||
onBar := b[barSpace] != 0
|
||||
|
||||
var moves [][]int
|
||||
var moves [][2]int
|
||||
|
||||
if b.Acey() && ((player == 1 && b[SpaceEnteredPlayer] == 0) || (player == 2 && b[SpaceEnteredOpponent] == 0)) && b[homeSpace] != 0 {
|
||||
if b[SpaceAcey] == 1 && ((player == 1 && b[SpaceEnteredPlayer] == 0) || (player == 2 && b[SpaceEnteredOpponent] == 0)) && b[homeSpace] != 0 {
|
||||
for space := 1; space < 25; space++ {
|
||||
v := b[space]
|
||||
if ((player == 1 && v >= -1) || (player == 2 && v <= 1)) && b.HaveRoll(homeSpace, space, player) {
|
||||
moves = append(moves, []int{homeSpace, space})
|
||||
moves = append(moves, [2]int{homeSpace, space})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for from := 0; from < 28; from++ {
|
||||
if from == SpaceHomePlayer || from == SpaceHomeOpponent || from == opponentBarSpace || b.Checkers(player, from) == 0 || (onBar && from != barSpace) {
|
||||
if from == SpaceHomePlayer || from == SpaceHomeOpponent || from == opponentBarSpace || checkers(player, b[from]) == 0 || (onBar && from != barSpace) {
|
||||
continue
|
||||
}
|
||||
if player == 1 {
|
||||
|
@ -272,7 +280,7 @@ func (b Board) _available(player int) [][]int {
|
|||
if (player == 1 && v < -1) || (player == 2 && v > 1) || !b.HaveRoll(from, to, player) {
|
||||
continue
|
||||
}
|
||||
moves = append(moves, []int{from, to})
|
||||
moves = append(moves, [2]int{from, to})
|
||||
}
|
||||
} else { // TODO clean up
|
||||
start := from + 1
|
||||
|
@ -287,7 +295,7 @@ func (b Board) _available(player int) [][]int {
|
|||
if (player == 1 && v < -1) || (player == 2 && v > 1) || !b.HaveRoll(from, to, player) {
|
||||
continue
|
||||
}
|
||||
moves = append(moves, []int{from, to})
|
||||
moves = append(moves, [2]int{from, to})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -296,14 +304,14 @@ func (b Board) _available(player int) [][]int {
|
|||
}
|
||||
|
||||
// Available returns legal moves available.
|
||||
func (b Board) Available(player int) ([][][]int, []Board) {
|
||||
var allMoves [][][]int
|
||||
func (b Board) Available(player int) ([][4][2]int, []Board) {
|
||||
var allMoves [][4][2]int
|
||||
|
||||
resultMutex := &sync.Mutex{}
|
||||
movesFound := func(moves [][]int) bool {
|
||||
movesFound := func(moves [4][2]int) bool {
|
||||
resultMutex.Lock()
|
||||
for _, f := range allMoves {
|
||||
if movesEqual(f, moves) {
|
||||
for i := range allMoves {
|
||||
if movesEqual(allMoves[i], moves) {
|
||||
resultMutex.Unlock()
|
||||
return true
|
||||
}
|
||||
|
@ -316,11 +324,10 @@ func (b Board) Available(player int) ([][][]int, []Board) {
|
|||
a := b._available(player)
|
||||
maxLen := 1
|
||||
for _, move := range a {
|
||||
move := move
|
||||
newBoard := b.Move(move[0], move[1], player).UseRoll(move[0], move[1], player)
|
||||
newAvailable := newBoard._available(player)
|
||||
if len(newAvailable) == 0 {
|
||||
moves := [][]int{move}
|
||||
moves := [4][2]int{move}
|
||||
if !movesFound(moves) {
|
||||
allMoves = append(allMoves, moves)
|
||||
boards = append(boards, newBoard)
|
||||
|
@ -331,7 +338,7 @@ func (b Board) Available(player int) ([][][]int, []Board) {
|
|||
newBoard2 := newBoard.Move(move2[0], move2[1], player).UseRoll(move2[0], move2[1], player)
|
||||
newAvailable2 := newBoard2._available(player)
|
||||
if len(newAvailable2) == 0 {
|
||||
moves := [][]int{move, move2}
|
||||
moves := [4][2]int{move, move2}
|
||||
if !movesFound(moves) {
|
||||
allMoves = append(allMoves, moves)
|
||||
boards = append(boards, newBoard2)
|
||||
|
@ -343,7 +350,7 @@ func (b Board) Available(player int) ([][][]int, []Board) {
|
|||
newBoard3 := newBoard2.Move(move3[0], move3[1], player).UseRoll(move3[0], move3[1], player)
|
||||
newAvailable3 := newBoard3._available(player)
|
||||
if len(newAvailable3) == 0 {
|
||||
moves := [][]int{move, move2, move3}
|
||||
moves := [4][2]int{move, move2, move3}
|
||||
if !movesFound(moves) {
|
||||
allMoves = append(allMoves, moves)
|
||||
boards = append(boards, newBoard3)
|
||||
|
@ -353,7 +360,7 @@ func (b Board) Available(player int) ([][][]int, []Board) {
|
|||
}
|
||||
for _, move4 := range newAvailable3 {
|
||||
newBoard4 := newBoard3.Move(move4[0], move4[1], player).UseRoll(move4[0], move4[1], player)
|
||||
moves := [][]int{move, move2, move3, move4}
|
||||
moves := [4][2]int{move, move2, move3, move4}
|
||||
if !movesFound(moves) {
|
||||
allMoves = append(allMoves, moves)
|
||||
boards = append(boards, newBoard4)
|
||||
|
@ -363,9 +370,16 @@ func (b Board) Available(player int) ([][][]int, []Board) {
|
|||
}
|
||||
}
|
||||
}
|
||||
var newMoves [][][]int
|
||||
var newMoves [][4][2]int
|
||||
for i := 0; i < len(allMoves); i++ {
|
||||
if len(allMoves[i]) >= maxLen {
|
||||
l := 0
|
||||
for j := 0; j < 4; j++ {
|
||||
if allMoves[i][j][0] == 0 && allMoves[i][j][1] == 0 {
|
||||
break
|
||||
}
|
||||
l = j + 1
|
||||
}
|
||||
if l >= maxLen {
|
||||
newMoves = append(newMoves, allMoves[i])
|
||||
}
|
||||
}
|
||||
|
@ -396,20 +410,20 @@ func (b Board) Past() bool {
|
|||
|
||||
func (b Board) Pips(player int) int {
|
||||
var pips int
|
||||
if b.Acey() {
|
||||
if b[SpaceAcey] == 1 {
|
||||
if player == 1 && b[SpaceEnteredPlayer] == 0 {
|
||||
pips += int(b.Checkers(player, SpaceHomePlayer)) * PseudoPips(player, SpaceHomePlayer)
|
||||
pips += int(checkers(player, b[SpaceHomePlayer])) * PseudoPips(player, SpaceHomePlayer)
|
||||
} else if player == 2 && b[SpaceEnteredOpponent] == 0 {
|
||||
pips += int(b.Checkers(player, SpaceHomeOpponent)) * PseudoPips(player, SpaceHomeOpponent)
|
||||
pips += int(checkers(player, b[SpaceHomeOpponent])) * PseudoPips(player, SpaceHomeOpponent)
|
||||
}
|
||||
}
|
||||
if player == 1 {
|
||||
pips += int(b.Checkers(player, SpaceBarPlayer)) * PseudoPips(player, SpaceBarPlayer)
|
||||
pips += int(checkers(player, b[SpaceBarPlayer])) * PseudoPips(player, SpaceBarPlayer)
|
||||
} else {
|
||||
pips += int(b.Checkers(player, SpaceBarOpponent)) * PseudoPips(player, SpaceBarOpponent)
|
||||
pips += int(checkers(player, b[SpaceBarOpponent])) * PseudoPips(player, SpaceBarOpponent)
|
||||
}
|
||||
for space := 1; space < 25; space++ {
|
||||
pips += int(b.Checkers(player, space)) * PseudoPips(player, space)
|
||||
pips += int(checkers(player, b[space])) * PseudoPips(player, space)
|
||||
}
|
||||
return pips
|
||||
}
|
||||
|
@ -418,11 +432,9 @@ func (b Board) Blots(player int) int {
|
|||
o := opponent(player)
|
||||
var pips int
|
||||
for space := 1; space < 25; space++ {
|
||||
checkers := b.Checkers(player, space)
|
||||
if checkers != 1 {
|
||||
continue
|
||||
if checkers(player, b[space]) == 1 {
|
||||
pips += PseudoPips(o, space)
|
||||
}
|
||||
pips += checkers * PseudoPips(o, space)
|
||||
}
|
||||
return pips
|
||||
}
|
||||
|
@ -442,7 +454,7 @@ func (b Board) evaluate(player int, hitScore int, a *Analysis) {
|
|||
a.hitScore = hitScore
|
||||
}
|
||||
|
||||
func (b Board) Evaluation(player int, hitScore int, moves [][]int) *Analysis {
|
||||
func (b Board) Evaluation(player int, hitScore int, moves [4][2]int) *Analysis {
|
||||
a := &Analysis{
|
||||
Board: b,
|
||||
Moves: moves,
|
||||
|
@ -454,7 +466,7 @@ func (b Board) Evaluation(player int, hitScore int, moves [][]int) *Analysis {
|
|||
return a
|
||||
}
|
||||
|
||||
func (b Board) Analyze(available [][][]int, result *[]*Analysis) {
|
||||
func (b Board) Analyze(available [][4][2]int, result *[]*Analysis) {
|
||||
if len(available) == 0 {
|
||||
*result = (*result)[:0]
|
||||
return
|
||||
|
@ -537,14 +549,14 @@ func (b Board) Analyze(available [][][]int, result *[]*Analysis) {
|
|||
}
|
||||
|
||||
func (b Board) ChooseDoubles(result *[]*Analysis) int {
|
||||
if !b.Acey() {
|
||||
if b[SpaceAcey] == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
bestDoubles := 6
|
||||
bestScore := math.MaxFloat64
|
||||
|
||||
var available [][][]int
|
||||
var available [][4][2]int
|
||||
for i := 0; i < 6; i++ {
|
||||
doubles := int8(i + 1)
|
||||
bc := b
|
||||
|
@ -590,133 +602,86 @@ func PseudoPips(player int, space int) int {
|
|||
return v
|
||||
}
|
||||
|
||||
func movesEqual(a [][]int, b [][]int) bool {
|
||||
l := len(a)
|
||||
if len(b) != l {
|
||||
return false
|
||||
}
|
||||
for _, m := range a {
|
||||
switch m[0] {
|
||||
case SpaceBarPlayer, SpaceBarOpponent:
|
||||
return false
|
||||
}
|
||||
switch m[1] {
|
||||
case SpaceHomePlayer, SpaceHomeOpponent:
|
||||
return false
|
||||
}
|
||||
}
|
||||
switch l {
|
||||
case 0:
|
||||
return true
|
||||
case 1:
|
||||
return a[0][0] == b[0][0] && a[0][1] == b[0][1]
|
||||
case 2:
|
||||
return (a[0][0] == b[0][0] && a[0][1] == b[0][1] && a[1][0] == b[1][0] && a[1][1] == b[1][1]) || // 1, 2
|
||||
(a[0][0] == b[1][0] && a[0][1] == b[1][1] && a[1][0] == b[0][0] && a[1][1] == b[0][1]) // 2, 1
|
||||
case 3:
|
||||
if a[0][0] == b[0][0] && a[0][1] == b[0][1] { // 1
|
||||
if (a[1][0] == b[1][0] && a[1][1] == b[1][1] && a[2][0] == b[2][0] && a[2][1] == b[2][1]) || // 2, 3
|
||||
(a[1][0] == b[2][0] && a[1][1] == b[2][1] && a[2][0] == b[1][0] && a[2][1] == b[1][1]) { // 3, 2
|
||||
func movesEqual(a [4][2]int, b [4][2]int) bool {
|
||||
if a[0][0] == b[0][0] && a[0][1] == b[0][1] { // 1
|
||||
if a[1][0] == b[1][0] && a[1][1] == b[1][1] { // 2
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 3,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 4,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[0][0] == b[1][0] && a[0][1] == b[1][1] { // 2
|
||||
if (a[1][0] == b[0][0] && a[1][1] == b[0][1] && a[2][0] == b[2][0] && a[2][1] == b[2][1]) ||
|
||||
(a[1][0] == b[2][0] && a[1][1] == b[2][1] && a[2][0] == b[0][0] && a[2][1] == b[0][1]) {
|
||||
if a[1][0] == b[2][0] && a[1][1] == b[2][1] { // 3
|
||||
if (a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 2,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) { // 4,2
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[0][0] == b[2][0] && a[0][1] == b[2][1] { // 3
|
||||
if (a[1][0] == b[0][0] && a[1][1] == b[0][1] && a[2][0] == b[1][0] && a[2][1] == b[1][1]) || // 1, 2
|
||||
(a[1][0] == b[1][0] && a[1][1] == b[1][1] && a[2][0] == b[0][0] && a[2][1] == b[0][1]) { // 2, 1
|
||||
if a[1][0] == b[3][0] && a[1][1] == b[3][1] { // 4
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) || // 3,2
|
||||
(a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 2,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case 4:
|
||||
if a[0][0] == b[0][0] && a[0][1] == b[0][1] { // 1
|
||||
if a[1][0] == b[1][0] && a[1][1] == b[1][1] { // 2
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 3,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 4,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[2][0] && a[1][1] == b[2][1] { // 3
|
||||
if (a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 2,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) { // 4,2
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[3][0] && a[1][1] == b[3][1] { // 4
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) || // 3,2
|
||||
(a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 2,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if a[0][0] == b[1][0] && a[0][1] == b[1][1] { // 2
|
||||
if a[1][0] == b[0][0] && a[1][1] == b[0][1] { // 1
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 3,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 4,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[2][0] && a[1][1] == b[2][1] { // 3
|
||||
if (a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) || // 4,1
|
||||
(a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) { // 1,4
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[3][0] && a[1][1] == b[3][1] { // 4
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) || // 3,1
|
||||
(a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 1,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if a[0][0] == b[2][0] && a[0][1] == b[2][1] { // 3
|
||||
if a[1][0] == b[0][0] && a[1][1] == b[0][1] { // 1
|
||||
if (a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 2,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) { // 4,2
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[1][0] && a[1][1] == b[1][1] { // 2
|
||||
if (a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 1,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) { // 4,1
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[3][0] && a[1][1] == b[3][1] { // 4
|
||||
if (a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) || // 2,1
|
||||
(a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) { // 1,2
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if a[0][0] == b[3][0] && a[0][1] == b[3][1] { // 4
|
||||
if a[1][0] == b[0][0] && a[1][1] == b[0][1] { // 1
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) || // 3,2
|
||||
(a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 2,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[1][0] && a[1][1] == b[1][1] { // 2
|
||||
if (a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) || // 1,3
|
||||
(a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) { // 3,1
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[2][0] && a[1][1] == b[2][1] { // 3
|
||||
if (a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) || // 1,2
|
||||
(a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) { // 2,1
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
default:
|
||||
log.Panicf("more than 4 moves were provided: %+v %+v", a, b)
|
||||
return false
|
||||
}
|
||||
if a[0][0] == b[1][0] && a[0][1] == b[1][1] { // 2
|
||||
if a[1][0] == b[0][0] && a[1][1] == b[0][1] { // 1
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 3,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 4,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[2][0] && a[1][1] == b[2][1] { // 3
|
||||
if (a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) || // 4,1
|
||||
(a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) { // 1,4
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[3][0] && a[1][1] == b[3][1] { // 4
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) || // 3,1
|
||||
(a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 1,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if a[0][0] == b[2][0] && a[0][1] == b[2][1] { // 3
|
||||
if a[1][0] == b[0][0] && a[1][1] == b[0][1] { // 1
|
||||
if (a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 2,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) { // 4,2
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[1][0] && a[1][1] == b[1][1] { // 2
|
||||
if (a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[3][0] && a[3][1] == b[3][1]) || // 1,4
|
||||
(a[2][0] == b[3][0] && a[2][1] == b[3][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) { // 4,1
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[3][0] && a[1][1] == b[3][1] { // 4
|
||||
if (a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) || // 2,1
|
||||
(a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) { // 1,2
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if a[0][0] == b[3][0] && a[0][1] == b[3][1] { // 4
|
||||
if a[1][0] == b[0][0] && a[1][1] == b[0][1] { // 1
|
||||
if (a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) || // 3,2
|
||||
(a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) { // 2,3
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[1][0] && a[1][1] == b[1][1] { // 2
|
||||
if (a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[2][0] && a[3][1] == b[2][1]) || // 1,3
|
||||
(a[2][0] == b[2][0] && a[2][1] == b[2][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) { // 3,1
|
||||
return true
|
||||
}
|
||||
}
|
||||
if a[1][0] == b[2][0] && a[1][1] == b[2][1] { // 3
|
||||
if (a[2][0] == b[0][0] && a[2][1] == b[0][1] && a[3][0] == b[1][0] && a[3][1] == b[1][1]) || // 1,2
|
||||
(a[2][0] == b[1][0] && a[2][1] == b[1][1] && a[3][0] == b[0][0] && a[3][1] == b[0][1]) { // 2,1
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ func BenchmarkAvailable(b *testing.B) {
|
|||
board[SpaceRoll3] = c.roll3
|
||||
board[SpaceRoll4] = c.roll4
|
||||
|
||||
var available [][][]int
|
||||
var available [][4][2]int
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
available, _ = board.Available(1)
|
||||
|
@ -227,3 +227,15 @@ func BenchmarkChooseDoubles(b *testing.B) {
|
|||
}
|
||||
_ = doubles
|
||||
}
|
||||
|
||||
func BenchmarkMayBearOff(b *testing.B) {
|
||||
board := NewBoard(false)
|
||||
|
||||
var allowed bool
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
allowed = board.MayBearOff(1)
|
||||
}
|
||||
|
||||
_ = allowed
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue