diff --git a/src/attack.rs b/src/attack.rs index 6a98689..f9cf02d 100644 --- a/src/attack.rs +++ b/src/attack.rs @@ -1,6 +1,6 @@ use crate::{ bitboard::{ - intersect, lsb, square_to_bitboard, square_to_bitboard_wrapping, EMPTY, NOT_FILE_A, + have_common_bit, lsb, square_to_bitboard, square_to_bitboard_wrapping, EMPTY, NOT_FILE_A, NOT_FILE_AB, NOT_FILE_GH, NOT_FILE_H, }, board::Color, @@ -152,7 +152,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo for (rank, file) in (rank..=7).zip(file..=7) { let attack_square = square_to_bitboard(coords_to_square(rank, file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } @@ -161,7 +161,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo for (rank, file) in (0..target_rank).rev().zip(file..=7) { let attack_square = square_to_bitboard(coords_to_square(rank, file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } @@ -170,7 +170,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo for (rank, file) in (rank..=7).zip((0..target_file).rev()) { let attack_square = square_to_bitboard(coords_to_square(rank, file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } @@ -178,7 +178,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo for (rank, file) in (0..target_rank).rev().zip((0..target_file).rev()) { let attack_square = square_to_bitboard(coords_to_square(rank, file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } @@ -197,14 +197,14 @@ pub fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboar for rank in rank..=7 { let attack_square = square_to_bitboard(coords_to_square(rank, target_file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } for file in file..=7 { let attack_square = square_to_bitboard(coords_to_square(target_rank, file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } @@ -213,14 +213,14 @@ pub fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboar for rank in (0..=rank).rev() { let attack_square = square_to_bitboard(coords_to_square(rank, target_file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } for file in (0..=file).rev() { let attack_square = square_to_bitboard(coords_to_square(target_rank, file)); attacks |= attack_square; - if attack_square & blocker != 0 { + if have_common_bit(attack_square, blocker) { break; } } @@ -234,7 +234,7 @@ pub fn set_occupancy(index: u64, relevant_bits: usize, mut attack_mask: Bitboard for bit in 0..relevant_bits { let square = lsb(attack_mask); attack_mask &= !square_to_bitboard(square); - if intersect(index, square_to_bitboard(bit)) { + if have_common_bit(index, square_to_bitboard(bit)) { occupancy |= square_to_bitboard(square); } } diff --git a/src/bitboard.rs b/src/bitboard.rs index 75cefac..b7fe7cb 100644 --- a/src/bitboard.rs +++ b/src/bitboard.rs @@ -3,10 +3,15 @@ use u64 as Bitboard; pub const EMPTY: Bitboard = 0x0; pub const FULL: Bitboard = 0xffffffffffffffff; pub const NOT_FILE_A: Bitboard = 0xfefefefefefefefe; -pub const NOT_FILE_AB: Bitboard = 0xfcfcfcfcfcfcfcfc; pub const NOT_FILE_H: Bitboard = 0x7f7f7f7f7f7f7f7f; +pub const NOT_FILE_AB: Bitboard = 0xfcfcfcfcfcfcfcfc; pub const NOT_FILE_GH: Bitboard = 0x3f3f3f3f3f3f3f3f; -pub const RANK_8: Bitboard = 0x0ff00000000000000; +pub const RANK_1: Bitboard = 0xff; +pub const RANK_2: Bitboard = 0xff00; +pub const RANK_4: Bitboard = 0xff000000; +pub const RANK_5: Bitboard = 0xff00000000; +pub const RANK_7: Bitboard = 0xff000000000000; +pub const RANK_8: Bitboard = 0xff00000000000000; pub const fn square_to_bitboard(square: usize) -> Bitboard { 1_u64 << square @@ -24,6 +29,6 @@ pub const fn bit_count(bitboard: Bitboard) -> usize { bitboard.count_ones() as usize } -pub const fn intersect(bitboard_a: Bitboard, bitboard_b: Bitboard) -> bool { +pub const fn have_common_bit(bitboard_a: Bitboard, bitboard_b: Bitboard) -> bool { bitboard_a & bitboard_b != 0 } diff --git a/src/board.rs b/src/board.rs index 5e5e7fe..1024f15 100644 --- a/src/board.rs +++ b/src/board.rs @@ -4,6 +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::bitboard::{have_common_bit, lsb, square_to_bitboard}; use crate::game::{Castle, State}; use crate::movegen::{ bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves, @@ -93,12 +94,23 @@ impl Board { Color::White => (&self.white_pieces, Color::Black), }; - 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 - || enemy[Kind::Queen.idx()].bitboard & get_queen_attacks(all_occupancies, sq) != 0 - || enemy[Kind::King.idx()].bitboard & get_king_attacks(sq) != 0 + have_common_bit( + enemy[Kind::Pawn.idx()].bitboard, + get_pawn_attacks(sq, own_color), + ) || have_common_bit(enemy[Kind::Knight.idx()].bitboard, get_knight_attacks(sq)) + || have_common_bit( + enemy[Kind::Bishop.idx()].bitboard, + get_bishop_attacks(all_occupancies, sq), + ) + || have_common_bit( + enemy[Kind::Rook.idx()].bitboard, + get_rook_attacks(all_occupancies, sq), + ) + || have_common_bit( + enemy[Kind::Queen.idx()].bitboard, + get_queen_attacks(all_occupancies, sq), + ) + || have_common_bit(enemy[Kind::King.idx()].bitboard, get_king_attacks(sq)) } pub fn is_move_legit(&self, square: usize, opponent_color: Color) -> bool { @@ -162,13 +174,12 @@ impl Board { Color::Black => &self.black_pieces, }; + self.state.update_castling_state_quiet(mv.source, color); 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)); + .update_castling_state_capture(mv.target, Color::opponent_color(color)); self.state.change_side(); - let own_king_square = pieces[Kind::King.idx()].bitboard.trailing_zeros() as usize; + let own_king_square = lsb(pieces[Kind::King.idx()].bitboard); self.is_move_legit(own_king_square, Color::opponent_color(color)) } @@ -180,58 +191,58 @@ impl Board { match &mv.move_type { MoveType::Quiet => { - Self::move_piece(mv.source as u8, mv.target as u8, own_pieces); + Self::move_piece(mv.source, mv.target, own_pieces); self.state.set_en_passant_target_square(None); } MoveType::Capture => { - Self::move_piece(mv.source as u8, mv.target as u8, own_pieces); - Self::remove_piece(mv.target as u8, opponent_pieces); + Self::move_piece(mv.source, mv.target, own_pieces); + Self::remove_piece(mv.target, opponent_pieces); self.state.set_en_passant_target_square(None); } MoveType::EnPassant => { - Self::move_piece(mv.source as u8, mv.target as u8, own_pieces); - Self::remove_pawn_enpassant(mv.target as u8, opponent_pieces, color); + Self::move_piece(mv.source, mv.target, own_pieces); + Self::remove_pawn_enpassant(mv.target, opponent_pieces, color); self.state.set_en_passant_target_square(None); } MoveType::DoublePush => { - Self::move_piece(mv.source as u8, mv.target as u8, own_pieces); + Self::move_piece(mv.source, mv.target, own_pieces); let en_passant = match color { - Color::White => Some((mv.source + 8) as u8), - Color::Black => Some((mv.source - 8) as u8), + Color::White => Some(mv.source + 8), + Color::Black => Some(mv.source - 8), }; self.state.set_en_passant_target_square(en_passant); } MoveType::Promotion(promote) => { - Self::remove_piece(mv.source as u8, own_pieces); - Self::promote_piece(mv.target as u8, own_pieces, *promote); + Self::remove_piece(mv.source, own_pieces); + Self::promote_piece(mv.target, own_pieces, *promote); self.state.set_en_passant_target_square(None); } MoveType::PromotionCapture(promote) => { - Self::remove_piece(mv.source as u8, own_pieces); - Self::remove_piece(mv.target as u8, opponent_pieces); - Self::promote_piece(mv.target as u8, own_pieces, *promote); + Self::remove_piece(mv.source, own_pieces); + Self::remove_piece(mv.target, opponent_pieces); + Self::promote_piece(mv.target, own_pieces, *promote); self.state.set_en_passant_target_square(None); } MoveType::Castle => { - Self::move_piece(mv.source as u8, mv.target as u8, own_pieces); - Self::move_rook_castle(mv.target as u8, own_pieces); + Self::move_piece(mv.source, mv.target, own_pieces); + Self::move_rook_castle(mv.target, own_pieces); self.state.set_en_passant_target_square(None); self.state.set_castling_ability(color, Castle::None) } } } - fn move_piece(source: u8, target: u8, pieces: &mut [Piece; 6]) { + fn move_piece(source: usize, target: usize, pieces: &mut [Piece; 6]) { for p in pieces.iter_mut() { - if p.bitboard & (1_u64 << source) != 0 { - p.bitboard &= !(1_u64 << source); - p.bitboard |= 1_u64 << target; + if have_common_bit(p.bitboard, square_to_bitboard(source)) { + p.bitboard &= !square_to_bitboard(source); + p.bitboard |= square_to_bitboard(target); break; } } } - fn move_rook_castle(square: u8, pieces: &mut [Piece; 6]) { + fn move_rook_castle(square: usize, pieces: &mut [Piece; 6]) { let (rook_source, rook_target) = match square { 2 | 58 => (square - 2, square + 1), 6 | 62 => (square + 1, square - 1), @@ -241,33 +252,33 @@ impl Board { Self::move_piece(rook_source, rook_target, pieces); } - fn promote_piece(square: u8, pieces: &mut [Piece; 6], promote: Promote) { + fn promote_piece(square: usize, pieces: &mut [Piece; 6], promote: Promote) { match promote { - Promote::Knight => pieces[Kind::Knight.idx()].bitboard |= 1_u64 << square, - Promote::Bishop => pieces[Kind::Bishop.idx()].bitboard |= 1_u64 << square, - Promote::Rook => pieces[Kind::Rook.idx()].bitboard |= 1_u64 << square, - Promote::Queen => pieces[Kind::Queen.idx()].bitboard |= 1_u64 << square, + Promote::Knight => pieces[Kind::Knight.idx()].bitboard |= square_to_bitboard(square), + Promote::Bishop => pieces[Kind::Bishop.idx()].bitboard |= square_to_bitboard(square), + Promote::Rook => pieces[Kind::Rook.idx()].bitboard |= square_to_bitboard(square), + Promote::Queen => pieces[Kind::Queen.idx()].bitboard |= square_to_bitboard(square), }; } - fn remove_piece(square: u8, pieces: &mut [Piece; 6]) { + fn remove_piece(square: usize, pieces: &mut [Piece; 6]) { for p in pieces.iter_mut() { - if p.bitboard & (1_u64 << square) != 0 { - p.bitboard &= !(1_u64 << square); + if have_common_bit(p.bitboard, square_to_bitboard(square)) { + p.bitboard &= !(square_to_bitboard(square)); break; } } } - fn remove_pawn_enpassant(square: u8, pieces: &mut [Piece; 6], color: Color) { + fn remove_pawn_enpassant(square: usize, pieces: &mut [Piece; 6], color: Color) { let piece_to_remove = match color { Color::White => square - 8, Color::Black => square + 8, }; for p in pieces.iter_mut() { - if p.bitboard & (1_u64 << piece_to_remove) != 0 { - p.bitboard &= !(1_u64 << piece_to_remove); + if have_common_bit(p.bitboard, square_to_bitboard(piece_to_remove)) { + p.bitboard &= !(square_to_bitboard(piece_to_remove)); break; } } diff --git a/src/fen.rs b/src/fen.rs index 4337155..3ee569c 100644 --- a/src/fen.rs +++ b/src/fen.rs @@ -122,10 +122,10 @@ fn castling_ability(castling: &str) -> Result<[Castle; 2], FenError> { use std::collections::HashMap; -fn en_passant_target_square(square: &str) -> Result, FenError> { +fn en_passant_target_square(square: &str) -> Result, FenError> { let mut sqr = square.chars(); - let mut files: HashMap = HashMap::new(); + let mut files: HashMap = HashMap::new(); files.insert('a', 0); files.insert('b', 1); files.insert('c', 2); @@ -135,7 +135,7 @@ fn en_passant_target_square(square: &str) -> Result, FenError> { files.insert('g', 6); files.insert('h', 7); - let mut ranks: HashMap = HashMap::new(); + let mut ranks: HashMap = HashMap::new(); ranks.insert('3', 2); ranks.insert('6', 5); diff --git a/src/game.rs b/src/game.rs index 7854a76..977c5d9 100644 --- a/src/game.rs +++ b/src/game.rs @@ -35,7 +35,7 @@ impl Default for Game { pub struct State { side_to_move: Color, castling_ability: [Castle; 2], - en_passant_target_square: Option, + en_passant_target_square: Option, halfmove_clock: u8, fullmove_counter: u8, } @@ -54,7 +54,7 @@ impl State { pub const fn load_state( side_to_move: Color, castling_ability: [Castle; 2], - en_passant_target_square: Option, + en_passant_target_square: Option, halfmove_clock: u8, fullmove_counter: u8, ) -> Self { @@ -67,7 +67,7 @@ impl State { } } - pub const fn get_en_passant_target_square(&self) -> Option { + pub const fn get_en_passant_target_square(&self) -> Option { self.en_passant_target_square } @@ -78,7 +78,7 @@ impl State { } } - pub fn update_castling_state_quiet(&mut self, source: u8, color: Color) { + pub fn update_castling_state_quiet(&mut self, source: usize, color: Color) { self.update_castling_state_capture(source, color); match (source, color) { @@ -88,7 +88,7 @@ impl State { } } - pub fn update_castling_state_capture(&mut self, target: u8, color: Color) { + pub fn update_castling_state_capture(&mut self, target: usize, color: Color) { let (short_square, long_square) = match color { Color::White => (7, 0), Color::Black => (63, 56), @@ -122,7 +122,7 @@ impl State { self.side_to_move } - pub fn set_en_passant_target_square(&mut self, sq: Option) { + pub fn set_en_passant_target_square(&mut self, sq: Option) { self.en_passant_target_square = sq; } diff --git a/src/move.rs b/src/move.rs index 970711c..5c839f2 100644 --- a/src/move.rs +++ b/src/move.rs @@ -19,13 +19,13 @@ pub enum MoveType { #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub struct Move { - pub source: u32, - pub target: u32, + pub source: usize, + pub target: usize, pub move_type: MoveType, } impl Move { - pub const fn new(source: u32, target: u32) -> Self { + pub const fn new(source: usize, target: usize) -> Self { Self { source, target, @@ -33,7 +33,7 @@ impl Move { } } - pub const fn new_with_type(source: u32, target: u32, move_type: MoveType) -> Self { + pub const fn new_with_type(source: usize, target: usize, move_type: MoveType) -> Self { Self { source, target, diff --git a/src/movegen.rs b/src/movegen.rs index 8f06140..7893b88 100644 --- a/src/movegen.rs +++ b/src/movegen.rs @@ -2,21 +2,20 @@ use crate::attack::{ get_bishop_attacks, get_king_attacks, get_knight_attacks, get_pawn_attacks, get_queen_attacks, get_rook_attacks, }; +use crate::bitboard::{ + have_common_bit, lsb, square_to_bitboard, NOT_FILE_A, NOT_FILE_H, RANK_1, RANK_2, RANK_4, + RANK_5, RANK_7, RANK_8, +}; use crate::board::{Board, Color}; use crate::game::Castle; use crate::r#move::{Move, MoveType, Promote}; use u64 as Bitboard; -const NOT_A_FILE: Bitboard = 0xfefefefefefefefe; -const NOT_H_FILE: Bitboard = 0x7f7f7f7f7f7f7f7f; -const RANK_4: Bitboard = 0x00000000ff000000; -const RANK_5: Bitboard = 0x000000ff00000000; - pub fn pawn_pseudo_moves( pawns: Bitboard, all_occupancies: Bitboard, enemy_occupancies: Bitboard, - en_passant_square: Option, + en_passant_square: Option, color: Color, ) -> Vec { let mut moves = vec![]; @@ -47,10 +46,10 @@ fn white_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec { let mut single_push_targets = (pawns << 8) & empty; while single_push_targets != 0 { - let to = single_push_targets.trailing_zeros(); + let to = lsb(single_push_targets); let from = to - 8; - if 1_u64 << from as u64 & 0xff000000000000 != 0 { + if have_common_bit(square_to_bitboard(from), RANK_7) { moves.extend([ Move::new_with_type(from, to, MoveType::Promotion(Promote::Knight)), Move::new_with_type(from, to, MoveType::Promotion(Promote::Bishop)), @@ -62,10 +61,11 @@ fn white_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec { } single_push_targets &= single_push_targets - 1; } + let single_push_targets = (pawns << 8) & empty; let mut double_push_targets = (single_push_targets << 8) & empty & RANK_4; while double_push_targets != 0 { - let to = double_push_targets.trailing_zeros(); + let to = lsb(double_push_targets); let from = to - 16; moves.push(Move::new_with_type(from, to, MoveType::DoublePush)); double_push_targets &= double_push_targets - 1; @@ -79,10 +79,10 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec { let mut single_push_targets = (pawns >> 8) & empty; while single_push_targets != 0 { - let to = single_push_targets.trailing_zeros(); + let to = lsb(single_push_targets); let from = to + 8; - if 1_u64 << from as u64 & 0xff00 != 0 { + if have_common_bit(square_to_bitboard(from), RANK_2) { moves.extend([ Move::new_with_type(from, to, MoveType::Promotion(Promote::Knight)), Move::new_with_type(from, to, MoveType::Promotion(Promote::Bishop)), @@ -98,7 +98,7 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec { let single_push_targets = (pawns >> 8) & empty; let mut double_push_targets = (single_push_targets >> 8) & empty & RANK_5; while double_push_targets != 0 { - let to = double_push_targets.trailing_zeros(); + let to = lsb(double_push_targets); let from = to + 16; moves.push(Move::new_with_type(from, to, MoveType::DoublePush)); double_push_targets &= double_push_targets - 1; @@ -109,17 +109,17 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec { fn white_pawn_capture_moves( pawns: Bitboard, enemy_occupancies: Bitboard, - en_passant_square: Option, + en_passant_square: Option, ) -> Vec { let mut moves = vec![]; - let mut w_pawns_capture_east = pawns & ((enemy_occupancies >> 9) & NOT_H_FILE); - let mut w_pawns_capture_west = pawns & ((enemy_occupancies >> 7) & NOT_A_FILE); + let mut w_pawns_capture_east = pawns & ((enemy_occupancies >> 9) & NOT_FILE_H); + let mut w_pawns_capture_west = pawns & ((enemy_occupancies >> 7) & NOT_FILE_A); while w_pawns_capture_east != 0 { - let from = w_pawns_capture_east.trailing_zeros(); + let from = lsb(w_pawns_capture_east); let to = from + 9; - if 1_u64 << to as u64 & 0xff00000000000000 != 0 { + if have_common_bit(square_to_bitboard(to), RANK_8) { moves.extend([ Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)), Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)), @@ -132,10 +132,10 @@ fn white_pawn_capture_moves( w_pawns_capture_east &= w_pawns_capture_east - 1; } while w_pawns_capture_west != 0 { - let from = w_pawns_capture_west.trailing_zeros(); + let from = lsb(w_pawns_capture_west); let to = from + 7; - if 1_u64 << to as u64 & 0xff00000000000000 != 0 { + if have_common_bit(square_to_bitboard(to), RANK_8) { moves.extend([ Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)), Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)), @@ -149,12 +149,12 @@ fn white_pawn_capture_moves( } if let Some(en_passant_square) = en_passant_square { - let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::Black); + let attacked_from = get_pawn_attacks(en_passant_square, Color::Black); let mut result = attacked_from & pawns; while result != 0 { moves.push(Move::new_with_type( - result.trailing_zeros(), - en_passant_square as u32, + lsb(result), + en_passant_square, MoveType::EnPassant, )); result &= result - 1; @@ -166,16 +166,17 @@ fn white_pawn_capture_moves( fn black_pawn_capture_moves( pawns: Bitboard, enemy_occupancies: Bitboard, - en_passant_square: Option, + en_passant_square: Option, ) -> Vec { let mut moves = vec![]; - let mut b_pawns_capture_east = pawns & ((enemy_occupancies << 7) & NOT_H_FILE); - let mut b_pawns_capture_west = pawns & ((enemy_occupancies << 9) & NOT_A_FILE); + let mut b_pawns_capture_east = pawns & ((enemy_occupancies << 7) & NOT_FILE_H); + let mut b_pawns_capture_west = pawns & ((enemy_occupancies << 9) & NOT_FILE_A); while b_pawns_capture_east != 0 { - let from = b_pawns_capture_east.trailing_zeros(); + let from = lsb(b_pawns_capture_east); let to = from - 7; - if 1_u64 << to as u64 & 0xff != 0 { + + if have_common_bit(square_to_bitboard(to), RANK_1) { moves.extend([ Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)), Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)), @@ -189,9 +190,9 @@ fn black_pawn_capture_moves( } while b_pawns_capture_west != 0 { - let from = b_pawns_capture_west.trailing_zeros(); + let from = lsb(b_pawns_capture_west); let to = from - 9; - if 1_u64 << to as u64 & 0xff != 0 { + if have_common_bit(square_to_bitboard(to), RANK_1) { moves.extend([ Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)), Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)), @@ -205,12 +206,12 @@ fn black_pawn_capture_moves( } if let Some(en_passant_square) = en_passant_square { - let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::White); + let attacked_from = get_pawn_attacks(en_passant_square, Color::White); let mut result = attacked_from & pawns; while result != 0 { moves.push(Move::new_with_type( - result.trailing_zeros(), - en_passant_square as u32, + lsb(result), + en_passant_square, MoveType::EnPassant, )); result &= result - 1; @@ -228,13 +229,13 @@ pub fn knight_pseudo_moves( let enemy_occupancies = all_occupancies ^ own_occupancies; while knights != 0 { - let knight_square = knights.trailing_zeros() as usize; - let from = knight_square as u32; + let knight_square = lsb(knights); + let from = knight_square; let mut attacks = get_knight_attacks(knight_square) & !own_occupancies; while attacks != 0 { - let attack_sq = attacks.trailing_zeros(); - if (1_u64 << attack_sq) & enemy_occupancies != 0 { + let attack_sq = lsb(attacks); + if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) { moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture)); } else { moves.push(Move::new(from, attack_sq)); @@ -255,13 +256,13 @@ pub fn bishop_pseudo_moves( let enemy_occupancies = all_occupancies ^ own_occupancies; while bishops != 0 { - let bishop_square = bishops.trailing_zeros() as usize; - let from = bishop_square as u32; + let bishop_square = lsb(bishops); + let from = bishop_square; let mut attacks = get_bishop_attacks(all_occupancies, bishop_square) & !own_occupancies; while attacks != 0 { - let attack_sq = attacks.trailing_zeros(); - if (1_u64 << attack_sq) & enemy_occupancies != 0 { + let attack_sq = lsb(attacks); + if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) { moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture)); } else { moves.push(Move::new(from, attack_sq)); @@ -282,13 +283,13 @@ pub fn rook_pseudo_moves( let enemy_occupancies = all_occupancies ^ own_occupancies; while rooks != 0 { - let rook_square = rooks.trailing_zeros() as usize; - let from = rook_square as u32; + let rook_square = lsb(rooks); + let from = rook_square; let mut attacks = get_rook_attacks(all_occupancies, rook_square) & !own_occupancies; while attacks != 0 { - let attack_sq = attacks.trailing_zeros(); - if (1_u64 << attack_sq) & enemy_occupancies != 0 { + let attack_sq = lsb(attacks); + if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) { moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture)); } else { moves.push(Move::new(from, attack_sq)); @@ -309,13 +310,13 @@ pub fn queen_pseudo_moves( let enemy_occupancies = all_occupancies ^ own_occupancies; while queens != 0 { - let queen_square = queens.trailing_zeros() as usize; - let from = queen_square as u32; + let queen_square = lsb(queens); + let from = queen_square; let mut attacks = get_queen_attacks(all_occupancies, queen_square) & !own_occupancies; while attacks != 0 { - let attack_sq = attacks.trailing_zeros(); - if (1_u64 << attack_sq) & enemy_occupancies != 0 { + let attack_sq = lsb(attacks); + if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) { moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture)); } else { moves.push(Move::new(from, attack_sq)); @@ -335,14 +336,14 @@ pub fn king_pseudo_moves( color: Color, ) -> Vec { let mut moves = vec![]; - let king_square = king.trailing_zeros() as usize; - let from = king_square as u32; + let king_square = lsb(king); + let from = king_square; let mut attacks = get_king_attacks(king_square) & !own_occupancies; let enemy_occupancies = all_occupancies ^ own_occupancies; while attacks != 0 { - let attack_sq = attacks.trailing_zeros(); - if (1_u64 << attack_sq) & enemy_occupancies != 0 { + let attack_sq = lsb(attacks); + if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) { moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture)); } else { moves.push(Move::new(from, attack_sq)); diff --git a/src/perft.rs b/src/perft.rs index 376b8ff..bf0be06 100644 --- a/src/perft.rs +++ b/src/perft.rs @@ -27,8 +27,6 @@ pub fn perftree_script() { let mut game = crate::fen::from_fen(fen).expect("Invalid FEN string"); let (mut nodes, depth): (u64, u8) = (0, MAX_DEPTH); driver(&mut game, &mut nodes, depth); - println!(); - println!("{}", nodes) } use std::collections::HashMap;