Introduce checkmate check and send out 'gameEnded' message

This commit is contained in:
Marco 2024-01-17 22:52:44 +01:00
parent 387125e828
commit c0bb9e152a
3 changed files with 46 additions and 46 deletions

View File

@ -57,7 +57,7 @@ func (b *Board) Init() {
b.position[types.Coordinate{Row: 8, Col: 8}] = Rook{Color: types.Black} b.position[types.Coordinate{Row: 8, Col: 8}] = Rook{Color: types.Black}
} }
func (b *Board) CheckAndPlay(move types.Move) (bool, Violation) { func (b *Board) CheckAndPlay(move *types.Move) (bool, Violation) {
tempBoard := b.getCopyOfBoard() tempBoard := b.getCopyOfBoard()
//Check start square of move //Check start square of move
@ -80,7 +80,7 @@ func (b *Board) CheckAndPlay(move types.Move) (bool, Violation) {
} }
} }
wasSpecialMove, err := tempBoard.handleSpecialMove(move) wasSpecialMove, err := tempBoard.handleSpecialMove(*move)
if err != nil { if err != nil {
return false, InvalidMove return false, InvalidMove
} }
@ -109,7 +109,7 @@ func (b *Board) CheckAndPlay(move types.Move) (bool, Violation) {
b.position = tempBoard.position b.position = tempBoard.position
b.history = tempBoard.history b.history = tempBoard.history
b.colorToMove = b.colorToMove.Opposite() b.colorToMove = b.colorToMove.Opposite()
b.appendMoveToHistory(move) b.appendMoveToHistory(*move)
pieceAtStartSquare.AfterMoveAction(b, move.StartSquare) pieceAtStartSquare.AfterMoveAction(b, move.StartSquare)
@ -255,7 +255,7 @@ func (b *Board) isColorCheckmated(color types.ChessColor) bool {
} }
for _, move := range movesToCheck { for _, move := range movesToCheck {
valid, _ := copyOfBoard.CheckAndPlay(move) valid, _ := copyOfBoard.CheckAndPlay(&move)
if valid { if valid {
return false return false
} }

View File

@ -20,7 +20,7 @@ func Test_CheckMove_validPawnMove(t *testing.T) {
EndSquare: types.Coordinate{Col: 1, Row: 3}, EndSquare: types.Coordinate{Col: 1, Row: 3},
} }
good, _ := board.CheckAndPlay(move) good, _ := board.CheckAndPlay(&move)
assert.True(t, good) assert.True(t, good)
//we take the pawn //we take the pawn
@ -28,7 +28,7 @@ func Test_CheckMove_validPawnMove(t *testing.T) {
StartSquare: types.Coordinate{Col: 2, Row: 4}, StartSquare: types.Coordinate{Col: 2, Row: 4},
EndSquare: types.Coordinate{Col: 1, Row: 3}, EndSquare: types.Coordinate{Col: 1, Row: 3},
} }
good, _ = board.CheckAndPlay(secondMove) good, _ = board.CheckAndPlay(&secondMove)
assert.True(t, good) assert.True(t, good)
} }
@ -45,7 +45,7 @@ func Test_CheckMove_enPassant(t *testing.T) {
EndSquare: types.Coordinate{Col: 5, Row: 4}, EndSquare: types.Coordinate{Col: 5, Row: 4},
} }
good, reason := board.CheckAndPlay(move) good, reason := board.CheckAndPlay(&move)
assert.True(t, good) assert.True(t, good)
assert.Empty(t, reason) assert.Empty(t, reason)
assert.Equal(t, Pawn{Color: types.White}, board.position[types.Coordinate{Col: 5, Row: 4}]) assert.Equal(t, Pawn{Color: types.White}, board.position[types.Coordinate{Col: 5, Row: 4}])
@ -54,7 +54,7 @@ func Test_CheckMove_enPassant(t *testing.T) {
StartSquare: types.Coordinate{Col: 6, Row: 4}, StartSquare: types.Coordinate{Col: 6, Row: 4},
EndSquare: types.Coordinate{Col: 5, Row: 3}, EndSquare: types.Coordinate{Col: 5, Row: 3},
} }
good, reason = board.CheckAndPlay(newMove) good, reason = board.CheckAndPlay(&newMove)
assert.True(t, good) assert.True(t, good)
assert.Empty(t, reason) assert.Empty(t, reason)
// the black pawn is on its correct square // the black pawn is on its correct square
@ -77,7 +77,7 @@ func Test_CheckMove_invalidPawnMoves(t *testing.T) {
StartSquare: types.Coordinate{Col: 2, Row: 5}, StartSquare: types.Coordinate{Col: 2, Row: 5},
EndSquare: types.Coordinate{Col: 2, Row: 6}, EndSquare: types.Coordinate{Col: 2, Row: 6},
} }
legalMove, _ := board.CheckAndPlay(move) legalMove, _ := board.CheckAndPlay(&move)
assert.False(t, legalMove) assert.False(t, legalMove)
}) })
@ -93,7 +93,7 @@ func Test_CheckMove_invalidPawnMoves(t *testing.T) {
StartSquare: types.Coordinate{Col: 2, Row: 5}, StartSquare: types.Coordinate{Col: 2, Row: 5},
EndSquare: types.Coordinate{Col: 3, Row: 5}, EndSquare: types.Coordinate{Col: 3, Row: 5},
} }
legal, _ := board.CheckAndPlay(move) legal, _ := board.CheckAndPlay(&move)
assert.False(t, legal) assert.False(t, legal)
assert.Equal(t, boardBeforeMove, board) assert.Equal(t, boardBeforeMove, board)
@ -102,7 +102,7 @@ func Test_CheckMove_invalidPawnMoves(t *testing.T) {
StartSquare: types.Coordinate{Col: 2, Row: 5}, StartSquare: types.Coordinate{Col: 2, Row: 5},
EndSquare: types.Coordinate{Col: 1, Row: 5}, EndSquare: types.Coordinate{Col: 1, Row: 5},
} }
legal, _ = board.CheckAndPlay(move) legal, _ = board.CheckAndPlay(&move)
assert.False(t, legal) assert.False(t, legal)
assert.Equal(t, boardBeforeMove, board) assert.Equal(t, boardBeforeMove, board)
@ -111,7 +111,7 @@ func Test_CheckMove_invalidPawnMoves(t *testing.T) {
StartSquare: types.Coordinate{Col: 2, Row: 5}, StartSquare: types.Coordinate{Col: 2, Row: 5},
EndSquare: types.Coordinate{Col: 6, Row: 5}, EndSquare: types.Coordinate{Col: 6, Row: 5},
} }
legal, _ = board.CheckAndPlay(move) legal, _ = board.CheckAndPlay(&move)
assert.False(t, legal) assert.False(t, legal)
assert.Equal(t, boardBeforeMove, board) assert.Equal(t, boardBeforeMove, board)
@ -130,7 +130,7 @@ func Test_CheckMove_invalidPawnMoves(t *testing.T) {
StartSquare: types.Coordinate{Col: 2, Row: 6}, StartSquare: types.Coordinate{Col: 2, Row: 6},
EndSquare: types.Coordinate{Col: 2, Row: 7}, EndSquare: types.Coordinate{Col: 2, Row: 7},
} }
good, _ := board.CheckAndPlay(move) good, _ := board.CheckAndPlay(&move)
assert.False(t, good) assert.False(t, good)
assert.Equal(t, boardBeforeMove, board) assert.Equal(t, boardBeforeMove, board)
@ -151,7 +151,7 @@ func Test_CheckMove_validPromotion(t *testing.T) {
EndSquare: types.Coordinate{Col: 1, Row: 8}, EndSquare: types.Coordinate{Col: 1, Row: 8},
PromotionToPiece: &shortName, PromotionToPiece: &shortName,
} }
good, reason := board.CheckAndPlay(move) good, reason := board.CheckAndPlay(&move)
assert.Empty(t, reason) assert.Empty(t, reason)
assert.True(t, good) assert.True(t, good)
@ -179,13 +179,13 @@ func Test_CheckMove_HistoryWorks(t *testing.T) {
EndSquare: types.Coordinate{Col: 1, Row: 4}, EndSquare: types.Coordinate{Col: 1, Row: 4},
} }
good, _ := board.CheckAndPlay(firstMove) good, _ := board.CheckAndPlay(&firstMove)
assert.True(t, good) assert.True(t, good)
good, _ = board.CheckAndPlay(secondMove) good, _ = board.CheckAndPlay(&secondMove)
assert.True(t, good) assert.True(t, good)
good, _ = board.CheckAndPlay(thirdMove) good, _ = board.CheckAndPlay(&thirdMove)
assert.True(t, good) assert.True(t, good)
expectedHistory := []types.Move{ expectedHistory := []types.Move{
@ -221,13 +221,13 @@ func Test_Promotion_BlackKing(t *testing.T) {
board.position[types.Coordinate{Col: 8, Row: 8}] = Rook{Color: types.Black} board.position[types.Coordinate{Col: 8, Row: 8}] = Rook{Color: types.Black}
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
move := types.Move{ move := types.Move{
StartSquare: types.Coordinate{Col: 5, Row: 8}, StartSquare: types.Coordinate{Col: 5, Row: 8},
EndSquare: types.Coordinate{Col: 7, Row: 8}, EndSquare: types.Coordinate{Col: 7, Row: 8},
} }
good, reason := board.CheckAndPlay(move) good, reason := board.CheckAndPlay(&move)
assert.True(t, good) assert.True(t, good)
assert.Empty(t, reason) assert.Empty(t, reason)
@ -246,13 +246,13 @@ func Test_Promotion_BlackKing(t *testing.T) {
board.position[types.Coordinate{Col: 8, Row: 8}] = Rook{Color: types.Black} board.position[types.Coordinate{Col: 8, Row: 8}] = Rook{Color: types.Black}
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
move := types.Move{ move := types.Move{
StartSquare: types.Coordinate{Col: 5, Row: 8}, StartSquare: types.Coordinate{Col: 5, Row: 8},
EndSquare: types.Coordinate{Col: 3, Row: 8}, EndSquare: types.Coordinate{Col: 3, Row: 8},
} }
good, reason := board.CheckAndPlay(move) good, reason := board.CheckAndPlay(&move)
assert.True(t, good) assert.True(t, good)
assert.Empty(t, reason) assert.Empty(t, reason)
@ -272,25 +272,25 @@ func Test_Promotion_BlackKing(t *testing.T) {
board.position[types.Coordinate{Col: 8, Row: 8}] = Rook{Color: types.Black} board.position[types.Coordinate{Col: 8, Row: 8}] = Rook{Color: types.Black}
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
//Move black //Move black
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 8}, EndSquare: types.Coordinate{Col: 4, Row: 8}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 8}, EndSquare: types.Coordinate{Col: 4, Row: 8}})
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 2}, EndSquare: types.Coordinate{Col: 5, Row: 1}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 2}, EndSquare: types.Coordinate{Col: 5, Row: 1}})
//Move black back //Move black back
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 4, Row: 8}, EndSquare: types.Coordinate{Col: 5, Row: 8}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 4, Row: 8}, EndSquare: types.Coordinate{Col: 5, Row: 8}})
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
move := types.Move{ move := types.Move{
StartSquare: types.Coordinate{Col: 5, Row: 8}, StartSquare: types.Coordinate{Col: 5, Row: 8},
EndSquare: types.Coordinate{Col: 3, Row: 8}, EndSquare: types.Coordinate{Col: 3, Row: 8},
} }
good, _ := board.CheckAndPlay(move) good, _ := board.CheckAndPlay(&move)
assert.False(t, good) assert.False(t, good)
}) })
@ -304,13 +304,13 @@ func Test_Promotion_BlackKing(t *testing.T) {
board.position[types.Coordinate{Col: 7, Row: 8}] = Bishop{Color: types.Black} board.position[types.Coordinate{Col: 7, Row: 8}] = Bishop{Color: types.Black}
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
move := types.Move{ move := types.Move{
StartSquare: types.Coordinate{Col: 5, Row: 8}, StartSquare: types.Coordinate{Col: 5, Row: 8},
EndSquare: types.Coordinate{Col: 7, Row: 8}, EndSquare: types.Coordinate{Col: 7, Row: 8},
} }
good, _ := board.CheckAndPlay(move) good, _ := board.CheckAndPlay(&move)
assert.False(t, good) assert.False(t, good)
}) })
@ -324,13 +324,13 @@ func Test_Promotion_BlackKing(t *testing.T) {
board.position[types.Coordinate{Col: 4, Row: 8}] = Bishop{Color: types.Black} board.position[types.Coordinate{Col: 4, Row: 8}] = Bishop{Color: types.Black}
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
move := types.Move{ move := types.Move{
StartSquare: types.Coordinate{Col: 5, Row: 8}, StartSquare: types.Coordinate{Col: 5, Row: 8},
EndSquare: types.Coordinate{Col: 3, Row: 8}, EndSquare: types.Coordinate{Col: 3, Row: 8},
} }
good, _ := board.CheckAndPlay(move) good, _ := board.CheckAndPlay(&move)
assert.False(t, good) assert.False(t, good)
}) })
@ -344,13 +344,13 @@ func Test_Promotion_BlackKing(t *testing.T) {
board.position[types.Coordinate{Col: 3, Row: 8}] = Bishop{Color: types.Black} board.position[types.Coordinate{Col: 3, Row: 8}] = Bishop{Color: types.Black}
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
move := types.Move{ move := types.Move{
StartSquare: types.Coordinate{Col: 5, Row: 8}, StartSquare: types.Coordinate{Col: 5, Row: 8},
EndSquare: types.Coordinate{Col: 3, Row: 8}, EndSquare: types.Coordinate{Col: 3, Row: 8},
} }
good, _ := board.CheckAndPlay(move) good, _ := board.CheckAndPlay(&move)
assert.False(t, good) assert.False(t, good)
}) })
@ -364,13 +364,13 @@ func Test_Promotion_BlackKing(t *testing.T) {
board.position[types.Coordinate{Col: 2, Row: 8}] = Bishop{Color: types.Black} board.position[types.Coordinate{Col: 2, Row: 8}] = Bishop{Color: types.Black}
//Make dummy move for white //Make dummy move for white
board.CheckAndPlay(types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}}) board.CheckAndPlay(&types.Move{StartSquare: types.Coordinate{Col: 5, Row: 1}, EndSquare: types.Coordinate{Col: 5, Row: 2}})
move := types.Move{ move := types.Move{
StartSquare: types.Coordinate{Col: 5, Row: 8}, StartSquare: types.Coordinate{Col: 5, Row: 8},
EndSquare: types.Coordinate{Col: 3, Row: 8}, EndSquare: types.Coordinate{Col: 3, Row: 8},
} }
good, _ := board.CheckAndPlay(move) good, _ := board.CheckAndPlay(&move)
assert.False(t, good) assert.False(t, good)
}) })
} }
@ -390,7 +390,7 @@ func Test_Board_HasGameEnded(t *testing.T) {
EndSquare: types.Coordinate{Col: 8, Row: 6}, EndSquare: types.Coordinate{Col: 8, Row: 6},
ColorMoved: types.White, ColorMoved: types.White,
} }
valid, violation := board.CheckAndPlay(whiteMove) valid, violation := board.CheckAndPlay(&whiteMove)
assert.True(t, valid) assert.True(t, valid)
assert.Empty(t, violation) assert.Empty(t, violation)
@ -406,7 +406,7 @@ func Test_Board_HasGameEnded(t *testing.T) {
EndSquare: types.Coordinate{Col: 1, Row: 8}, EndSquare: types.Coordinate{Col: 1, Row: 8},
ColorMoved: types.Black, ColorMoved: types.Black,
} }
valid, violation := board.CheckAndPlay(blackMove) valid, violation := board.CheckAndPlay(&blackMove)
assert.True(t, valid) assert.True(t, valid)
assert.Empty(t, violation) assert.Empty(t, violation)
@ -416,7 +416,7 @@ func Test_Board_HasGameEnded(t *testing.T) {
ColorMoved: types.White, ColorMoved: types.White,
} }
valid, violation = board.CheckAndPlay(checkmateMove) valid, violation = board.CheckAndPlay(&checkmateMove)
assert.True(t, valid) assert.True(t, valid)
assert.Empty(t, violation) assert.Empty(t, violation)
@ -441,7 +441,7 @@ func Test_Board_HasGameEnded_RookBlocks(t *testing.T) {
EndSquare: types.Coordinate{Col: 8, Row: 8}, EndSquare: types.Coordinate{Col: 8, Row: 8},
ColorMoved: types.White, ColorMoved: types.White,
} }
valid, violation := board.CheckAndPlay(whiteMove) valid, violation := board.CheckAndPlay(&whiteMove)
assert.True(t, valid) assert.True(t, valid)
assert.Empty(t, violation) assert.Empty(t, violation)

View File

@ -110,7 +110,7 @@ func (game *Game) Handle() {
game.gameState = CheckMove game.gameState = CheckMove
case CheckMove: case CheckMove:
valid, ruleViolation := game.board.CheckAndPlay(receivedMove) valid, ruleViolation := game.board.CheckAndPlay(&receivedMove)
if !valid { if !valid {
invalidMoveMessage, err := api.GetInvalidMoveMessage(receivedMove, ruleViolation.String()) invalidMoveMessage, err := api.GetInvalidMoveMessage(receivedMove, ruleViolation.String())
@ -123,12 +123,6 @@ func (game *Game) Handle() {
continue continue
} }
gameEnded, reason := game.board.HasGameEnded(receivedMove)
if gameEnded {
gameEndReason = reason
continue
}
game.gameState = CheckPlayerChange game.gameState = CheckPlayerChange
case CheckPlayerChange: case CheckPlayerChange:
@ -144,6 +138,12 @@ func (game *Game) Handle() {
return return
} }
if gameEnded, reason := game.board.HasGameEnded(receivedMove); gameEnded {
gameEndReason = reason
game.gameState = GameEnded
continue
}
game.gameState = PlayerToMove game.gameState = PlayerToMove
case GameEnded: case GameEnded: