bgammon/board.go

113 lines
2.8 KiB
Go

package bgammon
import (
"log"
"sort"
"strconv"
"strings"
)
const (
SpaceHomePlayer int8 = 0 // Current player's home.
SpaceHomeOpponent int8 = 25 // Opponent player's home.
SpaceBarPlayer int8 = 26 // Current player's bar.
SpaceBarOpponent int8 = 27 // Opponent player's bar.
)
// BoardSpaces is the total number of spaces needed to represent a backgammon board.
const BoardSpaces = 28
// NewBoard returns a new backgammon board represented as integers. Positive
// integers represent player 1's checkers and negative integers represent
// player 2's checkers. The board's space numbering is always from the
// perspective of the current player (i.e. the 1 space will always be in the
// current player's home board).
func NewBoard(variant int8) []int8 {
space := make([]int8, BoardSpaces)
switch variant {
case VariantBackgammon:
space[24], space[1] = 2, -2
space[19], space[6] = -5, 5
space[17], space[8] = -3, 3
space[13], space[12] = 5, -5
case VariantAceyDeucey, VariantTabula:
space[SpaceHomePlayer], space[SpaceHomeOpponent] = 15, -15
default:
log.Panicf("failed to initialize board: unknown variant: %d", variant)
}
return space
}
// HomeRange returns the start and end space of the provided player's home board.
func HomeRange(player int8, variant int8) (from int8, to int8) {
if player == 2 || variant == VariantTabula {
return 24, 19
}
return 1, 6
}
// RollForMove returns the roll needed to move a checker from the provided spaces.
func RollForMove(from int8, to int8, player int8, variant int8) int8 {
if !ValidSpace(from) || !ValidSpace(to) {
return 0
}
// Handle standard moves.
if from >= 1 && from <= 24 && to >= 1 && to <= 24 {
return SpaceDiff(from, to, variant)
}
playerHome := SpaceHomePlayer
playerBar := SpaceBarPlayer
oppHome := SpaceHomeOpponent
oppBar := SpaceBarOpponent
if player == 2 {
playerHome, oppHome, playerBar, oppBar = oppHome, playerHome, oppBar, playerBar
}
// Handle moves with special 'to' space.
if to == playerBar || to == oppBar || to == oppHome {
return 0
} else if to == playerHome {
}
// Handle moves with special 'from' space.
if from == SpaceBarPlayer {
if player == 2 && variant != VariantTabula {
return 25 - to
} else {
return to
}
}
return 0
}
func ParseSpace(space string) int8 {
i, err := strconv.Atoi(space)
if err != nil {
switch strings.ToLower(space) {
case "bar", "b":
return SpaceBarPlayer
case "off", "o", "home", "h":
return SpaceHomePlayer
}
return -1
}
return int8(i)
}
func compareMoveFunc(moves [][]int8) func(i, j int) bool {
return func(i, j int) bool {
if moves[j][0] == moves[i][0] {
return moves[j][1] < moves[i][1]
}
return moves[j][0] < moves[i][0]
}
}
// SortMoves sorts moves from highest to lowest.
func SortMoves(moves [][]int8) {
sort.Slice(moves, compareMoveFunc(moves))
}