use crate::utils::{lower_ones, upper_ones};
use crate::Direction::*;
pub const RAY_ATTACKS: [[u64; 8]; 64] = ray_attacks();
pub const ROOK_ATTACKS: [[u64; 4]; 64] = piece_attacks().0;
pub const BISHOP_ATTACKS: [[u64; 4]; 64] = piece_attacks().1;
#[inline]
pub const fn ray_attacks() -> [[u64; 8]; 64] {
let mut rays = [[0u64; 8]; 64];
let mut north = 0x0101010101010100_u64;
let mut sq = 0;
while sq < 64 {
rays[sq][North as usize] = north;
north <<= 1;
let one = 1_u64;
rays[sq][East as usize] = 2 * ((one << (sq | 7)) - (one << sq));
rays[sq][West as usize] = (one << sq) - (one << (sq & 56));
rays[sq][South as usize] = 0x0080808080808080_u64 >> (sq ^ 63);
(rays[sq][SouthWest as usize], rays[sq][NorthEast as usize]) = ray_attacks_diag(sq);
(rays[sq][SouthEast as usize], rays[sq][NorthWest as usize]) = ray_attacks_antidiag(sq);
sq += 1;
}
rays
}
#[inline]
pub const fn piece_attacks() -> ([[u64; 4]; 64], [[u64; 4]; 64]) {
let mut bishop = [[0u64; 4]; 64];
let mut rook = [[0u64; 4]; 64];
let mut north = 0x0101010101010100_u64;
let mut sq = 0;
while sq < 64 {
rook[sq][0] = north;
north <<= 1;
let one = 1_u64;
rook[sq][1] = 2 * ((one << (sq | 7)) - (one << sq));
rook[sq][2] = (one << sq) - (one << (sq & 56));
rook[sq][3] = 0x0080808080808080_u64 >> (sq ^ 63);
(bishop[sq][0], bishop[sq][1]) = ray_attacks_diag(sq);
(bishop[sq][2], bishop[sq][3]) = ray_attacks_antidiag(sq);
sq += 1;
}
(rook, bishop)
}
#[inline]
pub const fn ray_attacks_diag(sq: usize) -> (u64, u64) {
let maindia = 0x8040201008040201_u64;
let diag = (8 * (sq as isize & 7)).wrapping_sub(sq as isize & 56);
let north = -diag & (diag >> 31);
let south = diag & (-diag >> 31);
let diags = (maindia >> south) << north;
let south_west = lower_ones(sq as u8) & diags;
let north_east = upper_ones(sq as u8) & diags;
(south_west, north_east)
}
#[inline]
pub const fn ray_attacks_antidiag(sq: usize) -> (u64, u64) {
let maindia = 0x0102040810204080_u64;
let antidiag: isize = 7 - (sq as isize & 7) - (sq as isize >> 3);
let antidiags = if antidiag >= 0 {
maindia >> (antidiag * 8)
} else {
maindia << (-antidiag * 8)
};
let south_east = lower_ones(sq as u8) & antidiags;
let north_west = upper_ones(sq as u8) & antidiags;
(south_east, north_west)
}