@@ -36,13 +36,8 @@ using std::string;
3636using std::cout;
3737using std::endl;
3838
39- Key Position::zobrist[2 ][8 ][64 ];
40- Key Position::zobEp[8 ];
41- Key Position::zobCastle[16 ];
42- Key Position::zobSideToMove;
43- Key Position::zobExclusion;
44-
45- Score Position::pieceSquareTable[16 ][64 ];
39+ // To convert a Piece to and from a FEN char
40+ static const string PieceToChar (" PNBRQK pnbrqk" );
4641
4742// Material values arrays, indexed by Piece
4843const Value PieceValueMidgame[17 ] = {
@@ -63,8 +58,62 @@ const Value PieceValueEndgame[17] = {
6358 RookValueEndgame, QueenValueEndgame
6459};
6560
66- // To convert a Piece to and from a FEN char
67- static const string PieceToChar (" PNBRQK pnbrqk" );
61+ CACHE_LINE_ALIGNMENT
62+
63+ Score pieceSquareTable[16 ][64 ];
64+
65+ namespace Zobrist {
66+
67+ Key psq[2 ][8 ][64 ]; // [color][pieceType][square]/[piece count]
68+ Key enpassant[8 ]; // [file]
69+ Key castle[16 ]; // [castleRight]
70+ Key side;
71+ Key exclusion;
72+
73+ // / init() initializes at startup the various arrays used to compute hash keys
74+ // / and the piece square tables. The latter is a two-step operation: First, the
75+ // / white halves of the tables are copied from PSQT[] tables. Second, the black
76+ // / halves of the tables are initialized by flipping and changing the sign of
77+ // / the white scores.
78+
79+ void init () {
80+
81+ RKISS rk;
82+
83+ for (Color c = WHITE; c <= BLACK; c++)
84+ for (PieceType pt = PAWN; pt <= KING; pt++)
85+ for (Square s = SQ_A1; s <= SQ_H8; s++)
86+ psq[c][pt][s] = rk.rand <Key>();
87+
88+ for (File f = FILE_A; f <= FILE_H; f++)
89+ enpassant[f] = rk.rand <Key>();
90+
91+ for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
92+ {
93+ Bitboard b = cr;
94+ while (b)
95+ {
96+ Key k = castle[1ULL << pop_lsb (&b)];
97+ castle[cr] ^= k ? k : rk.rand <Key>();
98+ }
99+ }
100+
101+ side = rk.rand <Key>();
102+ exclusion = rk.rand <Key>();
103+
104+ for (PieceType pt = PAWN; pt <= KING; pt++)
105+ {
106+ Score v = make_score (PieceValueMidgame[pt], PieceValueEndgame[pt]);
107+
108+ for (Square s = SQ_A1; s <= SQ_H8; s++)
109+ {
110+ pieceSquareTable[make_piece (WHITE, pt)][ s] = (v + PSQT[pt][s]);
111+ pieceSquareTable[make_piece (BLACK, pt)][~s] = -(v + PSQT[pt][s]);
112+ }
113+ }
114+ }
115+
116+ } // namespace Zobrist
68117
69118
70119// / CheckInfo c'tor
@@ -709,7 +758,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
709758 st = &newSt;
710759
711760 // Update side to move
712- k ^= zobSideToMove ;
761+ k ^= Zobrist::side ;
713762
714763 // Increment the 50 moves rule draw counter. Resetting it to zero in the
715764 // case of a capture or a pawn move is taken care of later.
@@ -756,7 +805,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
756805 board[capsq] = NO_PIECE;
757806 }
758807
759- st->pawnKey ^= zobrist [them][PAWN][capsq];
808+ st->pawnKey ^= Zobrist::psq [them][PAWN][capsq];
760809 }
761810 else
762811 st->npMaterial [them] -= PieceValueMidgame[capture];
@@ -779,8 +828,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
779828 pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
780829
781830 // Update hash keys
782- k ^= zobrist [them][capture][capsq];
783- st->materialKey ^= zobrist [them][capture][pieceCount[them][capture]];
831+ k ^= Zobrist::psq [them][capture][capsq];
832+ st->materialKey ^= Zobrist::psq [them][capture][pieceCount[them][capture]];
784833
785834 // Update incremental scores
786835 st->psqScore -= pieceSquareTable[make_piece (them, capture)][capsq];
@@ -790,20 +839,20 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
790839 }
791840
792841 // Update hash key
793- k ^= zobrist [us][pt][from] ^ zobrist [us][pt][to];
842+ k ^= Zobrist::psq [us][pt][from] ^ Zobrist::psq [us][pt][to];
794843
795844 // Reset en passant square
796845 if (st->epSquare != SQ_NONE)
797846 {
798- k ^= zobEp [file_of (st->epSquare )];
847+ k ^= Zobrist::enpassant [file_of (st->epSquare )];
799848 st->epSquare = SQ_NONE;
800849 }
801850
802851 // Update castle rights if needed
803852 if (st->castleRights && (castleRightsMask[from] | castleRightsMask[to]))
804853 {
805854 int cr = castleRightsMask[from] | castleRightsMask[to];
806- k ^= zobCastle [st->castleRights & cr];
855+ k ^= Zobrist::castle [st->castleRights & cr];
807856 st->castleRights &= ~cr;
808857 }
809858
@@ -832,7 +881,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
832881 && (attacks_from<PAWN>(from + pawn_push (us), us) & pieces (them, PAWN)))
833882 {
834883 st->epSquare = Square ((from + to) / 2 );
835- k ^= zobEp [file_of (st->epSquare )];
884+ k ^= Zobrist::enpassant [file_of (st->epSquare )];
836885 }
837886
838887 if (type_of (m) == PROMOTION)
@@ -857,10 +906,10 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
857906 pieceList[us][promotion][index[to]] = to;
858907
859908 // Update hash keys
860- k ^= zobrist [us][PAWN][to] ^ zobrist [us][promotion][to];
861- st->pawnKey ^= zobrist [us][PAWN][to];
862- st->materialKey ^= zobrist [us][promotion][pieceCount[us][promotion]++]
863- ^ zobrist [us][PAWN][pieceCount[us][PAWN]];
909+ k ^= Zobrist::psq [us][PAWN][to] ^ Zobrist::psq [us][promotion][to];
910+ st->pawnKey ^= Zobrist::psq [us][PAWN][to];
911+ st->materialKey ^= Zobrist::psq [us][promotion][pieceCount[us][promotion]++]
912+ ^ Zobrist::psq [us][PAWN][pieceCount[us][PAWN]];
864913
865914 // Update incremental score
866915 st->psqScore += pieceSquareTable[make_piece (us, promotion)][to]
@@ -871,7 +920,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
871920 }
872921
873922 // Update pawn hash key
874- st->pawnKey ^= zobrist [us][PAWN][from] ^ zobrist [us][PAWN][to];
923+ st->pawnKey ^= Zobrist::psq [us][PAWN][from] ^ Zobrist::psq [us][PAWN][to];
875924
876925 // Reset rule 50 draw counter
877926 st->rule50 = 0 ;
@@ -1089,18 +1138,18 @@ void Position::do_castle_move(Move m) {
10891138 st->psqScore += psq_delta (rook, rfrom, rto);
10901139
10911140 // Update hash key
1092- st->key ^= zobrist [us][KING][kfrom] ^ zobrist [us][KING][kto];
1093- st->key ^= zobrist [us][ROOK][rfrom] ^ zobrist [us][ROOK][rto];
1141+ st->key ^= Zobrist::psq [us][KING][kfrom] ^ Zobrist::psq [us][KING][kto];
1142+ st->key ^= Zobrist::psq [us][ROOK][rfrom] ^ Zobrist::psq [us][ROOK][rto];
10941143
10951144 // Clear en passant square
10961145 if (st->epSquare != SQ_NONE)
10971146 {
1098- st->key ^= zobEp [file_of (st->epSquare )];
1147+ st->key ^= Zobrist::enpassant [file_of (st->epSquare )];
10991148 st->epSquare = SQ_NONE;
11001149 }
11011150
11021151 // Update castling rights
1103- st->key ^= zobCastle [st->castleRights & castleRightsMask[kfrom]];
1152+ st->key ^= Zobrist::castle [st->castleRights & castleRightsMask[kfrom]];
11041153 st->castleRights &= ~castleRightsMask[kfrom];
11051154
11061155 // Update checkers BB
@@ -1141,9 +1190,9 @@ void Position::do_null_move(StateInfo& backupSt) {
11411190 if (Do)
11421191 {
11431192 if (st->epSquare != SQ_NONE)
1144- st->key ^= zobEp [file_of (st->epSquare )];
1193+ st->key ^= Zobrist::enpassant [file_of (st->epSquare )];
11451194
1146- st->key ^= zobSideToMove ;
1195+ st->key ^= Zobrist::side ;
11471196 prefetch ((char *)TT.first_entry (st->key ));
11481197
11491198 st->epSquare = SQ_NONE;
@@ -1320,19 +1369,19 @@ void Position::put_piece(Piece p, Square s) {
13201369
13211370Key Position::compute_key () const {
13221371
1323- Key k = zobCastle [st->castleRights ];
1372+ Key k = Zobrist::castle [st->castleRights ];
13241373
13251374 for (Bitboard b = pieces (); b; )
13261375 {
13271376 Square s = pop_lsb (&b);
1328- k ^= zobrist [color_of (piece_on (s))][type_of (piece_on (s))][s];
1377+ k ^= Zobrist::psq [color_of (piece_on (s))][type_of (piece_on (s))][s];
13291378 }
13301379
13311380 if (ep_square () != SQ_NONE)
1332- k ^= zobEp [file_of (ep_square ())];
1381+ k ^= Zobrist::enpassant [file_of (ep_square ())];
13331382
13341383 if (sideToMove == BLACK)
1335- k ^= zobSideToMove ;
1384+ k ^= Zobrist::side ;
13361385
13371386 return k;
13381387}
@@ -1351,7 +1400,7 @@ Key Position::compute_pawn_key() const {
13511400 for (Bitboard b = pieces (PAWN); b; )
13521401 {
13531402 Square s = pop_lsb (&b);
1354- k ^= zobrist [color_of (piece_on (s))][PAWN][s];
1403+ k ^= Zobrist::psq [color_of (piece_on (s))][PAWN][s];
13551404 }
13561405
13571406 return k;
@@ -1371,7 +1420,7 @@ Key Position::compute_material_key() const {
13711420 for (Color c = WHITE; c <= BLACK; c++)
13721421 for (PieceType pt = PAWN; pt <= QUEEN; pt++)
13731422 for (int cnt = 0 ; cnt < piece_count (c, pt); cnt++)
1374- k ^= zobrist [c][pt][cnt];
1423+ k ^= Zobrist::psq [c][pt][cnt];
13751424
13761425 return k;
13771426}
@@ -1455,50 +1504,6 @@ template bool Position::is_draw<false>() const;
14551504template bool Position::is_draw<true >() const ;
14561505
14571506
1458- // / Position::init() is a static member function which initializes at startup
1459- // / the various arrays used to compute hash keys and the piece square tables.
1460- // / The latter is a two-step operation: First, the white halves of the tables
1461- // / are copied from PSQT[] tables. Second, the black halves of the tables are
1462- // / initialized by flipping and changing the sign of the white scores.
1463-
1464- void Position::init () {
1465-
1466- RKISS rk;
1467-
1468- for (Color c = WHITE; c <= BLACK; c++)
1469- for (PieceType pt = PAWN; pt <= KING; pt++)
1470- for (Square s = SQ_A1; s <= SQ_H8; s++)
1471- zobrist[c][pt][s] = rk.rand <Key>();
1472-
1473- for (File f = FILE_A; f <= FILE_H; f++)
1474- zobEp[f] = rk.rand <Key>();
1475-
1476- for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
1477- {
1478- Bitboard b = cr;
1479- while (b)
1480- {
1481- Key k = zobCastle[1ULL << pop_lsb (&b)];
1482- zobCastle[cr] ^= k ? k : rk.rand <Key>();
1483- }
1484- }
1485-
1486- zobSideToMove = rk.rand <Key>();
1487- zobExclusion = rk.rand <Key>();
1488-
1489- for (PieceType pt = PAWN; pt <= KING; pt++)
1490- {
1491- Score v = make_score (PieceValueMidgame[pt], PieceValueEndgame[pt]);
1492-
1493- for (Square s = SQ_A1; s <= SQ_H8; s++)
1494- {
1495- pieceSquareTable[make_piece (WHITE, pt)][ s] = (v + PSQT[pt][s]);
1496- pieceSquareTable[make_piece (BLACK, pt)][~s] = -(v + PSQT[pt][s]);
1497- }
1498- }
1499- }
1500-
1501-
15021507// / Position::flip() flips position with the white and black sides reversed. This
15031508// / is only useful for debugging especially for finding evaluation symmetry bugs.
15041509
0 commit comments