Improve attack table init, add inline to fetch fns

This commit is contained in:
stefiosif
2025-03-29 20:57:03 +02:00
parent d1bdc140a5
commit 6653d8034f

View File

@@ -35,9 +35,8 @@ pub const BISHOP_RELEVANT_BITS: [usize; 64] = [
static PAWN_ATTACKS: LazyLock<[[Bitboard; 2]; 64]> = LazyLock::new(init_pawn_attacks); static PAWN_ATTACKS: LazyLock<[[Bitboard; 2]; 64]> = LazyLock::new(init_pawn_attacks);
static KNIGHT_ATTACKS: LazyLock<[Bitboard; 64]> = LazyLock::new(init_knight_attacks); static KNIGHT_ATTACKS: LazyLock<[Bitboard; 64]> = LazyLock::new(init_knight_attacks);
static KING_ATTACKS: LazyLock<[Bitboard; 64]> = LazyLock::new(init_king_attacks); static KING_ATTACKS: LazyLock<[Bitboard; 64]> = LazyLock::new(init_king_attacks);
static BISHOP_ATTACKS: LazyLock<Box<[[Bitboard; 512]; 64]>> = LazyLock::new(init_bishop_attacks); static BISHOP_ATTACKS: LazyLock<Vec<Vec<Bitboard>>> = LazyLock::new(init_bishop_attacks);
static ROOK_ATTACKS: LazyLock<HashMap<usize, HashMap<usize, u64>>> = static ROOK_ATTACKS: LazyLock<Vec<Vec<Bitboard>>> = LazyLock::new(init_rook_attacks);
LazyLock::new(init_rook_attacks);
const fn pawn_attacks(bitboard: Bitboard, color: Color) -> Bitboard { const fn pawn_attacks(bitboard: Bitboard, color: Color) -> Bitboard {
let mut attacks = EMPTY; let mut attacks = EMPTY;
@@ -86,7 +85,7 @@ const fn king_attacks(bitboard: Bitboard) -> Bitboard {
attacks attacks
} }
pub fn mask_bishop_attacks(bitboard: Bitboard) -> Bitboard { fn mask_bishop_attacks(bitboard: Bitboard) -> Bitboard {
let mut attacks = EMPTY; let mut attacks = EMPTY;
let (rank_dst, file_dst) = bitboard_to_coords(bitboard); let (rank_dst, file_dst) = bitboard_to_coords(bitboard);
@@ -109,7 +108,7 @@ pub fn mask_bishop_attacks(bitboard: Bitboard) -> Bitboard {
attacks attacks
} }
pub fn mask_rook_attacks(bitboard: Bitboard) -> Bitboard { fn mask_rook_attacks(bitboard: Bitboard) -> Bitboard {
let mut attacks = EMPTY; let mut attacks = EMPTY;
let (rank_dst, file_dst) = bitboard_to_coords(bitboard); let (rank_dst, file_dst) = bitboard_to_coords(bitboard);
@@ -135,7 +134,7 @@ pub fn mask_rook_attacks(bitboard: Bitboard) -> Bitboard {
attacks attacks
} }
pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboard { fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboard {
let mut attacks = EMPTY; let mut attacks = EMPTY;
let (rank_dst, file_dst) = bitboard_to_coords(bitboard); let (rank_dst, file_dst) = bitboard_to_coords(bitboard);
@@ -164,7 +163,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo
attacks attacks
} }
pub fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboard { fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboard {
let mut attacks = EMPTY; let mut attacks = EMPTY;
let (rank_dst, file_dst) = bitboard_to_coords(bitboard); let (rank_dst, file_dst) = bitboard_to_coords(bitboard);
@@ -194,7 +193,7 @@ pub fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboar
attacks attacks
} }
pub fn set_occupancy(idx: u64, relevant_bits: usize, mut attack_mask: Bitboard) -> Bitboard { fn set_occupancy(idx: u64, relevant_bits: usize, mut attack_mask: Bitboard) -> Bitboard {
let mut occupancy = EMPTY; let mut occupancy = EMPTY;
for bit in 0..relevant_bits { for bit in 0..relevant_bits {
@@ -208,6 +207,7 @@ pub fn set_occupancy(idx: u64, relevant_bits: usize, mut attack_mask: Bitboard)
occupancy occupancy
} }
#[inline(always)]
pub fn fetch_pawn_attacks(square: usize, color: Color) -> Bitboard { pub fn fetch_pawn_attacks(square: usize, color: Color) -> Bitboard {
match color { match color {
Color::White => PAWN_ATTACKS[square][0], Color::White => PAWN_ATTACKS[square][0],
@@ -215,16 +215,19 @@ pub fn fetch_pawn_attacks(square: usize, color: Color) -> Bitboard {
} }
} }
#[inline(always)]
pub fn fetch_knight_attacks(square: usize) -> Bitboard { pub fn fetch_knight_attacks(square: usize) -> Bitboard {
KNIGHT_ATTACKS[square] KNIGHT_ATTACKS[square]
} }
#[inline(always)]
pub fn fetch_king_attacks(square: usize) -> Bitboard { pub fn fetch_king_attacks(square: usize) -> Bitboard {
KING_ATTACKS[square] KING_ATTACKS[square]
} }
use crate::movegen::magic_bitboards::{BISHOP_MAGIC, ROOK_MAGIC}; use crate::movegen::magic_bitboards::{BISHOP_MAGIC, ROOK_MAGIC};
#[inline(always)]
pub fn fetch_bishop_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard { pub fn fetch_bishop_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard {
occupancy &= mask_bishop_attacks(square_to_bitboard_wrapping(square)); occupancy &= mask_bishop_attacks(square_to_bitboard_wrapping(square));
occupancy = occupancy.wrapping_mul(BISHOP_MAGIC[square]); occupancy = occupancy.wrapping_mul(BISHOP_MAGIC[square]);
@@ -232,18 +235,20 @@ pub fn fetch_bishop_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard
BISHOP_ATTACKS[square][occupancy as usize] BISHOP_ATTACKS[square][occupancy as usize]
} }
#[inline(always)]
pub fn fetch_rook_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard { pub fn fetch_rook_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard {
occupancy &= mask_rook_attacks(square_to_bitboard_wrapping(square)); occupancy &= mask_rook_attacks(square_to_bitboard_wrapping(square));
occupancy = occupancy.wrapping_mul(ROOK_MAGIC[square]); occupancy = occupancy.wrapping_mul(ROOK_MAGIC[square]);
occupancy >>= 64 - ROOK_RELEVANT_BITS[square]; occupancy >>= 64 - ROOK_RELEVANT_BITS[square];
ROOK_ATTACKS[&square][&(occupancy as usize)] ROOK_ATTACKS[square][occupancy as usize]
} }
#[inline(always)]
pub fn fetch_queen_attacks(occupancy: Bitboard, square: usize) -> Bitboard { pub fn fetch_queen_attacks(occupancy: Bitboard, square: usize) -> Bitboard {
fetch_rook_attacks(occupancy, square) | fetch_bishop_attacks(occupancy, square) fetch_rook_attacks(occupancy, square) | fetch_bishop_attacks(occupancy, square)
} }
pub fn init_pawn_attacks() -> [[Bitboard; 2]; 64] { fn init_pawn_attacks() -> [[Bitboard; 2]; 64] {
array::from_fn(|square| { array::from_fn(|square| {
[ [
pawn_attacks(square_to_bitboard(square), Color::White), pawn_attacks(square_to_bitboard(square), Color::White),
@@ -252,74 +257,68 @@ pub fn init_pawn_attacks() -> [[Bitboard; 2]; 64] {
}) })
} }
pub fn init_knight_attacks() -> [Bitboard; 64] { fn init_knight_attacks() -> [Bitboard; 64] {
array::from_fn(|square| knight_attacks(square_to_bitboard(square))) array::from_fn(|square| knight_attacks(square_to_bitboard(square)))
} }
pub fn init_king_attacks() -> [Bitboard; 64] { fn init_king_attacks() -> [Bitboard; 64] {
array::from_fn(|square| king_attacks(square_to_bitboard(square))) array::from_fn(|square| king_attacks(square_to_bitboard(square)))
} }
pub fn init_bishop_attacks() -> Box<[[Bitboard; 512]; 64]> { fn init_bishop_attacks() -> Vec<Vec<Bitboard>> {
let mut bishop_masks = [0; 64]; let mut bishop_masks = [0; 64];
let mut bishop_atks: Box<[[Bitboard; 512]; 64]> = Box::new([[0; 512]; 64]); let mut bishop_atks: Vec<Vec<Bitboard>> = Vec::with_capacity(64);
for square in 0..64 { for square in 0..64 {
bishop_masks[square] = mask_bishop_attacks(square_to_bitboard(square)); bishop_masks[square] = mask_bishop_attacks(square_to_bitboard(square));
let attack_mask = bishop_masks[square]; let attack_mask = bishop_masks[square];
let occupancy_indices = square_to_bitboard(BISHOP_RELEVANT_BITS[square]); let occupancy_indices = square_to_bitboard(BISHOP_RELEVANT_BITS[square]);
let mut square_attacks = vec![0; occupancy_indices as usize];
for idx in 0..occupancy_indices { for idx in 0..occupancy_indices {
let occupancy = set_occupancy(idx, BISHOP_RELEVANT_BITS[square], attack_mask); let occupancy = set_occupancy(idx, BISHOP_RELEVANT_BITS[square], attack_mask);
let magic_idx = (occupancy.wrapping_mul(BISHOP_MAGIC[square]) let magic_idx =
>> (64 - BISHOP_RELEVANT_BITS[square])) as usize; occupancy.wrapping_mul(BISHOP_MAGIC[square]) >> (64 - BISHOP_RELEVANT_BITS[square]);
bishop_atks[square][magic_idx] = square_attacks[magic_idx as usize] =
bishop_attacks_on_the_fly(square_to_bitboard(square), occupancy); bishop_attacks_on_the_fly(square_to_bitboard(square), occupancy);
} }
bishop_atks.push(square_attacks);
} }
bishop_atks bishop_atks
} }
use std::collections::HashMap; fn init_rook_attacks() -> Vec<Vec<Bitboard>> {
#[allow(clippy::large_stack_frames)]
pub fn init_rook_attacks() -> HashMap<usize, HashMap<usize, Bitboard>> {
let mut rook_masks: Vec<Bitboard> = vec![0; 64]; let mut rook_masks: Vec<Bitboard> = vec![0; 64];
let mut rook_atks: HashMap<usize, HashMap<usize, Bitboard>> = HashMap::new(); let mut rook_atks: Vec<Vec<Bitboard>> = Vec::with_capacity(64);
for square in 0..64 { for square in 0..64 {
rook_masks[square] = mask_rook_attacks(square_to_bitboard(square)); rook_masks[square] = mask_rook_attacks(square_to_bitboard(square));
let attack_mask = rook_masks[square]; let attack_mask = rook_masks[square];
let occupancy_indices = square_to_bitboard(ROOK_RELEVANT_BITS[square]); let occupancy_indices = square_to_bitboard(ROOK_RELEVANT_BITS[square]);
let mut square_attacks = vec![0; occupancy_indices as usize];
let mut square_map: HashMap<usize, Bitboard> = HashMap::new();
for idx in 0..occupancy_indices { for idx in 0..occupancy_indices {
let occupancy = set_occupancy(idx, ROOK_RELEVANT_BITS[square], attack_mask); let occupancy = set_occupancy(idx as u64, ROOK_RELEVANT_BITS[square], attack_mask);
let magic_idx = (occupancy.wrapping_mul(ROOK_MAGIC[square]) let magic_idx =
>> (64 - ROOK_RELEVANT_BITS[square])) as usize; occupancy.wrapping_mul(ROOK_MAGIC[square]) >> (64 - ROOK_RELEVANT_BITS[square]);
square_map.insert( square_attacks[magic_idx as usize] =
magic_idx, rook_attacks_on_the_fly(square_to_bitboard(square), occupancy);
rook_attacks_on_the_fly(square_to_bitboard(square), occupancy),
);
} }
rook_atks.push(square_attacks);
rook_atks.insert(square, square_map);
} }
rook_atks rook_atks
} }
use std::{array, sync::LazyLock}; use std::{array, sync::LazyLock};
pub fn init_attacks() { pub fn init_attacks() {
init_pawn_attacks(); let _ = &*PAWN_ATTACKS;
init_knight_attacks(); let _ = &*KNIGHT_ATTACKS;
init_king_attacks(); let _ = &*KING_ATTACKS;
init_bishop_attacks(); let _ = &*BISHOP_ATTACKS;
init_rook_attacks(); let _ = &*ROOK_ATTACKS;
} }
#[cfg(test)] #[cfg(test)]