mchess-server/chess/king.go
Marco af993876fd Introduce check if the game has ended (checkmate/stalemate)
Introduce checkmate check and send out 'gameEnded' message
2024-01-17 23:06:48 +01:00

131 lines
3.5 KiB
Go

package chess
import (
"mchess_server/types"
)
type King struct {
Color types.ChessColor
}
func (k King) GetAllAttackedSquares(board Board, fromSquare types.Coordinate) []types.Coordinate {
return k.GetAllNonBlockedSquares(board, fromSquare)
}
func (k King) GetColor() types.ChessColor {
return k.Color
}
func (k King) GetAllNonBlockedSquares(board Board, fromSquare types.Coordinate) []types.Coordinate {
return board.GetNonBlockedKingMoves(fromSquare)
}
func (k King) AfterMoveAction(board *Board, fromSquare types.Coordinate) {
switch k.Color {
case types.Black:
board.state.BlackKingMoved = true
case types.White:
board.state.WhiteKingMoved = true
}
}
func (k King) HandleCastling(board *Board, move types.Move) (bool, error) {
if k.hadMovedBefore(board) {
return false, nil
}
valid, dir := k.movedOnValidCastlingSquare(board, move)
if !valid {
return false, nil
}
switch k.Color {
case types.White:
board.state.WhiteKingMoved = true
case types.Black:
board.state.BlackKingMoved = true
}
k.playCastlingOnBoard(board, move, dir)
return true, nil
}
func (k King) hadMovedBefore(b *Board) bool {
var hasMoved bool
switch k.Color {
case types.White:
hasMoved = b.state.WhiteKingMoved
case types.Black:
hasMoved = b.state.BlackKingMoved
}
return hasMoved
}
type CastlingDirection string
const (
CastlingRight CastlingDirection = "right"
CastlingLeft CastlingDirection = "left"
)
func (k King) movedOnValidCastlingSquare(b *Board, move types.Move) (bool, CastlingDirection) {
var valid = false
switch k.Color {
case types.White:
castlingSquareRight := types.Coordinate{Col: 7, Row: 1}
castlingSquareLeft := types.Coordinate{Col: 3, Row: 1}
if move.EndSquare == castlingSquareRight &&
b.getPieceAt(castlingSquareRight) == nil &&
b.getPieceAt(*castlingSquareRight.Left(1)) == nil &&
!b.state.WhiteHRookMoved {
return true, CastlingRight
}
if move.EndSquare == castlingSquareLeft &&
b.getPieceAt(castlingSquareLeft) == nil &&
b.getPieceAt(*castlingSquareLeft.Right(1)) == nil &&
b.getPieceAt(*castlingSquareLeft.Left(1)) == nil &&
!b.state.WhiteARookMoved {
return true, CastlingLeft
}
case types.Black:
castlingSquareRight := types.Coordinate{Col: 7, Row: 8}
castlingSquareLeft := types.Coordinate{Col: 3, Row: 8}
if move.EndSquare == castlingSquareRight &&
b.getPieceAt(castlingSquareRight) == nil &&
b.getPieceAt(*castlingSquareRight.Left(1)) == nil &&
!b.state.BlackHRookMoved {
return true, CastlingRight
}
if move.EndSquare == castlingSquareLeft &&
b.getPieceAt(castlingSquareLeft) == nil &&
b.getPieceAt(*castlingSquareLeft.Right(1)) == nil &&
b.getPieceAt(*castlingSquareLeft.Left(1)) == nil &&
!b.state.BlackARookMoved {
return true, CastlingLeft
}
}
return valid, CastlingRight
}
func (k King) playCastlingOnBoard(board *Board, move types.Move, dir CastlingDirection) {
onRow := move.StartSquare.Row
switch dir {
case CastlingRight:
delete(board.position, types.Coordinate{Col: 8, Row: onRow})
delete(board.position, types.Coordinate{Col: 5, Row: onRow})
board.position[types.Coordinate{Col: 7, Row: onRow}] = King{Color: k.Color}
board.position[types.Coordinate{Col: 6, Row: onRow}] = Rook(k)
case CastlingLeft:
delete(board.position, types.Coordinate{Col: 1, Row: onRow})
delete(board.position, types.Coordinate{Col: 5, Row: onRow})
board.position[types.Coordinate{Col: 3, Row: onRow}] = King{Color: k.Color}
board.position[types.Coordinate{Col: 4, Row: onRow}] = Rook(k)
}
}