Support moving checkers

This commit is contained in:
Trevor Slocum 2023-09-02 14:48:49 -07:00
parent 7a7141d189
commit 0df16bc71a
4 changed files with 126 additions and 58 deletions

View file

@ -71,7 +71,14 @@ func (g *serverGame) sendBoard(client *serverClient) {
ev.GameState.Game = ev.GameState.Copy()
for space := 1; space <= 24; space++ {
ev.Board[space] = g.Game.Board[24-space+1]
ev.Board[space] = g.Game.Board[bgammon.FlipSpace(space, client.playerNumber)]
}
ev.Moves = bgammon.FlipMoves(g.Game.Moves, client.playerNumber)
legalMoves := g.LegalMoves()
for i := range ev.GameState.Available {
ev.GameState.Available[i][0], ev.GameState.Available[i][1] = bgammon.FlipSpace(legalMoves[i][0], client.playerNumber), bgammon.FlipSpace(legalMoves[i][1], client.playerNumber)
}
log.Println(g.Game.Board)
@ -219,8 +226,3 @@ func (g *serverGame) opponent(client *serverClient) *serverClient {
}
return nil
}
type ServerGameState struct {
bgammon.GameState
Board []int
}

View file

@ -264,13 +264,6 @@ COMMANDS:
}
clientGame := s.gameByClient(cmd.client)
clientNumber := 0
if clientGame != nil {
clientNumber = 1
if clientGame.client2 == cmd.client {
clientNumber = 2
}
}
switch keyword {
case bgammon.CommandHelp, "h":
@ -416,7 +409,7 @@ COMMANDS:
continue
}
if !clientGame.roll(clientNumber) {
if !clientGame.roll(cmd.client.playerNumber) {
cmd.client.sendEvent(&bgammon.EventFailedRoll{
Reason: "It is not your turn to roll.",
})
@ -427,12 +420,6 @@ COMMANDS:
Roll2: clientGame.Roll2,
}
ev.Player = string(cmd.client.name)
clientGame.eachClient(func(client *serverClient) {
client.sendEvent(ev)
if !client.json {
clientGame.sendBoard(client)
}
})
if clientGame.Turn == 0 && clientGame.Roll1 != 0 && clientGame.Roll2 != 0 {
if clientGame.Roll1 > clientGame.Roll2 {
clientGame.Turn = 1
@ -443,6 +430,12 @@ COMMANDS:
clientGame.Roll2 = 0
}
}
clientGame.eachClient(func(client *serverClient) {
client.sendEvent(ev)
if clientGame.Turn != 0 || !client.json {
clientGame.sendBoard(client)
}
})
case bgammon.CommandMove, "m", "mv":
if clientGame == nil {
cmd.client.sendEvent(&bgammon.EventFailedMove{
@ -451,7 +444,7 @@ COMMANDS:
continue
}
if clientGame.Turn != clientNumber {
if clientGame.Turn != cmd.client.playerNumber {
cmd.client.sendEvent(&bgammon.EventFailedMove{
Reason: "It is not your turn to move.",
})
@ -492,7 +485,8 @@ COMMANDS:
}
originalFrom, originalTo := from, to
from, to = bgammon.FlipSpace(from, clientNumber), bgammon.FlipSpace(to, clientNumber)
from, to = bgammon.FlipSpace(from, cmd.client.playerNumber), bgammon.FlipSpace(to, cmd.client.playerNumber)
log.Printf("translated player %d %d-%d as %d-%d", cmd.client.playerNumber, originalFrom, originalTo, from, to)
legalMoves := gameCopy.LegalMoves()
var found bool
@ -503,7 +497,7 @@ COMMANDS:
}
}
if !found {
log.Printf("available legal moves: %s", bgammon.FormatMoves(legalMoves, clientNumber))
log.Printf("available legal moves: %s", bgammon.FormatMoves(legalMoves, cmd.client.playerNumber))
cmd.client.sendEvent(&bgammon.EventFailedMove{
From: originalFrom,
To: originalTo,
@ -526,12 +520,10 @@ COMMANDS:
})
continue
}
ev := &bgammon.EventMoved{
Moves: moves,
}
ev.Player = string(cmd.client.name)
clientGame.eachClient(func(client *serverClient) {
client.sendEvent(ev)
client.sendEvent(&bgammon.EventMoved{
Moves: bgammon.FlipMoves(moves, client.playerNumber),
})
clientGame.sendBoard(client)
})
case bgammon.CommandOk, "k":
@ -552,7 +544,14 @@ COMMANDS:
continue
}
log.Println("legal to pass turn")
nextTurn := 1
if clientGame.Turn == 1 {
nextTurn = 2
}
clientGame.Roll1, clientGame.Roll2, clientGame.Moves, clientGame.Turn = 0, 0, nil, nextTurn
clientGame.eachClient(func(client *serverClient) {
clientGame.sendBoard(client)
})
case bgammon.CommandBoard, "b":
if clientGame == nil {
cmd.client.sendNotice("You are not currently in a game.")

70
game.go
View file

@ -91,16 +91,17 @@ ADDMOVES:
l := g.LegalMoves()
for _, lm := range l {
if lm[0] == move[0] && lm[1] == move[1] {
log.Printf("ADD MOV %d/%d", lm[0], lm[1])
delta := 1
if g.Turn == 2 {
delta = -1
}
lm[0] -= delta
opponentCheckers := numOpponentCheckers(g.Board[lm[1]], g.Turn)
g.Board[lm[0]] -= delta
opponentCheckers := OpponentCheckers(g.Board[lm[1]], g.Turn)
if opponentCheckers == 1 {
lm[1] = delta
g.Board[lm[1]] = delta
} else {
lm[1] += delta
g.Board[lm[1]] += delta
}
continue ADDMOVES
}
@ -165,7 +166,7 @@ func (g *Game) LegalMoves() [][]int {
}
checkers := g.Board[space]
playerCheckers := numPlayerCheckers(checkers, g.Turn)
playerCheckers := PlayerCheckers(checkers, g.Turn)
if playerCheckers == 0 {
continue
}
@ -180,7 +181,7 @@ func (g *Game) LegalMoves() [][]int {
if spaceCount != g.Roll1 && spaceCount != g.Roll2 {
return
}
opponentCheckers := numOpponentCheckers(g.Board[homeSpace], g.Turn)
opponentCheckers := OpponentCheckers(g.Board[homeSpace], g.Turn)
if opponentCheckers <= 1 {
moves = append(moves, []int{space, homeSpace})
}
@ -207,7 +208,7 @@ func (g *Game) LegalMoves() [][]int {
return // TODO
}
opponentCheckers := numOpponentCheckers(g.Board[to], g.Turn)
opponentCheckers := OpponentCheckers(g.Board[to], g.Turn)
if opponentCheckers <= 1 {
movable := 1
if g.Roll1 == g.Roll2 {
@ -243,9 +244,9 @@ func (g *Game) RenderSpace(player int, space int, spaceValue int, legalMoves [][
pieceColor = opponentColor
} else {
if value < 0 {
pieceColor = "x"
} else if value > 0 {
pieceColor = "o"
} else if value > 0 {
pieceColor = "x"
} else {
pieceColor = playerColor
}
@ -358,33 +359,24 @@ func (g *Game) BoardState(player int) []byte {
return g.RenderSpace(player, SpaceBarPlayer, spaceValue, legalMoves)
}
var index int
if !white {
if row < 6 {
col = 12 - col
} else {
col = 11 - col
}
index = col
var space int
if white {
space = 24 - col
if row > 5 {
index = 11 - col + 13
space = 1 + col
}
} else {
index = col + 3
space = 13 + col
if row > 5 {
index = 11 - col + 15
space = 12 - col
}
}
if white {
index = BoardSpaces - 1 - index
}
if row == 5 {
return []byte(" ")
}
return g.RenderSpace(player, index, spaceValue, legalMoves)
return g.RenderSpace(player, space, spaceValue, legalMoves)
}
for i := 0; i < 11; i++ {
@ -476,7 +468,7 @@ func spaceDiff(from int, to int) int {
return diff
}
func numPlayerCheckers(checkers int, player int) int {
func PlayerCheckers(checkers int, player int) int {
if player == 1 {
if checkers > 0 {
return checkers
@ -490,7 +482,7 @@ func numPlayerCheckers(checkers int, player int) int {
}
}
func numOpponentCheckers(checkers int, player int) int {
func OpponentCheckers(checkers int, player int) int {
if player == 2 {
if checkers > 0 {
return checkers
@ -509,18 +501,38 @@ func FlipSpace(space int, player int) int {
return space
}
if space < 1 || space > 24 {
return space // TODO fix
switch space {
case SpaceHomePlayer:
return SpaceHomeOpponent
case SpaceHomeOpponent:
return SpaceHomePlayer
case SpaceBarPlayer:
return SpaceBarOpponent
case SpaceBarOpponent:
return SpaceBarPlayer
default:
log.Panicf("unknown space %d", space)
}
}
return 24 - space + 1
}
func FlipMoves(moves [][]int, player int) [][]int {
m := make([][]int, len(moves))
for i := range moves {
m[i] = []int{FlipSpace(moves[i][0], player), FlipSpace(moves[i][1], player)}
}
return m
}
func FormatMoves(moves [][]int, player int) []byte {
var out bytes.Buffer
for i := range moves {
if i != 0 {
out.WriteByte(' ')
}
out.Write([]byte(fmt.Sprintf("%d/%d", FlipSpace(moves[i][0], player), FlipSpace(moves[i][1], player))))
// TODO
out.Write([]byte(fmt.Sprintf("{{%d/%d}}", FlipSpace(moves[i][0], player), FlipSpace(moves[i][1], player))))
}
return out.Bytes()
}

View file

@ -1,5 +1,9 @@
package bgammon
import (
"log"
)
type GameState struct {
*Game
PlayerNumber int
@ -19,3 +23,54 @@ func (g *GameState) LocalPlayer() Player {
}
return g.Player2
}
func (g *GameState) SpaceAt(x int, y int) int {
if (x < 0 || x > 12) || (y < 0 || y > 9) {
return -1
}
space := -1
if x <= 5 {
space = x + 1
} else if x == 6 {
if y <= 4 {
return SpaceBarOpponent
} else {
return SpaceBarPlayer
}
} else {
space = x
}
if g.PlayerNumber == 2 {
if y <= 4 {
space = 25 - space
}
} else {
if y <= 4 {
space += 12
} else {
space = 13 - space
}
}
return space
}
func (g *GameState) NeedRoll() bool {
switch g.Turn {
case 0:
if g.PlayerNumber == 1 {
return g.Player2.Name != "" && g.Roll1 == 0
} else if g.PlayerNumber == 2 {
return g.Player1.Name != "" && g.Roll2 == 0
}
return false
case 1:
return g.PlayerNumber == g.Turn && g.Player2.Name != "" && g.Roll1 == 0
case 2:
return g.PlayerNumber == g.Turn && g.Player1.Name != "" && g.Roll1 == 0
default:
log.Panicf("unknown turn %d", g.Turn)
return false
}
}