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}
}
func (b *Board) CheckAndPlay(move types.Move) (bool, string) {
// 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
func (b *Board) CheckAndPlay(move types.Move) (bool, Violation) {
tempBoard := b.getCopyOfBoard()
//Check start square of move
pieceAtStartSquare := tempBoard.getPieceAt(move.StartSquare)
if pieceAtStartSquare == nil {
return false, "no piece at start square"
return false, NoPieceAtStartSquare
}
move.ColorMoved = pieceAtStartSquare.GetColor()
if move.ColorMoved != tempBoard.colorToMove {
return false, "wrong color moved"
return false, WrongColorMoved
}
move.PieceMoved = GetShortNameForPiece(pieceAtStartSquare)
@ -78,19 +76,17 @@ func (b *Board) CheckAndPlay(move types.Move) (bool, string) {
pieceAtEndSquare := tempBoard.getPieceAt(move.EndSquare)
if pieceAtEndSquare != nil {
if pieceAtEndSquare.GetColor() == pieceAtStartSquare.GetColor() {
return false, "same-coloured piece at end square"
return false, TargetSquareIsOccupied
}
}
wasSpecialMove := tempBoard.handleSpecialMove(move)
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.
wasSpecialMove, err := tempBoard.handleSpecialMove(move)
if !wasSpecialMove {
allMovesExceptBlocked := pieceAtStartSquare.GetAllNonBlockedMoves(tempBoard, move.StartSquare)
legal := lo.Contains(allMovesExceptBlocked, move.EndSquare)
if !legal {
return false, "not a legal square"
return false, InvalidMove
}
//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)
if err != nil {
return false, "something went wrong"
return false, SomethingWentWrong
}
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
b.position = tempBoard.position
b.history = tempBoard.history
@ -202,18 +185,19 @@ func (p Position) getCopyOfPosition() Position {
return position
}
func (b *Board) handleSpecialMove(move types.Move) bool {
func (b *Board) handleSpecialMove(move types.Move) (bool, error) {
var was bool
var err error
var pieceAtStartSquare = b.getPieceAt(move.StartSquare)
switch piece := pieceAtStartSquare.(type) {
case Pawn:
was = piece.HandlePossiblePromotion(b, move)
was, err = piece.HandlePossiblePromotion(b, move)
if !was {
was = piece.HandleEnPassant(b, move, b.getLastMove())
was, err = piece.HandleEnPassant(b, move, b.getLastMove())
}
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
case CheckMove:
valid, reason := game.board.CheckAndPlay(receivedMove)
valid, ruleViolation := game.board.CheckAndPlay(receivedMove)
if valid {
gameState = CheckPlayerChange
} else {
log.Println("invalid move because " + reason)
invalidMoveMessage, err := api.GetInvalidMoveMessage(receivedMove, reason)
log.Println(err)
invalidMoveMessage, err := api.GetInvalidMoveMessage(receivedMove, ruleViolation.String())
if err != nil {
log.Println("Error marshalling 'colorDetermined' message for player 1", err)
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) {
return false
return false, nil
}
valid, dir := k.movedOnValidCastlingSquare(board, move)
if !valid {
return false
return false, nil
}
switch k.Color {
@ -47,7 +47,7 @@ func (k King) HandleCastling(board *Board, move types.Move) bool {
}
k.playCastlingOnBoard(board, move, dir)
return true
return true, nil
}
func (k King) hadMovedBefore(b *Board) bool {

View File

@ -32,7 +32,7 @@ func (p Pawn) GetColor() types.ChessColor {
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 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)
}
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
if lastMove.PieceMoved != types.PawnShortName {
return false
return false, nil
}
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)
}
return wasEnPassant
return wasEnPassant, nil
}
func (p Pawn) getAllMoves(fromSquare types.Coordinate) []types.Coordinate {
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)
}