Restructure special move handling.

This commit is contained in:
Marco 2023-07-11 22:28:07 +02:00
parent a93b1a1aca
commit 81898d150b
5 changed files with 44 additions and 44 deletions

View File

@ -57,20 +57,18 @@ 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, string) { func (b *Board) CheckAndPlay(move types.Move) (bool, Violation) {
// We make a copy of the original board to play moves on it,
// We can play the move on it and then check if it is invalid
tempBoard := b.getCopyOfBoard() tempBoard := b.getCopyOfBoard()
//Check start square of move //Check start square of move
pieceAtStartSquare := tempBoard.getPieceAt(move.StartSquare) pieceAtStartSquare := tempBoard.getPieceAt(move.StartSquare)
if pieceAtStartSquare == nil { if pieceAtStartSquare == nil {
return false, "no piece at start square" return false, NoPieceAtStartSquare
} }
move.ColorMoved = pieceAtStartSquare.GetColor() move.ColorMoved = pieceAtStartSquare.GetColor()
if move.ColorMoved != tempBoard.colorToMove { if move.ColorMoved != tempBoard.colorToMove {
return false, "wrong color moved" return false, WrongColorMoved
} }
move.PieceMoved = GetShortNameForPiece(pieceAtStartSquare) move.PieceMoved = GetShortNameForPiece(pieceAtStartSquare)
@ -78,19 +76,17 @@ func (b *Board) CheckAndPlay(move types.Move) (bool, string) {
pieceAtEndSquare := tempBoard.getPieceAt(move.EndSquare) pieceAtEndSquare := tempBoard.getPieceAt(move.EndSquare)
if pieceAtEndSquare != nil { if pieceAtEndSquare != nil {
if pieceAtEndSquare.GetColor() == pieceAtStartSquare.GetColor() { if pieceAtEndSquare.GetColor() == pieceAtStartSquare.GetColor() {
return false, "same-coloured piece at end square" return false, TargetSquareIsOccupied
} }
} }
wasSpecialMove := tempBoard.handleSpecialMove(move) wasSpecialMove, err := tempBoard.handleSpecialMove(move)
if !wasSpecialMove { if !wasSpecialMove {
// At the moment, we do not need to check if the correct color is moving,
//since we are only reading moves from the player whose turn it is.
allMovesExceptBlocked := pieceAtStartSquare.GetAllNonBlockedMoves(tempBoard, move.StartSquare) allMovesExceptBlocked := pieceAtStartSquare.GetAllNonBlockedMoves(tempBoard, move.StartSquare)
legal := lo.Contains(allMovesExceptBlocked, move.EndSquare) legal := lo.Contains(allMovesExceptBlocked, move.EndSquare)
if !legal { if !legal {
return false, "not a legal square" return false, InvalidMove
} }
//We play the move on the temporary board //We play the move on the temporary board
@ -100,25 +96,12 @@ func (b *Board) CheckAndPlay(move types.Move) (bool, string) {
kingAttacked, err := tempBoard.isKingOfMovingColorInCheck(move.ColorMoved) kingAttacked, err := tempBoard.isKingOfMovingColorInCheck(move.ColorMoved)
if err != nil { if err != nil {
return false, "something went wrong" return false, SomethingWentWrong
} }
if kingAttacked { if kingAttacked {
return false, "king would be in check after move" return false, KingInCheck
} }
//Check for checkmat&e
//Is every square that the king can move to attacked? And can no other
//piece block? -> checkmate
//only check if paths of attacking pieces can be blocked
//Maybe for checking checkmate, we have to check the 'path' in which the
//checkmate is given
// |K| | | | |Q|
// in this scenaria the path are all the squares between queen and king.
// If a piece can be moved into the path, it is no checkmate
//We play the move on the real board //We play the move on the real board
b.position = tempBoard.position b.position = tempBoard.position
b.history = tempBoard.history b.history = tempBoard.history
@ -202,18 +185,19 @@ func (p Position) getCopyOfPosition() Position {
return position return position
} }
func (b *Board) handleSpecialMove(move types.Move) bool { func (b *Board) handleSpecialMove(move types.Move) (bool, error) {
var was bool var was bool
var err error
var pieceAtStartSquare = b.getPieceAt(move.StartSquare) var pieceAtStartSquare = b.getPieceAt(move.StartSquare)
switch piece := pieceAtStartSquare.(type) { switch piece := pieceAtStartSquare.(type) {
case Pawn: case Pawn:
was = piece.HandlePossiblePromotion(b, move) was, err = piece.HandlePossiblePromotion(b, move)
if !was { if !was {
was = piece.HandleEnPassant(b, move, b.getLastMove()) was, err = piece.HandleEnPassant(b, move, b.getLastMove())
} }
case King: case King:
was = piece.HandleCastling(b, move) was, err = piece.HandleCastling(b, move)
} }
return was return was, err
} }

View File

@ -75,13 +75,13 @@ func (game *Game) Handle() {
gameState = CheckMove gameState = CheckMove
case CheckMove: case CheckMove:
valid, reason := game.board.CheckAndPlay(receivedMove) valid, ruleViolation := game.board.CheckAndPlay(receivedMove)
if valid { if valid {
gameState = CheckPlayerChange gameState = CheckPlayerChange
} else { } else {
log.Println("invalid move because " + reason) log.Println(err)
invalidMoveMessage, err := api.GetInvalidMoveMessage(receivedMove, reason) invalidMoveMessage, err := api.GetInvalidMoveMessage(receivedMove, ruleViolation.String())
if err != nil { if err != nil {
log.Println("Error marshalling 'colorDetermined' message for player 1", err) log.Println("Error marshalling 'colorDetermined' message for player 1", err)
return return

View File

@ -29,14 +29,14 @@ func (k King) AfterMoveAction(board *Board, fromSquare types.Coordinate) {
} }
} }
func (k King) HandleCastling(board *Board, move types.Move) bool { func (k King) HandleCastling(board *Board, move types.Move) (bool,error) {
if k.hadMovedBefore(board) { if k.hadMovedBefore(board) {
return false return false, nil
} }
valid, dir := k.movedOnValidCastlingSquare(board, move) valid, dir := k.movedOnValidCastlingSquare(board, move)
if !valid { if !valid {
return false return false, nil
} }
switch k.Color { switch k.Color {
@ -47,7 +47,7 @@ func (k King) HandleCastling(board *Board, move types.Move) bool {
} }
k.playCastlingOnBoard(board, move, dir) k.playCastlingOnBoard(board, move, dir)
return true return true, nil
} }
func (k King) hadMovedBefore(b *Board) bool { func (k King) hadMovedBefore(b *Board) bool {

View File

@ -32,7 +32,7 @@ func (p Pawn) GetColor() types.ChessColor {
return p.Color return p.Color
} }
func (p *Pawn) HandlePossiblePromotion(b *Board, move types.Move) bool { func (p *Pawn) HandlePossiblePromotion(b *Board, move types.Move) (bool,error) {
var isPromotionMove bool var isPromotionMove bool
var promotionToPiece types.PieceShortName var promotionToPiece types.PieceShortName
@ -62,14 +62,14 @@ func (p *Pawn) HandlePossiblePromotion(b *Board, move types.Move) bool {
b.position[move.EndSquare] = GetPieceForShortName(promotionToPiece, move.ColorMoved) b.position[move.EndSquare] = GetPieceForShortName(promotionToPiece, move.ColorMoved)
} }
return isPromotionMove return isPromotionMove, nil
} }
func (p *Pawn) HandleEnPassant(b *Board, move, lastMove types.Move) bool { func (p *Pawn) HandleEnPassant(b *Board, move, lastMove types.Move) (bool, error){
var wasEnPassant bool var wasEnPassant bool
if lastMove.PieceMoved != types.PawnShortName { if lastMove.PieceMoved != types.PawnShortName {
return false return false, nil
} }
switch move.ColorMoved { switch move.ColorMoved {
@ -126,7 +126,7 @@ func (p *Pawn) HandleEnPassant(b *Board, move, lastMove types.Move) bool {
b.position[move.EndSquare] = GetPieceForShortName(move.PieceMoved, move.ColorMoved) b.position[move.EndSquare] = GetPieceForShortName(move.PieceMoved, move.ColorMoved)
} }
return wasEnPassant return wasEnPassant, nil
} }
func (p Pawn) getAllMoves(fromSquare types.Coordinate) []types.Coordinate { func (p Pawn) getAllMoves(fromSquare types.Coordinate) []types.Coordinate {
theoreticalMoves := make([]types.Coordinate, 0, 4) theoreticalMoves := make([]types.Coordinate, 0, 4)

16
chess/violation.go Normal file
View File

@ -0,0 +1,16 @@
package chess
type Violation string
var (
InvalidMove Violation = "invalid move"
NoPieceAtStartSquare Violation = "no piece at start square"
WrongColorMoved Violation = "wrong color moved"
TargetSquareIsOccupied Violation = "target square is occupied"
KingInCheck Violation = "king would be in check after move"
SomethingWentWrong Violation = "something went wrong"
)
func (v Violation) String() string {
return string(v)
}