Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hyperbola Quintessence #81

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 42 additions & 50 deletions src/attacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::{
bitboard::Bitboard,
bootstrap::{
ATTACKS, BLACK_PAWN_ATTACKS, KING_ATTACKS, KNIGHT_ATTACKS, RAYS, WHITE_PAWN_ATTACKS,
DIAG_RANGE, ANTI_DIAG_RANGE, FILE_RANGE, RANK_RANGE,
},
color::Color,
magics,
Expand Down Expand Up @@ -54,10 +55,35 @@ pub fn king_attacks(sq: Square) -> Bitboard {
Bitboard(KING_ATTACKS[usize::from(sq)])
}

fn hyperbola(sq: Square, range: u64, occupied: Bitboard) -> Bitboard {
let forward = occupied & Bitboard(range);
let reverse = forward.flip_vertical();
let forward = Bitboard(forward.0.wrapping_sub(1 << usize::from(sq)));
let reverse = Bitboard(reverse.0.wrapping_sub(1 << usize::from(sq.flip_vertical())));
(forward ^ reverse.flip_vertical()) & range
}
fn file_attacks(sq: Square, occupied: Bitboard) -> Bitboard {
hyperbola(sq, FILE_RANGE[usize::from(sq)], occupied)
}
fn rank_attacks(sq: Square, occupied: Bitboard) -> Bitboard {
let range = RANK_RANGE[usize::from(sq)];
let forward = occupied & range;
let reverse = forward.rotate_180();
let forward = Bitboard(forward.0.wrapping_sub(1 << usize::from(sq)));
let reverse = Bitboard(reverse.0.wrapping_sub(1 << usize::from(sq.rotate_180())));
(forward ^ reverse.rotate_180()) & range
}
pub fn bishop_attacks(sq: Square, occupied: Bitboard) -> Bitboard {
hyperbola(sq, DIAG_RANGE[usize::from(sq)], occupied) ^ hyperbola(sq, ANTI_DIAG_RANGE[usize::from(sq)], occupied)
}
pub fn rook_attacks(sq: Square, occupied: Bitboard) -> Bitboard {
file_attacks(sq, occupied) ^ rank_attacks(sq, occupied)
}

static ROOK_MAGICS: [Magic; 64] = magics::ROOK_MAGICS;

/// Looks up attacks for a rook on `sq` with `occupied` squares.
#[inline]
/* #[inline]
pub fn rook_attacks(sq: Square, occupied: Bitboard) -> Bitboard {
let m = ROOK_MAGICS[usize::from(sq)];

Expand All @@ -69,29 +95,6 @@ pub fn rook_attacks(sq: Square, occupied: Bitboard) -> Bitboard {
Bitboard(unsafe { *ATTACKS.get_unchecked(idx) })
}

/// Gets the set of potential blocking squares for a rook on `sq`.
///
/// # Example
///
/// ```
/// use shakmaty::{attacks, Square};
///
/// let mask = attacks::rook_mask(Square::E8);
/// // 0 1 1 1 0 1 1 0
/// // . . . . 1 . . .
/// // . . . . 1 . . .
/// // . . . . 1 . . .
/// // . . . . 1 . . .
/// // . . . . 1 . . .
/// // . . . . 1 . . .
/// // . . . . 0 . . .
///
/// assert_eq!(mask.count(), 11);
#[inline]
pub fn rook_mask(sq: Square) -> Bitboard {
Bitboard(ROOK_MAGICS[usize::from(sq)].mask)
}

static BISHOP_MAGICS: [Magic; 64] = magics::BISHOP_MAGICS;

/// Looks up attacks for a bishop on `sq` with `occupied` squares.
Expand All @@ -105,31 +108,7 @@ pub fn bishop_attacks(sq: Square, occupied: Bitboard) -> Bitboard {
let idx = (m.factor.wrapping_mul(occupied.0 & m.mask) >> (64 - 9)) as usize + m.offset;
debug_assert!(idx < ATTACKS.len());
Bitboard(unsafe { *ATTACKS.get_unchecked(idx) })
}

/// Gets the set of potential blocking squares for a bishop on `sq`.
///
/// # Example
///
/// ```
/// use shakmaty::{attacks, Square};
///
/// let mask = attacks::bishop_mask(Square::D5);
/// // 0 . . . . . 0 .
/// // . 1 . . . 1 . .
/// // . . 1 . 1 . . .
/// // . . . 0 . . . .
/// // . . 1 . 1 . . .
/// // . 1 . . . 1 . .
/// // 0 . . . . . 1 .
/// // . . . . . . . 0
///
/// assert_eq!(mask.count(), 9);
/// ```
#[inline]
pub fn bishop_mask(sq: Square) -> Bitboard {
Bitboard(BISHOP_MAGICS[usize::from(sq)].mask)
}
} */

/// Looks up attacks for a queen on `sq` with `occupied` squares.
#[inline]
Expand Down Expand Up @@ -169,7 +148,20 @@ pub fn attacks(sq: Square, piece: Piece, occupied: Bitboard) -> Bitboard {
/// ```
#[inline]
pub fn ray(a: Square, b: Square) -> Bitboard {
Bitboard(RAYS[usize::from(a)][usize::from(b)])
if a == b {
Bitboard::EMPTY
} else if a.rank() == b.rank() {
Bitboard::from_rank(a.rank())
} else if a.file() == b.file() {
Bitboard::from_file(a.file())
} else if Bitboard(DIAG_RANGE[usize::from(a)]).contains(b) {
Bitboard(DIAG_RANGE[usize::from(a)]).with(a)
} else if Bitboard(ANTI_DIAG_RANGE[usize::from(a)]).contains(b) {
Bitboard(ANTI_DIAG_RANGE[usize::from(a)]).with(a)
} else {
Bitboard::EMPTY
}
//Bitboard(RAYS[usize::from(a)][usize::from(b)])
}

/// The squares between the two squares (bounds not included), or an empty
Expand Down
30 changes: 20 additions & 10 deletions src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ const KNIGHT_DELTAS: [i32; 8] = [17, 15, 10, 6, -17, -15, -10, -6];
const WHITE_PAWN_DELTAS: [i32; 2] = [7, 9];
const BLACK_PAWN_DELTAS: [i32; 2] = [-7, -9];

const FILE_DELTAS: [i32; 2] = [8, -8];
const RANK_DELTAS: [i32; 2] = [1, -1];
const DIAG_DELTAS: [i32; 2] = [9, -9];
const ANTI_DIAG_DELTAS: [i32; 2] = [7, -7];

const fn sliding_attacks(square: i32, occupied: u64, deltas: &[i32]) -> u64 {
let mut attack = 0;

Expand All @@ -35,22 +40,31 @@ const fn sliding_attacks(square: i32, occupied: u64, deltas: &[i32]) -> u64 {
attack
}

const fn init_stepping_attacks(deltas: &[i32]) -> [u64; 64] {
const fn init_sliding_attacks(occupied: u64, deltas: &[i32]) -> [u64; 64] {
let mut table = [0; 64];
let mut sq = 0;
while sq < 64 {
table[sq] = sliding_attacks(sq as i32, !0, deltas);
table[sq] = sliding_attacks(sq as i32, occupied, deltas);
sq += 1;
}
table
}

const fn init_stepping_attacks(deltas: &[i32]) -> [u64; 64] {
init_sliding_attacks(!0, deltas)
}

pub static KNIGHT_ATTACKS: [u64; 64] = init_stepping_attacks(&KNIGHT_DELTAS);
pub static KING_ATTACKS: [u64; 64] = init_stepping_attacks(&KING_DELTAS);
pub static WHITE_PAWN_ATTACKS: [u64; 64] = init_stepping_attacks(&WHITE_PAWN_DELTAS);
pub static BLACK_PAWN_ATTACKS: [u64; 64] = init_stepping_attacks(&BLACK_PAWN_DELTAS);

const fn init_rays() -> [[u64; 64]; 64] {
pub static FILE_RANGE: [u64; 64] = init_sliding_attacks(0, &FILE_DELTAS);
pub static RANK_RANGE: [u64; 64] = init_sliding_attacks(0, &RANK_DELTAS);
pub static DIAG_RANGE: [u64; 64] = init_sliding_attacks(0, &DIAG_DELTAS);
pub static ANTI_DIAG_RANGE: [u64; 64] = init_sliding_attacks(0, &ANTI_DIAG_DELTAS);

pub static RAYS: [[u64; 64]; 64] = {
let mut table = [[0; 64]; 64];
let mut a = 0;
while a < 64 {
Expand Down Expand Up @@ -86,11 +100,9 @@ const fn init_rays() -> [[u64; 64]; 64] {
a += 1;
}
table
}

pub static RAYS: [[u64; 64]; 64] = init_rays();
};

const fn init_magics() -> [u64; 88772] {
pub static ATTACKS: [u64; 88772] = {
let mut table = [0; 88772];
let mut square = 0;
while square < 64 {
Expand Down Expand Up @@ -125,6 +137,4 @@ const fn init_magics() -> [u64; 88772] {
square += 1;
}
table
}

pub static ATTACKS: [u64; 88772] = init_magics();
};