X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=ebbf82992273cd44b60d8a6d600b0626d5bdf63f;hp=d00a531c0d5caa1d9e726171d0953ab37ac60f13;hb=1e032ece92da0085000cfdde28cab05029dedce3;hpb=cc3002ff0450e4f396cd95c0dcbf44bb66dab695 diff --git a/src/position.cpp b/src/position.cpp index d00a531c..ebbf8299 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -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; @@ -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]; } @@ -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. @@ -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; @@ -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(st->checkersBB) > 2) + if ((*step)++, testCheckerCount && popcount(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)) @@ -1305,30 +1270,33 @@ 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(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) @@ -1336,7 +1304,7 @@ bool Position::pos_is_ok(int* failedStep) const { || 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)) {