diff --git a/engine/src/bitboard.rs b/engine/src/bitboard.rs index 1486484..177e4a5 100644 --- a/engine/src/bitboard.rs +++ b/engine/src/bitboard.rs @@ -5,5 +5,6 @@ mod checkinfo; mod attacks; mod bitmove; mod movebuffer; +mod movegen; pub mod board; \ No newline at end of file diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index f7fe35f..b99a4db 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -94,6 +94,64 @@ pub static RAY_TABLE: Lazy<[[u64; 8]; 64]> = Lazy::new(|| { return table; }); +// ROOK_MOVE_MASK[] +pub static ROOK_MOVE_MASK: Lazy<[u64; 64]> = Lazy::new(|| { + let mut table = [0u64; 64]; + + for sq in 0..64 { + for dir in [0, 2, 4, 6] { + table[sq] |= RAY_TABLE[sq][dir]; + } + } + table +}); + +// BISHOP_MOVE_MASK[] +pub static BISHOP_MOVE_MASK: Lazy<[u64; 64]> = Lazy::new(|| { + let mut table = [0u64; 64]; + + for sq in 0..64 { + for dir in [1, 3, 5, 7] { + table[sq] |= RAY_TABLE[sq][dir]; + } + } + table +}); + +// KING_SAFETY_ROOK_MASK[] +pub static KING_SAFETY_ROOK_MASK: Lazy<[u64; 64]> = Lazy::new(|| { + let mut table = [0u64; 64]; + + for sq in 0..64 { + let mut mask = KING_ATTACK_MAP[sq]; + + while mask != 0 { + let next_sq = mask.trailing_zeros(); + table[sq] |= ROOK_MOVE_MASK[next_sq as usize]; + mask &= !(1 << next_sq); + } + } + + table +}); + +// KING_SAFETY_BISHOP_MASK[] +pub static KING_SAFETY_BISHOP_MASK: Lazy<[u64; 64]> = Lazy::new(|| { + let mut table = [0u64; 64]; + + for sq in 0..64 { + let mut mask = KING_ATTACK_MAP[sq]; + + while mask != 0 { + let next_sq = mask.trailing_zeros(); + table[sq] |= BISHOP_MOVE_MASK[next_sq as usize]; + mask &= !(1 << next_sq); + } + } + + table +}); + // <----- TESTS -----> diff --git a/engine/src/bitboard/attacks.rs b/engine/src/bitboard/attacks.rs index a348d96..63b0c32 100644 --- a/engine/src/bitboard/attacks.rs +++ b/engine/src/bitboard/attacks.rs @@ -5,6 +5,8 @@ impl Board { const RANK_2: u64 = 0x0000_0000_0000_FF00; const RANK_7: u64 = 0x00FF_0000_0000_0000; + const A_FILE: u64 = 0x0101_0101_0101_0101; + const H_FILE: u64 = 0x8080_8080_8080_8080; pub fn get_pseudo_pawn_moves(&self, sq: u32) -> u64 { let pawn: u64 = 1 << sq; @@ -71,6 +73,111 @@ impl Board { pub fn get_pseudo_queen_moves(&self, sq: u32) -> u64 { return self.get_pseudo_bishop_moves(sq) | self.get_pseudo_rook_moves(sq); } + + #[inline] + pub fn get_pseudo_bishop_moves_ignore_king(&self, sq: u32) -> u64 { + let mut moves = 0u64; + let sq = sq as usize; + let king = self.bitboards[5 + 6*self.side_to_move as usize]; + let occupancy = self.occupancy[2] & !king; + moves |= get_raycast_from_square_in_direction(occupancy, sq, 1); + moves |= get_raycast_from_square_in_direction(occupancy, sq, 3); + moves |= get_raycast_from_square_in_direction(occupancy, sq, 5); + moves |= get_raycast_from_square_in_direction(occupancy, sq, 7); + + return moves; + } + #[inline] + pub fn get_pseudo_rook_moves_ignore_king(&self, sq: u32) -> u64 { + let mut moves: u64 = 0u64; + let sq = sq as usize; + let king = self.bitboards[5 + 6*self.side_to_move as usize]; + let occupancy = self.occupancy[2] & !king; + moves |= get_raycast_from_square_in_direction(occupancy, sq, 0); + moves |= get_raycast_from_square_in_direction(occupancy, sq, 2); + moves |= get_raycast_from_square_in_direction(occupancy, sq, 4); + moves |= get_raycast_from_square_in_direction(occupancy, sq, 6); + + return moves; + } + + #[inline] + pub fn is_square_attacked(&self, king_sq: u32) -> bool { + let offset: usize = 6 * self.side_to_move as usize; + + // rook-queen checks (+) + let mut threat_mask: u64 = self.get_pseudo_rook_moves(king_sq); + let mut attacker_mask: u64 = self.bitboards[10 - offset] | self.bitboards[9 - offset]; + if threat_mask & attacker_mask != 0 { return true; } + + // bishop-queen checks (x) + threat_mask = self.get_pseudo_bishop_moves(king_sq); + attacker_mask = self.bitboards[10 - offset] | self.bitboards[8 - offset]; + if threat_mask & attacker_mask != 0 { return true; } + + // knight checks (L) + threat_mask = KNIGHT_ATTACK_MAP[king_sq as usize]; + attacker_mask = self.bitboards[7 - offset]; + if threat_mask & attacker_mask != 0 { return true; } + + // pawn checks (v) + threat_mask = PAWN_ATTACK_MAP[king_sq as usize][self.side_to_move as usize]; + attacker_mask = self.bitboards[6 - offset]; + return threat_mask & attacker_mask != 0; + } + pub fn get_safe_king_squares(&self) -> u64 { + let offset: usize = 6 * (1 - self.side_to_move as usize); + let king_sq = self.bitboards[11 - offset].trailing_zeros() as usize; + let bishop_mask = KING_SAFETY_BISHOP_MASK[king_sq]; + let rook_mask = KING_SAFETY_ROOK_MASK[king_sq]; + let mut attack_map: u64 = 0u64; + + let mut board: u64 = self.bitboards[offset]; + if self.side_to_move() == 0 { + attack_map |= (board >> 9 & !Self::H_FILE) | (board >> 7 & !Self::A_FILE); + } + else { + attack_map |= (board << 9 & !Self::A_FILE) | (board << 7 & !Self::H_FILE); + } + + board = self.bitboards[offset + 1]; + while board != 0 { + let piece_sq: u32 = board.trailing_zeros(); + board &= !(1 << piece_sq); + + attack_map |= self.get_pseudo_knight_moves(piece_sq); + } + + board = self.bitboards[offset + 2] & bishop_mask; + while board != 0 { + let piece_sq: u32 = board.trailing_zeros(); + board &= !(1 << piece_sq); + + attack_map |= self.get_pseudo_bishop_moves_ignore_king(piece_sq); + } + + board = self.bitboards[offset + 3] & rook_mask; + while board != 0 { + let piece_sq: u32 = board.trailing_zeros(); + board &= !(1 << piece_sq); + + attack_map |= self.get_pseudo_rook_moves_ignore_king(piece_sq); + } + + board = self.bitboards[offset + 4] & (bishop_mask | rook_mask); + while board != 0 { + let piece_sq: u32 = board.trailing_zeros(); + board &= !(1 << piece_sq); + + attack_map |= self.get_pseudo_rook_moves_ignore_king(piece_sq) | self.get_pseudo_bishop_moves_ignore_king(piece_sq); + } + + board = self.bitboards[offset + 5]; + let piece_sq: u32 = board.trailing_zeros(); + attack_map |= self.get_pseudo_king_moves(piece_sq); + + return !attack_map; + } } #[inline(always)] diff --git a/engine/src/bitboard/legality.rs b/engine/src/bitboard/legality.rs index f42fdc1..f81973e 100644 --- a/engine/src/bitboard/legality.rs +++ b/engine/src/bitboard/legality.rs @@ -93,6 +93,13 @@ impl Board { } } + #[inline] + pub(in super) fn get_pin_masked_moves(&self, moves: u64, sq: u32) -> u64 { + let sq: usize = sq as usize; + if self.pinned_squares[sq] == 4 { return moves; } + let dir: u8 = self.pinned_squares[sq]; + return moves & (RAY_TABLE[sq][dir as usize] | RAY_TABLE[sq][4 + dir as usize]); + } } // <----- TESTS -----> diff --git a/engine/src/bitboard/movegen.rs b/engine/src/bitboard/movegen.rs new file mode 100644 index 0000000..b702f4a --- /dev/null +++ b/engine/src/bitboard/movegen.rs @@ -0,0 +1,67 @@ +mod pawns; +mod knights; +mod bishops; +mod rooks; +mod queens; +mod kings; + +use super::board::Board; +use super::movebuffer::MoveBuffer; +use super::bitmove::BitMove; +use super::checkinfo::CheckInfo; +use super::utils::*; + +impl Board { + + const NO_FILTER: u64 = 0xFFFF_FFFF_FFFF_FFFF; + + pub fn collect_moves(&mut self, buffer: &mut MoveBuffer, temp_buffer: &mut MoveBuffer) -> bool { + buffer.clear(); + self.calc_pinned_squares(); + let check_info = self.check_test(); + + match check_info.check_count { + 0 => self.collect_all_moves(buffer, temp_buffer), + 1 => self.collect_moves_single_check(buffer, temp_buffer, &check_info), + 2 => self.collect_king_evasion(buffer, temp_buffer), + _ => panic!("More than 2 checking pieces found as the same time!") + } + return check_info.check_count > 0; + } + + pub(in super) fn collect_all_moves(&self, buffer: &mut MoveBuffer, temp_buffer: &mut MoveBuffer) { + let safe_squares = self.get_safe_king_squares(); + + self.add_pawn_moves(buffer, temp_buffer, Self::NO_FILTER); + self.add_knight_moves(buffer, temp_buffer, Self::NO_FILTER); + self.add_bishop_moves(buffer, temp_buffer, Self::NO_FILTER); + self.add_rook_moves(buffer, temp_buffer, Self::NO_FILTER); + self.add_queen_moves(buffer, temp_buffer, Self::NO_FILTER); + self.add_king_moves(buffer, temp_buffer, safe_squares); + self.add_king_castles(buffer, safe_squares); + + buffer.append(temp_buffer); + temp_buffer.clear(); + } + pub(in super) fn collect_moves_single_check(&self, buffer: &mut MoveBuffer, temp_buffer: &mut MoveBuffer, check_info: &CheckInfo) { + let safe_squares = self.get_safe_king_squares(); + + self.add_pawn_moves(buffer, temp_buffer, check_info.move_mask); + self.add_knight_moves(buffer, temp_buffer, check_info.move_mask); + self.add_bishop_moves(buffer, temp_buffer, check_info.move_mask); + self.add_rook_moves(buffer, temp_buffer, check_info.move_mask); + self.add_queen_moves(buffer, temp_buffer, check_info.move_mask); + self.add_king_moves(buffer, temp_buffer, safe_squares); + + buffer.append(temp_buffer); + temp_buffer.clear(); + } + pub(in super) fn collect_king_evasion(&self, buffer: &mut MoveBuffer, temp_buffer: &mut MoveBuffer) { + let safe_squares = self.get_safe_king_squares(); + + self.add_king_moves(buffer, temp_buffer, safe_squares); + + buffer.append(&temp_buffer); + temp_buffer.clear(); + } +} \ No newline at end of file diff --git a/engine/src/bitboard/movegen/bishops.rs b/engine/src/bitboard/movegen/bishops.rs new file mode 100644 index 0000000..3d41916 --- /dev/null +++ b/engine/src/bitboard/movegen/bishops.rs @@ -0,0 +1,55 @@ +use super::*; + +impl Board { + + pub fn add_bishop_moves(&self, capture_buffer: &mut MoveBuffer, quiet_buffer: &mut MoveBuffer, move_mask: u64) { + let piece_index = 2 + self.side_to_move * 6; + let mut bishops = self.bitboards[piece_index as usize]; + let empty = !self.occupancy[2]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while bishops != 0 { + let from_sq = pop_lsb(&mut bishops); + let raw_move_map = self.get_pseudo_bishop_moves(from_sq) & move_mask; + let move_map = self.get_pin_masked_moves(raw_move_map, from_sq); + + let mut quiet_map = move_map & empty; + let mut capture_map = move_map & opponents; + + while quiet_map != 0 { + let to_sq = pop_lsb(&mut quiet_map); + quiet_buffer.add(BitMove::quiet( + from_sq as u8, + to_sq as u8, + None + )); + } + while capture_map != 0 { + let to_sq = pop_lsb(&mut capture_map); + capture_buffer.add(BitMove::capture( + from_sq as u8, + to_sq as u8, + None + )); + } + } + } + pub fn add_bishop_captures(&self, buffer: &mut MoveBuffer, move_mask: u64) { + let offset = 6 * self.side_to_move as usize; + let mut bishops: u64 = self.bitboards[2 + offset]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while bishops != 0 { + let next_sq: u32 = pop_lsb(&mut bishops); + let mut attacks: u64 = self.get_pseudo_bishop_moves(next_sq) & opponents & move_mask; + attacks = self.get_pin_masked_moves(attacks, next_sq); + + while attacks != 0 { + let to_sq = pop_lsb(&mut attacks); + buffer.add(BitMove::capture( + next_sq as u8, + to_sq as u8, + None + )); + } + } + } +} \ No newline at end of file diff --git a/engine/src/bitboard/movegen/kings.rs b/engine/src/bitboard/movegen/kings.rs new file mode 100644 index 0000000..60e7daf --- /dev/null +++ b/engine/src/bitboard/movegen/kings.rs @@ -0,0 +1,88 @@ +use super::*; + +impl Board { + + pub fn add_king_moves(&self, capture_buffer: &mut MoveBuffer, quiet_buffer: &mut MoveBuffer, move_mask: u64) { + let piece_index = 5 + self.side_to_move * 6; + let mut kings = self.bitboards[piece_index as usize]; + let empty = !self.occupancy[2]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while kings != 0 { + let from_sq = pop_lsb(&mut kings); + let move_map = self.get_pseudo_king_moves(from_sq) & move_mask; + + let mut quiet_map = move_map & empty; + let mut capture_map = move_map & opponents; + + while quiet_map != 0 { + let to_sq = pop_lsb(&mut quiet_map); + quiet_buffer.add(BitMove::quiet( + from_sq as u8, + to_sq as u8, + None + )); + } + while capture_map != 0 { + let to_sq = pop_lsb(&mut capture_map); + capture_buffer.add(BitMove::capture( + from_sq as u8, + to_sq as u8, + None + )); + } + } + } + pub fn add_king_captures(&self, buffer: &mut MoveBuffer, move_mask: u64) { + let offset = 6 * self.side_to_move as usize; + let mut kings: u64 = self.bitboards[5 + offset]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while kings != 0 { + let next_sq: u32 = pop_lsb(&mut kings); + let mut attacks: u64 = self.get_pseudo_king_moves(next_sq) & opponents & move_mask; + attacks = self.get_pin_masked_moves(attacks, next_sq); + + while attacks != 0 { + let to_sq = pop_lsb(&mut attacks); + buffer.add(BitMove::capture( + next_sq as u8, + to_sq as u8, + None + )); + } + } + } + pub fn add_king_castles(&self, buffer: &mut MoveBuffer, move_mask: u64) { + if self.castling_rights & (0b11 << (2 - 2 * self.side_to_move)) == 0 { + return; + } + + let offset = 5 + 6 * self.side_to_move as u8; + let castle_offset = 2 - 2 * self.side_to_move as u8; + let castling_rights = self.castling_rights & 3 << castle_offset; + let occupied = self.occupancy[2]; + let king_sq = self.bitboards[offset as usize].trailing_zeros(); + + let queenside_mask = 0b111 << (king_sq - 3); + let kingside_mask = 0b11 << (king_sq + 1); + + if (castling_rights & 1 << castle_offset) != 0 + && queenside_mask & occupied == 0 + && !move_mask & 0b11 << (king_sq - 2) == 0 + && !self.is_square_attacked(king_sq - 2) { + buffer.add(BitMove::castle( + king_sq as u8, + (king_sq - 2) as u8 + )); + } + if (castling_rights & 2 << castle_offset) != 0 + && kingside_mask & occupied == 0 + && !move_mask & 0b11 << (king_sq + 1) == 0 + && !self.is_square_attacked(king_sq + 2) { + buffer.add(BitMove::castle( + king_sq as u8, + (king_sq + 2) as u8 + )); + } + + } +} \ No newline at end of file diff --git a/engine/src/bitboard/movegen/knights.rs b/engine/src/bitboard/movegen/knights.rs new file mode 100644 index 0000000..4c0efce --- /dev/null +++ b/engine/src/bitboard/movegen/knights.rs @@ -0,0 +1,55 @@ +use super::*; + +impl Board { + + pub fn add_knight_moves(&self, capture_buffer: &mut MoveBuffer, quiet_buffer: &mut MoveBuffer, move_mask: u64) { + let piece_index = 1 + self.side_to_move * 6; + let mut knights = self.bitboards[piece_index as usize]; + let empty = !self.occupancy[2]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while knights != 0 { + let from_sq = pop_lsb(&mut knights); + let raw_move_map = self.get_pseudo_knight_moves(from_sq) & move_mask; + let move_map = self.get_pin_masked_moves(raw_move_map, from_sq); + + let mut quiet_map = move_map & empty; + let mut capture_map = move_map & opponents; + + while quiet_map != 0 { + let to_sq = pop_lsb(&mut quiet_map); + quiet_buffer.add(BitMove::quiet( + from_sq as u8, + to_sq as u8, + None + )); + } + while capture_map != 0 { + let to_sq = pop_lsb(&mut capture_map); + capture_buffer.add(BitMove::capture( + from_sq as u8, + to_sq as u8, + None + )); + } + } + } + pub fn add_knight_captures(&self, buffer: &mut MoveBuffer, move_mask: u64) { + let offset = 6 * self.side_to_move as usize; + let mut knights: u64 = self.bitboards[1 + offset]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while knights != 0 { + let next_sq: u32 = pop_lsb(&mut knights); + let mut attacks: u64 = self.get_pseudo_knight_moves(next_sq) & opponents & move_mask; + attacks = self.get_pin_masked_moves(attacks, next_sq); + + while attacks != 0 { + let to_sq = pop_lsb(&mut attacks); + buffer.add(BitMove::capture( + next_sq as u8, + to_sq as u8, + None + )); + } + } + } +} \ No newline at end of file diff --git a/engine/src/bitboard/movegen/pawns.rs b/engine/src/bitboard/movegen/pawns.rs new file mode 100644 index 0000000..444b387 --- /dev/null +++ b/engine/src/bitboard/movegen/pawns.rs @@ -0,0 +1,76 @@ +use super::*; + +impl Board { + + pub fn add_pawn_quiets(&self, buffer: &mut MoveBuffer, move_mask: u64) { + let offset: u8 = self.side_to_move * 6; + let mut pawns: u64 = self.bitboards[offset as usize]; + while pawns != 0 { + let next_sq = pop_lsb(&mut pawns); + + let mut quiets: u64 = self.get_pseudo_pawn_moves(next_sq) & move_mask; + quiets = self.get_pin_masked_moves(quiets, next_sq); + while quiets != 0 { + let to_sq = quiets.trailing_zeros(); + + if (self.side_to_move == 0 && quiets.trailing_zeros() / 8 == 7) + || (self.side_to_move == 1 && quiets.trailing_zeros() / 8 == 0) { + for piece_type in [4, 3, 2, 1] { + buffer.add(BitMove::quiet( + next_sq as u8, + to_sq as u8, + Some(piece_type) + )); + } + } + else { + buffer.add(BitMove::quiet( + next_sq as u8, + to_sq as u8, + None + )); + } + quiets &= !(1 << to_sq); + } + } + } + pub fn add_pawn_captures(&self, buffer: &mut MoveBuffer, move_mask: u64) { + let offset = 6 * self.side_to_move as usize; + let mut pawns: u64 = self.bitboards[offset]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while pawns != 0 { + let next_sq = pop_lsb(&mut pawns); + + let mut attacks: u64 = self.get_pseudo_pawn_captures(next_sq) & move_mask; + attacks = self.get_pin_masked_moves(attacks, next_sq); + attacks &= opponents; + + while attacks != 0 { + let to_sq = attacks.trailing_zeros(); + + if (self.side_to_move == 0 && attacks.trailing_zeros() / 8 == 7) + || (self.side_to_move == 1 && attacks.trailing_zeros() / 8 == 0) { + for piece_type in [4, 3, 2, 1] { + buffer.add(BitMove::capture( + next_sq as u8, + to_sq as u8, + Some(piece_type) + )); + } + } + else { + buffer.add(BitMove::capture( + next_sq as u8, + to_sq as u8, + None + )); + } + attacks &= !(1 << to_sq); + } + } + } + pub fn add_pawn_moves(&self, capture_buffer: &mut MoveBuffer, quiet_buffer: &mut MoveBuffer, move_mask: u64) { + self.add_pawn_captures(capture_buffer, move_mask); + self.add_pawn_quiets(quiet_buffer, move_mask); + } +} \ No newline at end of file diff --git a/engine/src/bitboard/movegen/queens.rs b/engine/src/bitboard/movegen/queens.rs new file mode 100644 index 0000000..960f49a --- /dev/null +++ b/engine/src/bitboard/movegen/queens.rs @@ -0,0 +1,55 @@ +use super::*; + +impl Board { + + pub fn add_queen_moves(&self, capture_buffer: &mut MoveBuffer, quiet_buffer: &mut MoveBuffer, move_mask: u64) { + let piece_index = 4 + self.side_to_move * 6; + let mut queens = self.bitboards[piece_index as usize]; + let empty = !self.occupancy[2]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while queens != 0 { + let from_sq = pop_lsb(&mut queens); + let raw_move_map = self.get_pseudo_queen_moves(from_sq) & move_mask; + let move_map = self.get_pin_masked_moves(raw_move_map, from_sq); + + let mut quiet_map = move_map & empty; + let mut capture_map = move_map & opponents; + + while quiet_map != 0 { + let to_sq = pop_lsb(&mut quiet_map); + quiet_buffer.add(BitMove::quiet( + from_sq as u8, + to_sq as u8, + None + )); + } + while capture_map != 0 { + let to_sq = pop_lsb(&mut capture_map); + capture_buffer.add(BitMove::capture( + from_sq as u8, + to_sq as u8, + None + )); + } + } + } + pub fn add_queen_captures(&self, buffer: &mut MoveBuffer, move_mask: u64) { + let offset = 6 * self.side_to_move as usize; + let mut queens: u64 = self.bitboards[4 + offset]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while queens != 0 { + let next_sq: u32 = pop_lsb(&mut queens); + let mut attacks: u64 = self.get_pseudo_queen_moves(next_sq) & opponents & move_mask; + attacks = self.get_pin_masked_moves(attacks, next_sq); + + while attacks != 0 { + let to_sq = pop_lsb(&mut attacks); + buffer.add(BitMove::capture( + next_sq as u8, + to_sq as u8, + None + )); + } + } + } +} \ No newline at end of file diff --git a/engine/src/bitboard/movegen/rooks.rs b/engine/src/bitboard/movegen/rooks.rs new file mode 100644 index 0000000..749e2d8 --- /dev/null +++ b/engine/src/bitboard/movegen/rooks.rs @@ -0,0 +1,55 @@ +use super::*; + +impl Board { + + pub fn add_rook_moves(&self, capture_buffer: &mut MoveBuffer, quiet_buffer: &mut MoveBuffer, move_mask: u64) { + let piece_index = 3 + self.side_to_move * 6; + let mut rooks = self.bitboards[piece_index as usize]; + let empty = !self.occupancy[2]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while rooks != 0 { + let from_sq = pop_lsb(&mut rooks); + let raw_move_map = self.get_pseudo_rook_moves(from_sq) & move_mask; + let move_map = self.get_pin_masked_moves(raw_move_map, from_sq); + + let mut quiet_map = move_map & empty; + let mut capture_map = move_map & opponents; + + while quiet_map != 0 { + let to_sq = pop_lsb(&mut quiet_map); + quiet_buffer.add(BitMove::quiet( + from_sq as u8, + to_sq as u8, + None + )); + } + while capture_map != 0 { + let to_sq = pop_lsb(&mut capture_map); + capture_buffer.add(BitMove::capture( + from_sq as u8, + to_sq as u8, + None + )); + } + } + } + pub fn add_rook_captures(&self, buffer: &mut MoveBuffer, move_mask: u64) { + let offset = 6 * self.side_to_move as usize; + let mut rooks: u64 = self.bitboards[3 + offset]; + let opponents = self.occupancy[1 - self.side_to_move as usize]; + while rooks != 0 { + let next_sq: u32 = pop_lsb(&mut rooks); + let mut attacks: u64 = self.get_pseudo_rook_moves(next_sq) & opponents & move_mask; + attacks = self.get_pin_masked_moves(attacks, next_sq); + + while attacks != 0 { + let to_sq = pop_lsb(&mut attacks); + buffer.add(BitMove::capture( + next_sq as u8, + to_sq as u8, + None + )); + } + } + } +} \ No newline at end of file diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index f7f83fe..81cc68f 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -1,13 +1,13 @@ #[inline(always)] -pub fn pop_lsb(value: &mut u64) -> usize { - let idx = value.trailing_zeros() as usize; +pub fn pop_lsb(value: &mut u64) -> u32 { + let idx = value.trailing_zeros(); *value &= !(1 << idx); return idx; } #[inline(always)] -pub fn pop_msb(value: &mut u64) -> usize { - let idx = 63 - value.leading_zeros() as usize; +pub fn pop_msb(value: &mut u64) -> u32 { + let idx = 63 - value.leading_zeros(); *value &= !(1 << idx); return idx; } @@ -72,7 +72,7 @@ mod tests { 0xBEAC_DBE0_903A_AC00, 0x01E8_C895_A6F0_0000 ]; - let expected_values: [usize; 6] = [63, 0, 4, 2, 10, 20]; + let expected_values: [u32; 6] = [63, 0, 4, 2, 10, 20]; // tests for index in 0..6 { @@ -92,7 +92,7 @@ mod tests { 0x0000_C1C3_201C_0DB1, 0x0000_0203_0DE4_E944 ]; - let expected_values: [usize; 6] = [63, 0, 61, 57, 47, 41]; + let expected_values: [u32; 6] = [63, 0, 61, 57, 47, 41]; // tests for index in 0..6 {