From 6653d8034f6761a489a62c3acce76505ba881104 Mon Sep 17 00:00:00 2001 From: stefiosif Date: Sat, 29 Mar 2025 20:57:03 +0200 Subject: [PATCH] Improve attack table init, add inline to fetch fns --- src/movegen/attack_generator.rs | 77 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/src/movegen/attack_generator.rs b/src/movegen/attack_generator.rs index e70f22e..e881fdb 100644 --- a/src/movegen/attack_generator.rs +++ b/src/movegen/attack_generator.rs @@ -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> = LazyLock::new(init_bishop_attacks); -static ROOK_ATTACKS: LazyLock>> = - LazyLock::new(init_rook_attacks); +static BISHOP_ATTACKS: LazyLock>> = LazyLock::new(init_bishop_attacks); +static ROOK_ATTACKS: LazyLock>> = 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> { 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::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> { +fn init_rook_attacks() -> Vec> { let mut rook_masks: Vec = vec![0; 64]; - let mut rook_atks: HashMap> = HashMap::new(); + let mut rook_atks: Vec> = 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 = 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)]