Move zobrist keys out of Position

Are used by Position but do not belong to that class,
there is only one instance of them (that's why were
defined as static), so move to a proper namespace instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba
2012-08-20 18:09:57 +01:00
parent ec9038b7b4
commit 7c8b7222f5
4 changed files with 98 additions and 92 deletions

View File

@@ -36,13 +36,8 @@ using std::string;
using std::cout;
using std::endl;
Key Position::zobrist[2][8][64];
Key Position::zobEp[8];
Key Position::zobCastle[16];
Key Position::zobSideToMove;
Key Position::zobExclusion;
Score Position::pieceSquareTable[16][64];
// To convert a Piece to and from a FEN char
static const string PieceToChar(" PNBRQK pnbrqk");
// Material values arrays, indexed by Piece
const Value PieceValueMidgame[17] = {
@@ -63,8 +58,62 @@ const Value PieceValueEndgame[17] = {
RookValueEndgame, QueenValueEndgame
};
// To convert a Piece to and from a FEN char
static const string PieceToChar(" PNBRQK pnbrqk");
CACHE_LINE_ALIGNMENT
Score pieceSquareTable[16][64];
namespace Zobrist {
Key psq[2][8][64]; // [color][pieceType][square]/[piece count]
Key enpassant[8]; // [file]
Key castle[16]; // [castleRight]
Key side;
Key exclusion;
/// init() initializes at startup the various arrays used to compute hash keys
/// and the piece square tables. The latter is a two-step operation: First, the
/// white halves of the tables are copied from PSQT[] tables. Second, the black
/// halves of the tables are initialized by flipping and changing the sign of
/// the white scores.
void init() {
RKISS rk;
for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= KING; pt++)
for (Square s = SQ_A1; s <= SQ_H8; s++)
psq[c][pt][s] = rk.rand<Key>();
for (File f = FILE_A; f <= FILE_H; f++)
enpassant[f] = rk.rand<Key>();
for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
{
Bitboard b = cr;
while (b)
{
Key k = castle[1ULL << pop_lsb(&b)];
castle[cr] ^= k ? k : rk.rand<Key>();
}
}
side = rk.rand<Key>();
exclusion = rk.rand<Key>();
for (PieceType pt = PAWN; pt <= KING; pt++)
{
Score v = make_score(PieceValueMidgame[pt], PieceValueEndgame[pt]);
for (Square s = SQ_A1; s <= SQ_H8; s++)
{
pieceSquareTable[make_piece(WHITE, pt)][ s] = (v + PSQT[pt][s]);
pieceSquareTable[make_piece(BLACK, pt)][~s] = -(v + PSQT[pt][s]);
}
}
}
} // namespace Zobrist
/// CheckInfo c'tor
@@ -709,7 +758,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
st = &newSt;
// Update side to move
k ^= zobSideToMove;
k ^= Zobrist::side;
// Increment the 50 moves rule draw counter. Resetting it to zero in the
// 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
board[capsq] = NO_PIECE;
}
st->pawnKey ^= zobrist[them][PAWN][capsq];
st->pawnKey ^= Zobrist::psq[them][PAWN][capsq];
}
else
st->npMaterial[them] -= PieceValueMidgame[capture];
@@ -779,8 +828,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
// Update hash keys
k ^= zobrist[them][capture][capsq];
st->materialKey ^= zobrist[them][capture][pieceCount[them][capture]];
k ^= Zobrist::psq[them][capture][capsq];
st->materialKey ^= Zobrist::psq[them][capture][pieceCount[them][capture]];
// Update incremental scores
st->psqScore -= pieceSquareTable[make_piece(them, capture)][capsq];
@@ -790,12 +839,12 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
}
// Update hash key
k ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
k ^= Zobrist::psq[us][pt][from] ^ Zobrist::psq[us][pt][to];
// Reset en passant square
if (st->epSquare != SQ_NONE)
{
k ^= zobEp[file_of(st->epSquare)];
k ^= Zobrist::enpassant[file_of(st->epSquare)];
st->epSquare = SQ_NONE;
}
@@ -803,7 +852,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
if (st->castleRights && (castleRightsMask[from] | castleRightsMask[to]))
{
int cr = castleRightsMask[from] | castleRightsMask[to];
k ^= zobCastle[st->castleRights & cr];
k ^= Zobrist::castle[st->castleRights & cr];
st->castleRights &= ~cr;
}
@@ -832,7 +881,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
&& (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(them, PAWN)))
{
st->epSquare = Square((from + to) / 2);
k ^= zobEp[file_of(st->epSquare)];
k ^= Zobrist::enpassant[file_of(st->epSquare)];
}
if (type_of(m) == PROMOTION)
@@ -857,10 +906,10 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
pieceList[us][promotion][index[to]] = to;
// Update hash keys
k ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to];
st->pawnKey ^= zobrist[us][PAWN][to];
st->materialKey ^= zobrist[us][promotion][pieceCount[us][promotion]++]
^ zobrist[us][PAWN][pieceCount[us][PAWN]];
k ^= Zobrist::psq[us][PAWN][to] ^ Zobrist::psq[us][promotion][to];
st->pawnKey ^= Zobrist::psq[us][PAWN][to];
st->materialKey ^= Zobrist::psq[us][promotion][pieceCount[us][promotion]++]
^ Zobrist::psq[us][PAWN][pieceCount[us][PAWN]];
// Update incremental score
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
}
// Update pawn hash key
st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
st->pawnKey ^= Zobrist::psq[us][PAWN][from] ^ Zobrist::psq[us][PAWN][to];
// Reset rule 50 draw counter
st->rule50 = 0;
@@ -1089,18 +1138,18 @@ void Position::do_castle_move(Move m) {
st->psqScore += psq_delta(rook, rfrom, rto);
// Update hash key
st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto];
st->key ^= zobrist[us][ROOK][rfrom] ^ zobrist[us][ROOK][rto];
st->key ^= Zobrist::psq[us][KING][kfrom] ^ Zobrist::psq[us][KING][kto];
st->key ^= Zobrist::psq[us][ROOK][rfrom] ^ Zobrist::psq[us][ROOK][rto];
// Clear en passant square
if (st->epSquare != SQ_NONE)
{
st->key ^= zobEp[file_of(st->epSquare)];
st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
st->epSquare = SQ_NONE;
}
// Update castling rights
st->key ^= zobCastle[st->castleRights & castleRightsMask[kfrom]];
st->key ^= Zobrist::castle[st->castleRights & castleRightsMask[kfrom]];
st->castleRights &= ~castleRightsMask[kfrom];
// Update checkers BB
@@ -1141,9 +1190,9 @@ void Position::do_null_move(StateInfo& backupSt) {
if (Do)
{
if (st->epSquare != SQ_NONE)
st->key ^= zobEp[file_of(st->epSquare)];
st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
st->key ^= zobSideToMove;
st->key ^= Zobrist::side;
prefetch((char*)TT.first_entry(st->key));
st->epSquare = SQ_NONE;
@@ -1320,19 +1369,19 @@ void Position::put_piece(Piece p, Square s) {
Key Position::compute_key() const {
Key k = zobCastle[st->castleRights];
Key k = Zobrist::castle[st->castleRights];
for (Bitboard b = pieces(); b; )
{
Square s = pop_lsb(&b);
k ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s];
k ^= Zobrist::psq[color_of(piece_on(s))][type_of(piece_on(s))][s];
}
if (ep_square() != SQ_NONE)
k ^= zobEp[file_of(ep_square())];
k ^= Zobrist::enpassant[file_of(ep_square())];
if (sideToMove == BLACK)
k ^= zobSideToMove;
k ^= Zobrist::side;
return k;
}
@@ -1351,7 +1400,7 @@ Key Position::compute_pawn_key() const {
for (Bitboard b = pieces(PAWN); b; )
{
Square s = pop_lsb(&b);
k ^= zobrist[color_of(piece_on(s))][PAWN][s];
k ^= Zobrist::psq[color_of(piece_on(s))][PAWN][s];
}
return k;
@@ -1371,7 +1420,7 @@ Key Position::compute_material_key() const {
for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= QUEEN; pt++)
for (int cnt = 0; cnt < piece_count(c, pt); cnt++)
k ^= zobrist[c][pt][cnt];
k ^= Zobrist::psq[c][pt][cnt];
return k;
}
@@ -1455,50 +1504,6 @@ template bool Position::is_draw<false>() const;
template bool Position::is_draw<true>() const;
/// Position::init() is a static member function which initializes at startup
/// the various arrays used to compute hash keys and the piece square tables.
/// The latter is a two-step operation: First, the white halves of the tables
/// are copied from PSQT[] tables. Second, the black halves of the tables are
/// initialized by flipping and changing the sign of the white scores.
void Position::init() {
RKISS rk;
for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= KING; pt++)
for (Square s = SQ_A1; s <= SQ_H8; s++)
zobrist[c][pt][s] = rk.rand<Key>();
for (File f = FILE_A; f <= FILE_H; f++)
zobEp[f] = rk.rand<Key>();
for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
{
Bitboard b = cr;
while (b)
{
Key k = zobCastle[1ULL << pop_lsb(&b)];
zobCastle[cr] ^= k ? k : rk.rand<Key>();
}
}
zobSideToMove = rk.rand<Key>();
zobExclusion = rk.rand<Key>();
for (PieceType pt = PAWN; pt <= KING; pt++)
{
Score v = make_score(PieceValueMidgame[pt], PieceValueEndgame[pt]);
for (Square s = SQ_A1; s <= SQ_H8; s++)
{
pieceSquareTable[make_piece(WHITE, pt)][ s] = (v + PSQT[pt][s]);
pieceSquareTable[make_piece(BLACK, pt)][~s] = -(v + PSQT[pt][s]);
}
}
}
/// Position::flip() flips position with the white and black sides reversed. This
/// is only useful for debugging especially for finding evaluation symmetry bugs.