Store board state as []int8
This commit is contained in:
parent
fb58a25c67
commit
f049353bd3
11 changed files with 152 additions and 151 deletions
30
board.go
30
board.go
|
@ -7,10 +7,10 @@ import (
|
|||
)
|
||||
|
||||
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.
|
||||
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.
|
||||
|
@ -21,8 +21,8 @@ const BoardSpaces = 28
|
|||
// 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(acey bool) []int {
|
||||
space := make([]int, BoardSpaces)
|
||||
func NewBoard(acey bool) []int8 {
|
||||
space := make([]int8, BoardSpaces)
|
||||
if acey {
|
||||
space[SpaceHomePlayer], space[SpaceHomeOpponent] = 15, -15
|
||||
} else {
|
||||
|
@ -35,7 +35,7 @@ func NewBoard(acey bool) []int {
|
|||
}
|
||||
|
||||
// HomeRange returns the start and end space of the provided player's home board.
|
||||
func HomeRange(player int) (from int, to int) {
|
||||
func HomeRange(player int8) (from int8, to int8) {
|
||||
if player == 2 {
|
||||
return 24, 19
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func HomeRange(player int) (from int, to int) {
|
|||
}
|
||||
|
||||
// RollForMove returns the roll needed to move a checker from the provided spaces.
|
||||
func RollForMove(from int, to int, player int, acey bool) int {
|
||||
func RollForMove(from int8, to int8, player int8, acey bool) int8 {
|
||||
if !ValidSpace(from) || !ValidSpace(to) {
|
||||
return 0
|
||||
}
|
||||
|
@ -80,17 +80,17 @@ func RollForMove(from int, to int, player int, acey bool) int {
|
|||
}
|
||||
|
||||
// CanBearOff returns whether the provided player can bear checkers off of the board.
|
||||
func CanBearOff(board []int, player int, local bool) bool {
|
||||
func CanBearOff(board []int8, player int8, local bool) bool {
|
||||
if PlayerCheckers(board[SpaceBarPlayer], player) > 0 || PlayerCheckers(board[SpaceBarOpponent], player) > 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
homeStart, homeEnd := 1, 6
|
||||
homeStart, homeEnd := int8(1), int8(6)
|
||||
if !local {
|
||||
homeStart, homeEnd = HomeRange(player)
|
||||
homeStart, homeEnd = minInt(homeStart, homeEnd), maxInt(homeStart, homeEnd)
|
||||
}
|
||||
for i := 1; i <= 24; i++ {
|
||||
for i := int8(1); i <= 24; i++ {
|
||||
if (i < homeStart || i > homeEnd) && PlayerCheckers(board[i], player) > 0 {
|
||||
return false
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func CanBearOff(board []int, player int, local bool) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func ParseSpace(space string) int {
|
||||
func ParseSpace(space string) int8 {
|
||||
i, err := strconv.Atoi(space)
|
||||
if err != nil {
|
||||
switch strings.ToLower(space) {
|
||||
|
@ -109,10 +109,10 @@ func ParseSpace(space string) int {
|
|||
}
|
||||
return -1
|
||||
}
|
||||
return i
|
||||
return int8(i)
|
||||
}
|
||||
|
||||
func compareMoveFunc(moves [][]int) func(i, j int) bool {
|
||||
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]
|
||||
|
@ -122,6 +122,6 @@ func compareMoveFunc(moves [][]int) func(i, j int) bool {
|
|||
}
|
||||
|
||||
// SortMoves sorts moves from highest to lowest.
|
||||
func SortMoves(moves [][]int) {
|
||||
func SortMoves(moves [][]int8) {
|
||||
sort.Slice(moves, compareMoveFunc(moves))
|
||||
}
|
||||
|
|
22
event.go
22
event.go
|
@ -41,8 +41,8 @@ type EventSay struct {
|
|||
type GameListing struct {
|
||||
ID int
|
||||
Password bool
|
||||
Points int
|
||||
Players int
|
||||
Points int8
|
||||
Players int8
|
||||
Name string
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ type EventList struct {
|
|||
type EventJoined struct {
|
||||
Event
|
||||
GameID int
|
||||
PlayerNumber int
|
||||
PlayerNumber int8
|
||||
}
|
||||
|
||||
type EventFailedJoin struct {
|
||||
|
@ -78,8 +78,8 @@ type EventBoard struct {
|
|||
|
||||
type EventRolled struct {
|
||||
Event
|
||||
Roll1 int
|
||||
Roll2 int
|
||||
Roll1 int8
|
||||
Roll2 int8
|
||||
Selected bool // Whether the roll is selected by the player (used in acey-deucey games).
|
||||
}
|
||||
|
||||
|
@ -90,13 +90,13 @@ type EventFailedRoll struct {
|
|||
|
||||
type EventMoved struct {
|
||||
Event
|
||||
Moves [][]int
|
||||
Moves [][]int8
|
||||
}
|
||||
|
||||
type EventFailedMove struct {
|
||||
Event
|
||||
From int
|
||||
To int
|
||||
From int8
|
||||
To int8
|
||||
Reason string
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ type EventFailedOk struct {
|
|||
|
||||
type EventWin struct {
|
||||
Event
|
||||
Points int
|
||||
Points int8
|
||||
}
|
||||
|
||||
type EventSettings struct {
|
||||
|
@ -127,9 +127,9 @@ type EventReplay struct {
|
|||
type HistoryMatch struct {
|
||||
ID int
|
||||
Timestamp int64
|
||||
Points int
|
||||
Points int8
|
||||
Opponent string
|
||||
Winner int
|
||||
Winner int8
|
||||
}
|
||||
|
||||
type EventHistory struct {
|
||||
|
|
157
game.go
157
game.go
|
@ -22,21 +22,21 @@ type Game struct {
|
|||
Player2 Player
|
||||
|
||||
Acey bool // Acey-deucey.
|
||||
Board []int
|
||||
Turn int
|
||||
Roll1 int
|
||||
Roll2 int
|
||||
Moves [][]int // Pending moves.
|
||||
Winner int
|
||||
Board []int8
|
||||
Turn int8
|
||||
Roll1 int8
|
||||
Roll2 int8
|
||||
Moves [][]int8 // Pending moves.
|
||||
Winner int8
|
||||
|
||||
Points int // Points required to win the match.
|
||||
DoubleValue int // Doubling cube value.
|
||||
DoublePlayer int // Player that currently posesses the doubling cube.
|
||||
Points int8 // Points required to win the match.
|
||||
DoubleValue int8 // Doubling cube value.
|
||||
DoublePlayer int8 // Player that currently posesses the doubling cube.
|
||||
DoubleOffered bool // Whether the current player is offering a double.
|
||||
|
||||
Reroll bool // Used in acey-deucey.
|
||||
|
||||
boardStates [][]int // One board state for each move to allow undoing a move.
|
||||
boardStates [][]int8 // One board state for each move to allow undoing a move.
|
||||
}
|
||||
|
||||
func NewGame(acey bool) *Game {
|
||||
|
@ -64,11 +64,11 @@ func (g *Game) Copy() *Game {
|
|||
Player2: g.Player2,
|
||||
|
||||
Acey: g.Acey,
|
||||
Board: make([]int, len(g.Board)),
|
||||
Board: make([]int8, len(g.Board)),
|
||||
Turn: g.Turn,
|
||||
Roll1: g.Roll1,
|
||||
Roll2: g.Roll2,
|
||||
Moves: make([][]int, len(g.Moves)),
|
||||
Moves: make([][]int8, len(g.Moves)),
|
||||
Winner: g.Winner,
|
||||
|
||||
Points: g.Points,
|
||||
|
@ -78,7 +78,7 @@ func (g *Game) Copy() *Game {
|
|||
|
||||
Reroll: g.Reroll,
|
||||
|
||||
boardStates: make([][]int, len(g.boardStates)),
|
||||
boardStates: make([][]int8, len(g.boardStates)),
|
||||
}
|
||||
copy(newGame.Board, g.Board)
|
||||
copy(newGame.Moves, g.Moves)
|
||||
|
@ -101,7 +101,7 @@ func (g *Game) NextTurn(replay bool) {
|
|||
}
|
||||
|
||||
if !replay {
|
||||
nextTurn := 1
|
||||
var nextTurn int8 = 1
|
||||
if g.Turn == 1 {
|
||||
nextTurn = 2
|
||||
}
|
||||
|
@ -148,18 +148,18 @@ func (g *Game) opponentPlayer() Player {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *Game) addMove(move []int) bool {
|
||||
func (g *Game) addMove(move []int8) bool {
|
||||
opponentCheckers := OpponentCheckers(g.Board[move[1]], g.Turn)
|
||||
if opponentCheckers > 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
delta := 1
|
||||
var delta int8 = 1
|
||||
if g.Turn == 2 {
|
||||
delta = -1
|
||||
}
|
||||
|
||||
boardState := make([]int, len(g.Board))
|
||||
boardState := make([]int8, len(g.Board))
|
||||
copy(boardState, g.Board)
|
||||
g.boardStates = append(g.boardStates, boardState)
|
||||
|
||||
|
@ -177,26 +177,26 @@ func (g *Game) addMove(move []int) bool {
|
|||
g.Board[move[1]] += delta
|
||||
}
|
||||
|
||||
g.Moves = append(g.Moves, []int{move[0], move[1]})
|
||||
g.Moves = append(g.Moves, []int8{move[0], move[1]})
|
||||
return true
|
||||
}
|
||||
|
||||
// AddLocalMove adds a move without performing any validation. This is useful when
|
||||
// adding a move locally while waiting for an EventBoard response from the server.
|
||||
func (g *Game) AddLocalMove(move []int) bool {
|
||||
func (g *Game) AddLocalMove(move []int8) bool {
|
||||
return g.addMove(move)
|
||||
}
|
||||
|
||||
func (g *Game) ExpandMove(move []int, currentSpace int, moves [][]int, local bool) ([][]int, bool) {
|
||||
func (g *Game) ExpandMove(move []int8, currentSpace int8, moves [][]int8, local bool) ([][]int8, bool) {
|
||||
l := g.LegalMoves(local)
|
||||
var hitMoves [][]int
|
||||
var hitMoves [][]int8
|
||||
for _, m := range l {
|
||||
if OpponentCheckers(g.Board[m[1]], g.Turn) == 1 {
|
||||
hitMoves = append(hitMoves, m)
|
||||
}
|
||||
}
|
||||
for i := 0; i < 2; i++ {
|
||||
var checkMoves [][]int
|
||||
var checkMoves [][]int8
|
||||
if i == 0 { // Try moves that will hit an opponent's checker first.
|
||||
checkMoves = hitMoves
|
||||
} else {
|
||||
|
@ -207,9 +207,9 @@ func (g *Game) ExpandMove(move []int, currentSpace int, moves [][]int, local boo
|
|||
continue
|
||||
}
|
||||
|
||||
newMoves := make([][]int, len(moves))
|
||||
newMoves := make([][]int8, len(moves))
|
||||
copy(newMoves, moves)
|
||||
newMoves = append(newMoves, []int{lm[0], lm[1]})
|
||||
newMoves = append(newMoves, []int8{lm[0], lm[1]})
|
||||
|
||||
if lm[1] == move[1] {
|
||||
return newMoves, true
|
||||
|
@ -229,13 +229,13 @@ func (g *Game) ExpandMove(move []int, currentSpace int, moves [][]int, local boo
|
|||
}
|
||||
|
||||
// AddMoves adds moves to the game state. Adding a backwards move will remove the equivalent existing move.
|
||||
func (g *Game) AddMoves(moves [][]int, local bool) (bool, [][]int) {
|
||||
func (g *Game) AddMoves(moves [][]int8, local bool) (bool, [][]int8) {
|
||||
if g.Player1.Name == "" || g.Player2.Name == "" || g.Winner != 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var addMoves [][]int
|
||||
var undoMoves [][]int
|
||||
var addMoves [][]int8
|
||||
var undoMoves [][]int8
|
||||
|
||||
gameCopy := g.Copy()
|
||||
|
||||
|
@ -245,7 +245,7 @@ VALIDATEMOVES:
|
|||
l := gameCopy.LegalMoves(local)
|
||||
for _, lm := range l {
|
||||
if lm[0] == move[0] && lm[1] == move[1] {
|
||||
addMoves = append(addMoves, []int{move[0], move[1]})
|
||||
addMoves = append(addMoves, []int8{move[0], move[1]})
|
||||
continue VALIDATEMOVES
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ VALIDATEMOVES:
|
|||
}
|
||||
gameMove := gameCopy.Moves[i]
|
||||
if move[0] == gameMove[1] && move[1] == gameMove[0] {
|
||||
undoMoves = append(undoMoves, []int{gameMove[1], gameMove[0]})
|
||||
undoMoves = append(undoMoves, []int8{gameMove[1], gameMove[0]})
|
||||
validateOffset++
|
||||
continue VALIDATEMOVES
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ VALIDATEMOVES:
|
|||
expandedMoves, ok := g.ExpandMove(move, move[0], nil, local)
|
||||
if ok {
|
||||
for _, expanded := range expandedMoves {
|
||||
addMoves = append(addMoves, []int{expanded[0], expanded[1]})
|
||||
addMoves = append(addMoves, []int8{expanded[0], expanded[1]})
|
||||
}
|
||||
continue VALIDATEMOVES
|
||||
}
|
||||
|
@ -347,12 +347,12 @@ ADDMOVES:
|
|||
}
|
||||
}
|
||||
|
||||
func (g *Game) LegalMoves(local bool) [][]int {
|
||||
func (g *Game) LegalMoves(local bool) [][]int8 {
|
||||
if g.Winner != 0 || g.Roll1 == 0 || g.Roll2 == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
rolls := []int{
|
||||
rolls := []int8{
|
||||
g.Roll1,
|
||||
g.Roll2,
|
||||
}
|
||||
|
@ -360,9 +360,9 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
rolls = append(rolls, g.Roll1, g.Roll2)
|
||||
}
|
||||
|
||||
haveDiceRoll := func(from, to int) int {
|
||||
haveDiceRoll := func(from, to int8) int8 {
|
||||
diff := SpaceDiff(from, to, g.Acey)
|
||||
var c int
|
||||
var c int8
|
||||
for _, roll := range rolls {
|
||||
if roll == diff {
|
||||
c++
|
||||
|
@ -371,8 +371,8 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
return c
|
||||
}
|
||||
|
||||
haveBearOffDiceRoll := func(diff int) int {
|
||||
var c int
|
||||
haveBearOffDiceRoll := func(diff int8) int8 {
|
||||
var c int8
|
||||
for _, roll := range rolls {
|
||||
if roll == diff || (roll > diff && !g.Acey) {
|
||||
c++
|
||||
|
@ -381,7 +381,7 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
return c
|
||||
}
|
||||
|
||||
useDiceRoll := func(from, to int) bool {
|
||||
useDiceRoll := func(from, to int8) bool {
|
||||
if to == SpaceHomePlayer || to == SpaceHomeOpponent {
|
||||
needRoll := from
|
||||
if to == SpaceHomeOpponent {
|
||||
|
@ -418,11 +418,11 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
}
|
||||
}
|
||||
|
||||
var moves [][]int
|
||||
var movesFound = make(map[int]bool)
|
||||
var moves [][]int8
|
||||
var movesFound = make(map[int8]bool)
|
||||
|
||||
var mustEnter bool
|
||||
var barSpace int
|
||||
var barSpace int8
|
||||
if PlayerCheckers(g.Board[SpaceBarPlayer], g.Turn) > 0 {
|
||||
mustEnter = true
|
||||
barSpace = SpaceBarPlayer
|
||||
|
@ -432,7 +432,7 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
}
|
||||
if mustEnter { // Must enter from bar.
|
||||
from, to := HomeRange(g.opponentPlayer().Number)
|
||||
IterateSpaces(from, to, g.Acey, func(homeSpace int, spaceCount int) {
|
||||
IterateSpaces(from, to, g.Acey, func(homeSpace int8, spaceCount int8) {
|
||||
if movesFound[barSpace*100+homeSpace] {
|
||||
return
|
||||
}
|
||||
|
@ -442,13 +442,14 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
}
|
||||
opponentCheckers := OpponentCheckers(g.Board[homeSpace], g.Turn)
|
||||
if opponentCheckers <= 1 {
|
||||
moves = append(moves, []int{barSpace, homeSpace})
|
||||
moves = append(moves, []int8{barSpace, homeSpace})
|
||||
movesFound[barSpace*100+homeSpace] = true
|
||||
}
|
||||
})
|
||||
} else {
|
||||
canBearOff := CanBearOff(g.Board, g.Turn, false)
|
||||
for space := range g.Board {
|
||||
for sp := range g.Board {
|
||||
space := int8(sp)
|
||||
if space == SpaceBarPlayer || space == SpaceBarOpponent { // Handled above.
|
||||
continue
|
||||
} else if space == SpaceHomePlayer || space == SpaceHomeOpponent {
|
||||
|
@ -499,19 +500,19 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
}
|
||||
}
|
||||
if ok {
|
||||
moves = append(moves, []int{space, homeSpace})
|
||||
moves = append(moves, []int8{space, homeSpace})
|
||||
movesFound[space*100+homeSpace] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move normally.
|
||||
lastSpace := 1
|
||||
var lastSpace int8 = 1
|
||||
if g.Turn == 2 {
|
||||
lastSpace = 24
|
||||
}
|
||||
|
||||
f := func(to int, spaceCount int) {
|
||||
f := func(to int8, spaceCount int8) {
|
||||
if movesFound[space*100+to] {
|
||||
return
|
||||
}
|
||||
|
@ -522,7 +523,7 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
|
||||
opponentCheckers := OpponentCheckers(g.Board[to], g.Turn)
|
||||
if opponentCheckers <= 1 {
|
||||
moves = append(moves, []int{space, to})
|
||||
moves = append(moves, []int8{space, to})
|
||||
movesFound[space*100+to] = true
|
||||
}
|
||||
}
|
||||
|
@ -537,14 +538,14 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
}
|
||||
|
||||
// totalMoves tries all legal moves in a game and returns the maximum total number of moves that a player may consecutively make.
|
||||
var totalMoves func(in *Game, move []int) int
|
||||
totalMoves = func(in *Game, move []int) int {
|
||||
var totalMoves func(in *Game, move []int8) int8
|
||||
totalMoves = func(in *Game, move []int8) int8 {
|
||||
gc := in.Copy()
|
||||
if !gc.addMove(move) {
|
||||
log.Panicf("failed to add move %+v to game %+v", move, in)
|
||||
}
|
||||
|
||||
maxTotal := 1
|
||||
var maxTotal int8 = 1
|
||||
for _, m := range gc.LegalMoves(local) {
|
||||
total := totalMoves(gc, m)
|
||||
if total+1 > maxTotal {
|
||||
|
@ -555,8 +556,8 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
}
|
||||
|
||||
// Simulate all possible moves to their final value and only allow moves that will achieve the maximum total moves.
|
||||
var maxMoves int
|
||||
moveCounts := make([]int, len(moves))
|
||||
var maxMoves int8
|
||||
moveCounts := make([]int8, len(moves))
|
||||
for i, move := range moves {
|
||||
moveCounts[i] = totalMoves(g, move)
|
||||
if moveCounts[i] > maxMoves {
|
||||
|
@ -564,7 +565,7 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
}
|
||||
}
|
||||
if maxMoves > 1 {
|
||||
var newMoves [][]int
|
||||
var newMoves [][]int8
|
||||
for i, move := range moves {
|
||||
if moveCounts[i] >= maxMoves {
|
||||
newMoves = append(newMoves, move)
|
||||
|
@ -576,7 +577,7 @@ func (g *Game) LegalMoves(local bool) [][]int {
|
|||
return moves
|
||||
}
|
||||
|
||||
func (g *Game) RenderSpace(player int, space int, spaceValue int, legalMoves [][]int) []byte {
|
||||
func (g *Game) RenderSpace(player int8, space int8, spaceValue int8, legalMoves [][]int8) []byte {
|
||||
var playerColor = "x"
|
||||
var opponentColor = "o"
|
||||
if player == 2 {
|
||||
|
@ -610,8 +611,8 @@ func (g *Game) RenderSpace(player int, space int, spaceValue int, legalMoves [][
|
|||
top = !top
|
||||
}
|
||||
|
||||
firstDigit := 4
|
||||
secondDigit := 5
|
||||
var firstDigit int8 = 4
|
||||
var secondDigit int8 = 5
|
||||
if !top {
|
||||
firstDigit = 5
|
||||
secondDigit = 4
|
||||
|
@ -623,10 +624,10 @@ func (g *Game) RenderSpace(player int, space int, spaceValue int, legalMoves [][
|
|||
if abs > 9 {
|
||||
firstNumeral = "1"
|
||||
} else {
|
||||
firstNumeral = strconv.Itoa(abs)
|
||||
firstNumeral = strconv.Itoa(int(abs))
|
||||
}
|
||||
if abs > 9 {
|
||||
secondNumeral = strconv.Itoa(abs - 10)
|
||||
secondNumeral = strconv.Itoa(int(abs) - 10)
|
||||
}
|
||||
|
||||
if spaceValue == firstDigit && (!top || abs > 9) {
|
||||
|
@ -651,7 +652,7 @@ func (g *Game) RenderSpace(player int, space int, spaceValue int, legalMoves [][
|
|||
return append(append([]byte(" "), r...), ' ')
|
||||
}
|
||||
|
||||
func (g *Game) BoardState(player int, local bool) []byte {
|
||||
func (g *Game) BoardState(player int8, local bool) []byte {
|
||||
var t bytes.Buffer
|
||||
|
||||
playerRating := "0"
|
||||
|
@ -694,8 +695,8 @@ func (g *Game) BoardState(player int, local bool) []byte {
|
|||
t.WriteByte('\n')
|
||||
|
||||
legalMoves := g.LegalMoves(local)
|
||||
space := func(row int, col int) []byte {
|
||||
spaceValue := row + 1
|
||||
space := func(row int8, col int8) []byte {
|
||||
var spaceValue int8 = row + 1
|
||||
if row > 5 {
|
||||
spaceValue = 5 - (row - 6)
|
||||
}
|
||||
|
@ -707,7 +708,7 @@ func (g *Game) BoardState(player int, local bool) []byte {
|
|||
return g.RenderSpace(player, SpaceBarPlayer, spaceValue, legalMoves)
|
||||
}
|
||||
|
||||
var space int
|
||||
var space int8
|
||||
if white {
|
||||
space = 24 - col
|
||||
if row > 5 {
|
||||
|
@ -727,10 +728,10 @@ func (g *Game) BoardState(player int, local bool) []byte {
|
|||
return g.RenderSpace(player, space, spaceValue, legalMoves)
|
||||
}
|
||||
|
||||
for i := 0; i < 11; i++ {
|
||||
for i := int8(0); i < 11; i++ {
|
||||
t.WriteRune(VerticalBar)
|
||||
t.Write([]byte(""))
|
||||
for j := 0; j < 12; j++ {
|
||||
for j := int8(0); j < 12; j++ {
|
||||
t.Write(space(i, j))
|
||||
|
||||
if j == 5 {
|
||||
|
@ -808,7 +809,7 @@ func (g *Game) BoardState(player int, local bool) []byte {
|
|||
return t.Bytes()
|
||||
}
|
||||
|
||||
func SpaceDiff(from int, to int, acey bool) int {
|
||||
func SpaceDiff(from int8, to int8, acey bool) int8 {
|
||||
if from < 0 || from > 27 || to < 0 || to > 27 {
|
||||
return 0
|
||||
} else if to == SpaceBarPlayer || to == SpaceBarOpponent {
|
||||
|
@ -847,13 +848,13 @@ func SpaceDiff(from int, to int, acey bool) int {
|
|||
return diff
|
||||
}
|
||||
|
||||
func IterateSpaces(from int, to int, acey bool, f func(space int, spaceCount int)) {
|
||||
func IterateSpaces(from int8, to int8, acey bool, f func(space int8, spaceCount int8)) {
|
||||
if from == to || from < 0 || from > 25 || to < 0 || to > 25 {
|
||||
return
|
||||
} else if !acey && (from == 0 || from == 25 || to == 0 || to == 25) {
|
||||
return
|
||||
}
|
||||
i := 1
|
||||
var i int8 = 1
|
||||
if to > from {
|
||||
for space := from; space <= to; space++ {
|
||||
f(space, i)
|
||||
|
@ -867,7 +868,7 @@ func IterateSpaces(from int, to int, acey bool, f func(space int, spaceCount int
|
|||
}
|
||||
}
|
||||
|
||||
func PlayerCheckers(checkers int, player int) int {
|
||||
func PlayerCheckers(checkers int8, player int8) int8 {
|
||||
if player == 1 {
|
||||
if checkers > 0 {
|
||||
return checkers
|
||||
|
@ -881,7 +882,7 @@ func PlayerCheckers(checkers int, player int) int {
|
|||
}
|
||||
}
|
||||
|
||||
func OpponentCheckers(checkers int, player int) int {
|
||||
func OpponentCheckers(checkers int8, player int8) int8 {
|
||||
if player == 2 {
|
||||
if checkers > 0 {
|
||||
return checkers
|
||||
|
@ -895,7 +896,7 @@ func OpponentCheckers(checkers int, player int) int {
|
|||
}
|
||||
}
|
||||
|
||||
func FlipSpace(space int, player int) int {
|
||||
func FlipSpace(space int8, player int8) int8 {
|
||||
if player == 1 {
|
||||
return space
|
||||
}
|
||||
|
@ -916,17 +917,17 @@ func FlipSpace(space int, player int) int {
|
|||
return 24 - space + 1
|
||||
}
|
||||
|
||||
func FlipMoves(moves [][]int, player int) [][]int {
|
||||
m := make([][]int, len(moves))
|
||||
func FlipMoves(moves [][]int8, player int8) [][]int8 {
|
||||
m := make([][]int8, len(moves))
|
||||
for i := range moves {
|
||||
m[i] = []int{FlipSpace(moves[i][0], player), FlipSpace(moves[i][1], player)}
|
||||
m[i] = []int8{FlipSpace(moves[i][0], player), FlipSpace(moves[i][1], player)}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func FormatSpace(space int) []byte {
|
||||
func FormatSpace(space int8) []byte {
|
||||
if space >= 1 && space <= 24 {
|
||||
return []byte(strconv.Itoa(space))
|
||||
return []byte(strconv.Itoa(int(space)))
|
||||
} else if space == SpaceBarPlayer || space == SpaceBarOpponent {
|
||||
return []byte("bar")
|
||||
} else if space == SpaceHomePlayer || space == SpaceHomeOpponent {
|
||||
|
@ -935,7 +936,7 @@ func FormatSpace(space int) []byte {
|
|||
return []byte("?")
|
||||
}
|
||||
|
||||
func FormatMoves(moves [][]int) []byte {
|
||||
func FormatMoves(moves [][]int8) []byte {
|
||||
if len(moves) == 0 {
|
||||
return []byte("none")
|
||||
}
|
||||
|
@ -950,11 +951,11 @@ func FormatMoves(moves [][]int) []byte {
|
|||
return out.Bytes()
|
||||
}
|
||||
|
||||
func FormatAndFlipMoves(moves [][]int, player int) []byte {
|
||||
func FormatAndFlipMoves(moves [][]int8, player int8) []byte {
|
||||
return FormatMoves(FlipMoves(moves, player))
|
||||
}
|
||||
|
||||
func ValidSpace(space int) bool {
|
||||
func ValidSpace(space int8) bool {
|
||||
return space >= 0 && space <= 27
|
||||
}
|
||||
|
||||
|
|
20
gamestate.go
20
gamestate.go
|
@ -6,8 +6,8 @@ import (
|
|||
|
||||
type GameState struct {
|
||||
*Game
|
||||
PlayerNumber int
|
||||
Available [][]int // Legal moves.
|
||||
PlayerNumber int8
|
||||
Available [][]int8 // Legal moves.
|
||||
Spectating bool
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,12 @@ func (g *GameState) LocalPlayer() Player {
|
|||
return g.Player2
|
||||
}
|
||||
|
||||
func (g *GameState) SpaceAt(x int, y int) int {
|
||||
func (g *GameState) SpaceAt(x int8, y int8) int8 {
|
||||
if (x < 0 || x > 12) || (y < 0 || y > 9) {
|
||||
return -1
|
||||
}
|
||||
|
||||
space := -1
|
||||
var space int8 = -1
|
||||
if x <= 5 {
|
||||
space = x + 1
|
||||
} else if x == 6 {
|
||||
|
@ -58,19 +58,19 @@ func (g *GameState) SpaceAt(x int, y int) int {
|
|||
}
|
||||
|
||||
// Pips returns the pip count for the specified player.
|
||||
func (g *GameState) Pips(player int) int {
|
||||
func (g *GameState) Pips(player int8) int {
|
||||
var pips int
|
||||
var spaceValue int
|
||||
if player == 1 {
|
||||
pips += PlayerCheckers(g.Board[SpaceBarPlayer], player) * 25
|
||||
pips += int(PlayerCheckers(g.Board[SpaceBarPlayer], player)) * 25
|
||||
} else {
|
||||
pips += PlayerCheckers(g.Board[SpaceBarOpponent], player) * 25
|
||||
pips += int(PlayerCheckers(g.Board[SpaceBarOpponent], player)) * 25
|
||||
}
|
||||
if g.Acey {
|
||||
if player == 1 && !g.Player1.Entered {
|
||||
pips += PlayerCheckers(g.Board[SpaceHomePlayer], player) * 25
|
||||
pips += int(PlayerCheckers(g.Board[SpaceHomePlayer], player)) * 25
|
||||
} else if player == 2 && !g.Player2.Entered {
|
||||
pips += PlayerCheckers(g.Board[SpaceHomeOpponent], player) * 25
|
||||
pips += int(PlayerCheckers(g.Board[SpaceHomeOpponent], player)) * 25
|
||||
}
|
||||
}
|
||||
for i := 1; i < 25; i++ {
|
||||
|
@ -79,7 +79,7 @@ func (g *GameState) Pips(player int) int {
|
|||
} else {
|
||||
spaceValue = 25 - i
|
||||
}
|
||||
pips += PlayerCheckers(g.Board[i], player) * spaceValue
|
||||
pips += int(PlayerCheckers(g.Board[i], player)) * spaceValue
|
||||
}
|
||||
return pips
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ type serverClient struct {
|
|||
lastActive int64
|
||||
lastPing int64
|
||||
commands chan []byte
|
||||
playerNumber int
|
||||
playerNumber int8
|
||||
terminating bool
|
||||
bgammon.Client
|
||||
}
|
||||
|
|
|
@ -421,7 +421,7 @@ func setAccountSetting(id int, name string, value int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int, replay [][]byte) error {
|
||||
func recordGameResult(g *bgammon.Game, winType int8, account1 int, account2 int, replay [][]byte) error {
|
||||
dbLock.Lock()
|
||||
defer dbLock.Unlock()
|
||||
|
||||
|
@ -587,7 +587,7 @@ func matchHistory(username string) ([]*bgammon.HistoryMatch, error) {
|
|||
|
||||
var matches []*bgammon.HistoryMatch
|
||||
var player1, player2 string
|
||||
var winner int
|
||||
var winner int8
|
||||
rows, err := tx.Query(context.Background(), "SELECT id, started, player1, player2, points, winner FROM game WHERE (LOWER(player1) = $1 OR LOWER(player2) = $2) AND replay != '' ORDER BY id DESC", username, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -51,7 +51,7 @@ func replayByID(id int) ([]byte, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int, replay [][]byte) error {
|
||||
func recordGameResult(g *bgammon.Game, winType int8, account1 int, account2 int, replay [][]byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ type serverGame struct {
|
|||
allowed2 []byte
|
||||
account1 int
|
||||
account2 int
|
||||
forefeit int
|
||||
rematch int
|
||||
forefeit int8
|
||||
rematch int8
|
||||
rejoin1 bool
|
||||
rejoin2 bool
|
||||
replay [][]byte
|
||||
|
@ -39,7 +39,7 @@ func newServerGame(id int, acey bool) *serverGame {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *serverGame) roll(player int) bool {
|
||||
func (g *serverGame) roll(player int8) bool {
|
||||
if g.client1 == nil || g.client2 == nil || g.Winner != 0 {
|
||||
return false
|
||||
}
|
||||
|
@ -49,12 +49,12 @@ func (g *serverGame) roll(player int) bool {
|
|||
if g.Roll1 != 0 {
|
||||
return false
|
||||
}
|
||||
g.Roll1 = RandInt(6) + 1
|
||||
g.Roll1 = int8(RandInt(6) + 1)
|
||||
} else {
|
||||
if g.Roll2 != 0 {
|
||||
return false
|
||||
}
|
||||
g.Roll2 = RandInt(6) + 1
|
||||
g.Roll2 = int8(RandInt(6) + 1)
|
||||
}
|
||||
|
||||
// Only allow the same players to rejoin the game.
|
||||
|
@ -72,8 +72,8 @@ func (g *serverGame) roll(player int) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
g.Roll1 = RandInt(6) + 1
|
||||
g.Roll2 = RandInt(6) + 1
|
||||
g.Roll1 = int8(RandInt(6) + 1)
|
||||
g.Roll2 = int8(RandInt(6) + 1)
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (g *serverGame) sendBoard(client *serverClient) {
|
|||
}
|
||||
|
||||
// Flip board.
|
||||
for space := 1; space <= 24; space++ {
|
||||
for space := int8(1); space <= 24; space++ {
|
||||
ev.Board[space] = g.Game.Board[bgammon.FlipSpace(space, client.playerNumber)] * -1
|
||||
}
|
||||
ev.Board[bgammon.SpaceHomePlayer], ev.Board[bgammon.SpaceHomeOpponent] = ev.Board[bgammon.SpaceHomeOpponent]*-1, ev.Board[bgammon.SpaceHomePlayer]*-1
|
||||
|
@ -153,8 +153,8 @@ func (g *serverGame) sendBoard(client *serverClient) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *serverGame) playerCount() int {
|
||||
c := 0
|
||||
func (g *serverGame) playerCount() int8 {
|
||||
var c int8
|
||||
if g.client1 != nil {
|
||||
c++
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func (g *serverGame) addClient(client *serverClient) (spectator bool) {
|
|||
return spectator
|
||||
}
|
||||
|
||||
var playerNumber int
|
||||
var playerNumber int8
|
||||
defer func() {
|
||||
ev := &bgammon.EventJoined{
|
||||
GameID: g.id,
|
||||
|
@ -361,7 +361,7 @@ func (g *serverGame) listing(playerName []byte) *bgammon.GameListing {
|
|||
return nil
|
||||
}
|
||||
|
||||
var playerCount int
|
||||
var playerCount int8
|
||||
if len(g.allowed1) != 0 && (len(playerName) == 0 || (!bytes.Equal(g.allowed1, playerName) && !bytes.Equal(g.allowed2, playerName))) {
|
||||
playerCount = 2
|
||||
} else {
|
||||
|
|
|
@ -1031,7 +1031,7 @@ COMMANDS:
|
|||
|
||||
g := newServerGame(<-s.newGameIDs, acey)
|
||||
g.name = gameName
|
||||
g.Points = points
|
||||
g.Points = int8(points)
|
||||
g.password = gamePassword
|
||||
g.addClient(cmd.client)
|
||||
|
||||
|
@ -1442,7 +1442,7 @@ COMMANDS:
|
|||
continue
|
||||
}
|
||||
|
||||
var moves [][]int
|
||||
var moves [][]int8
|
||||
for i := range params {
|
||||
split := bytes.Split(params[i], []byte("/"))
|
||||
if len(split) != 2 {
|
||||
|
@ -1470,7 +1470,7 @@ COMMANDS:
|
|||
}
|
||||
|
||||
from, to = bgammon.FlipSpace(from, cmd.client.playerNumber), bgammon.FlipSpace(to, cmd.client.playerNumber)
|
||||
moves = append(moves, []int{from, to})
|
||||
moves = append(moves, []int8{from, to})
|
||||
}
|
||||
|
||||
ok, expandedMoves := clientGame.AddMoves(moves, false)
|
||||
|
@ -1485,7 +1485,7 @@ COMMANDS:
|
|||
|
||||
var winEvent *bgammon.EventWin
|
||||
if clientGame.Winner != 0 {
|
||||
opponent := 1
|
||||
var opponent int8 = 1
|
||||
opponentHome := bgammon.SpaceHomePlayer
|
||||
opponentEntered := clientGame.Player1.Entered
|
||||
playerBar := bgammon.SpaceBarPlayer
|
||||
|
@ -1499,14 +1499,14 @@ COMMANDS:
|
|||
backgammon := bgammon.PlayerCheckers(clientGame.Board[playerBar], opponent) != 0
|
||||
if !backgammon {
|
||||
homeStart, homeEnd := bgammon.HomeRange(clientGame.Winner)
|
||||
bgammon.IterateSpaces(homeStart, homeEnd, clientGame.Acey, func(space, spaceCount int) {
|
||||
bgammon.IterateSpaces(homeStart, homeEnd, clientGame.Acey, func(space int8, spaceCount int8) {
|
||||
if bgammon.PlayerCheckers(clientGame.Board[space], opponent) != 0 {
|
||||
backgammon = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var winPoints int
|
||||
var winPoints int8
|
||||
if !clientGame.Acey {
|
||||
if backgammon {
|
||||
winPoints = 3 // Award backgammon.
|
||||
|
@ -1516,7 +1516,7 @@ COMMANDS:
|
|||
winPoints = 1
|
||||
}
|
||||
} else {
|
||||
for space := 0; space < bgammon.BoardSpaces; space++ {
|
||||
for space := int8(0); space < bgammon.BoardSpaces; space++ {
|
||||
if (space == bgammon.SpaceHomePlayer || space == bgammon.SpaceHomeOpponent) && opponentEntered {
|
||||
continue
|
||||
}
|
||||
|
@ -1613,9 +1613,9 @@ COMMANDS:
|
|||
}
|
||||
|
||||
l := len(clientGame.Moves)
|
||||
undoMoves := make([][]int, l)
|
||||
undoMoves := make([][]int8, l)
|
||||
for i, move := range clientGame.Moves {
|
||||
undoMoves[l-1-i] = []int{move[1], move[0]}
|
||||
undoMoves[l-1-i] = []int8{move[1], move[0]}
|
||||
}
|
||||
ok, _ := clientGame.AddMoves(undoMoves, false)
|
||||
if !ok {
|
||||
|
@ -1714,7 +1714,7 @@ COMMANDS:
|
|||
|
||||
recordEvent()
|
||||
clientGame.NextTurn(true)
|
||||
clientGame.Roll1, clientGame.Roll2 = doubles, doubles
|
||||
clientGame.Roll1, clientGame.Roll2 = int8(doubles), int8(doubles)
|
||||
clientGame.Reroll = true
|
||||
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
|
@ -1986,7 +1986,7 @@ COMMANDS:
|
|||
clientGame.Turn = 1
|
||||
clientGame.Roll1 = 6
|
||||
clientGame.Roll2 = 6
|
||||
clientGame.Board = []int{1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0}
|
||||
clientGame.Board = []int8{1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0}
|
||||
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
clientGame.sendBoard(client)
|
||||
|
@ -2007,7 +2007,7 @@ func RandInt(max int) int {
|
|||
}
|
||||
|
||||
func gnubgPosition(g *bgammon.Game) string {
|
||||
opponent := 2
|
||||
var opponent int8 = 2
|
||||
start := 0
|
||||
end := 25
|
||||
boardStart := 1
|
||||
|
@ -2033,26 +2033,26 @@ func gnubgPosition(g *bgammon.Game) string {
|
|||
var buf []byte
|
||||
for space := boardStart; space != end; space += delta {
|
||||
playerCheckers := bgammon.PlayerCheckers(g.Board[space], g.Turn)
|
||||
for i := 0; i < playerCheckers; i++ {
|
||||
for i := int8(0); i < playerCheckers; i++ {
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
playerCheckers := bgammon.PlayerCheckers(g.Board[playerBarSpace], g.Turn)
|
||||
for i := 0; i < playerCheckers; i++ {
|
||||
for i := int8(0); i < playerCheckers; i++ {
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
buf = append(buf, '0')
|
||||
|
||||
for space := boardEnd; space != start; space -= delta {
|
||||
opponentCheckers := bgammon.PlayerCheckers(g.Board[space], opponent)
|
||||
for i := 0; i < opponentCheckers; i++ {
|
||||
for i := int8(0); i < opponentCheckers; i++ {
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
opponentCheckers := bgammon.PlayerCheckers(g.Board[opponentBarSpace], opponent)
|
||||
for i := 0; i < opponentCheckers; i++ {
|
||||
for i := int8(0); i < opponentCheckers; i++ {
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
buf = append(buf, '0')
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package bgammon
|
||||
|
||||
type Player struct {
|
||||
Number int // 1 black, 2 white
|
||||
Number int8 // 1 black, 2 white
|
||||
Name string
|
||||
Points int
|
||||
Points int8
|
||||
Entered bool // Whether all checkers have entered the board. (Acey-deucey)
|
||||
}
|
||||
|
||||
func NewPlayer(number int) Player {
|
||||
func NewPlayer(number int8) Player {
|
||||
return Player{
|
||||
Number: number,
|
||||
}
|
||||
|
|
4
util.go
4
util.go
|
@ -1,13 +1,13 @@
|
|||
package bgammon
|
||||
|
||||
func minInt(a int, b int) int {
|
||||
func minInt(a int8, b int8) int8 {
|
||||
if b < a {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func maxInt(a int, b int) int {
|
||||
func maxInt(a int8, b int8) int8 {
|
||||
if b > a {
|
||||
return b
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue