Store board state as []int8

This commit is contained in:
Trevor Slocum 2024-01-05 18:18:54 -08:00
parent fb58a25c67
commit f049353bd3
11 changed files with 152 additions and 151 deletions

View File

@ -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))
}

View File

@ -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
View File

@ -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
}

View File

@ -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
}

View File

@ -20,7 +20,7 @@ type serverClient struct {
lastActive int64
lastPing int64
commands chan []byte
playerNumber int
playerNumber int8
terminating bool
bgammon.Client
}

View File

@ -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

View File

@ -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
}

View File

@ -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 {

View File

@ -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')

View File

@ -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,
}

View File

@ -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
}