diff --git a/src/board/chess_board/error.rs b/src/board/chess_board/error.rs index e531f54..e6ef030 100644 --- a/src/board/chess_board/error.rs +++ b/src/board/chess_board/error.rs @@ -9,7 +9,7 @@ pub enum InvalidError { InvalidPawnPosition, /// Castling rights do not match up with the state of the board. InvalidCastlingRights, - /// En-passant target square is not empty and behind an opponent's pawn. + /// En-passant target square is not empty, behind an opponent's pawn, on the correct rank. InvalidEnPassant, /// The two kings are next to each other. NeighbouringKings, @@ -33,7 +33,7 @@ impl std::fmt::Display for InvalidError { "Castling rights do not match up with the state of the board." } Self::InvalidEnPassant => { - "En-passant target square is not empty and behind an opponent's pawn." + "En-passant target square is not empty, behind an opponent's pawn, on the correct rank." } Self::NeighbouringKings => "The two kings are next to each other.", Self::OpponentInCheck => "The opponent is currently in check.", diff --git a/src/board/chess_board/mod.rs b/src/board/chess_board/mod.rs index 9b25dd3..122880a 100644 --- a/src/board/chess_board/mod.rs +++ b/src/board/chess_board/mod.rs @@ -297,12 +297,22 @@ impl ChessBoard { } } - // The current en-passant target square must be empty, right behind an opponent's pawn. + // En-passant validation if let Some(square) = self.en_passant() { + // Must be empty if !(self.combined_occupancy() & square).is_empty() { return Err(InvalidError::InvalidEnPassant); } - let opponent_pawns = self.occupancy(Piece::Pawn, !self.current_player()); + + let opponent = !self.current_player(); + + // Must be on the opponent's third rank + if (square & opponent.third_rank().into_bitboard()).is_empty() { + return Err(InvalidError::InvalidEnPassant); + } + + // Must be behind a pawn + let opponent_pawns = self.occupancy(Piece::Pawn, opponent); let double_pushed_pawn = self .current_player() .backward_direction()