diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/attacks.rs | 28 | ||||
-rw-r--r-- | src/board.rs | 21 |
2 files changed, 33 insertions, 16 deletions
diff --git a/src/attacks.rs b/src/attacks.rs index 5399c96..6762bb3 100644 --- a/src/attacks.rs +++ b/src/attacks.rs @@ -45,6 +45,7 @@ pub struct Attacks { /// TODO: compute pawn attacks set-wise pub pawn: [AttackTable; 2], pub pawn_pushes: [AttackTable; 2], + pub pawn_double_pushes: [AttackTable; 2], pub first_rank_attacks: FirstRankAttacks, /// Should be indexed by Direction @@ -59,13 +60,14 @@ impl Attacks { let first_rank_attacks = Self::precompute_first_rank_attacks(); let ray_attacks = Self::precompute_ray_attacks(); let pawn = Self::precompute_pawn_attacks(); - let pawn_pushes = Self::precompute_pawn_pushes(); + let (pawn_pushes, pawn_double_pushes) = Self::precompute_pawn_pushes(); Self { knight, king, pawn, pawn_pushes, + pawn_double_pushes, first_rank_attacks, ray_attacks, } @@ -81,14 +83,19 @@ impl Attacks { attacks } - fn precompute_pawn_pushes() -> [AttackTable; 2] { + fn precompute_pawn_pushes() -> ([AttackTable; 2], [AttackTable; 2]) { let mut pushes = [[0; 64]; 2]; + let mut double_pushes = [[0; 64]; 2]; + for index in 0..64 { let square = 1u64 << index; - pushes[Color::White as usize][index] = (square << 8) | ((square & RANK_2) << 16); - pushes[Color::Black as usize][index] = (square >> 8) | ((square & RANK_6) >> 16); + pushes [Color::White as usize][index] = (square << 8); + double_pushes[Color::White as usize][index] = ((square & RANK_2) << 16); + + pushes [Color::Black as usize][index] = (square >> 8); + double_pushes[Color::Black as usize][index] = ((square & RANK_6) >> 16); } - pushes + (pushes, double_pushes) } fn precompute_knight_attacks() -> AttackTable { @@ -332,11 +339,16 @@ mod tests { #[test] fn test_pawn_pushes() { - let pushes = Attacks::precompute_pawn_pushes(); + let (pushes, double_pushes) = Attacks::precompute_pawn_pushes(); assert_eq!(pushes[Color::White as usize][Square::E4 as usize], Square::E5.to_bitboard()); - assert_eq!(pushes[Color::White as usize][Square::A2 as usize], Square::A3.to_bitboard() | Square::A4.to_bitboard()); + assert_eq!(pushes[Color::White as usize][Square::A2 as usize], Square::A3.to_bitboard()); assert_eq!(pushes[Color::Black as usize][Square::E4 as usize], Square::E3.to_bitboard()); - assert_eq!(pushes[Color::Black as usize][Square::H6 as usize], Square::H5.to_bitboard() | Square::H4.to_bitboard()); + assert_eq!(pushes[Color::Black as usize][Square::H6 as usize], Square::H5.to_bitboard()); + + assert_eq!(double_pushes[Color::White as usize][Square::E4 as usize], 0); + assert_eq!(double_pushes[Color::White as usize][Square::A2 as usize], Square::A4.to_bitboard()); + assert_eq!(double_pushes[Color::Black as usize][Square::E4 as usize], 0); + assert_eq!(double_pushes[Color::Black as usize][Square::H6 as usize], Square::H4.to_bitboard()); } #[test] diff --git a/src/board.rs b/src/board.rs index 625711e..24bdefa 100644 --- a/src/board.rs +++ b/src/board.rs @@ -144,7 +144,8 @@ impl Board { pub fn generate_moves(&self, color: Color) -> Vec<Move> { let mut moves = Vec::with_capacity(1024); let opponent_occupancy = self.color_occupancy(Color::from(1 - color as u8)); - let available_targets = opponent_occupancy | self.empty(); + let empty = self.empty(); + let available_targets = opponent_occupancy | empty; for (piece_type, piece) in self.pieces_by_color(color).iter().enumerate() { match PieceType::from(piece_type) { PieceType::Pawn => { @@ -152,14 +153,18 @@ impl Board { for target in serialize_bitboard(self.attacks.pawn[color as usize][source as usize] & opponent_occupancy) { moves.push(Move { source, target }); }; - } - for source in serialize_bitboard(*piece) { for target in serialize_bitboard(self.attacks.pawn_pushes[color as usize][source as usize] & available_targets) { - // Exclude double pushes in a monkey way - // TODO: properly rewrite this storing a separate bitboard for double pushes - if !((source as u8 / 8 == 1) && (target as u8 / 8 == 3) && (self.occupancy & (1 << (source as u8 + 8)) > 0)) { - moves.push(Move { source, target }); - } + moves.push(Move { source, target }); + }; + } + + let able_to_double_push_mask = match color { + Color::White => empty >> 8, + Color::Black => empty << 8, + }; + 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] & available_targets) { + moves.push(Move { source, target }); }; } } |