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 KNIGHT_ATTACKS: LazyLock<[Bitboard; 64]> = LazyLock::new(init_knight_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 ROOK_ATTACKS: LazyLock<HashMap<usize, HashMap<usize, u64>>> =
LazyLock::new(init_rook_attacks);
static BISHOP_ATTACKS: LazyLock<Vec<Vec<Bitboard>>> = LazyLock::new(init_bishop_attacks);
static ROOK_ATTACKS: LazyLock<Vec<Vec<Bitboard>>> = LazyLock::new(init_rook_attacks);
const fn pawn_attacks(bitboard: Bitboard, color: Color) -> Bitboard {
let mut attacks = EMPTY;
@@ -86,7 +85,7 @@ const fn king_attacks(bitboard: Bitboard) -> Bitboard {
attacks
}
pub fn mask_bishop_attacks(bitboard: Bitboard) -> Bitboard {
fn mask_bishop_attacks(bitboard: Bitboard) -> Bitboard {
let mut attacks = EMPTY;
let (rank_dst, file_dst) = bitboard_to_coords(bitboard);
@@ -109,7 +108,7 @@ pub fn mask_bishop_attacks(bitboard: Bitboard) -> Bitboard {
attacks
}
pub fn mask_rook_attacks(bitboard: Bitboard) -> Bitboard {
fn mask_rook_attacks(bitboard: Bitboard) -> Bitboard {
let mut attacks = EMPTY;
let (rank_dst, file_dst) = bitboard_to_coords(bitboard);
@@ -135,7 +134,7 @@ pub fn mask_rook_attacks(bitboard: Bitboard) -> Bitboard {
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 (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
}
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 (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
}
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;
for bit in 0..relevant_bits {
@@ -208,6 +207,7 @@ pub fn set_occupancy(idx: u64, relevant_bits: usize, mut attack_mask: Bitboard)
occupancy
}
#[inline(always)]
pub fn fetch_pawn_attacks(square: usize, color: Color) -> Bitboard {
match color {
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 {
KNIGHT_ATTACKS[square]
}
#[inline(always)]
pub fn fetch_king_attacks(square: usize) -> Bitboard {
KING_ATTACKS[square]
}
use crate::movegen::magic_bitboards::{BISHOP_MAGIC, ROOK_MAGIC};
#[inline(always)]
pub fn fetch_bishop_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard {
occupancy &= mask_bishop_attacks(square_to_bitboard_wrapping(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]
}
#[inline(always)]
pub fn fetch_rook_attacks(mut occupancy: Bitboard, square: usize) -> Bitboard {
occupancy &= mask_rook_attacks(square_to_bitboard_wrapping(square));
occupancy = occupancy.wrapping_mul(ROOK_MAGIC[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 {
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| {
[
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)))
}
pub fn init_king_attacks() -> [Bitboard; 64] {
fn init_king_attacks() -> [Bitboard; 64] {
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_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 {
bishop_masks[square] = mask_bishop_attacks(square_to_bitboard(square));
let attack_mask = bishop_masks[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 {
let occupancy = set_occupancy(idx, BISHOP_RELEVANT_BITS[square], attack_mask);
let magic_idx = (occupancy.wrapping_mul(BISHOP_MAGIC[square])
>> (64 - BISHOP_RELEVANT_BITS[square])) as usize;
let magic_idx =
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_atks.push(square_attacks);
}
bishop_atks
}
use std::collections::HashMap;
#[allow(clippy::large_stack_frames)]
pub fn init_rook_attacks() -> HashMap<usize, HashMap<usize, Bitboard>> {
fn init_rook_attacks() -> Vec<Vec<Bitboard>> {
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 {
rook_masks[square] = mask_rook_attacks(square_to_bitboard(square));
let attack_mask = rook_masks[square];
let occupancy_indices = square_to_bitboard(ROOK_RELEVANT_BITS[square]);
let mut square_map: HashMap<usize, Bitboard> = HashMap::new();
let mut square_attacks = vec![0; occupancy_indices as usize];
for idx in 0..occupancy_indices {
let occupancy = set_occupancy(idx, ROOK_RELEVANT_BITS[square], attack_mask);
let magic_idx = (occupancy.wrapping_mul(ROOK_MAGIC[square])
>> (64 - ROOK_RELEVANT_BITS[square])) as usize;
let occupancy = set_occupancy(idx as u64, ROOK_RELEVANT_BITS[square], attack_mask);
let magic_idx =
occupancy.wrapping_mul(ROOK_MAGIC[square]) >> (64 - ROOK_RELEVANT_BITS[square]);
square_map.insert(
magic_idx,
rook_attacks_on_the_fly(square_to_bitboard(square), occupancy),
);
square_attacks[magic_idx as usize] =
rook_attacks_on_the_fly(square_to_bitboard(square), occupancy);
}
rook_atks.insert(square, square_map);
rook_atks.push(square_attacks);
}
rook_atks
}
use std::{array, sync::LazyLock};
pub fn init_attacks() {
init_pawn_attacks();
init_knight_attacks();
init_king_attacks();
init_bishop_attacks();
init_rook_attacks();
let _ = &*PAWN_ATTACKS;
let _ = &*KNIGHT_ATTACKS;
let _ = &*KING_ATTACKS;
let _ = &*BISHOP_ATTACKS;
let _ = &*ROOK_ATTACKS;
}
#[cfg(test)]