wip
This commit is contained in:
parent
149aa841c9
commit
68f068989d
3 changed files with 103 additions and 126 deletions
40
src/board.rs
40
src/board.rs
|
|
@ -9,22 +9,23 @@ macro_rules! container {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
impl<T> $b<T> {
|
impl<T> $b<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new<F>(f: F) -> Self
|
pub const fn new(inner: [T; $n]) -> Self {
|
||||||
|
Self(inner)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn with<F>(f: F) -> Self
|
||||||
where
|
where
|
||||||
F: FnMut($a) -> T,
|
F: FnMut($a) -> T,
|
||||||
{
|
{
|
||||||
Self($a::all().map(f))
|
Self($a::all().map(f))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, k: $a) -> &T {
|
pub const fn get(&self, k: $a) -> &T {
|
||||||
unsafe { self.0.get_unchecked(k as usize) }
|
&self.0[k as usize]
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_mut(&mut self, k: $a) -> &mut T {
|
pub const fn get_mut(&mut self, k: $a) -> &mut T {
|
||||||
unsafe { self.0.get_unchecked_mut(k as usize) }
|
&mut self.0[k as usize]
|
||||||
}
|
|
||||||
pub(crate) const fn get_const(&self, k: $a) -> &T {
|
|
||||||
&self.0[k as usize]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -519,7 +520,11 @@ pub(crate) struct ByRole<T>(pub(crate) [T; 6]);
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
impl<T> ByRole<T> {
|
impl<T> ByRole<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new<F>(f: F) -> Self
|
pub const fn new(inner: [T; 6]) -> Self {
|
||||||
|
Self(inner)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn with<F>(f: F) -> Self
|
||||||
where
|
where
|
||||||
F: FnMut(Role) -> T,
|
F: FnMut(Role) -> T,
|
||||||
{
|
{
|
||||||
|
|
@ -527,13 +532,13 @@ impl<T> ByRole<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, kind: Role) -> &T {
|
pub const fn get(&self, role: Role) -> &T {
|
||||||
unsafe { self.0.get_unchecked((kind as usize).unchecked_sub(1)) }
|
&self.0[role as usize - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_mut(&mut self, kind: Role) -> &mut T {
|
pub const fn get_mut(&mut self, role: Role) -> &mut T {
|
||||||
unsafe { self.0.get_unchecked_mut((kind as usize).unchecked_sub(1)) }
|
&mut self.0[role as usize - 1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -604,15 +609,6 @@ impl Direction {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate) const fn from_index(index: u8) -> Option<Self> {
|
|
||||||
if index < 8 {
|
|
||||||
Some(unsafe { Self::transmute(index) })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
const unsafe fn transmute(value: u8) -> Self {
|
const unsafe fn transmute(value: u8) -> Self {
|
||||||
debug_assert!(value < 8);
|
debug_assert!(value < 8);
|
||||||
|
|
|
||||||
185
src/lookup.rs
185
src/lookup.rs
|
|
@ -2,6 +2,8 @@ use crate::bitboard::*;
|
||||||
use crate::board::*;
|
use crate::board::*;
|
||||||
use crate::magics::*;
|
use crate::magics::*;
|
||||||
|
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
macro_rules! loop_subsets {
|
macro_rules! loop_subsets {
|
||||||
($premask: ident, $subset: ident, $e: expr) => {{
|
($premask: ident, $subset: ident, $e: expr) => {{
|
||||||
let mut $subset: u64 = 0;
|
let mut $subset: u64 = 0;
|
||||||
|
|
@ -16,8 +18,8 @@ macro_rules! loop_subsets {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! by_color {
|
macro_rules! by_color {
|
||||||
($c: ident, $e: expr) => {{
|
($c: ident, $e: expr) => {
|
||||||
ByColor([
|
ByColor::new([
|
||||||
{
|
{
|
||||||
let $c = Color::White;
|
let $c = Color::White;
|
||||||
$e
|
$e
|
||||||
|
|
@ -27,21 +29,21 @@ macro_rules! by_color {
|
||||||
$e
|
$e
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! by_square {
|
macro_rules! by_square {
|
||||||
($sq: ident, $init: expr, $e: expr) => {{
|
($s: ident, $t: ty, $e: expr) => {{
|
||||||
let mut res = [$init; 64];
|
let mut res = [MaybeUninit::uninit(); 64];
|
||||||
let mut $sq: u8 = 0;
|
let mut $s: u8 = 0;
|
||||||
while $sq < 64 {
|
while $s < 64 {
|
||||||
res[$sq as usize] = {
|
res[$s as usize].write({
|
||||||
let $sq = Square::from_index($sq).unwrap();
|
let $s = Square::from_index($s).unwrap();
|
||||||
$e
|
$e
|
||||||
};
|
});
|
||||||
$sq += 1;
|
$s += 1;
|
||||||
}
|
}
|
||||||
BySquare(res)
|
BySquare::new(unsafe { std::mem::transmute::<_, [$t;64]>(res) })
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,24 +97,19 @@ macro_rules! loop_all_directions {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! by_direction {
|
macro_rules! by_direction {
|
||||||
($d: ident, $e: expr) => {{
|
($d: ident, $t: ty, $e: expr) => {{
|
||||||
let mut res = [Bitboard(0); 8];
|
let mut res = [MaybeUninit::uninit(); 8];
|
||||||
let mut $d: u8 = 0;
|
loop_all_directions!($d, {
|
||||||
while $d < 8 {
|
res[$d as u8 as usize].write($e);
|
||||||
res[$d as usize] = {
|
});
|
||||||
let $d = Direction::from_index($d).unwrap();
|
ByDirection(unsafe { std::mem::transmute::<_, [$t;8]>(res) })
|
||||||
$e
|
|
||||||
};
|
|
||||||
$d += 1;
|
|
||||||
}
|
|
||||||
ByDirection(res)
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
const RAYS: BySquare<ByDirection<Bitboard>> = by_square!(
|
const RAYS: BySquare<ByDirection<Bitboard>> = by_square!(
|
||||||
square,
|
square,
|
||||||
ByDirection([Bitboard(0); 8]),
|
ByDirection<Bitboard>,
|
||||||
by_direction!(direction, {
|
by_direction!(direction, Bitboard, {
|
||||||
let mut square = square;
|
let mut square = square;
|
||||||
let mut res = 0;
|
let mut res = 0;
|
||||||
while let Some(x) = square.trans(direction) {
|
while let Some(x) = square.trans(direction) {
|
||||||
|
|
@ -123,11 +120,11 @@ const RAYS: BySquare<ByDirection<Bitboard>> = by_square!(
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const LINES: BySquare<BySquare<Bitboard>> = by_square!(a, BySquare([Bitboard(0); 64]), {
|
const LINES: BySquare<BySquare<Bitboard>> = by_square!(a, BySquare<Bitboard>, {
|
||||||
by_square!(b, Bitboard(0), {
|
by_square!(b, Bitboard, {
|
||||||
let mut res = Bitboard(0);
|
let mut res = Bitboard(0);
|
||||||
loop_all_directions!(d, {
|
loop_all_directions!(d, {
|
||||||
let r = *RAYS.get_const(a).get_const(d);
|
let r = *RAYS.get(a).get(d);
|
||||||
if r.contains(b) {
|
if r.contains(b) {
|
||||||
res = r;
|
res = r;
|
||||||
}
|
}
|
||||||
|
|
@ -136,20 +133,20 @@ const LINES: BySquare<BySquare<Bitboard>> = by_square!(a, BySquare([Bitboard(0);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const SEGMENTS: BySquare<BySquare<Bitboard>> = by_square!(a, BySquare([Bitboard(0); 64]), {
|
const SEGMENTS: BySquare<BySquare<Bitboard>> = by_square!(a, BySquare<Bitboard>, {
|
||||||
by_square!(b, Bitboard(0), {
|
by_square!(b, Bitboard, {
|
||||||
let mut res = 0;
|
let mut res = 0;
|
||||||
loop_all_directions!(d, {
|
loop_all_directions!(d, {
|
||||||
let r = *RAYS.get_const(a).get_const(d);
|
let r = *RAYS.get(a).get(d);
|
||||||
if r.contains(b) {
|
if r.contains(b) {
|
||||||
res = r.0 & !RAYS.get_const(b).get_const(d).0;
|
res = r.0 & !RAYS.get(b).get(d).0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Bitboard(res | b.bitboard().0)
|
Bitboard(res | b.bitboard().0)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const KING_MOVES: BySquare<Bitboard> = by_square!(sq, Bitboard(0), {
|
const KING_MOVES: BySquare<Bitboard> = by_square!(sq, Bitboard, {
|
||||||
let mut res = 0;
|
let mut res = 0;
|
||||||
loop_all_directions!(d, {
|
loop_all_directions!(d, {
|
||||||
if let Some(x) = sq.trans(d) {
|
if let Some(x) = sq.trans(d) {
|
||||||
|
|
@ -159,7 +156,7 @@ const KING_MOVES: BySquare<Bitboard> = by_square!(sq, Bitboard(0), {
|
||||||
Bitboard(res)
|
Bitboard(res)
|
||||||
});
|
});
|
||||||
|
|
||||||
const KNIGHT_MOVES: BySquare<Bitboard> = by_square!(s, Bitboard(0), {
|
const KNIGHT_MOVES: BySquare<Bitboard> = by_square!(s, Bitboard, {
|
||||||
let mut res = Bitboard(0);
|
let mut res = Bitboard(0);
|
||||||
if let Some(s) = s.trans(Direction::North) {
|
if let Some(s) = s.trans(Direction::North) {
|
||||||
if let Some(s) = s.trans(Direction::NorthEast) {
|
if let Some(s) = s.trans(Direction::NorthEast) {
|
||||||
|
|
@ -202,7 +199,7 @@ const PAWN_ATTACKS: ByColor<BySquare<Bitboard>> = {
|
||||||
Color::White => Direction::North,
|
Color::White => Direction::North,
|
||||||
Color::Black => Direction::South,
|
Color::Black => Direction::South,
|
||||||
};
|
};
|
||||||
by_square!(square, Bitboard(0), {
|
by_square!(square, Bitboard, {
|
||||||
let mut res = Bitboard(0);
|
let mut res = Bitboard(0);
|
||||||
if let Some(square) = square.trans(direction) {
|
if let Some(square) = square.trans(direction) {
|
||||||
if let Some(s) = square.trans(Direction::East) {
|
if let Some(s) = square.trans(Direction::East) {
|
||||||
|
|
@ -218,7 +215,7 @@ const PAWN_ATTACKS: ByColor<BySquare<Bitboard>> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const fn blocked_ray(square: Square, direction: Direction, blockers: Bitboard) -> Bitboard {
|
const fn blocked_ray(square: Square, direction: Direction, blockers: Bitboard) -> Bitboard {
|
||||||
let ray = *RAYS.get_const(square).get_const(direction);
|
let ray = *RAYS.get(square).get(direction);
|
||||||
let blockers = Bitboard(blockers.0 & ray.0);
|
let blockers = Bitboard(blockers.0 & ray.0);
|
||||||
let square = if (direction as u8) < 4 {
|
let square = if (direction as u8) < 4 {
|
||||||
Bitboard::first(&blockers)
|
Bitboard::first(&blockers)
|
||||||
|
|
@ -227,7 +224,7 @@ const fn blocked_ray(square: Square, direction: Direction, blockers: Bitboard) -
|
||||||
};
|
};
|
||||||
match square {
|
match square {
|
||||||
None => ray,
|
None => ray,
|
||||||
Some(square) => Bitboard(ray.0 & !RAYS.get_const(square).get_const(direction).0),
|
Some(square) => Bitboard(ray.0 & !RAYS.get(square).get(direction).0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,7 +256,7 @@ pub(crate) fn pawn_attack(color: Color, square: Square) -> Bitboard {
|
||||||
const fn bishop_premask(square: Square) -> Bitboard {
|
const fn bishop_premask(square: Square) -> Bitboard {
|
||||||
let mut premask = 0;
|
let mut premask = 0;
|
||||||
loop_bishop_directions!(direction, {
|
loop_bishop_directions!(direction, {
|
||||||
premask |= RAYS.get_const(square).get_const(direction).0;
|
premask |= RAYS.get(square).get(direction).0;
|
||||||
});
|
});
|
||||||
premask &= !Rank::First.bitboard().0;
|
premask &= !Rank::First.bitboard().0;
|
||||||
premask &= !Rank::Eighth.bitboard().0;
|
premask &= !Rank::Eighth.bitboard().0;
|
||||||
|
|
@ -269,78 +266,62 @@ const fn bishop_premask(square: Square) -> Bitboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn rook_premask(square: Square) -> Bitboard {
|
const fn rook_premask(square: Square) -> Bitboard {
|
||||||
let rays = RAYS.get_const(square);
|
let rays = RAYS.get(square);
|
||||||
let mut premask = 0;
|
let mut premask = 0;
|
||||||
premask |= rays.get_const(Direction::East).0 & !File::H.bitboard().0;
|
premask |= rays.get(Direction::East).0 & !File::H.bitboard().0;
|
||||||
premask |= rays.get_const(Direction::North).0 & !Rank::Eighth.bitboard().0;
|
premask |= rays.get(Direction::North).0 & !Rank::Eighth.bitboard().0;
|
||||||
premask |= rays.get_const(Direction::West).0 & !File::A.bitboard().0;
|
premask |= rays.get(Direction::West).0 & !File::A.bitboard().0;
|
||||||
premask |= rays.get_const(Direction::South).0 & !Rank::First.bitboard().0;
|
premask |= rays.get(Direction::South).0 & !Rank::First.bitboard().0;
|
||||||
Bitboard(premask)
|
Bitboard(premask)
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAGICS: (BySquare<Magic>, BySquare<Magic>, usize) = {
|
const MAGICS: (BySquare<Magic>, BySquare<Magic>, usize) = {
|
||||||
let mut len: usize = 0;
|
let mut len: usize = 0;
|
||||||
(
|
(
|
||||||
by_square!(
|
by_square!(square, Magic, {
|
||||||
square,
|
let premask = bishop_premask(square).0;
|
||||||
Magic {
|
let factor = bishop_factor(square);
|
||||||
premask: Bitboard(0),
|
let mut i = usize::MAX;
|
||||||
factor: 0,
|
let mut j = 0;
|
||||||
offset: 0
|
loop_subsets!(premask, blockers, {
|
||||||
},
|
let cur = hash(BISHOP_SHR, factor, Bitboard(blockers | !premask));
|
||||||
{
|
if cur < i {
|
||||||
let premask = bishop_premask(square).0;
|
i = cur;
|
||||||
let factor = bishop_factor(square);
|
|
||||||
let mut i = usize::MAX;
|
|
||||||
let mut j = 0;
|
|
||||||
loop_subsets!(premask, blockers, {
|
|
||||||
let cur = hash(BISHOP_SHR, factor, Bitboard(blockers | !premask));
|
|
||||||
if cur < i {
|
|
||||||
i = cur;
|
|
||||||
}
|
|
||||||
if cur > j {
|
|
||||||
j = cur;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let offset = len as isize - i as isize;
|
|
||||||
len += j - i + 1;
|
|
||||||
Magic {
|
|
||||||
premask: Bitboard(!premask),
|
|
||||||
factor,
|
|
||||||
offset,
|
|
||||||
}
|
}
|
||||||
}
|
if cur > j {
|
||||||
),
|
j = cur;
|
||||||
by_square!(
|
|
||||||
square,
|
|
||||||
Magic {
|
|
||||||
premask: Bitboard(0),
|
|
||||||
factor: 0,
|
|
||||||
offset: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
let premask = rook_premask(square).0;
|
|
||||||
let factor = rook_factor(square);
|
|
||||||
let mut i = usize::MAX;
|
|
||||||
let mut j = 0;
|
|
||||||
loop_subsets!(premask, blockers, {
|
|
||||||
let cur = hash(ROOK_SHR, factor, Bitboard(blockers | !premask));
|
|
||||||
if cur < i {
|
|
||||||
i = cur;
|
|
||||||
}
|
|
||||||
if cur > j {
|
|
||||||
j = cur;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let offset = len as isize - i as isize;
|
|
||||||
len += j - i + 1;
|
|
||||||
Magic {
|
|
||||||
premask: Bitboard(!premask),
|
|
||||||
factor,
|
|
||||||
offset,
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
let offset = len as isize - i as isize;
|
||||||
|
len += j - i + 1;
|
||||||
|
Magic {
|
||||||
|
premask: Bitboard(!premask),
|
||||||
|
factor,
|
||||||
|
offset,
|
||||||
}
|
}
|
||||||
),
|
}),
|
||||||
|
by_square!(square, Magic, {
|
||||||
|
let premask = rook_premask(square).0;
|
||||||
|
let factor = rook_factor(square);
|
||||||
|
let mut i = usize::MAX;
|
||||||
|
let mut j = 0;
|
||||||
|
loop_subsets!(premask, blockers, {
|
||||||
|
let cur = hash(ROOK_SHR, factor, Bitboard(blockers | !premask));
|
||||||
|
if cur < i {
|
||||||
|
i = cur;
|
||||||
|
}
|
||||||
|
if cur > j {
|
||||||
|
j = cur;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let offset = len as isize - i as isize;
|
||||||
|
len += j - i + 1;
|
||||||
|
Magic {
|
||||||
|
premask: Bitboard(!premask),
|
||||||
|
factor,
|
||||||
|
offset,
|
||||||
|
}
|
||||||
|
}),
|
||||||
len,
|
len,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
@ -360,7 +341,7 @@ const MAGIC_TABLE: [Bitboard; MAGICS.2] = {
|
||||||
premask,
|
premask,
|
||||||
factor,
|
factor,
|
||||||
offset,
|
offset,
|
||||||
} = *MAGICS.0.get_const(square);
|
} = *MAGICS.0.get(square);
|
||||||
let premask = !premask.0;
|
let premask = !premask.0;
|
||||||
loop_subsets!(premask, blockers, {
|
loop_subsets!(premask, blockers, {
|
||||||
let index = (hash(BISHOP_SHR, factor, Bitboard(blockers | !premask)) as isize + offset)
|
let index = (hash(BISHOP_SHR, factor, Bitboard(blockers | !premask)) as isize + offset)
|
||||||
|
|
@ -378,7 +359,7 @@ const MAGIC_TABLE: [Bitboard; MAGICS.2] = {
|
||||||
premask,
|
premask,
|
||||||
factor,
|
factor,
|
||||||
offset,
|
offset,
|
||||||
} = *MAGICS.1.get_const(square);
|
} = *MAGICS.1.get(square);
|
||||||
let premask = !premask.0;
|
let premask = !premask.0;
|
||||||
loop_subsets!(premask, blockers, {
|
loop_subsets!(premask, blockers, {
|
||||||
let index =
|
let index =
|
||||||
|
|
|
||||||
|
|
@ -490,12 +490,12 @@ impl Setup {
|
||||||
let n = n_b_k ^ b ^ k;
|
let n = n_b_k ^ b ^ k;
|
||||||
let r = r_q_k ^ q ^ k;
|
let r = r_q_k ^ q ^ k;
|
||||||
let p = p_b_q ^ b ^ q;
|
let p = p_b_q ^ b ^ q;
|
||||||
ByColor::new(|color| {
|
ByColor::with(|color| {
|
||||||
let mask = match color {
|
let mask = match color {
|
||||||
Color::White => w,
|
Color::White => w,
|
||||||
Color::Black => !w,
|
Color::Black => !w,
|
||||||
};
|
};
|
||||||
ByRole::new(|kind| {
|
ByRole::with(|kind| {
|
||||||
mask & match kind {
|
mask & match kind {
|
||||||
Role::Pawn => p,
|
Role::Pawn => p,
|
||||||
Role::Knight => n,
|
Role::Knight => n,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue