149 lines
4.5 KiB
Go
149 lines
4.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, Violation) {
|
|
if k.hadMovedBefore(board) {
|
|
return false, ""
|
|
}
|
|
|
|
if board.isSquareAttacked(move.StartSquare, k.Color.Opposite()) {
|
|
return false, CastlingWhileKingInCheck
|
|
}
|
|
|
|
valid, dir := k.isCastlingAllowed(board, move)
|
|
if !valid {
|
|
return false, ""
|
|
}
|
|
|
|
k.playCastlingOnBoard(board, move, dir)
|
|
return true, ""
|
|
}
|
|
|
|
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 (
|
|
NoDirection CastlingDirection = ""
|
|
CastlingRight CastlingDirection = "right"
|
|
CastlingLeft CastlingDirection = "left"
|
|
)
|
|
|
|
func (k King) isCastlingAllowed(b *Board, move types.Move) (bool, CastlingDirection) {
|
|
var valid = false
|
|
|
|
switch k.Color {
|
|
case types.White:
|
|
destinationSquareForKingRight := types.Coordinate{Col: 7, Row: 1}
|
|
destinationSquareForKingLeft := types.Coordinate{Col: 3, Row: 1}
|
|
|
|
if move.EndSquare == destinationSquareForKingRight &&
|
|
b.getPieceAt(destinationSquareForKingRight) == nil &&
|
|
b.getPieceAt(*destinationSquareForKingRight.Left(1)) == nil &&
|
|
!b.isSquareAttacked(destinationSquareForKingRight, types.Black) &&
|
|
!b.isSquareAttacked(*destinationSquareForKingRight.Left(1), types.Black) &&
|
|
!b.state.WhiteHRookMoved {
|
|
_, ok := b.getPieceAt(types.Coordinate{Col: 8, Row: 1}).(Rook)
|
|
if ok {
|
|
return true, CastlingRight
|
|
}
|
|
}
|
|
|
|
if move.EndSquare == destinationSquareForKingLeft &&
|
|
b.getPieceAt(destinationSquareForKingLeft) == nil &&
|
|
b.getPieceAt(*destinationSquareForKingLeft.Right(1)) == nil &&
|
|
b.getPieceAt(*destinationSquareForKingLeft.Left(1)) == nil &&
|
|
!b.isSquareAttacked(destinationSquareForKingLeft, types.Black) &&
|
|
!b.isSquareAttacked(*destinationSquareForKingLeft.Right(1), types.Black) &&
|
|
!b.state.WhiteARookMoved {
|
|
_, ok := b.getPieceAt(types.Coordinate{Col: 1, Row: 1}).(Rook)
|
|
if ok {
|
|
return true, CastlingLeft
|
|
}
|
|
}
|
|
case types.Black:
|
|
destinationSquareForKingRight := types.Coordinate{Col: 7, Row: 8}
|
|
destinationSquareForKingLeft := types.Coordinate{Col: 3, Row: 8}
|
|
|
|
if move.EndSquare == destinationSquareForKingRight &&
|
|
b.getPieceAt(destinationSquareForKingRight) == nil &&
|
|
b.getPieceAt(*destinationSquareForKingRight.Left(1)) == nil &&
|
|
!b.isSquareAttacked(destinationSquareForKingRight, types.White) &&
|
|
!b.isSquareAttacked(*destinationSquareForKingRight.Left(1), types.White) &&
|
|
!b.state.BlackHRookMoved {
|
|
_, ok := b.getPieceAt(types.Coordinate{Col: 8, Row: 8}).(Rook)
|
|
if ok {
|
|
return true, CastlingRight
|
|
}
|
|
}
|
|
|
|
if move.EndSquare == destinationSquareForKingLeft &&
|
|
b.getPieceAt(destinationSquareForKingLeft) == nil &&
|
|
b.getPieceAt(*destinationSquareForKingLeft.Right(1)) == nil &&
|
|
b.getPieceAt(*destinationSquareForKingLeft.Left(1)) == nil &&
|
|
!b.isSquareAttacked(destinationSquareForKingLeft, types.White) &&
|
|
!b.isSquareAttacked(*destinationSquareForKingLeft.Right(1), types.White) &&
|
|
!b.state.BlackARookMoved {
|
|
_, ok := b.getPieceAt(types.Coordinate{Col: 1, Row: 8}).(Rook)
|
|
if ok {
|
|
return true, CastlingLeft
|
|
}
|
|
}
|
|
}
|
|
return valid, NoDirection
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|