diff --git a/src/lookup.rs b/src/lookup.rs index dcd6fef..2761923 100644 --- a/src/lookup.rs +++ b/src/lookup.rs @@ -2,78 +2,42 @@ use crate::bitboard::*; use crate::board::*; use crate::magics::*; -macro_rules! loop_bishop_directions { - ($d: ident, $body: expr) => {{ - { - let $d = Direction::NorthEast; - $body +macro_rules! loop_subsets { + ($premask: ident, $subset: ident, $e: expr) => {{ + let mut $subset: u64 = 0; + loop { + $subset = $subset.wrapping_sub($premask) & $premask; + $e + if $subset == 0 { + break; + } } - { - let $d = Direction::NorthWest; - $body - } - { - let $d = Direction::SouthWest; - $body - } - { - let $d = Direction::SouthEast; - $body - } - }}; -} - -macro_rules! loop_rook_directions { - ($d: ident, $body: expr) => {{ - { - let $d = Direction::East; - $body - } - { - let $d = Direction::North; - $body - } - { - let $d = Direction::West; - $body - } - { - let $d = Direction::South; - $body - } - }}; -} - -macro_rules! loop_all_directions { - ($d: ident, $body: expr) => {{ - loop_bishop_directions!($d, $body); - loop_rook_directions!($d, $body); }}; } macro_rules! by_color { - ($c: ident, $body: expr) => {{ + ($c: ident, $e: expr) => {{ ByColor([ { let $c = Color::White; - $body + $e }, { let $c = Color::Black; - $body + $e }, ]) }}; } macro_rules! by_square { - ($sq: ident, $init: expr, $body: expr) => {{ + ($sq: ident, $init: expr, $e: expr) => {{ let mut res = [$init; 64]; let mut $sq: u8 = 0; while $sq < 64 { res[$sq as usize] = { let $sq = Square::new($sq).unwrap(); - $body + $e }; $sq += 1; } @@ -81,14 +45,63 @@ macro_rules! by_square { }}; } +macro_rules! loop_bishop_directions { + ($d: ident, $e: expr) => {{ + { + let $d = Direction::NorthEast; + $e + } + { + let $d = Direction::NorthWest; + $e + } + { + let $d = Direction::SouthWest; + $e + } + { + let $d = Direction::SouthEast; + $e + } + }}; +} + +macro_rules! loop_rook_directions { + ($d: ident, $e: expr) => {{ + { + let $d = Direction::East; + $e + } + { + let $d = Direction::North; + $e + } + { + let $d = Direction::West; + $e + } + { + let $d = Direction::South; + $e + } + }}; +} + +macro_rules! loop_all_directions { + ($d: ident, $e: expr) => {{ + loop_bishop_directions!($d, $e); + loop_rook_directions!($d, $e); + }}; +} + macro_rules! by_direction { - ($d: ident, $body: expr) => {{ + ($d: ident, $e: expr) => {{ let mut res = [Bitboard(0); 8]; let mut $d: u8 = 0; while $d < 8 { res[$d as usize] = { let $d = Direction::new($d).unwrap(); - $body + $e }; $d += 1; } @@ -109,6 +122,7 @@ const RAYS: BySquare> = by_square!( Bitboard(res) }) ); + const LINES: BySquare> = by_square!(a, BySquare([Bitboard(0); 64]), { by_square!(b, Bitboard(0), { let mut res = Bitboard(0); @@ -134,6 +148,7 @@ const SEGMENTS: BySquare> = by_square!(a, BySquare([Bitboard( Bitboard(res | b.bitboard().0) }) }); + const KING_MOVES: BySquare = by_square!(sq, Bitboard(0), { let mut res = 0; loop_all_directions!(d, { @@ -143,8 +158,9 @@ const KING_MOVES: BySquare = by_square!(sq, Bitboard(0), { }); Bitboard(res) }); + const KNIGHT_MOVES: BySquare = by_square!(s, Bitboard(0), { - let mut res = Bitboard::new(); + let mut res = Bitboard(0); if let Some(s) = s.trans(Direction::North) { if let Some(s) = s.trans(Direction::NorthEast) { res.insert(s); @@ -179,6 +195,7 @@ const KNIGHT_MOVES: BySquare = by_square!(s, Bitboard(0), { } res }); + const PAWN_ATTACKS: ByColor> = { by_color!(color, { let direction = match color { @@ -239,32 +256,6 @@ pub(crate) fn pawn_attack(color: Color, square: Square) -> Bitboard { *PAWN_ATTACKS.get(color).get(square) } -/// `role != Pawn` -#[inline] -pub(crate) fn targets(role: Role, from: Square, blockers: Bitboard) -> Bitboard { - match role { - Role::Pawn => unreachable!(), - Role::Knight => knight(from), - Role::Bishop => bishop(from, blockers), - Role::Rook => rook(from, blockers), - Role::Queen => bishop(from, blockers) | rook(from, blockers), - Role::King => king(from), - } -} - -macro_rules! loop_subsets { - ($premask: ident, $subset: ident, $body: expr) => {{ - let mut $subset: u64 = 0; - loop { - $subset = $subset.wrapping_sub($premask) & $premask; - $body - if $subset == 0 { - break; - } - } - }}; -} - const fn bishop_premask(square: Square) -> Bitboard { let mut premask = 0; loop_bishop_directions!(direction, { @@ -300,20 +291,19 @@ const MAGICS: (BySquare, BySquare, usize) = { { let premask = bishop_premask(square).0; let factor = bishop_factor(square); - let mut a = usize::MAX; - let mut b = 0; + let mut i = usize::MAX; + let mut j = 0; loop_subsets!(premask, blockers, { let cur = hash(BISHOP_SHR, factor, Bitboard(blockers | !premask)); - if cur < a { - a = cur; + if cur < i { + i = cur; } - if cur > b { - b = cur; + if cur > j { + j = cur; } }); - assert!(b > a); - let offset = len as isize - a as isize; - len += b - a + 1; + let offset = len as isize - i as isize; + len += j - i + 1; Magic { premask: Bitboard(!premask), factor, @@ -331,20 +321,19 @@ const MAGICS: (BySquare, BySquare, usize) = { { let premask = rook_premask(square).0; let factor = rook_factor(square); - let mut a = usize::MAX; - let mut b = 0; + let mut i = usize::MAX; + let mut j = 0; loop_subsets!(premask, blockers, { let cur = hash(ROOK_SHR, factor, Bitboard(blockers | !premask)); - if cur < a { - a = cur; + if cur < i { + i = cur; } - if cur > b { - b = cur; + if cur > j { + j = cur; } }); - assert!(b > a); - let offset = len as isize - a as isize; - len += b - a + 1; + let offset = len as isize - i as isize; + len += j - i + 1; Magic { premask: Bitboard(!premask), factor, @@ -438,3 +427,15 @@ unsafe fn magic_aux(shr: u8, magic: Magic, blockers: Bitboard) -> Bitboard { const fn hash(shr: u8, factor: u64, x: Bitboard) -> usize { (x.0.wrapping_mul(factor) >> shr) as usize } + +#[inline] +pub(crate) fn targets(role: Role, from: Square, blockers: Bitboard) -> Bitboard { + match role { + Role::Pawn => unreachable!(), + Role::Knight => knight(from), + Role::Bishop => bishop(from, blockers), + Role::Rook => rook(from, blockers), + Role::Queen => bishop(from, blockers) | rook(from, blockers), + Role::King => king(from), + } +}