[board] Add a test for capturing en passant; fix the bugs
I wrote a test for capturing en passant that revealed some bugs. Cool! Implement the missing part of move validation that checks for an en passant move. Implement PositionBuilder::to_move() to set player_to_move. The most difficult part of this fix was finding the logic error in Move::is_en_passant(). Instead of checking for non-zero, check for equality against the en passant flag value. Checking for non-zero was causing this method to return true in the double push case.
This commit is contained in:
parent
683d89b726
commit
f90ea2d1be
3 changed files with 69 additions and 3 deletions
|
@ -193,7 +193,7 @@ impl Move {
|
|||
}
|
||||
|
||||
pub fn is_en_passant(&self) -> bool {
|
||||
(self.0 & 0b0101) != 0
|
||||
(self.0 & 0b0101) == 0b0101
|
||||
}
|
||||
|
||||
pub fn is_promotion(&self) -> bool {
|
||||
|
@ -272,6 +272,11 @@ impl MoveBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn capturing_en_passant(mut self, captured_piece: PlacedPiece) -> Self {
|
||||
self.kind = Kind::EnPassantCapture(captured_piece);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn promoting_to(mut self, shape: Shape) -> Self {
|
||||
if let Some(shape) = PromotableShape::try_from(shape).ok() {
|
||||
self.kind = match self.kind {
|
||||
|
|
|
@ -63,7 +63,20 @@ where
|
|||
let to_square = mv.to_square();
|
||||
let player = self.position.player_to_move();
|
||||
|
||||
let captured_piece: Option<PlacedPiece> = if mv.is_capture() {
|
||||
let captured_piece: Option<PlacedPiece> = if mv.is_en_passant() {
|
||||
// En passant captures the pawn directly ahead (in the player's direction) of the en passant square.
|
||||
let capture_square = match player {
|
||||
Color::White => to_square.neighbor(Direction::South),
|
||||
Color::Black => to_square.neighbor(Direction::North),
|
||||
}
|
||||
.ok_or(MakeMoveError::NoCapturedPiece)?;
|
||||
|
||||
Some(
|
||||
self.position
|
||||
.piece_on_square(capture_square)
|
||||
.ok_or(MakeMoveError::NoCapturedPiece)?,
|
||||
)
|
||||
} else if mv.is_capture() {
|
||||
Some(
|
||||
self.position
|
||||
.piece_on_square(to_square)
|
||||
|
@ -207,7 +220,7 @@ impl<'p> From<&'p Position> for Builder<'p, NoMove> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{r#move::Castle, MoveBuilder};
|
||||
use crate::{r#move::Castle, MoveBuilder, PositionBuilder};
|
||||
|
||||
#[test]
|
||||
fn move_white_pawn_one_square() -> Result<(), MakeMoveError> {
|
||||
|
@ -272,4 +285,47 @@ mod tests {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn en_passant_capture() -> Result<(), MakeMoveError> {
|
||||
let pos = PositionBuilder::new()
|
||||
.place_piece(piece!(White Pawn on B5))
|
||||
.place_piece(piece!(Black Pawn on A7))
|
||||
.to_move(Color::Black)
|
||||
.build();
|
||||
println!("{pos}");
|
||||
|
||||
let black_pawn_move = MoveBuilder::new(piece!(Black Pawn), Square::A7, Square::A5).build();
|
||||
assert!(black_pawn_move.is_double_push());
|
||||
assert!(!black_pawn_move.is_en_passant());
|
||||
|
||||
let en_passant_position = Builder::<NoMove>::new(&pos).make(&black_pawn_move)?.build();
|
||||
println!("{en_passant_position}");
|
||||
|
||||
assert_eq!(
|
||||
en_passant_position.piece_on_square(Square::A5),
|
||||
Some(piece!(Black Pawn on A5))
|
||||
);
|
||||
assert_eq!(
|
||||
en_passant_position.piece_on_square(Square::B5),
|
||||
Some(piece!(White Pawn on B5))
|
||||
);
|
||||
|
||||
let white_pawn_capture = MoveBuilder::new(piece!(White Pawn), Square::B5, Square::A6)
|
||||
.capturing_en_passant(piece!(Black Pawn on A5))
|
||||
.build();
|
||||
let en_passant_capture = Builder::<NoMove>::new(&en_passant_position)
|
||||
.make(&white_pawn_capture)?
|
||||
.build();
|
||||
println!("{en_passant_capture}");
|
||||
|
||||
assert_eq!(en_passant_capture.piece_on_square(Square::A5), None);
|
||||
assert_eq!(en_passant_capture.piece_on_square(Square::B5), None);
|
||||
assert_eq!(
|
||||
en_passant_capture.piece_on_square(Square::A6),
|
||||
Some(piece!(White Pawn on A6))
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@ impl Builder {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
pub fn to_move(&mut self, player: Color) -> &mut Self {
|
||||
self.player_to_move = player;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn place_piece(&mut self, piece: PlacedPiece) -> &mut Self {
|
||||
let square = piece.square();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue