bgammon/board.go

122 lines
3 KiB
Go

package bgammon
import (
"sort"
"strconv"
"strings"
)
const (
SpaceHomePlayer = 0 // Current player's home.
SpaceHomeOpponent = 25 // Opponent player's home.
SpaceBarPlayer = 26 // Current player's bar.
SpaceBarOpponent = 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() []int {
space := make([]int, BoardSpaces)
space[24], space[1] = 2, -2
space[19], space[6] = -5, 5
space[17], space[8] = -3, 3
space[13], space[12] = 5, -5
return space
}
// HomeRange returns the start and end space of the provided player's home board.
func HomeRange(player int) (from int, to int) {
if player == 2 {
return 24, 19
}
return 1, 6
}
// RollForMove returns the roll needed to move a checker from the provided spaces.
func RollForMove(from int, to int, player int) int {
if !ValidSpace(from) || !ValidSpace(to) {
return 0
}
// Handle standard moves.
if from >= 1 && from <= 24 && to >= 1 && to <= 24 {
return SpaceDiff(from, to)
}
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 {
return 25 - to
} else {
return to
}
}
return 0
}
// CanBearOff returns whether the provided player can bear checkers off of the board.
func CanBearOff(board []int, player int) bool {
homeStart, homeEnd := HomeRange(player)
homeStart, homeEnd = minInt(homeStart, homeEnd), maxInt(homeStart, homeEnd)
ok := true
for i := 1; i < 24; i++ {
if (i < homeStart || i > homeEnd) && PlayerCheckers(board[i], player) > 0 {
ok = false
break
}
}
if ok && (PlayerCheckers(board[SpaceBarPlayer], player) > 0 || PlayerCheckers(board[SpaceBarOpponent], player) > 0) {
ok = false
}
return ok
}
func ParseSpace(space string) int {
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 i
}
func compareMoveFunc(moves [][]int) 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 [][]int) {
sort.Slice(moves, compareMoveFunc(moves))
}