Improve attack table init, add inline to fetch fns
This commit is contained in:
@@ -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)]
|
||||||
|
|||||||
Reference in New Issue
Block a user