Skip to content

Commit

Permalink
Merge hash key computation functions
Browse files Browse the repository at this point in the history
No functional change.
  • Loading branch information
mcostalba committed Mar 12, 2014
1 parent cc3002f commit 1e032ec
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 98 deletions.
146 changes: 57 additions & 89 deletions src/position.cpp
Expand Up @@ -284,12 +284,9 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) {
// handle also common incorrect FEN with fullmove = 0.
gamePly = std::max(2 * (gamePly - 1), 0) + int(sideToMove == BLACK);

st->key = compute_key();
st->pawnKey = compute_pawn_key();
st->materialKey = compute_material_key();
compute_keys(st);
compute_non_pawn_material(st);
st->psq = compute_psq_score();
st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
chess960 = isChess960;
thisThread = th;
Expand Down Expand Up @@ -1077,67 +1074,53 @@ void Position::clear() {
}


/// Position::compute_key() computes the hash key of the position. The hash
/// key is usually updated incrementally as moves are made and unmade. The
/// compute_key() function is only used when a new position is set up, and
/// to verify the correctness of the hash key when running in debug mode.
/// Position::compute_keys() computes the hash keys of the position, pawns and
/// material configuration. The hash keys are usually updated incrementally as
/// moves are made and unmade. The function is only used when a new position is
/// set up, and to verify the correctness of the keys when running in debug mode.

Key Position::compute_key() const {
void Position::compute_keys(StateInfo* si) const {

Key k = Zobrist::castling[st->castlingRights];
si->key = si->pawnKey = si->materialKey = 0;

for (Bitboard b = pieces(); b; )
{
Square s = pop_lsb(&b);
k ^= Zobrist::psq[color_of(piece_on(s))][type_of(piece_on(s))][s];
si->key ^= Zobrist::psq[color_of(piece_on(s))][type_of(piece_on(s))][s];
}

if (ep_square() != SQ_NONE)
k ^= Zobrist::enpassant[file_of(ep_square())];
si->key ^= Zobrist::enpassant[file_of(ep_square())];

if (sideToMove == BLACK)
k ^= Zobrist::side;
si->key ^= Zobrist::side;

return k;
}


/// Position::compute_pawn_key() computes the hash key of the position. The
/// hash key is usually updated incrementally as moves are made and unmade.
/// The compute_pawn_key() function is only used when a new position is set
/// up, and to verify the correctness of the pawn hash key when running in
/// debug mode.

Key Position::compute_pawn_key() const {

Key k = 0;
si->key ^= Zobrist::castling[st->castlingRights];

for (Bitboard b = pieces(PAWN); b; )
{
Square s = pop_lsb(&b);
k ^= Zobrist::psq[color_of(piece_on(s))][PAWN][s];
si->pawnKey ^= Zobrist::psq[color_of(piece_on(s))][PAWN][s];
}

return k;
for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
for (int cnt = 0; cnt < pieceCount[c][pt]; ++cnt)
si->materialKey ^= Zobrist::psq[c][pt][cnt];
}


/// Position::compute_material_key() computes the hash key of the position.
/// The hash key is usually updated incrementally as moves are made and unmade.
/// The compute_material_key() function is only used when a new position is set
/// up, and to verify the correctness of the material hash key when running in
/// debug mode.
/// Position::compute_non_pawn_material() computes the total non-pawn middlegame
/// material value for each side. Material values are updated incrementally during
/// the search. This function is only used when initializing a new Position object.

Key Position::compute_material_key() const {
void Position::compute_non_pawn_material(StateInfo* si) const {

Key k = 0;
si->npMaterial[WHITE] = si->npMaterial[BLACK] = VALUE_ZERO;

for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
for (int cnt = 0; cnt < pieceCount[c][pt]; ++cnt)
k ^= Zobrist::psq[c][pt][cnt];

return k;
for (PieceType pt = KNIGHT; pt <= QUEEN; ++pt)
si->npMaterial[c] += pieceCount[c][pt] * PieceValue[MG][pt];
}


Expand All @@ -1161,22 +1144,6 @@ Score Position::compute_psq_score() const {
}


/// Position::compute_non_pawn_material() computes the total non-pawn middlegame
/// material value for the given side. Material values are updated incrementally
/// during the search. This function is only used when initializing a new Position
/// object.

Value Position::compute_non_pawn_material(Color c) const {

Value value = VALUE_ZERO;

for (PieceType pt = KNIGHT; pt <= QUEEN; ++pt)
value += pieceCount[c][pt] * PieceValue[MG][pt];

return value;
}


/// Position::is_draw() tests whether the position is drawn by material, 50 moves
/// rule or repetition. It does not detect stalemates.

Expand Down Expand Up @@ -1250,18 +1217,16 @@ bool Position::pos_is_ok(int* failedStep) const {
// What features of the position should be verified?
const bool all = false;

const bool debugBitboards = all || false;
const bool debugKingCount = all || false;
const bool debugKingCapture = all || false;
const bool debugCheckerCount = all || false;
const bool debugKey = all || false;
const bool debugMaterialKey = all || false;
const bool debugPawnKey = all || false;
const bool debugIncrementalEval = all || false;
const bool debugNonPawnMaterial = all || false;
const bool debugPieceCounts = all || false;
const bool debugPieceList = all || false;
const bool debugCastlingSquares = all || false;
const bool testBitboards = all || false;
const bool testKingCount = all || false;
const bool testKingCapture = all || false;
const bool testCheckerCount = all || false;
const bool testKeys = all || false;
const bool testIncrementalEval = all || false;
const bool testNonPawnMaterial = all || false;
const bool testPieceCounts = all || false;
const bool testPieceList = all || false;
const bool testCastlingSquares = all || false;

if (*step = 1, sideToMove != WHITE && sideToMove != BLACK)
return false;
Expand All @@ -1272,19 +1237,19 @@ bool Position::pos_is_ok(int* failedStep) const {
if ((*step)++, piece_on(king_square(BLACK)) != B_KING)
return false;

if ((*step)++, debugKingCount)
if ((*step)++, testKingCount)
if ( std::count(board, board + SQUARE_NB, W_KING) != 1
|| std::count(board, board + SQUARE_NB, B_KING) != 1)
return false;

if ((*step)++, debugKingCapture)
if ((*step)++, testKingCapture)
if (attackers_to(king_square(~sideToMove)) & pieces(sideToMove))
return false;

if ((*step)++, debugCheckerCount && popcount<Full>(st->checkersBB) > 2)
if ((*step)++, testCheckerCount && popcount<Full>(st->checkersBB) > 2)
return false;

if ((*step)++, debugBitboards)
if ((*step)++, testBitboards)
{
// The intersection of the white and black pieces must be empty
if (pieces(WHITE) & pieces(BLACK))
Expand All @@ -1305,38 +1270,41 @@ bool Position::pos_is_ok(int* failedStep) const {
if ((*step)++, ep_square() != SQ_NONE && relative_rank(sideToMove, ep_square()) != RANK_6)
return false;

if ((*step)++, debugKey && st->key != compute_key())
return false;

if ((*step)++, debugPawnKey && st->pawnKey != compute_pawn_key())
return false;
if ((*step)++, testKeys)
{
StateInfo si;
compute_keys(&si);
if (st->key != si.key || st->pawnKey != si.pawnKey || st->materialKey != si.materialKey)
return false;
}

if ((*step)++, debugMaterialKey && st->materialKey != compute_material_key())
return false;
if ((*step)++, testNonPawnMaterial)
{
StateInfo si;
compute_non_pawn_material(&si);
if ( st->npMaterial[WHITE] != si.npMaterial[WHITE]
|| st->npMaterial[BLACK] != si.npMaterial[BLACK])
return false;
}

if ((*step)++, debugIncrementalEval && st->psq != compute_psq_score())
if ((*step)++, testIncrementalEval && st->psq != compute_psq_score())
return false;

if ((*step)++, debugNonPawnMaterial)
if ( st->npMaterial[WHITE] != compute_non_pawn_material(WHITE)
|| st->npMaterial[BLACK] != compute_non_pawn_material(BLACK))
return false;

if ((*step)++, debugPieceCounts)
if ((*step)++, testPieceCounts)
for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
if (pieceCount[c][pt] != popcount<Full>(pieces(c, pt)))
return false;

if ((*step)++, debugPieceList)
if ((*step)++, testPieceList)
for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
for (int i = 0; i < pieceCount[c][pt]; ++i)
if ( board[pieceList[c][pt][i]] != make_piece(c, pt)
|| index[pieceList[c][pt][i]] != i)
return false;

if ((*step)++, debugCastlingSquares)
if ((*step)++, testCastlingSquares)
for (Color c = WHITE; c <= BLACK; ++c)
for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1))
{
Expand Down
12 changes: 3 additions & 9 deletions src/position.h
Expand Up @@ -171,6 +171,9 @@ class Position {
// Initialization helpers (used while setting up a position)
void clear();
void set_castling_right(Color c, Square rfrom);
void compute_keys(StateInfo* si) const;
void compute_non_pawn_material(StateInfo* si) const;
Score compute_psq_score() const;

// Helper functions
void do_castling(Square kfrom, Square kto, Square rfrom, Square rto);
Expand All @@ -179,15 +182,6 @@ class Position {
void remove_piece(Square s, Color c, PieceType pt);
void move_piece(Square from, Square to, Color c, PieceType pt);

// Computing hash keys from scratch (for initialization and debugging)
Key compute_key() const;
Key compute_pawn_key() const;
Key compute_material_key() const;

// Computing incremental evaluation scores and material counts
Score compute_psq_score() const;
Value compute_non_pawn_material(Color c) const;

// Board and pieces
Piece board[SQUARE_NB];
Bitboard byTypeBB[PIECE_TYPE_NB];
Expand Down

0 comments on commit 1e032ec

Please sign in to comment.