diff --git a/res/scripts/gen_zobrist_keys.py b/res/scripts/gen_zobrist_keys.py new file mode 100755 index 0000000..9047448 --- /dev/null +++ b/res/scripts/gen_zobrist_keys.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""Generate Zobrist keys.""" + +import random + + +random.seed("vatu stop playing your queen first you have other pieces") + +TEMPLATE = """\ +pub const ZOBRIST_PIECES: [[[ZobristHash; 64]; 6]; 2] = [ +{} +]; + +pub const ZOBRIST_BLACK_TURN: ZobristHash = {}; + +pub const ZOBRIST_CASTLE_WH_K: usize = 0; +pub const ZOBRIST_CASTLE_WH_Q: usize = 1; +pub const ZOBRIST_CASTLE_BL_K: usize = 2; +pub const ZOBRIST_CASTLE_BL_Q: usize = 3; + +pub const ZOBRIST_CASTLES: [ZobristHash; 4] = [ +{} +]; + +pub const ZOBRIST_EN_PASSANT: [ZobristHash; 8] = [ +{} +]; +""" + + +def gen_hash(): + return random.getrandbits(64) + + +def gen_pieces_keys(): + pieces_str = "" + for color in range(2): + pieces_str += " [\n" + for piece in range(6): + pieces_str += " [\n" + for square in range(64): + k = gen_hash() + pieces_str += " {},\n".format(k) + pieces_str += " ],\n" + pieces_str += " ],\n" + return pieces_str + + +print( + TEMPLATE.format( + gen_pieces_keys(), + gen_hash(), + "\n".join([" {},".format(gen_hash()) for _ in range(4)]), + "\n".join([" {},".format(gen_hash()) for _ in range(8)]), + ) +) diff --git a/src/analysis.rs b/src/analysis.rs index b80b99f..66db6a9 100644 --- a/src/analysis.rs +++ b/src/analysis.rs @@ -190,10 +190,13 @@ impl Analyzer { let mut best_score = MIN_F32; let mut best_move = None; for m in &mut moves { - node.apply_move(m); + let hash_changes = node.apply_move(m); let result = self.negamax(node, -beta, -alpha, depth + 1); - node.unmake_move(m); + node.unmake_move(m, hash_changes); let score = -result.0; + if self.debug && depth == 0 { + self.log(format!("move {} evaluated {}", m.to_uci_string(), score)); + } if score > best_score { best_score = score; best_move = Some(m.to_owned()); diff --git a/src/board.rs b/src/board.rs index 0cb4941..b485e60 100644 --- a/src/board.rs +++ b/src/board.rs @@ -1,5 +1,6 @@ //! Basic type definitions and functions. +// Reexport all precomputed board data for simplicity. pub use crate::precomputed::*; /// Color type, used to index `Board.color`. diff --git a/src/engine.rs b/src/engine.rs index 79822e3..cfb7a68 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -186,7 +186,9 @@ impl Engine { /// Apply a series of moves to the current node. fn apply_moves(&mut self, moves: &mut Vec) { - moves.iter_mut().for_each(|m| m.apply_to(&mut self.node.board, &mut self.node.game_state)); + for m in moves.iter_mut() { + m.apply_to(&mut self.node.board, &mut self.node.game_state); + } } /// Start working on board, returning the best move found. diff --git a/src/main.rs b/src/main.rs index 2d056d4..a87d171 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ pub mod precomputed; pub mod rules; pub mod stats; pub mod uci; +pub mod zobrist; fn main() { let args = App::new("Vatu") diff --git a/src/movement.rs b/src/movement.rs index 669a89d..c6c1a8c 100644 --- a/src/movement.rs +++ b/src/movement.rs @@ -5,6 +5,7 @@ use std::fmt; use crate::board::*; use crate::castling::*; use crate::rules::GameState; +use crate::zobrist::*; /// A movement, with before/after positions and optional promotion. #[derive(Clone, PartialEq)] @@ -45,66 +46,106 @@ impl Move { /// /// Set automatic queen promotion for pawns, register captured /// pieces and castle options. - pub fn apply_to(&mut self, board: &mut Board, game_state: &mut GameState) { + pub fn apply_to(&mut self, board: &mut Board, game_state: &mut GameState) -> ZobristHash { + // Changes to a Zobrist hash due to this move. + let mut changes: ZobristHash = 0; // Save current castling options to unmake later. self.old_castles = game_state.castling; let piece = board.get_piece_on(self.source); - // Handle king castling. if piece == KING { + // Handle king castling. if let Some(castle) = self.get_castle() { match castle { CASTLE_WH_K => { board.move_square(E1, G1); board.move_square(H1, F1); game_state.castling &= !CASTLE_WH_MASK; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_K]; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_Q]; } CASTLE_WH_Q => { board.move_square(E1, C1); board.move_square(A1, D1); game_state.castling &= !CASTLE_WH_MASK; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_K]; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_Q]; } CASTLE_BL_K => { board.move_square(E8, G8); board.move_square(H8, F8); game_state.castling &= !CASTLE_BL_MASK; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_K]; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_Q]; } CASTLE_BL_Q => { board.move_square(E8, C8); board.move_square(A8, D8); game_state.castling &= !CASTLE_BL_MASK; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_K]; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_Q]; } _ => { panic!("Invalid castle.") } } game_state.color = opposite(game_state.color); - return + changes ^= ZOBRIST_BLACK_TURN; + return changes } else { // If the king moved from starting square, remove it from castling options. - if self.source == E1 { game_state.castling &= !CASTLE_WH_MASK; } - else if self.source == E8 { game_state.castling &= !CASTLE_BL_MASK; } + if self.source == E1 { + game_state.castling &= !CASTLE_WH_MASK; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_K]; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_Q]; + } + else if self.source == E8 { + game_state.castling &= !CASTLE_BL_MASK; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_K]; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_Q]; + } } } + // Record captured piece if any. if !board.is_empty(self.dest) { - self.capture = Some(board.get_piece_on(self.dest)); + let captured_piece = board.get_piece_on(self.dest); + changes ^= get_piece_hash(opposite(game_state.color), captured_piece, self.dest); + self.capture = Some(captured_piece); } - // Move the piece. + // Move the piece and apply promotion if any. board.move_square(self.source, self.dest); - - // Apply promotion if any. - if let Some(piece) = self.promotion { - board.set_piece(self.dest, PAWN, piece); + changes ^= get_piece_hash(game_state.color, piece, self.source); + if let Some(promotion_piece) = self.promotion { + board.set_piece(self.dest, PAWN, promotion_piece); + changes ^= get_piece_hash(game_state.color, promotion_piece, self.dest); + } else { + changes ^= get_piece_hash(game_state.color, piece, self.dest); } // If a rook moved, remove the castle side. - if self.source == A1 || self.dest == A1 { game_state.castling &= !CASTLE_WH_Q; } - else if self.source == H1 || self.dest == H1 { game_state.castling &= !CASTLE_WH_K; } - else if self.source == A8 || self.dest == A8 { game_state.castling &= !CASTLE_BL_Q; } - else if self.source == H8 || self.dest == H8 { game_state.castling &= !CASTLE_BL_K; } + if self.source == A1 || self.dest == A1 { + game_state.castling &= !CASTLE_WH_Q; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_Q]; + } + else if self.source == H1 || self.dest == H1 { + game_state.castling &= !CASTLE_WH_K; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_K]; + } + else if self.source == A8 || self.dest == A8 { + game_state.castling &= !CASTLE_BL_Q; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_Q]; + } + else if self.source == H8 || self.dest == H8 { + game_state.castling &= !CASTLE_BL_K; + changes ^= ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_K]; + } // Finally, switch to the opposing player in the game state. game_state.color = opposite(game_state.color); + changes ^= ZOBRIST_BLACK_TURN; + + // Return changes as a Zobrist hash. + changes } /// Unmake a move. diff --git a/src/node.rs b/src/node.rs index 2d152e8..5ccca37 100644 --- a/src/node.rs +++ b/src/node.rs @@ -4,6 +4,7 @@ use crate::board; use crate::movement::Move; use crate::rules; use crate::stats; +use crate::zobrist; /// Analysis node: a board along with the game state. #[derive(Clone, PartialEq)] @@ -12,6 +13,8 @@ pub struct Node { pub board: board::Board, /// Game state. pub game_state: rules::GameState, + /// Zobrist hash of the node. + pub hash: zobrist::ZobristHash, } impl Node { @@ -20,16 +23,20 @@ impl Node { Node { board: board::Board::new_empty(), game_state: rules::GameState::new(), + hash: zobrist::get_new_game_hash(), } } /// Apply a move to this node. - pub fn apply_move(&mut self, m: &mut Move) { - m.apply_to(&mut self.board, &mut self.game_state); + pub fn apply_move(&mut self, m: &mut Move) -> zobrist::ZobristHash { + let changes = m.apply_to(&mut self.board, &mut self.game_state); + self.hash ^= changes; + changes } - pub fn unmake_move(&mut self, m: &Move) { + pub fn unmake_move(&mut self, m: &Move, changes: zobrist::ZobristHash) { m.unmake(&mut self.board, &mut self.game_state); + self.hash ^= changes; } /// Return player moves from this node. diff --git a/src/precomputed.rs b/src/precomputed.rs index a496a05..7a0c425 100644 --- a/src/precomputed.rs +++ b/src/precomputed.rs @@ -1,6 +1,7 @@ //! Ugly module with all kind of precomputed stuff. use crate::board::{Square, Bitboard}; +use crate::zobrist::ZobristHash; // Generated by gen_squares.py. pub const A1: Square = 0; @@ -480,3 +481,828 @@ pub const KNIGHT_RAYS: [Bitboard; 64] = [ 0b00000000_00010000_10100000_00000000_00000000_00000000_00000000_00000000, 0b00000000_00100000_01000000_00000000_00000000_00000000_00000000_00000000, ]; + +// Generated by gen_zobrist_keys.py. +pub const ZOBRIST_PIECES: [[[ZobristHash; 64]; 6]; 2] = [ + [ + [ + 5230485930162234062, + 5238617895699405985, + 4709781846936492931, + 6480409461267432904, + 8432831256155652419, + 8368355871961019630, + 6670979618372292347, + 13946322022735355958, + 11653327786003412444, + 8911941857523270608, + 14005495020294378149, + 7052745365841946574, + 14947898973004813754, + 16568135084751874917, + 14416690837965125032, + 15250579260894613093, + 10390215563440607572, + 10539080371013975717, + 2553434971954616332, + 5946151574540099307, + 3953350499910303773, + 16353801647154993729, + 14581683459460399592, + 1588972894843982356, + 13601876592648600167, + 16416266883070977994, + 9498392293510493264, + 13935546522649706747, + 6020751534528485649, + 8481597454884198476, + 3376136817935597300, + 16450565490057008108, + 11565074623839806700, + 4890233796396413560, + 7215116870678099835, + 6873794952473427236, + 12300072587696359993, + 12162893891482918104, + 5465257053616860384, + 1622610263387597088, + 13686827634038573028, + 323412062311704186, + 12098218147116926368, + 11932768958909542210, + 4444153107121266078, + 9161358716497556452, + 9947823074072941469, + 16309853711454380872, + 10504119364825006378, + 7304017004164526840, + 2899661874339449941, + 15814184842154281937, + 7769082256869284807, + 17091389954059441018, + 16266438976026480979, + 3399909120097633104, + 17134297913307189661, + 7030596002635703563, + 247181462978570943, + 6993118257489773878, + 1300066214503768042, + 8616306703287618245, + 1444595249263426016, + 4472454400157367567, + ], + [ + 16870012156278751333, + 531833467239086523, + 9300020637154512591, + 10876403266138686713, + 11787037162931018360, + 16538542051640854716, + 2949365786808992369, + 200838742228975756, + 8948813227225445730, + 10860405833994886076, + 4982180702366509177, + 5541485968845342698, + 853747588266163105, + 9229530084210432146, + 10947913297977533433, + 1244374236106306927, + 9232078576388207554, + 5527939322396785193, + 7696495816285323401, + 8904890533379453265, + 8480684627479039053, + 368307738068001454, + 6340118528067380120, + 16831094406902436384, + 5305160523794712359, + 10004070766540006939, + 2318610231532354318, + 6228289580979833937, + 3413706597318350256, + 14521183780808125600, + 8905240684232440196, + 6051976334467601141, + 997466049696971043, + 10673900210924698162, + 8080663635672823570, + 16143246986091152429, + 3300934437120469004, + 12358684583582252763, + 3402331348166657827, + 13595117835485601528, + 13577678374328595748, + 8347496403565110819, + 7046818044845410377, + 838543581671692622, + 16423566748540790443, + 4821719899858903922, + 12202768873245030842, + 11112996853809213683, + 14379622223737851468, + 7168991259989620371, + 16516371120162298062, + 15768904307445868256, + 8154280165316852227, + 16841648413657914243, + 3860684121863922252, + 4560635471784971154, + 7158282956013622068, + 10365812987614738050, + 7890642237019126437, + 13638092628572997837, + 14796019704389458835, + 1273290748015117130, + 1176795631218840500, + 6137083668319746386, + ], + [ + 11820931779894469784, + 15136277269875643918, + 1632615076551529723, + 4430323096565861505, + 14135954698602281472, + 6412278352810143263, + 11785524538973515208, + 17872198660253372378, + 7321590440299771707, + 10783017979692218988, + 15746091964388443398, + 3258285182274634132, + 16921418972504038773, + 10232453762703303187, + 10926463029142964703, + 15108466217066884775, + 10751464182876849481, + 1900754345963399717, + 3424380236092961889, + 15836961247546890804, + 8124151540008929094, + 1716123330670750891, + 10253502390064916806, + 10350280256867581143, + 10584339840087513696, + 2251844348262642756, + 5165203963665674531, + 7556420914025941152, + 14715570898020776859, + 308630325998876035, + 10881885677771945928, + 6092365519022576559, + 10960750208698426147, + 6513460910848563992, + 4724146390064169895, + 6125334314524488599, + 11194397157478649499, + 7411374102826659960, + 8715426332997605026, + 7046906076992602354, + 16059272986481347448, + 12154129336412631215, + 2203988157688612704, + 11964328410181526149, + 16783977506495967848, + 2196724851160901293, + 9707361195379456616, + 12107810442518181902, + 16245560280933258534, + 735089856153651190, + 12667980741379685296, + 11976659714899734855, + 7714345689451818744, + 1838922122073170261, + 15035167043576194306, + 13198765821092057705, + 14290087918526366009, + 5792555790677224273, + 2313714371703668635, + 5879913901733308876, + 16179508217608549630, + 7181718019999081044, + 15777331336889182193, + 9272183542523540901, + ], + [ + 3046185151057768643, + 14999586703302978877, + 13016617089055366688, + 8101427684087419781, + 6240826148646721820, + 8269892959398732848, + 1307609977570482725, + 3146103343867840173, + 9586450071772290087, + 883546145042464039, + 12608000109279142266, + 14842973106852154561, + 8758836295588085341, + 6157186482470916499, + 5634623593539930052, + 4011391109192342465, + 252089486792519421, + 3211079009194937730, + 12304488700211518999, + 15695461864144928959, + 735639318468489544, + 4410058956507662326, + 1323285479418479885, + 3510608953685353427, + 15715296895112106230, + 3995833941249399976, + 5592511922822441728, + 2014379508941983134, + 3767549817103239211, + 12135306195399658233, + 11912764703813954387, + 12072295067365749250, + 9989979334209867805, + 10279700592288875857, + 17180330294388796088, + 581680140188195831, + 13185390910770158320, + 1480786962918473773, + 1137526092632836347, + 18089465931170292009, + 16006945081263834594, + 10670909949953786768, + 14574761639302612804, + 3143717041590487110, + 4714433656712106516, + 16732415614325784944, + 11144981911800849461, + 9068268952495590689, + 8146473186249219623, + 11291207280774372049, + 8487888294281363475, + 9086838583787313729, + 16954388340088140291, + 2135489908827437031, + 6018463847348107150, + 4498422873403632086, + 4767690060912814747, + 15780301696369031282, + 2488967008364257007, + 13920892508696217591, + 1687587573781656772, + 9675178683652863201, + 11324406578001815999, + 4228976538028331567, + ], + [ + 13924609616876551493, + 11147755785187061885, + 13092168412607830334, + 1122056342410353647, + 18146748013082870701, + 346060088367599844, + 13812010867645191279, + 504406042431043033, + 3222493086482886149, + 2477347116527048194, + 16229167715210064341, + 1381582240984556552, + 1981983069924379277, + 17296996880625752274, + 15689296760981280414, + 7154623696341899352, + 547285491505630409, + 3952248124965140480, + 9876781192270354538, + 14712400399965568809, + 6110890492936363585, + 6147339827009351917, + 2814931877793493925, + 15398170493100801629, + 5589314031846282669, + 6716683194641517943, + 14297939873221436852, + 7898996115215236681, + 16130345910674899169, + 13262143235009989280, + 6132121931715262458, + 13763963812999466126, + 5678139041278340963, + 7683187023717558620, + 2818448602564797489, + 7238872793005137867, + 17076056835961669551, + 15164919369839388812, + 12551309276841615101, + 16110780632881205055, + 3333579759449921317, + 40601572334588286, + 1712074107114000760, + 17334986079120239204, + 18314810228509582538, + 15350477369611077335, + 483704842904417018, + 11629959256108132178, + 5026536033685037585, + 556275634622862705, + 10206026998377231793, + 7940672859110387176, + 15599207977245592326, + 12763859418009364437, + 9013530784510263267, + 13952660324072064054, + 6527463565827187791, + 13300684702214000711, + 13614065249110795442, + 3882097314759228874, + 11901624115337304263, + 4603165982595088914, + 14027182079153010850, + 6292834061292910612, + ], + [ + 13415969423978073000, + 15984816522666103434, + 2652819057256759760, + 13621025970954576642, + 17449665072142616387, + 2605497450396760237, + 2730510600837337463, + 14785795532520840425, + 14938657157125707085, + 9011303197525585286, + 7263803361144685429, + 18134094269181316634, + 11161398315458363906, + 2893524915217510140, + 11543032553397817006, + 15816713703548814680, + 936191770742044571, + 8107399726839812303, + 7465519389244948553, + 10361884399467622288, + 15824431441299020940, + 12091629518780759593, + 4558438721296307423, + 13555890473828982007, + 16587759019945493860, + 2412077016767068627, + 9830609194755089279, + 3264443740839586061, + 17653890994902772286, + 3772083050313312581, + 7736380384575961560, + 4339139737758913996, + 10632771085655320231, + 11285161069857782675, + 10682185725861156935, + 13637965460951329980, + 4649344561846442339, + 12243470822564023182, + 3669339468858074705, + 6198269073190788754, + 9460527905908789128, + 9858505120448085116, + 5409940172565343524, + 7867268640165599320, + 8461123480813018984, + 17372600184640900943, + 7836103424799911754, + 6396276906594577713, + 3672488628096147826, + 14326625140932074604, + 4831191327853310068, + 8889797966048701450, + 1326857005228918419, + 16337461021431511547, + 13418379275080705069, + 12082996700572671516, + 16449704894881531984, + 14923027788355565995, + 8547791828218885799, + 14893932023895762368, + 7369376787490348042, + 5012733833855988234, + 14075011178452042417, + 10573894700557322171, + ], + ], + [ + [ + 1742532124052654467, + 11967260896221628601, + 7164205857163048909, + 809534787767160907, + 9909420791491645007, + 12126342127885623034, + 17923189097659138712, + 5928814002664070936, + 8560083204044088212, + 17411824408910571758, + 8863551055862989127, + 11119275295977703800, + 17583371545237180824, + 12095934975286897442, + 12958033763224041640, + 13270504314151635314, + 2456880627446127921, + 4451545295463721916, + 6268066738683655454, + 11772498000016058949, + 4123460670492272064, + 3701207562325584661, + 908408386271318093, + 2709175176654747444, + 9006545962788494332, + 7370624428636005747, + 17521483724668444084, + 18229567195295402798, + 4347671518863650257, + 18246377464295426097, + 4259051261706305040, + 2067080301851755164, + 7859088528902513789, + 7854654128819978086, + 1216030243531466191, + 14763093689341304995, + 1007999414859646207, + 2094657247121490203, + 13766997540106969045, + 7162825543639524618, + 10831570360831795991, + 15816761341358764433, + 14434804918032708126, + 14120812743157381482, + 8086479632455681168, + 4764601050213262762, + 681952129739260857, + 7213384526472144975, + 11866391103176903891, + 1629451314563510778, + 4145271991793565767, + 195442615079529527, + 14920636409777197788, + 3246236324255893399, + 16904213395482842837, + 3837194334247967091, + 8717852727742508324, + 1553148405430043724, + 16951703481381774464, + 15843193418920071477, + 12309712557884273432, + 12925573032594108612, + 5082870261613725953, + 5695297769753158695, + ], + [ + 2321317948404450511, + 1690929461481693223, + 5790862553086425076, + 3831996358965766015, + 5015090086762085776, + 4124427119168405360, + 3922206345093411535, + 6095962377070474522, + 13978110275238658500, + 16983473964374000251, + 5869403875434980156, + 15078678498642844340, + 9556710579694672296, + 14583140214087300984, + 17890653399731240071, + 14355915781299387729, + 13496513445026544319, + 4179030626971037619, + 7886116688869835054, + 1032512653546172102, + 12279556070489957177, + 18406392320738512665, + 18013165103942671844, + 9792582845781379318, + 9229934059385004114, + 12833918208592925403, + 14841086554108225200, + 13137274196078793342, + 16425890809400729170, + 543748023531482226, + 12911341824757765867, + 6130769529492555516, + 17464364513773308529, + 8135024473411487036, + 8199952496605296533, + 17000930268239208350, + 11365150528198970098, + 3910609664632887504, + 17015736495475695160, + 15830184836163169787, + 779275451287805172, + 9736929721512721880, + 10080335247001726566, + 15227726128874100012, + 1393190085778692529, + 9302463979857124089, + 14146909236891718692, + 6360433927422710088, + 1068109297951168379, + 14970291317558514300, + 18251834742899831204, + 8337441932856161550, + 8975764957939407830, + 16723933604537809656, + 14181029625715872807, + 8964235540437354159, + 7158553321742828616, + 2352463493722653363, + 3655135188814725195, + 10346795930764610188, + 6386044658556652360, + 16515536397065299998, + 2892694445438428269, + 990540318472389857, + ], + [ + 14849741581356091611, + 13953047772310366332, + 10633261504326595800, + 5733708757747985702, + 2556390231574911162, + 10626917001579573345, + 10633509801202537940, + 1686911392781141410, + 5639129121430519872, + 2985632805118924439, + 11423786337194206539, + 14618590950960551662, + 3062699519276168020, + 11566866649592852901, + 16633187448966215935, + 8834693927249245073, + 872180695736142129, + 10358972481939290612, + 9801768435872660888, + 14596026222927642280, + 2829854436173100462, + 13378812551658757200, + 17503623502361840337, + 4897629636187619580, + 1968018396796990407, + 5516379291872860712, + 14575598225767317841, + 6465311422799298575, + 6705914018783256253, + 9078148970688696767, + 12268291135902803407, + 3721447081500569193, + 8521178113410734205, + 265511362559666379, + 7110064706961992866, + 8464788157842975536, + 12486131210347647095, + 9171851522810154092, + 376253057309073521, + 1954075553568124000, + 16233425577355320017, + 12891218820996378536, + 3118609758744696679, + 17458579353753392132, + 12317353753597871574, + 13862746674503522835, + 11722307545198100664, + 13591439439148402981, + 13951670265160855627, + 9267431564010354000, + 17286601790357282787, + 9350425316280663882, + 9697163920834931593, + 10529134727302704903, + 15720421915194499552, + 13128851462050784572, + 3942937226007518902, + 9591161745312598409, + 3556667090572903329, + 16189383950414263960, + 428210347219958151, + 2795766616179392388, + 6411935405426735200, + 3704905749615557748, + ], + [ + 18016845575650718377, + 10276613593154530350, + 10640091575455315298, + 1221661866903636906, + 14365332218531812981, + 13544364184423968337, + 12461384581630362830, + 997242709366829489, + 13622312128853790825, + 8072786099502180970, + 8158663003131535196, + 9367349114229485217, + 9461383047484438844, + 2357242016491822549, + 12755474712998509663, + 9768458552620615774, + 4823809135465785107, + 2768308362137845456, + 3012883833502871742, + 6006390139055901721, + 8028824787201366396, + 7482246287535462233, + 17523133526919708402, + 2894859123557708669, + 17951399237407115697, + 15377386222094209036, + 17836204611672644168, + 12413029210400035613, + 8615403705959355031, + 6554537249093636763, + 17919666759153485338, + 4144167350879495211, + 983027456863392320, + 7724128919774820252, + 576099001832218419, + 12029185248175818703, + 8258924543961817504, + 9491805652083256113, + 11142164475553972407, + 4450491108098721368, + 3697489051241740604, + 4326070667946664398, + 14654980775062674677, + 7164393759970224779, + 6763621709896032169, + 4935071616379639239, + 15556627948684922602, + 16150662434123662642, + 15498002696461857780, + 2383098017664197063, + 15229497595935011607, + 13845162191801702183, + 9290775142145407982, + 5362909295303904739, + 136843864736711469, + 13057412136774387333, + 11060519906354337380, + 691208480072817593, + 5547215092743600855, + 9624087952374212334, + 15245986767878542936, + 6789734335256095458, + 8487287581332487525, + 11194381536812049039, + ], + [ + 14207499017760900374, + 14255228210761312180, + 12306900719525692526, + 10853161885522385616, + 13742277460701985870, + 15424334704761443115, + 12623321747943706707, + 17007035125949577966, + 3870822864152586264, + 7103311141794728179, + 17896833069581151675, + 2526832568692956128, + 3720866533358506086, + 17480154805493686218, + 15930467061899039405, + 17864964785419997219, + 17532658365710397682, + 10912855042689744124, + 12513916581746061895, + 936935090392388560, + 13347203578323605449, + 14118791656941390670, + 12677494567154340266, + 11651086515179508131, + 16543173710358132147, + 11277211671730677128, + 16874253062173679499, + 4485773131975877215, + 12833420558295790217, + 5368804114189644308, + 15899843864346960792, + 4508630623041454643, + 4116501047047189033, + 3529911464254879893, + 8491613217643546421, + 15578530492689893350, + 10967593072213245006, + 13526615399064781462, + 12005253469821520463, + 8951873683334129929, + 43518471402116944, + 3676389635540963717, + 13317191900089677469, + 5496688994596819218, + 17550867738688964971, + 14086963724633041570, + 249330153296993310, + 11307936793550706388, + 8712714125162934974, + 3337072566160888171, + 6995842130683462841, + 7215747697135091496, + 1546719819110900761, + 12849678058830286779, + 6314765524031697288, + 12419321953553988797, + 13650838063968793391, + 7958321890726488655, + 9015242661226385446, + 9769997204575419550, + 12190760804169107899, + 7798029174446179423, + 3173677334948865050, + 11797262036420789896, + ], + [ + 10460283023326496648, + 9437377412875693802, + 9921446917421829860, + 14599931889493045991, + 4268961049545963187, + 10848046681051236983, + 8578515789525175315, + 18290826087628927976, + 16703578029935928755, + 18246642560319906381, + 18310894933839866902, + 18189899495436209883, + 12245776650375205206, + 16950137755876869212, + 9294919412670909687, + 17653999331604650245, + 15507904384226397701, + 3149575904724991841, + 11773323204420371092, + 3635993261633686332, + 14760776134300129234, + 16413291273644443483, + 17247602357216070292, + 8546494309023155788, + 11896551736492725008, + 2574543911485860628, + 3418106081237248405, + 15876995998136068791, + 17745810661562334105, + 364732677102562669, + 6499259181196633520, + 17619214483464993001, + 1755375795884948711, + 15557023861829569960, + 2694521391989289169, + 3464852456067954004, + 15646777514161168311, + 12660697365465988554, + 7447210235083966536, + 4810973013228237082, + 6795350034557181509, + 11381865254854243368, + 7863880077475816918, + 13421787618868641563, + 9679728077436941505, + 17234589101232576295, + 16231530893888101938, + 6580659246984078181, + 9987433780337895460, + 8696404782017294090, + 12360032408990421426, + 6870496981670331011, + 12033158465144986566, + 17737575184655076961, + 4096614345953467746, + 10474845723594311031, + 3072380023051822731, + 12934338818107793655, + 6904395950861413644, + 13081228377736438990, + 4449691796442505131, + 14530599618042092556, + 11883685823810881117, + 14397843411117512826, + ], + ], +]; + +pub const ZOBRIST_BLACK_TURN: ZobristHash = 10021213122433903175; + +pub const ZOBRIST_CASTLE_WH_K: usize = 0; +pub const ZOBRIST_CASTLE_WH_Q: usize = 1; +pub const ZOBRIST_CASTLE_BL_K: usize = 2; +pub const ZOBRIST_CASTLE_BL_Q: usize = 3; + +pub const ZOBRIST_CASTLES: [ZobristHash; 4] = [ + 2292886189061561677, + 1107787351814947557, + 2627339987452959789, + 9362433047582633881, +]; + +pub const ZOBRIST_EN_PASSANT: [ZobristHash; 8] = [ + 13446489326168201208, + 16561127554913736295, + 706457826239777201, + 6940085010112087595, + 16571136595117891883, + 14041807556703902103, + 8978789431920423267, + 5492414369570698233, +]; diff --git a/src/zobrist.rs b/src/zobrist.rs new file mode 100644 index 0000000..b7c5c4a --- /dev/null +++ b/src/zobrist.rs @@ -0,0 +1,49 @@ +//! Functions related to Zobrist hashes. + +use crate::board::*; + +pub type ZobristHash = u64; + +pub fn get_new_game_hash() -> ZobristHash { + return + get_piece_hash(WHITE, ROOK, A1) + ^ get_piece_hash(WHITE, KNIGHT, B1) + ^ get_piece_hash(WHITE, BISHOP, C1) + ^ get_piece_hash(WHITE, QUEEN, D1) + ^ get_piece_hash(WHITE, KING, E1) + ^ get_piece_hash(WHITE, BISHOP, F1) + ^ get_piece_hash(WHITE, KNIGHT, G1) + ^ get_piece_hash(WHITE, ROOK, H1) + ^ get_piece_hash(WHITE, PAWN, A2) + ^ get_piece_hash(WHITE, PAWN, B2) + ^ get_piece_hash(WHITE, PAWN, C2) + ^ get_piece_hash(WHITE, PAWN, D2) + ^ get_piece_hash(WHITE, PAWN, E2) + ^ get_piece_hash(WHITE, PAWN, F2) + ^ get_piece_hash(WHITE, PAWN, G2) + ^ get_piece_hash(WHITE, PAWN, H2) + ^ get_piece_hash(BLACK, PAWN, A7) + ^ get_piece_hash(BLACK, PAWN, B7) + ^ get_piece_hash(BLACK, PAWN, C7) + ^ get_piece_hash(BLACK, PAWN, D7) + ^ get_piece_hash(BLACK, PAWN, E7) + ^ get_piece_hash(BLACK, PAWN, F7) + ^ get_piece_hash(BLACK, PAWN, G7) + ^ get_piece_hash(BLACK, PAWN, H7) + ^ get_piece_hash(BLACK, ROOK, A8) + ^ get_piece_hash(BLACK, KNIGHT, B8) + ^ get_piece_hash(BLACK, BISHOP, C8) + ^ get_piece_hash(BLACK, QUEEN, D8) + ^ get_piece_hash(BLACK, KING, E8) + ^ get_piece_hash(BLACK, BISHOP, F8) + ^ get_piece_hash(BLACK, KNIGHT, G8) + ^ get_piece_hash(BLACK, ROOK, H8) + ^ ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_K] + ^ ZOBRIST_CASTLES[ZOBRIST_CASTLE_WH_Q] + ^ ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_K] + ^ ZOBRIST_CASTLES[ZOBRIST_CASTLE_BL_Q] +} + +pub fn get_piece_hash(color: Color, piece: Piece, square: Square) -> ZobristHash { + ZOBRIST_PIECES[color][piece][square as usize] +}