Fix move generator bugs related to castling, enpassant, promotion

This commit is contained in:
2024-07-05 20:17:09 +03:00
parent 2a1a3224cb
commit e3123f17d3
4 changed files with 128 additions and 216 deletions

View File

@@ -4,7 +4,7 @@ use crate::attack::{
get_bishop_attacks, get_king_attacks, get_knight_attacks, get_pawn_attacks, get_queen_attacks,
get_rook_attacks,
};
use crate::game::State;
use crate::game::{Castle, State};
use crate::movegen::{
bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves,
queen_pseudo_moves, rook_pseudo_moves,
@@ -88,12 +88,12 @@ impl Board {
pub fn is_attacked(&self, sq: usize, opponent_color: Color) -> bool {
let all_occupancies = self.get_all_occupancies();
let enemy = match opponent_color {
Color::Black => &self.black_pieces,
Color::White => &self.white_pieces,
let (enemy, own_color) = match opponent_color {
Color::Black => (&self.black_pieces, Color::White),
Color::White => (&self.white_pieces, Color::Black),
};
enemy[Kind::Pawn.idx()].bitboard & get_pawn_attacks(sq, opponent_color) != 0
enemy[Kind::Pawn.idx()].bitboard & get_pawn_attacks(sq, own_color) != 0
|| enemy[Kind::Knight.idx()].bitboard & get_knight_attacks(sq) != 0
|| enemy[Kind::Bishop.idx()].bitboard & get_bishop_attacks(all_occupancies, sq) != 0
|| enemy[Kind::Rook.idx()].bitboard & get_rook_attacks(all_occupancies, sq) != 0
@@ -156,14 +156,18 @@ impl Board {
pub fn make_move(&mut self, mv: Move, color: Color) -> bool {
self.update_board_state(&mv, color);
self.state.update_castling_state(mv.source as u8, color);
self.state.change_side();
let pieces = match color {
Color::White => &self.white_pieces,
Color::Black => &self.black_pieces,
};
self.state
.update_castling_state_quiet(mv.source as u8, color);
self.state
.update_castling_state_capture(mv.target as u8, Color::opponent_color(color));
self.state.change_side();
let own_king_square = pieces[Kind::King.idx()].bitboard.trailing_zeros() as usize;
self.is_move_legit(own_king_square, Color::opponent_color(color))
}
@@ -191,7 +195,10 @@ impl Board {
}
MoveType::DoublePush => {
Board::move_piece(mv.source as u8, mv.target as u8, own_pieces);
let en_passant = Some(mv.source as u8 + 8);
let en_passant = match color {
Color::White => Some((mv.source + 8) as u8),
Color::Black => Some((mv.source - 8) as u8),
};
self.state.set_en_passant_target_square(en_passant);
}
MoveType::Promotion(promote) => {
@@ -209,6 +216,7 @@ impl Board {
Board::move_piece(mv.source as u8, mv.target as u8, own_pieces);
Board::move_rook_castle(mv.target as u8, own_pieces);
self.state.set_en_passant_target_square(None);
self.state.set_castling_ability(color, Castle::None)
}
}
}
@@ -230,13 +238,7 @@ impl Board {
_ => return,
};
for p in pieces.iter_mut() {
if p.bitboard & 1_u64 << rook_source != 0 {
p.bitboard &= !(1_u64 << rook_source);
p.bitboard |= 1_u64 << rook_target;
break;
}
}
Board::move_piece(rook_source, rook_target, pieces);
}
fn promote_piece(square: u8, pieces: &mut [Piece; 6], promote: Promote) {
@@ -464,28 +466,6 @@ mod tests {
let mv = Move::new_with_type(4, 6, MoveType::Castle);
game.board.make_move(mv, Color::White);
assert_eq!(game, from_fen(FEN_CASTLE[1])?);
Ok(())
}
#[test]
fn test_perftree_snapshots() -> Result<(), String> {
init_attacks();
let mut game = from_fen("rnbqkbnr/ppppp1pp/5p2/7Q/8/4P3/PPPP1PPP/RNB1KBNR w KQkq - 0 1")?;
for mv in game.board.pseudo_moves_all(Color::Black) {
if game.board.make_move_and_reset(mv, Color::Black) {
println!("{:?}", mv)
}
}
let mut game = from_fen("rnbqkbnr/1ppppppp/p7/8/Q7/2P5/PP1PPPPP/RNB1KBNR w KQkq - 0 1")?;
for mv in game.board.pseudo_moves_all(Color::Black) {
if game.board.make_move_and_reset(mv, Color::Black) {
println!("{:?}", mv)
}
}
Ok(())
}
}