Restructure special move handling.
This commit is contained in:
parent
a93b1a1aca
commit
81898d150b
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
16
chess/violation.go
Normal 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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user