Marco
ff2ec599fe
In order to simplify special moves like en passant or castling for the client, we want to deliver the board state after every move (and not only start square and end square). With PGN we can encode a chess position into a string. This commit implies changes to logic of the pieces' shortnames. This will break the client/server connection (at least for promotions).
131 lines
3.5 KiB
Go
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.GetAllNonBlockedMoves(board, fromSquare)
|
|
}
|
|
|
|
func (k King) GetColor() types.ChessColor {
|
|
return k.Color
|
|
}
|
|
|
|
func (k King) GetAllNonBlockedMoves(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)
|
|
}
|
|
}
|