diff options
Diffstat (limited to 'src/board.rs')
-rw-r--r-- | src/board.rs | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/src/board.rs b/src/board.rs index 186e569..58e4037 100644 --- a/src/board.rs +++ b/src/board.rs @@ -185,7 +185,7 @@ impl Board { }; for source in serialize_bitboard(*piece & able_to_double_push_mask) { for target in serialize_bitboard(self.attacks.pawn_double_pushes[color as usize][source as usize] & empty) { - moves.push(Move { source, target, kind: MoveKind::Quiet }); + moves.push(Move { source, target, kind: MoveKind::DoublePush }); }; } } @@ -254,7 +254,7 @@ impl Board { let move_target_bb = mov.target.to_bitboard(); // Remove existing piece (if any) from target square - let captured_piece = match self.pieces + let mut captured_piece = match self.pieces .iter() .enumerate() .find(|(piece_type, bitboard)| *bitboard & mov.target.to_bitboard() > 0) @@ -266,6 +266,26 @@ impl Board { None => None, }; + // En Passant captures diffirently + captured_piece = match mov.kind { + MoveKind::EnPassant => { + debug_assert!(captured_piece.is_none(), "No capture should be found at this point"); + let captured_bb = Square::from(mov.source.rank() * 8 + mov.target.file()).to_bitboard(); + match self.pieces + .iter() + .enumerate() + .find(|(piece_type, bitboard)| *bitboard & captured_bb > 0) + { + Some((pawn_type, _)) => { + self.pieces[pawn_type] ^= captured_bb; + Some(PieceType::from(pawn_type)) + } + None => panic!("Pawn captured by En Passant was not found"), + } + }, + _ => captured_piece, + }; + // Move a piece from source square to target match self.pieces .iter() @@ -282,13 +302,27 @@ impl Board { None => panic!("Move is malformed: source piece not found"), }; + // Double push should set En Passant target square + match mov.kind { + MoveKind::DoublePush => { + self.ep_target = match mov.source.rank() { + 1 => Some(mov.source.nort_one()), + 6 => Some(mov.source.sout_one()), + rank => panic!("Double-push was used from invalid rank({}) when trying to make {:?}", rank, mov), + }; + }, + _ => { + self.ep_target = None + }, + } + self.ply += 1; captured_piece } /// Completely reverse make_move as if it never happened - pub fn unmake_move(&mut self, mov: Move, captured_piece: Option<PieceType>) { + pub fn unmake_move(&mut self, mov: Move, captured_piece: Option<PieceType>, previous_ep_target: Option<Square>) { let move_source_bb = mov.source.to_bitboard(); let move_target_bb = mov.target.to_bitboard(); @@ -311,12 +345,24 @@ impl Board { // Return captured piece to target square match captured_piece { Some(target_piece) => { - self.pieces[target_piece as usize] |= move_target_bb; - self.occupancy |= move_target_bb; + match mov.kind { + // Return pawn captured by En Passant pawn if needed + MoveKind::EnPassant => { + let original_dead_pawn_bb = Square::from(mov.source.rank() * 8 + mov.target.file()).to_bitboard(); + self.pieces[target_piece as usize] |= original_dead_pawn_bb; + self.occupancy |= original_dead_pawn_bb; + }, + _ => { + self.pieces[target_piece as usize] |= move_target_bb; + self.occupancy |= move_target_bb; + }, + } }, None => {} } + + self.ep_target = previous_ep_target; self.ply -= 1; } @@ -338,6 +384,7 @@ impl Board { let mut checks = 0; for mov in moves { + let ep_target_before = self.ep_target.clone(); let captured_piece = self.make_move(mov); // King can not be in check after our own move if !self.is_king_in_check(color) { @@ -357,7 +404,7 @@ impl Board { checks += children_checks; } - self.unmake_move(mov, captured_piece); + self.unmake_move(mov, captured_piece, ep_target_before); } if print { @@ -539,7 +586,7 @@ mod tests { let captured_piece = board.make_move(mov); board.print(); - board.unmake_move(mov, captured_piece); + board.unmake_move(mov, captured_piece, None); board.print(); assert_eq!(board, initial_board, "Board state after unmake_move should be the same as before make_move"); |