diff --git a/src/attacks.rs b/src/attacks.rs index 75dea64..bd805e7 100644 --- a/src/attacks.rs +++ b/src/attacks.rs @@ -2,9 +2,10 @@ use super::bitboard::*; use super::magics::*; use super::piece::*; use super::square::*; +use crate::types::*; #[rustfmt::skip] -const KNIGHT_ATTACKS: [Bitboard; SQ::N_SQUARES] = [ +const KNIGHT_ATTACKS: SQMap = SQMap::new([ B!(0x0000000000020400), B!(0x0000000000050800), B!(0x00000000000a1100), B!(0x0000000000142200), B!(0x0000000000284400), B!(0x0000000000508800), B!(0x0000000000a01000), B!(0x0000000000402000), B!(0x0000000002040004), B!(0x0000000005080008), B!(0x000000000a110011), B!(0x0000000014220022), @@ -21,10 +22,10 @@ const KNIGHT_ATTACKS: [Bitboard; SQ::N_SQUARES] = [ B!(0x4400442800000000), B!(0x8800885000000000), B!(0x100010a000000000), B!(0x2000204000000000), B!(0x0004020000000000), B!(0x0008050000000000), B!(0x00110a0000000000), B!(0x0022140000000000), B!(0x0044280000000000), B!(0x0088500000000000), B!(0x0010a00000000000), B!(0x0020400000000000) -]; +]); #[rustfmt::skip] -const ADJACENT_ATTACKS: [Bitboard; SQ::N_SQUARES] = [ +const ADJACENT_ATTACKS: SQMap = SQMap::new([ B!(0x0000000000000302), B!(0x0000000000000705), B!(0x0000000000000e0a), B!(0x0000000000001c14), B!(0x0000000000003828), B!(0x0000000000007050), B!(0x000000000000e0a0), B!(0x000000000000c040), B!(0x0000000000030203), B!(0x0000000000070507), B!(0x00000000000e0a0e), B!(0x00000000001c141c), @@ -41,11 +42,11 @@ const ADJACENT_ATTACKS: [Bitboard; SQ::N_SQUARES] = [ B!(0x3828380000000000), B!(0x7050700000000000), B!(0xe0a0e00000000000), B!(0xc040c00000000000), B!(0x0203000000000000), B!(0x0507000000000000), B!(0x0a0e000000000000), B!(0x141c000000000000), B!(0x2838000000000000), B!(0x5070000000000000), B!(0xa0e0000000000000), B!(0x40c0000000000000) -]; +]); #[rustfmt::skip] -const PAWN_ATTACKS: [[Bitboard; SQ::N_SQUARES]; Color::N_COLORS] = [ - [ +const PAWN_ATTACKS: ColorMap>= ColorMap::new([ + SQMap::new([ B!(0x0000000000000200), B!(0x0000000000000500), B!(0x0000000000000a00), B!(0x0000000000001400), B!(0x0000000000002800), B!(0x0000000000005000), B!(0x000000000000a000), B!(0x0000000000004000), B!(0x0000000000020000), B!(0x0000000000050000), B!(0x00000000000a0000), B!(0x0000000000140000), @@ -62,8 +63,8 @@ const PAWN_ATTACKS: [[Bitboard; SQ::N_SQUARES]; Color::N_COLORS] = [ B!(0x2800000000000000), B!(0x5000000000000000), B!(0xa000000000000000), B!(0x4000000000000000), B!(0x0000000000000000), B!(0x0000000000000000), B!(0x0000000000000000), B!(0x0000000000000000), B!(0x0000000000000000), B!(0x0000000000000000), B!(0x0000000000000000), B!(0x0000000000000000), - ], - [ + ]), + SQMap::new([ B!(0x00000000000000), B!(0x00000000000000), B!(0x00000000000000), B!(0x00000000000000), B!(0x00000000000000), B!(0x00000000000000), B!(0x00000000000000), B!(0x00000000000000), B!(0x00000000000002), B!(0x00000000000005), B!(0x0000000000000a), B!(0x00000000000014), @@ -79,24 +80,24 @@ const PAWN_ATTACKS: [[Bitboard; SQ::N_SQUARES]; Color::N_COLORS] = [ B!(0x00020000000000), B!(0x00050000000000), B!(0x000a0000000000), B!(0x00140000000000), B!(0x00280000000000), B!(0x00500000000000), B!(0x00a00000000000), B!(0x00400000000000), B!(0x02000000000000), B!(0x05000000000000), B!(0x0a000000000000), B!(0x14000000000000), - B!(0x28000000000000), B!(0x50000000000000), B!(0xa0000000000000), B!(0x40000000000000)] + B!(0x28000000000000), B!(0x50000000000000), B!(0xa0000000000000), B!(0x40000000000000)]) -]; +]); pub fn rook_attacks(sq: SQ, occ: Bitboard) -> Bitboard { - unsafe { ROOK_MAGICS.attacks[sq.index()][ROOK_MAGICS.index(sq, occ)] } + unsafe { ROOK_MAGICS.attacks[sq][ROOK_MAGICS.index(sq, occ)] } } pub fn bishop_attacks(sq: SQ, occ: Bitboard) -> Bitboard { - unsafe { BISHOP_MAGICS.attacks[sq.index()][BISHOP_MAGICS.index(sq, occ)] } + unsafe { BISHOP_MAGICS.attacks[sq][BISHOP_MAGICS.index(sq, occ)] } } pub fn knight_attacks(sq: SQ) -> Bitboard { - KNIGHT_ATTACKS[sq.index()] + KNIGHT_ATTACKS[sq] } pub fn king_attacks(sq: SQ) -> Bitboard { - ADJACENT_ATTACKS[sq.index()] + ADJACENT_ATTACKS[sq] } pub fn pawn_attacks_bb(bb: Bitboard, color: Color) -> Bitboard { @@ -104,7 +105,7 @@ pub fn pawn_attacks_bb(bb: Bitboard, color: Color) -> Bitboard { } pub fn pawn_attacks_sq(sq: SQ, color: Color) -> Bitboard { - PAWN_ATTACKS[color.index()][sq.index()] + PAWN_ATTACKS[color][sq] } pub fn sliding_attacks(sq: SQ, occ: Bitboard, mask: Bitboard) -> Bitboard { diff --git a/src/bitboard.rs b/src/bitboard.rs index 29c217b..2dee160 100644 --- a/src/bitboard.rs +++ b/src/bitboard.rs @@ -3,7 +3,10 @@ use super::piece::*; use super::square::*; use super::types::*; use std::fmt; -use std::ops::*; +use std::ops::{ + BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Mul, Not, Shl, ShlAssign, Shr, + ShrAssign, Sub, +}; #[derive(Clone, Copy, Default, PartialEq, Eq)] pub struct Bitboard(pub Hash); @@ -78,11 +81,11 @@ impl Bitboard { impl Bitboard { pub fn line(sq1: SQ, sq2: SQ) -> Self { - unsafe { LINES_BB[sq1.index()][sq2.index()] } + unsafe { LINES_BB[sq1][sq2] } } pub fn between(sq1: SQ, sq2: SQ) -> Self { - unsafe { BETWEEN_BB[sq1.index()][sq2.index()] } + unsafe { BETWEEN_BB[sq1][sq2] } } pub fn oo_mask(c: Color) -> Self { @@ -313,21 +316,21 @@ impl Bitboard { pub const CENTER: Self = B!(0x1818000000); } -static mut BETWEEN_BB: [[Bitboard; SQ::N_SQUARES]; SQ::N_SQUARES] = - [[B!(0); SQ::N_SQUARES]; SQ::N_SQUARES]; -static mut LINES_BB: [[Bitboard; SQ::N_SQUARES]; SQ::N_SQUARES] = - [[B!(0); SQ::N_SQUARES]; SQ::N_SQUARES]; +static mut BETWEEN_BB: SQMap> = + SQMap::new([SQMap::new([B!(0); SQ::N_SQUARES]); SQ::N_SQUARES]); +static mut LINES_BB: SQMap> = + SQMap::new([SQMap::new([B!(0); SQ::N_SQUARES]); SQ::N_SQUARES]); -fn init_between() -> [[Bitboard; SQ::N_SQUARES]; SQ::N_SQUARES] { - let mut between_bb = [[B!(0); SQ::N_SQUARES]; SQ::N_SQUARES]; +fn init_between() -> SQMap> { + let mut between_bb = SQMap::new([SQMap::new([B!(0); SQ::N_SQUARES]); SQ::N_SQUARES]); for sq1 in Bitboard::ALL { for sq2 in Bitboard::ALL { let sqs = sq1.bb() | sq2.bb(); if sq1.file() == sq2.file() || sq1.rank() == sq2.rank() { - between_bb[sq1.index()][sq2.index()] = attacks::rook_attacks_for_init(sq1, sqs) + between_bb[sq1][sq2] = attacks::rook_attacks_for_init(sq1, sqs) & attacks::rook_attacks_for_init(sq2, sqs); } else if sq1.diagonal() == sq2.diagonal() || sq1.antidiagonal() == sq2.antidiagonal() { - between_bb[sq1.index()][sq2.index()] = attacks::bishop_attacks_for_init(sq1, sqs) + between_bb[sq1][sq2] = attacks::bishop_attacks_for_init(sq1, sqs) & attacks::bishop_attacks_for_init(sq2, sqs); } } @@ -335,22 +338,20 @@ fn init_between() -> [[Bitboard; SQ::N_SQUARES]; SQ::N_SQUARES] { between_bb } -fn init_lines() -> [[Bitboard; SQ::N_SQUARES]; SQ::N_SQUARES] { - let mut lines_bb = [[B!(0); SQ::N_SQUARES]; SQ::N_SQUARES]; +fn init_lines() -> SQMap> { + let mut lines_bb = SQMap::new([SQMap::new([B!(0); SQ::N_SQUARES]); SQ::N_SQUARES]); for sq1 in Bitboard::ALL { for sq2 in Bitboard::ALL { if sq1.file() == sq2.file() || sq1.rank() == sq2.rank() { - lines_bb[sq1.index()][sq2.index()] = - attacks::rook_attacks_for_init(sq1, Bitboard::ZERO) - & attacks::rook_attacks_for_init(sq2, Bitboard::ZERO) - | sq1.bb() - | sq2.bb(); + lines_bb[sq1][sq2] = attacks::rook_attacks_for_init(sq1, Bitboard::ZERO) + & attacks::rook_attacks_for_init(sq2, Bitboard::ZERO) + | sq1.bb() + | sq2.bb(); } else if sq1.diagonal() == sq2.diagonal() || sq1.antidiagonal() == sq2.antidiagonal() { - lines_bb[sq1.index()][sq2.index()] = - attacks::bishop_attacks_for_init(sq1, Bitboard::ZERO) - & attacks::bishop_attacks_for_init(sq2, Bitboard::ZERO) - | sq1.bb() - | sq2.bb(); + lines_bb[sq1][sq2] = attacks::bishop_attacks_for_init(sq1, Bitboard::ZERO) + & attacks::bishop_attacks_for_init(sq2, Bitboard::ZERO) + | sq1.bb() + | sq2.bb(); } } } diff --git a/src/board.rs b/src/board.rs index b7234a1..874012a 100644 --- a/src/board.rs +++ b/src/board.rs @@ -8,15 +8,14 @@ use super::square::*; use super::types::*; use super::zobrist::*; use regex::Regex; -use std::convert::TryFrom; use std::fmt; use std::sync::LazyLock; #[derive(Clone)] pub struct Board { - board: [Option; SQ::N_SQUARES], - piece_type_bb: [Bitboard; PieceType::N_PIECE_TYPES], - color_bb: [Bitboard; Color::N_COLORS], + board: SQMap>, + piece_type_bb: PieceTypeMap, + color_bb: ColorMap, history: [HistoryEntry; Self::N_HISTORIES], ctm: Color, ply: usize, @@ -38,29 +37,29 @@ impl Board { self.ctm = Color::White; self.history = [HistoryEntry::default(); Self::N_HISTORIES]; - self.color_bb = [Bitboard::ZERO; Color::N_COLORS]; - self.piece_type_bb = [Bitboard::ZERO; PieceType::N_PIECE_TYPES]; - self.board = [None; SQ::N_SQUARES]; + self.color_bb = ColorMap::new([Bitboard::ZERO; Color::N_COLORS]); + self.piece_type_bb = PieceTypeMap::new([Bitboard::ZERO; PieceType::N_PIECE_TYPES]); + self.board = SQMap::new([None; SQ::N_SQUARES]); self.hasher.clear(); self.network = Network::new(); } pub fn piece_at(&self, sq: SQ) -> Option { - self.board[sq.index()] + self.board[sq] } pub fn piece_type_at(&self, sq: SQ) -> Option { - self.board[sq.index()].map(|pc| pc.type_of()) + self.board[sq].map(|pc| pc.type_of()) } pub fn set_piece_at(&mut self, pc: Piece, sq: SQ) { self.network.activate(pc, sq); self.hasher.update_piece(pc, sq); - self.board[sq.index()] = Some(pc); - self.color_bb[pc.color_of().index()] |= sq.bb(); - self.piece_type_bb[pc.type_of().index()] |= sq.bb(); + self.board[sq] = Some(pc); + self.color_bb[pc.color_of()] |= sq.bb(); + self.piece_type_bb[pc.type_of()] |= sq.bb(); } pub fn remove_piece(&mut self, sq: SQ) { @@ -71,9 +70,9 @@ impl Board { self.network.deactivate(pc, sq); self.hasher.update_piece(pc, sq); - self.piece_type_bb[pc.type_of().index()] &= !sq.bb(); - self.color_bb[pc.color_of().index()] &= !sq.bb(); - self.board[sq.index()] = None; + self.piece_type_bb[pc.type_of()] &= !sq.bb(); + self.color_bb[pc.color_of()] &= !sq.bb(); + self.board[sq] = None; } pub fn move_piece_quiet(&mut self, from_sq: SQ, to_sq: SQ) { @@ -85,10 +84,10 @@ impl Board { self.hasher.move_piece(pc, from_sq, to_sq); let mask = from_sq.bb() | to_sq.bb(); - self.piece_type_bb[pc.type_of().index()] ^= mask; - self.color_bb[pc.color_of().index()] ^= mask; - self.board[to_sq.index()] = self.board[from_sq.index()]; - self.board[from_sq.index()] = None; + self.piece_type_bb[pc.type_of()] ^= mask; + self.color_bb[pc.color_of()] ^= mask; + self.board[to_sq] = self.board[from_sq]; + self.board[from_sq] = None; } pub fn move_piece(&mut self, from_sq: SQ, to_sq: SQ) { @@ -101,15 +100,15 @@ impl Board { } pub fn bitboard_of(&self, c: Color, pt: PieceType) -> Bitboard { - self.piece_type_bb[pt.index()] & self.color_bb[c.index()] + self.piece_type_bb[pt] & self.color_bb[c] } pub fn bitboard_of_pc(&self, pc: Piece) -> Bitboard { - self.piece_type_bb[pc.type_of().index()] & self.color_bb[pc.color_of().index()] + self.piece_type_bb[pc.type_of().index()] & self.color_bb[pc.color_of()] } pub fn bitboard_of_pt(&self, pt: PieceType) -> Bitboard { - self.piece_type_bb[pt.index()] + self.piece_type_bb[pt] } pub fn diagonal_sliders(&self) -> Bitboard { @@ -129,11 +128,11 @@ impl Board { } pub fn all_pieces(&self) -> Bitboard { - self.color_bb[Color::White.index()] | self.color_bb[Color::Black.index()] + self.color_bb[Color::White] | self.color_bb[Color::Black] } pub fn all_pieces_c(&self, color: Color) -> Bitboard { - self.color_bb[color.index()] + self.color_bb[color] } pub fn attackers(&self, sq: SQ, occ: Bitboard) -> Bitboard { @@ -949,12 +948,13 @@ impl Board { } pub fn simple_eval_c(&self, color: Color) -> Value { - const PIECE_VALUES: [Value; PieceType::N_PIECE_TYPES] = [100, 305, 333, 563, 950, 0]; + const PIECE_TYPE_VALUES: PieceTypeMap = + PieceTypeMap::new([100, 305, 333, 563, 950, 0]); let mut eval = 0; for piece_type in PieceType::iter(PieceType::Pawn, PieceType::Queen) { eval += self.bitboard_of(color, piece_type).pop_count() - * PIECE_VALUES[piece_type.index()] as Value; + * PIECE_TYPE_VALUES[piece_type] as Value; } eval @@ -988,9 +988,9 @@ impl Board { impl Default for Board { fn default() -> Self { Self { - piece_type_bb: [Bitboard::ZERO; PieceType::N_PIECE_TYPES], - color_bb: [Bitboard::ZERO; Color::N_COLORS], - board: [None; SQ::N_SQUARES], + piece_type_bb: PieceTypeMap::new([Bitboard::ZERO; PieceType::N_PIECE_TYPES]), + color_bb: ColorMap::new([Bitboard::ZERO; Color::N_COLORS]), + board: SQMap::new([None; SQ::N_SQUARES]), ctm: Color::White, ply: 0, hasher: Hasher::new(), @@ -1019,7 +1019,7 @@ impl fmt::Display for Board { for file_idx in 0..=7 { let file = File::from(file_idx); let sq = SQ::encode(rank, file); - match self.board[sq.index()] { + match self.board[sq] { Some(pc) => { if empty_squares != 0 { board_str.push_str(empty_squares.to_string().as_str()); diff --git a/src/magics.rs b/src/magics.rs index c3169e0..0ddea78 100644 --- a/src/magics.rs +++ b/src/magics.rs @@ -1,6 +1,7 @@ use super::attacks::*; use super::bitboard::*; use super::square::*; +use crate::types::*; // Fancy magic bitboard implementation inspired by Rustfish's port of Stockfish @@ -19,7 +20,7 @@ macro_rules! M { } #[rustfmt::skip] -const BISHOP_MAGICS_INIT: [MagicInit; SQ::N_SQUARES] = [ +const BISHOP_MAGICS_INIT: SQMap = SQMap::new([ M!(0x007fbfbfbfbfbfff, 5378), M!(0x0000a060401007fc, 4093), M!(0x0001004008020000, 4314), M!(0x0000806004000000, 6587), M!(0x0000100400000000, 6491), M!(0x000021c100b20000, 6330), M!(0x0000040041008000, 5609), M!(0x00000fb0203fff80, 22236), M!(0x0000040100401004, 6106), M!(0x0000020080200802, 5625), M!(0x0000004010202000, 16785), M!(0x0000008060040000, 16817), @@ -36,10 +37,10 @@ const BISHOP_MAGICS_INIT: [MagicInit; SQ::N_SQUARES] = [ M!(0x0000000100202000, 4570), M!(0x0000004040802000, 4282), M!(0x0004010040100400, 14964), M!(0x00006020601803f4, 4026), M!(0x0003ffdfdfc28048, 4826), M!(0x0000000820820020, 7354), M!(0x0000000008208060, 4848), M!(0x0000000000808020, 15946), M!(0x0000000001002020, 14932), M!(0x0000000401002008, 16588), M!(0x0000004040404040, 6905), M!(0x007fff9fdf7ff813, 16076), -]; +]); #[rustfmt::skip] -const ROOK_MAGICS_INIT: [MagicInit; SQ::N_SQUARES] = [ +const ROOK_MAGICS_INIT: SQMap = SQMap::new([ M!(0x00280077ffebfffe, 26304), M!(0x2004010201097fff, 35520), M!(0x0010020010053fff, 38592), M!(0x0040040008004002, 8026), M!(0x7fd00441ffffd003, 22196), M!(0x4020008887dffffe, 80870), M!(0x004000888847ffff, 76747), M!(0x006800fbff75fffd, 30400), M!(0x000028010113ffff, 11115), M!(0x0020040201fcffff, 18205), M!(0x007fe80042ffffe8, 53577), M!(0x00001800217fffe8, 62724), @@ -56,34 +57,34 @@ const ROOK_MAGICS_INIT: [MagicInit; SQ::N_SQUARES] = [ M!(0x000ffff810280028, 64134), M!(0x0007ffd7f7feffd8, 41759), M!(0x0003fffc0c480048, 1394), M!(0x0001ffffafd7ffd8, 40910), M!(0x00ffffe4ffdfa3ba, 66516), M!(0x007fffef7ff3d3da, 3897), M!(0x003fffbfdfeff7fa, 3930), M!(0x001fffeff7fbfc22, 72934), M!(0x0000020408001001, 72662), M!(0x0007fffeffff77fd, 56325), M!(0x0003ffffbf7dfeec, 66501), M!(0x0001ffff9dffa333, 14826), -]; +]); pub static mut ATTACKS_TABLE: [Bitboard; 88772] = [Bitboard::ZERO; 88772]; pub struct Magics { - masks: [Bitboard; SQ::N_SQUARES], - magics: [Bitboard; SQ::N_SQUARES], - pub attacks: [&'static [Bitboard]; SQ::N_SQUARES], + masks: SQMap, + magics: SQMap, + pub attacks: SQMap<&'static [Bitboard]>, shift: u8, } impl Magics { pub fn index(&self, sq: SQ, occ: Bitboard) -> usize { - (((occ & self.masks[sq.index()]) * self.magics[sq.index()]) >> self.shift).0 as usize + (((occ & self.masks[sq]) * self.magics[sq]) >> self.shift).0 as usize } } pub static mut ROOK_MAGICS: Magics = Magics { - masks: [Bitboard::ZERO; SQ::N_SQUARES], - magics: [Bitboard::ZERO; SQ::N_SQUARES], - attacks: [&[]; SQ::N_SQUARES], + masks: SQMap::new([Bitboard::ZERO; SQ::N_SQUARES]), + magics: SQMap::new([Bitboard::ZERO; SQ::N_SQUARES]), + attacks: SQMap::new([&[]; SQ::N_SQUARES]), shift: 64 - 12, }; pub static mut BISHOP_MAGICS: Magics = Magics { - masks: [Bitboard::ZERO; SQ::N_SQUARES], - magics: [Bitboard::ZERO; SQ::N_SQUARES], - attacks: [&[]; SQ::N_SQUARES], + masks: SQMap::new([Bitboard::ZERO; SQ::N_SQUARES]), + magics: SQMap::new([Bitboard::ZERO; SQ::N_SQUARES]), + attacks: SQMap::new([&[]; SQ::N_SQUARES]), shift: 64 - 9, }; @@ -92,24 +93,24 @@ pub static mut BISHOP_MAGICS: Magics = Magics { ////////////////////////////////////////////// fn init_magics_type( - magic_init: &[MagicInit; 64], + magic_init: &SQMap, slow_attacks_gen: fn(SQ, Bitboard) -> Bitboard, shift: u8, ) -> Magics { let mut magics = Magics { - masks: [Bitboard::ZERO; SQ::N_SQUARES], - magics: [Bitboard::ZERO; SQ::N_SQUARES], - attacks: [&[]; SQ::N_SQUARES], + masks: SQMap::new([Bitboard::ZERO; SQ::N_SQUARES]), + magics: SQMap::new([Bitboard::ZERO; SQ::N_SQUARES]), + attacks: SQMap::new([&[]; SQ::N_SQUARES]), shift, }; for sq in Bitboard::ALL { let edges = ((Rank::One.bb() | Rank::Eight.bb()) & !sq.rank().bb()) | ((File::A.bb() | File::H.bb()) & !sq.file().bb()); - magics.masks[sq.index()] = slow_attacks_gen(sq, Bitboard::ZERO) & !edges; - magics.magics[sq.index()] = magic_init[sq.index()].magic; + magics.masks[sq] = slow_attacks_gen(sq, Bitboard::ZERO) & !edges; + magics.magics[sq] = magic_init[sq].magic; - let base = magic_init[sq.index()].index; + let base = magic_init[sq].index; let mut subset = Bitboard::ZERO; let mut size = 0; loop { @@ -119,12 +120,12 @@ fn init_magics_type( unsafe { ATTACKS_TABLE[base + index] = slow_attacks_gen(sq, subset) } // Carry-Rippler for iterating through the subset - subset = (subset - magics.masks[sq.index()]) & magics.masks[sq.index()]; + subset = (subset - magics.masks[sq]) & magics.masks[sq]; if subset == Bitboard::ZERO { break; } } - magics.attacks[sq.index()] = unsafe { &ATTACKS_TABLE[base..base + size] }; + magics.attacks[sq] = unsafe { &ATTACKS_TABLE[base..base + size] }; } magics } diff --git a/src/move_list.rs b/src/move_list.rs index f60e2d2..a77b533 100644 --- a/src/move_list.rs +++ b/src/move_list.rs @@ -94,14 +94,14 @@ impl MoveList { } } - pub fn iter_mut(&mut self) -> impl Iterator { - self.0.iter_mut() - } - pub fn iter_moves(&self) -> impl Iterator + '_ { self.0.iter().map(|entry| entry.m) } + pub fn iter_mut(&mut self) -> impl Iterator { + self.0.iter_mut() + } + pub fn next_best(&mut self, idx: usize) -> Option { if idx == self.len() { return None; @@ -123,6 +123,24 @@ impl MoveList { } } +impl<'a> IntoIterator for &'a mut MoveList { + type Item = &'a mut MoveListEntry; + type IntoIter = std::slice::IterMut<'a, MoveListEntry>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter_mut() + } +} + +impl<'a> IntoIterator for &'a MoveList { + type Item = &'a MoveListEntry; + type IntoIter = std::slice::Iter<'a, MoveListEntry>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + impl std::ops::Index for MoveList { type Output = MoveListEntry; diff --git a/src/move_sorter.rs b/src/move_sorter.rs index 27c2cce..568c150 100644 --- a/src/move_sorter.rs +++ b/src/move_sorter.rs @@ -8,15 +8,15 @@ use super::square::*; use super::types::*; pub struct MoveSorter { - killer_moves: [[[Option; Self::N_KILLERS]; MAX_MOVES]; Color::N_COLORS], - history_scores: [[Value; SQ::N_SQUARES]; SQ::N_SQUARES], + killer_moves: ColorMap<[[Option; Self::N_KILLERS]; MAX_MOVES]>, + history_scores: SQMap>, } impl MoveSorter { pub fn new() -> Self { Self { - killer_moves: [[[None; Self::N_KILLERS]; MAX_MOVES]; Color::N_COLORS], - history_scores: [[0; SQ::N_SQUARES]; SQ::N_SQUARES], + killer_moves: ColorMap::new([[[None; Self::N_KILLERS]; MAX_MOVES]; Color::N_COLORS]), + history_scores: SQMap::new([SQMap::new([0; SQ::N_SQUARES]); SQ::N_SQUARES]), } } @@ -86,8 +86,7 @@ impl MoveSorter { } pub fn add_killer(&mut self, board: &Board, m: Move, ply: Ply) { - let color = board.ctm().index(); - let killer_moves = &mut self.killer_moves[color][ply]; + let killer_moves = &mut self.killer_moves[board.ctm()][ply]; killer_moves.rotate_right(1); killer_moves[0] = Some(m); @@ -95,8 +94,8 @@ impl MoveSorter { pub fn add_history(&mut self, m: Move, depth: Depth) { let depth = depth as Value; - let from = m.from_sq().index(); - let to = m.to_sq().index(); + let from = m.from_sq(); + let to = m.to_sq(); self.history_scores[from][to] += depth * depth; if self.history_scores[from][to] >= -Self::HISTORY_MOVE_OFFSET { @@ -108,11 +107,11 @@ impl MoveSorter { } fn is_killer(&self, board: &Board, m: Move, ply: usize) -> bool { - self.killer_moves[board.ctm().index()][ply].contains(&Some(m)) + self.killer_moves[board.ctm()][ply].contains(&Some(m)) } fn history_score(&self, m: Move) -> Value { - self.history_scores[m.from_sq().index()][m.to_sq().index()] + self.history_scores[m.from_sq()][m.to_sq()] } pub fn see(board: &Board, m: Move) -> bool { @@ -127,7 +126,7 @@ impl MoveSorter { return false; }; - let mut value = Self::SEE_PIECE_TYPE[captured_pt.index()]; + let mut value = Self::SEE_PIECE_TYPE[captured_pt]; if value < 0 { return false; @@ -137,7 +136,7 @@ impl MoveSorter { return false; }; - value -= Self::SEE_PIECE_TYPE[attacking_pt.index()]; + value -= Self::SEE_PIECE_TYPE[attacking_pt]; if value >= 0 { return true; @@ -165,7 +164,7 @@ impl MoveSorter { ctm = !ctm; - value = -value - 1 - Self::SEE_PIECE_TYPE[attacking_pt.index()]; + value = -value - 1 - Self::SEE_PIECE_TYPE[attacking_pt]; if value >= 0 { if attacking_pt == PieceType::King @@ -212,7 +211,8 @@ impl MoveSorter { const HISTORY_MOVE_OFFSET: Value = -30000; const LOSING_CAPTURES_OFFSET: Value = -30001; - const SEE_PIECE_TYPE: [Value; PieceType::N_PIECE_TYPES] = [100, 375, 375, 500, 1025, 10000]; + const SEE_PIECE_TYPE: PieceTypeMap = + PieceTypeMap::new([100, 375, 375, 500, 1025, 10000]); #[rustfmt::skip] const MVV_LVA_SCORES: [Value; PieceType::N_PIECE_TYPES * PieceType::N_PIECE_TYPES] = [ diff --git a/src/nnue.rs b/src/nnue.rs index 13ffdc2..08dfa89 100644 --- a/src/nnue.rs +++ b/src/nnue.rs @@ -65,7 +65,7 @@ impl Network { sq: SQ, mut update_fn: impl FnMut(&mut i16, &i16), ) { - let feature_idx = piece.index() * SQ::N_SQUARES + sq.index(); + let feature_idx: usize = piece.index() * SQ::N_SQUARES + sq.index(); let accumulator_idx = feature_idx * self.input_layer.biases.len(); let weights = self.input_layer.weights [accumulator_idx..accumulator_idx + self.input_layer.biases.len()] diff --git a/src/nnue_weights.rs b/src/nnue_weights.rs index cc23f1a..19a21ae 100644 --- a/src/nnue_weights.rs +++ b/src/nnue_weights.rs @@ -1,4 +1,4 @@ -pub const INPUT_LAYER_WEIGHT: [i16; 393216] = [ +pub static INPUT_LAYER_WEIGHT: [i16; 393216] = [ 5, -2, -5, 8, -2, 7, 4, 5, 0, -9, 2, 8, -9, -1, -2, 0, 0, -7, 3, 2, -8, -2, 0, -4, 1, -4, 4, -7, 6, 3, 1, -1, -3, -6, 3, -2, -7, -6, 7, 7, 0, 2, -9, -6, -5, -3, 0, -4, 2, 4, -3, 3, -3, 0, 8, 4, 6, 5, 1, -2, 2, 2, 6, -4, -9, 6, -1, 3, -5, 5, 4, -4, -9, -1, 9, 5, -3, 8, 0, 1, -5, 7, @@ -19295,7 +19295,7 @@ pub const INPUT_LAYER_WEIGHT: [i16; 393216] = [ -72, -36, ]; -pub const INPUT_LAYER_BIAS: [i16; 512] = [ +pub static INPUT_LAYER_BIAS: [i16; 512] = [ -127, -97, -115, -216, -271, 91, -160, -218, -179, -219, -327, -397, -27, -106, -196, -88, -227, -133, -49, -57, -110, -266, -85, -98, -174, -341, -36, -211, 73, -7, -27, -112, -262, -145, -72, -228, -266, -208, -296, -145, -252, -54, -142, -7, -158, -377, -176, -334, -149, @@ -19329,7 +19329,7 @@ pub const INPUT_LAYER_BIAS: [i16; 512] = [ -184, -271, -83, -358, -114, -132, 69, -173, -125, 16, -63, -234, ]; -pub const HIDDEN_LAYER_0_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_0_WEIGHT: [i16; 512] = [ -1, 6, -2, 42, 13, 1, 11, -30, 41, -4, 11, 11, 1, 1, -26, 4, 6, 0, 5, 2, -3, 2, 7, 4, -21, -21, -3, -50, 5, 13, -9, -11, -7, -5, 17, 7, 7, -6, 3, 0, 3, 0, 5, 7, 20, 9, 3, 15, 0, -5, 24, -5, 3, 0, -6, -3, 7, -5, 3, 2, -4, -3, -1, 1, -34, -3, 5, -1, 6, -5, 1, 9, -62, -1, -3, 4, 7, 4, @@ -19353,9 +19353,9 @@ pub const HIDDEN_LAYER_0_WEIGHT: [i16; 512] = [ 1, 3, 0, -1, 4, ]; -pub const HIDDEN_LAYER_0_BIAS: [i16; 1] = [-4]; +pub static HIDDEN_LAYER_0_BIAS: [i16; 1] = [-4]; -pub const HIDDEN_LAYER_1_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_1_WEIGHT: [i16; 512] = [ -3, 6, -4, 52, -5, 3, 9, -35, 42, -5, 9, -6, -1, -1, -12, 0, 5, -1, -2, -4, -3, 4, 1, -4, -25, -9, -2, 6, 4, 8, -5, -9, 2, -9, 13, 5, 6, -8, -2, 3, 4, 2, 5, 2, 17, 7, 4, 13, 4, 0, 11, -9, -2, -3, -5, -5, 4, -36, 3, 3, 0, -3, -1, 6, -7, 10, 4, -3, 5, -7, 5, 16, -19, -3, 0, 0, 4, 1, @@ -19378,9 +19378,9 @@ pub const HIDDEN_LAYER_1_WEIGHT: [i16; 512] = [ 6, 11, -4, 4, -9, 0, 4, 27, -1, 5, -2, -3, -21, 2, -5, -3, -3, 5, -3, -1, 4, ]; -pub const HIDDEN_LAYER_1_BIAS: [i16; 1] = [-6]; +pub static HIDDEN_LAYER_1_BIAS: [i16; 1] = [-6]; -pub const HIDDEN_LAYER_2_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_2_WEIGHT: [i16; 512] = [ -3, 5, -5, 44, -9, 6, 8, -29, 47, -4, 9, -12, -3, -3, -10, -1, 6, -2, -4, -2, -2, 6, 2, -8, -29, -9, -2, 2, 4, 7, -3, -8, 9, -29, 5, 5, 8, -6, -1, 3, 6, 5, 6, 2, 17, 5, 5, 14, 2, 2, 6, -9, -3, -4, -8, -8, 6, -45, 5, 3, 0, 2, -3, 7, 0, 10, 4, -5, 5, -7, 4, 15, -12, -4, 0, -3, 4, @@ -19403,9 +19403,9 @@ pub const HIDDEN_LAYER_2_WEIGHT: [i16; 512] = [ 4, -9, 1, 5, 29, -2, 5, 5, 0, -21, 3, -5, -3, -5, 5, -4, 2, 5, ]; -pub const HIDDEN_LAYER_2_BIAS: [i16; 1] = [-7]; +pub static HIDDEN_LAYER_2_BIAS: [i16; 1] = [-7]; -pub const HIDDEN_LAYER_3_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_3_WEIGHT: [i16; 512] = [ -5, 5, -6, 43, -13, 6, 6, -25, 53, -5, 9, -13, -3, -4, -8, -1, 5, -3, -4, 0, -2, 8, 3, -8, -26, -8, -3, 0, 4, 5, -1, -8, 13, -48, 2, 5, 8, -5, 1, 3, 10, 6, 7, 3, 15, 4, 6, 13, 2, 3, 4, -10, -3, -8, -11, -11, 6, -45, 6, 3, 0, 3, -5, 7, 2, 10, 3, -4, 4, -5, 4, 13, -11, -4, 1, -1, 4, -2, @@ -19428,9 +19428,9 @@ pub const HIDDEN_LAYER_3_WEIGHT: [i16; 512] = [ 2, 5, 3, -7, 2, 4, 23, -3, 5, 9, 1, -20, 4, -5, -2, -5, 6, -6, 3, 12, ]; -pub const HIDDEN_LAYER_3_BIAS: [i16; 1] = [-6]; +pub static HIDDEN_LAYER_3_BIAS: [i16; 1] = [-6]; -pub const HIDDEN_LAYER_4_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_4_WEIGHT: [i16; 512] = [ -8, 4, -5, 35, -17, 6, 5, -27, 54, -6, 6, -11, -4, -5, -7, -2, 4, -4, -4, 2, -2, 9, 3, -8, -20, -7, -3, -1, 4, 3, 0, -8, 18, -56, 0, 4, 9, -4, 2, 3, 12, 8, 9, 3, 12, 4, 7, 10, 2, 5, 2, -11, -3, -13, -9, -10, 6, -41, 6, 6, 0, 3, -6, 7, 1, 10, 3, -4, 3, -6, 4, 11, -9, -5, 1, 2, 3, -2, @@ -19453,9 +19453,9 @@ pub const HIDDEN_LAYER_4_WEIGHT: [i16; 512] = [ 1, 9, 4, -4, 3, 3, 18, -4, 4, 11, 2, -17, 4, -5, -2, -5, 8, -6, 3, 14, ]; -pub const HIDDEN_LAYER_4_BIAS: [i16; 1] = [-3]; +pub static HIDDEN_LAYER_4_BIAS: [i16; 1] = [-3]; -pub const HIDDEN_LAYER_5_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_5_WEIGHT: [i16; 512] = [ -9, 5, -3, 69, -20, 5, 5, -49, 52, -6, 3, -7, -6, -6, -7, -3, 4, -4, -3, 3, -3, 8, 4, -8, -16, -6, -4, -3, 4, 2, 2, -9, 21, -59, -1, 4, 9, -3, 3, 4, 12, 8, 10, 3, 11, 3, 7, 7, 3, 7, 2, -13, -3, -13, -6, -9, 4, -34, 5, 8, -1, 4, -7, 8, 0, 10, 3, -4, 3, -6, 4, 9, -8, -5, 2, 5, 2, -3, 5, @@ -19478,9 +19478,9 @@ pub const HIDDEN_LAYER_5_WEIGHT: [i16; 512] = [ 11, 4, -1, 4, 2, 15, -4, 3, 10, 3, -9, 4, -4, -2, -6, 9, -7, 4, 15, ]; -pub const HIDDEN_LAYER_5_BIAS: [i16; 1] = [-2]; +pub static HIDDEN_LAYER_5_BIAS: [i16; 1] = [-2]; -pub const HIDDEN_LAYER_6_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_6_WEIGHT: [i16; 512] = [ -8, 6, -2, 48, -20, 3, 5, -8, 52, -6, 2, -5, -6, -7, -6, -3, 5, -5, -3, 3, -4, 8, 4, -7, -13, -5, -4, -4, 4, 2, 3, -10, 20, -64, 0, 3, 10, -2, 4, 4, 11, 7, 11, 3, 10, 3, 7, 4, 3, 7, 2, -13, -4, -12, -4, -8, 3, -31, 6, 9, -7, 4, -6, 9, 0, 9, 4, -4, 3, -5, 4, 7, -10, -5, 3, 7, 2, -3, 1, @@ -19503,9 +19503,9 @@ pub const HIDDEN_LAYER_6_WEIGHT: [i16; 512] = [ 3, -1, 4, 2, 13, -4, 2, 8, 5, -2, 4, -4, -4, -6, 9, -8, 5, 14, ]; -pub const HIDDEN_LAYER_6_BIAS: [i16; 1] = [0]; +pub static HIDDEN_LAYER_6_BIAS: [i16; 1] = [0]; -pub const HIDDEN_LAYER_7_WEIGHT: [i16; 512] = [ +pub static HIDDEN_LAYER_7_WEIGHT: [i16; 512] = [ -6, 7, -2, -10, -18, 1, 4, -13, 36, -5, 2, -4, -6, -6, -5, -4, 5, -4, -3, 4, -4, 7, 3, -6, -4, -7, -4, -5, 4, 2, 7, -11, 16, -72, 2, 2, 10, -1, 4, 4, 11, 6, 9, 3, -5, 3, 6, -2, 4, 6, 5, -12, -5, -8, -3, -6, 1, -30, 8, 9, -15, 5, -3, 10, -3, 7, 4, -4, 3, -4, 4, 4, -14, -5, 4, 8, 3, -5, @@ -19528,9 +19528,9 @@ pub const HIDDEN_LAYER_7_WEIGHT: [i16; 512] = [ 2, 35, 13, 3, -6, 3, 2, 7, -4, 5, 7, 5, 0, 4, -3, -5, -5, 9, -9, 7, 13, ]; -pub const HIDDEN_LAYER_7_BIAS: [i16; 1] = [1]; +pub static HIDDEN_LAYER_7_BIAS: [i16; 1] = [1]; -pub const PSQT_LAYER_WEIGHT: [i16; 768] = [ +pub static PSQT_LAYER_WEIGHT: [i16; 768] = [ 1, -2, -1, 2, -1, 2, -1, -2, 3, 6, 5, 5, 6, 7, 5, 6, 4, 3, 8, 4, 5, 7, 4, 8, 5, 7, 9, 5, 8, 7, 2, 8, 5, 7, 8, 10, 11, 10, 6, 7, 4, 5, 10, 16, 11, 11, 7, 8, 9, -1, 14, 15, 18, 18, 15, 7, 0, -2, -2, -1, -2, 0, 2, -2, -4, 1, 1, 3, 2, 2, 3, 2, 6, 1, 4, 5, 3, 6, 3, 2, 1, 4, 6, 7, 7, 5, 5, diff --git a/src/piece.rs b/src/piece.rs index e670b7c..4027a97 100644 --- a/src/piece.rs +++ b/src/piece.rs @@ -1,5 +1,4 @@ use super::types::*; -use std::convert::TryFrom; use std::fmt; use std::ops::Not; @@ -70,6 +69,12 @@ impl TryFrom for Piece { } } +impl Into for Piece { + fn into(self) -> usize { + self.index() + } +} + impl fmt::Display for Piece { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( @@ -114,6 +119,12 @@ impl From for PieceType { } } +impl Into for PieceType { + fn into(self) -> usize { + self.index() + } +} + impl fmt::Display for PieceType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( @@ -158,6 +169,12 @@ impl From for Color { } } +impl Into for Color { + fn into(self) -> usize { + self.index() + } +} + impl Not for Color { type Output = Color; diff --git a/src/search_master.rs b/src/search_master.rs index 31c54d4..2194f74 100644 --- a/src/search_master.rs +++ b/src/search_master.rs @@ -1,5 +1,4 @@ -use std::sync; -use std::sync::atomic::*; +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::mpsc::Receiver; use std::sync::Arc; use std::thread; @@ -13,7 +12,7 @@ use super::tt::*; use super::uci::*; pub struct SearchMaster { - stop: sync::Arc, + stop: Arc, board: Board, num_threads: u16, tt: TT, @@ -21,7 +20,7 @@ pub struct SearchMaster { } impl SearchMaster { - pub fn new(stop: sync::Arc) -> Self { + pub fn new(stop: Arc) -> Self { Self { stop, board: Board::new(), diff --git a/src/square.rs b/src/square.rs index c8cdb8c..dc26a28 100644 --- a/src/square.rs +++ b/src/square.rs @@ -1,7 +1,8 @@ use super::bitboard::*; use super::piece::*; +use super::types::*; use std::fmt; -use std::ops::*; +use std::ops::{Add, Sub}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)] #[rustfmt::skip] @@ -23,7 +24,7 @@ impl SQ { } pub fn bb(self) -> Bitboard { - B!(1 << self as usize) + Self::SQUARES_BB[self] } pub fn index(self) -> usize { @@ -98,7 +99,7 @@ impl TryFrom<&str> for SQ { fn try_from(value: &str) -> Result { let sq = Self::from( Self::SQ_DISPLAY - .iter() + .into_iter() .position(|potential_sq_str| *potential_sq_str == value) .ok_or("Invalid square.")? as u8, ); @@ -106,11 +107,17 @@ impl TryFrom<&str> for SQ { } } +impl Into for SQ { + fn into(self) -> usize { + self.index() + } +} + impl SQ { pub const N_SQUARES: usize = 64; #[rustfmt::skip] - const SQUARES_BB: [Bitboard; Self::N_SQUARES + 1] = [ + const SQUARES_BB: SQMap = SQMap::new([ B!(1 << 0), B!(1 << 1), B!(1 << 2), B!(1 << 3), B!(1 << 4), B!(1 << 5), B!(1 << 6), B!(1 << 7), B!(1 << 8), B!(1 << 9), B!(1 << 10), B!(1 << 11), B!(1 << 12), B!(1 << 13), B!(1 << 14), B!(1 << 15), B!(1 << 16), B!(1 << 17), B!(1 << 18), B!(1 << 19), B!(1 << 20), B!(1 << 21), B!(1 << 22), B!(1 << 23), @@ -119,11 +126,10 @@ impl SQ { B!(1 << 40), B!(1 << 41), B!(1 << 42), B!(1 << 43), B!(1 << 44), B!(1 << 45), B!(1 << 46), B!(1 << 47), B!(1 << 48), B!(1 << 49), B!(1 << 50), B!(1 << 51), B!(1 << 52), B!(1 << 53), B!(1 << 54), B!(1 << 55), B!(1 << 56), B!(1 << 57), B!(1 << 58), B!(1 << 59), B!(1 << 60), B!(1 << 61), B!(1 << 62), B!(1 << 63), - B!(0) - ]; + ]); #[rustfmt::skip] - pub const SQ_DISPLAY: [&'static str; Self::N_SQUARES] = [ + pub const SQ_DISPLAY: SQMap<&'static str> = SQMap::new([ "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", @@ -131,7 +137,7 @@ impl SQ { "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", - "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"]; + "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"]); } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)] @@ -196,9 +202,15 @@ impl From for Rank { } } +impl Into for Rank { + fn into(self) -> usize { + self.index() + } +} + impl Rank { pub const N_RANKS: usize = 8; - const RANK_BB: [Bitboard; Self::N_RANKS] = [ + const RANK_BB: RankMap = RankMap::new([ B!(0x0000_0000_0000_00FF), B!(0x0000_0000_0000_FF00), B!(0x0000_0000_00FF_0000), @@ -207,7 +219,7 @@ impl Rank { B!(0x0000_FF00_0000_0000), B!(0x00FF_0000_0000_0000), B!(0xFF00_0000_0000_0000), - ]; + ]); } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)] @@ -239,9 +251,15 @@ impl From for File { } } +impl Into for File { + fn into(self) -> usize { + self.index() + } +} + impl File { pub const N_FILES: usize = 8; - const FILE_BB: [Bitboard; Self::N_FILES] = [ + const FILE_BB: FileMap = FileMap::new([ B!(0x0101_0101_0101_0101), B!(0x0202_0202_0202_0202), B!(0x0404_0404_0404_0404), @@ -250,7 +268,7 @@ impl File { B!(0x2020_2020_2020_2020), B!(0x4040_4040_4040_4040), B!(0x8080_8080_8080_8080), - ]; + ]); } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -287,7 +305,7 @@ impl From for Diagonal { impl Diagonal { pub const N_DIAGONALS: usize = 15; - const DIAGONAL_BB: [Bitboard; Self::N_DIAGONALS] = [ + const DIAGONAL_BB: DiagonalMap = DiagonalMap::new([ B!(0x0000_0000_0000_0080), B!(0x0000_0000_0000_8040), B!(0x0000_0000_0080_4020), @@ -303,7 +321,7 @@ impl Diagonal { B!(0x0402_0100_0000_0000), B!(0x0201_0000_0000_0000), B!(0x0100_0000_0000_0000), - ]; + ]); } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -340,7 +358,7 @@ impl From for AntiDiagonal { impl AntiDiagonal { pub const N_ANTIDIAGONALS: usize = 15; - const ANTIDIAGONAL_BB: [Bitboard; Self::N_ANTIDIAGONALS] = [ + const ANTIDIAGONAL_BB: DiagonalMap = DiagonalMap::new([ B!(0x0000_0000_0000_0001), B!(0x0000_0000_0000_0102), B!(0x0000_0000_0001_0204), @@ -356,5 +374,5 @@ impl AntiDiagonal { B!(0x2040_8000_0000_0000), B!(0x4080_0000_0000_0000), B!(0x8000_0000_0000_0000), - ]; + ]); } diff --git a/src/tt.rs b/src/tt.rs index 9aba1ce..2033b53 100644 --- a/src/tt.rs +++ b/src/tt.rs @@ -129,7 +129,7 @@ impl TT { } pub fn mb_size(&self) -> usize { - self.table.len() * std::mem::size_of::() / 1024 / 1024 + self.table.len() * size_of::() / 1024 / 1024 } pub fn hashfull(&self) -> usize { diff --git a/src/types.rs b/src/types.rs index 4f66295..d4925a3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,73 @@ +use crate::piece::*; +use crate::square::*; +use std::ops::{Index, IndexMut}; +use std::slice::{Iter, IterMut}; + pub type Depth = i8; pub type Hash = u64; pub type MoveInt = u16; pub type Ply = usize; pub type Value = i32; + +pub type ColorMap = EnumMap; +pub type PieceMap = EnumMap; +pub type PieceTypeMap = EnumMap; +pub type SQMap = EnumMap; +pub type FileMap = EnumMap; +pub type RankMap = EnumMap; +pub type DiagonalMap = EnumMap; + +#[derive(Copy, Clone)] +pub struct EnumMap([T; N]); + +impl EnumMap { + pub const fn new(data: [T; N]) -> EnumMap { + EnumMap(data) + } + + pub fn iter_mut(&mut self) -> impl Iterator { + self.0.iter_mut() + } +} + +impl<'a, T, const N: usize> IntoIterator for &'a mut EnumMap { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter_mut() + } +} + +impl<'a, T, const N: usize> IntoIterator for &'a EnumMap { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + +impl Index for EnumMap +where + E: Into, +{ + type Output = T; + + fn index(&self, key: E) -> &Self::Output { + let idx = key.into(); + debug_assert!(idx < N); + &self.0[idx] + } +} + +impl IndexMut for EnumMap +where + E: Into, +{ + fn index_mut(&mut self, key: E) -> &mut Self::Output { + let idx = key.into(); + debug_assert!(idx < N); + &mut self.0[idx] + } +} diff --git a/src/zobrist.rs b/src/zobrist.rs index b7cda22..c9d1348 100644 --- a/src/zobrist.rs +++ b/src/zobrist.rs @@ -9,8 +9,8 @@ use rand::{RngCore, SeedableRng}; pub struct Hasher { hash: Hash, material_hash: Hash, - zobrist_table: [Hash; SQ::N_SQUARES * Piece::N_PIECES], - zobrist_ep: [Hash; File::N_FILES], + zobrist_table: PieceMap>, + zobrist_ep: FileMap, zobrist_color: Hash, } @@ -18,13 +18,14 @@ impl Hasher { pub fn new() -> Self { let mut rng = StdRng::seed_from_u64(1070372); - let mut zobrist_table = [0; SQ::N_SQUARES * Piece::N_PIECES]; - let mut zobrist_ep = [0; File::N_FILES]; + let mut zobrist_table = PieceMap::new([SQMap::new([0; SQ::N_SQUARES]); Piece::N_PIECES]); + let mut zobrist_ep = FileMap::new([0; File::N_FILES]); let zobrist_color = rng.next_u64(); zobrist_table .iter_mut() + .flatten() .for_each(|hash| *hash = rng.next_u64()); zobrist_ep @@ -41,21 +42,19 @@ impl Hasher { } pub fn move_piece(&mut self, pc: Piece, from_sq: SQ, to_sq: SQ) { - let pc_index = pc.index() * SQ::N_SQUARES; - let update = self.zobrist_table[pc_index + from_sq.index()] - ^ self.zobrist_table[pc_index + to_sq.index()]; + let update = self.zobrist_table[pc][from_sq] ^ self.zobrist_table[pc][to_sq]; self.hash ^= update; self.material_hash ^= update; } pub fn update_piece(&mut self, pc: Piece, sq: SQ) { - let update = self.zobrist_table[pc.index() * SQ::N_SQUARES + sq.index()]; + let update = self.zobrist_table[pc][sq]; self.hash ^= update; self.material_hash ^= update; } pub fn update_ep(&mut self, file: File) { - self.hash ^= self.zobrist_ep[file.index()]; + self.hash ^= self.zobrist_ep[file]; } pub fn update_color(&mut self) {