From f27ea438e5a7088bd40356fcf02b7c69962003ab Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 22 Jan 2023 03:40:46 +0300 Subject: feat: compute pawn attacks --- src/attacks.rs | 67 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 19 deletions(-) (limited to 'src/attacks.rs') diff --git a/src/attacks.rs b/src/attacks.rs index 4562f25..0315ec9 100644 --- a/src/attacks.rs +++ b/src/attacks.rs @@ -1,4 +1,4 @@ -use crate::bitboard::Bitboard; +use crate::{bitboard::Bitboard, board::Color}; static NOT_A_FILE: Bitboard = 0xFEFEFEFEFEFEFEFE; static NOT_B_FILE: Bitboard = 0xFDFDFDFDFDFDFDFD; @@ -40,6 +40,7 @@ enum Direction { pub struct Attacks { pub knight: AttackTable, pub king: AttackTable, + pub pawn: [AttackTable; 2], pub first_rank_attacks: FirstRankAttacks, /// Should be indexed by Direction pub ray_attacks: [AttackTable; 8], @@ -52,28 +53,40 @@ impl Attacks { let king = Self::precompute_king_attacks(); let first_rank_attacks = Self::precompute_first_rank_attacks(); let ray_attacks = Self::precompute_ray_attacks(); + let pawn = Self::precompute_pawn_attacks(); Self { knight, king, + pawn, first_rank_attacks, ray_attacks, } } + fn precompute_pawn_attacks() -> [AttackTable; 2] { + let mut attacks = [[0; 64]; 2]; + for index in 0..64 { + let square = 1u64 << index; + attacks[Color::White as usize][index] = ((square & NOT_A_FILE) << 7) | ((square & NOT_H_FILE) << 9); + attacks[Color::Black as usize][index] = ((square & NOT_A_FILE) >> 9) | ((square & NOT_H_FILE) >> 7); + } + attacks + } + fn precompute_knight_attacks() -> AttackTable { let mut attacks = [0; 64]; for index in 0..64 { - let position = 1u64 << index; + let square = 1u64 << index; attacks[index] = - ((position & NOT_A_FILE & NOT_B_FILE) << 6) | - ((position & NOT_G_FILE & NOT_H_FILE) << 10) | - ((position & NOT_A_FILE) << 15) | - ((position & NOT_H_FILE) << 17) | - ((position & NOT_G_FILE & NOT_H_FILE) >> 6) | - ((position & NOT_A_FILE & NOT_B_FILE) >> 10) | - ((position & NOT_H_FILE) >> 15) | - ((position & NOT_A_FILE) >> 17); + ((square & NOT_A_FILE & NOT_B_FILE) << 6) | + ((square & NOT_G_FILE & NOT_H_FILE) << 10) | + ((square & NOT_A_FILE) << 15) | + ((square & NOT_H_FILE) << 17) | + ((square & NOT_G_FILE & NOT_H_FILE) >> 6) | + ((square & NOT_A_FILE & NOT_B_FILE) >> 10) | + ((square & NOT_H_FILE) >> 15) | + ((square & NOT_A_FILE) >> 17); } attacks } @@ -81,16 +94,16 @@ impl Attacks { fn precompute_king_attacks() -> AttackTable { let mut attacks = [0; 64]; for index in 0..64 { - let position = 1u64 << index; + let square = 1u64 << index; attacks[index] = - ((position & NOT_A_FILE) >> 1) | - ((position & NOT_A_FILE) << 7) | - ((position & NOT_A_FILE) >> 9) | - ((position & NOT_H_FILE) << 1) | - ((position & NOT_H_FILE) >> 7) | - ((position & NOT_H_FILE) << 9) | - (position << 8) | - (position >> 8); + ((square & NOT_A_FILE) >> 1) | + ((square & NOT_A_FILE) << 7) | + ((square & NOT_A_FILE) >> 9) | + ((square & NOT_H_FILE) << 1) | + ((square & NOT_H_FILE) >> 7) | + ((square & NOT_H_FILE) << 9) | + (square << 8) | + (square >> 8); } attacks } @@ -277,6 +290,22 @@ mod tests { use super::*; + #[test] + fn test_pawn_attacks() { + let attacks = Attacks::precompute_pawn_attacks(); + let square = Square::E4 as usize; + + let white_attacks = attacks[Color::White as usize][square]; + assert_eq!(white_attacks, 1 << Square::D5 as usize | 1 << Square::F5 as usize); + print(white_attacks); + + assert_eq!(attacks[Color::White as usize][Square::H4 as usize], 1 << Square::G5 as usize); + assert_eq!(attacks[Color::White as usize][Square::A4 as usize], 1 << Square::B5 as usize); + + assert_eq!(pop_count(attacks[Color::White as usize][Square::E8 as usize]), 0); + assert_eq!(pop_count(attacks[Color::Black as usize][Square::E1 as usize]), 0); + } + #[test] fn test_knight_attacks() { let attacks = Attacks::precompute_knight_attacks(); -- cgit v1.2.3