From 6f3d78769257c9ef1678a35b0b7b48629e0aab1e Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Wed, 12 Mar 2014 22:46:17 +0100 Subject: [PATCH] Further merge StateInfo setup functions No functional change. --- src/position.cpp | 186 +++++++++++++++++++---------------------------- src/position.h | 4 +- 2 files changed, 76 insertions(+), 114 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index ebbf8299..3f019770 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -172,6 +172,21 @@ Position& Position::operator=(const Position& pos) { } +/// Position::clear() erases the position object to a pristine state, with an +/// empty board, white to move, and no castling rights. + +void Position::clear() { + + std::memset(this, 0, sizeof(Position)); + startState.epSquare = SQ_NONE; + st = &startState; + + for (int i = 0; i < PIECE_TYPE_NB; ++i) + for (int j = 0; j < 16; ++j) + pieceList[WHITE][i][j] = pieceList[BLACK][i][j] = SQ_NONE; +} + + /// Position::set() initializes the position object with the given FEN string. /// This function is not very robust - make sure that input FENs are correct, /// this is assumed to be the responsibility of the GUI. @@ -284,12 +299,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); - compute_keys(st); - compute_non_pawn_material(st); - st->psq = compute_psq_score(); - st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove); chess960 = isChess960; thisThread = th; + set_state(st); assert(pos_is_ok()); } @@ -322,6 +334,52 @@ void Position::set_castling_right(Color c, Square rfrom) { } +/// Position::set_state() computes the hash keys of the position, and other +/// data that once computed is updated incrementally as moves are made. +/// The function is only used when a new position is set up, and to verify +/// the correctness of the StateInfo data when running in debug mode. + +void Position::set_state(StateInfo* si) const { + + si->key = si->pawnKey = si->materialKey = 0; + si->npMaterial[WHITE] = si->npMaterial[BLACK] = VALUE_ZERO; + si->psq = SCORE_ZERO; + + si->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove); + + for (Bitboard b = pieces(); b; ) + { + Square s = pop_lsb(&b); + Piece pc = piece_on(s); + si->key ^= Zobrist::psq[color_of(pc)][type_of(pc)][s]; + si->psq += psq[color_of(pc)][type_of(pc)][s]; + } + + if (ep_square() != SQ_NONE) + si->key ^= Zobrist::enpassant[file_of(ep_square())]; + + if (sideToMove == BLACK) + si->key ^= Zobrist::side; + + si->key ^= Zobrist::castling[st->castlingRights]; + + for (Bitboard b = pieces(PAWN); b; ) + { + Square s = pop_lsb(&b); + si->pawnKey ^= Zobrist::psq[color_of(piece_on(s))][PAWN][s]; + } + + 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]; + + for (Color c = WHITE; c <= BLACK; ++c) + for (PieceType pt = KNIGHT; pt <= QUEEN; ++pt) + si->npMaterial[c] += pieceCount[c][pt] * PieceValue[MG][pt]; +} + + /// Position::fen() returns a FEN representation of the position. In case of /// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function. @@ -1059,91 +1117,6 @@ Value Position::see(Move m) const { } -/// Position::clear() erases the position object to a pristine state, with an -/// empty board, white to move, and no castling rights. - -void Position::clear() { - - std::memset(this, 0, sizeof(Position)); - startState.epSquare = SQ_NONE; - st = &startState; - - for (int i = 0; i < PIECE_TYPE_NB; ++i) - for (int j = 0; j < 16; ++j) - pieceList[WHITE][i][j] = pieceList[BLACK][i][j] = SQ_NONE; -} - - -/// 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. - -void Position::compute_keys(StateInfo* si) const { - - si->key = si->pawnKey = si->materialKey = 0; - - for (Bitboard b = pieces(); b; ) - { - Square s = pop_lsb(&b); - si->key ^= Zobrist::psq[color_of(piece_on(s))][type_of(piece_on(s))][s]; - } - - if (ep_square() != SQ_NONE) - si->key ^= Zobrist::enpassant[file_of(ep_square())]; - - if (sideToMove == BLACK) - si->key ^= Zobrist::side; - - si->key ^= Zobrist::castling[st->castlingRights]; - - for (Bitboard b = pieces(PAWN); b; ) - { - Square s = pop_lsb(&b); - si->pawnKey ^= Zobrist::psq[color_of(piece_on(s))][PAWN][s]; - } - - 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_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. - -void Position::compute_non_pawn_material(StateInfo* si) const { - - si->npMaterial[WHITE] = si->npMaterial[BLACK] = VALUE_ZERO; - - for (Color c = WHITE; c <= BLACK; ++c) - for (PieceType pt = KNIGHT; pt <= QUEEN; ++pt) - si->npMaterial[c] += pieceCount[c][pt] * PieceValue[MG][pt]; -} - - -/// Position::compute_psq_score() computes the incremental scores for the middlegame -/// and the endgame. These functions are used to initialize the incremental scores -/// when a new position is set up, and to verify that the scores are correctly -/// updated by do_move and undo_move when the program is running in debug mode. - -Score Position::compute_psq_score() const { - - Score score = SCORE_ZERO; - - for (Bitboard b = pieces(); b; ) - { - Square s = pop_lsb(&b); - Piece pc = piece_on(s); - score += psq[color_of(pc)][type_of(pc)][s]; - } - - return score; -} - - /// Position::is_draw() tests whether the position is drawn by material, 50 moves /// rule or repetition. It does not detect stalemates. @@ -1220,10 +1193,8 @@ bool Position::pos_is_ok(int* failedStep) const { const bool testBitboards = all || false; const bool testKingCount = all || false; const bool testKingCapture = all || false; + const bool testState = 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; @@ -1237,6 +1208,9 @@ bool Position::pos_is_ok(int* failedStep) const { if ((*step)++, piece_on(king_square(BLACK)) != B_KING) return false; + if ((*step)++, ep_square() != SQ_NONE && relative_rank(sideToMove, ep_square()) != RANK_6) + return false; + if ((*step)++, testKingCount) if ( std::count(board, board + SQUARE_NB, W_KING) != 1 || std::count(board, board + SQUARE_NB, B_KING) != 1) @@ -1246,9 +1220,6 @@ bool Position::pos_is_ok(int* failedStep) const { if (attackers_to(king_square(~sideToMove)) & pieces(sideToMove)) return false; - if ((*step)++, testCheckerCount && popcount(st->checkersBB) > 2) - return false; - if ((*step)++, testBitboards) { // The intersection of the white and black pieces must be empty @@ -1267,27 +1238,20 @@ bool Position::pos_is_ok(int* failedStep) const { return false; } - if ((*step)++, ep_square() != SQ_NONE && relative_rank(sideToMove, ep_square()) != RANK_6) - 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)++, testNonPawnMaterial) + if ((*step)++, testState) { StateInfo si; - compute_non_pawn_material(&si); - if ( st->npMaterial[WHITE] != si.npMaterial[WHITE] - || st->npMaterial[BLACK] != si.npMaterial[BLACK]) + set_state(&si); + if ( st->key != si.key + || st->pawnKey != si.pawnKey + || st->materialKey != si.materialKey + || st->npMaterial[WHITE] != si.npMaterial[WHITE] + || st->npMaterial[BLACK] != si.npMaterial[BLACK] + || st->psq != si.psq) return false; } - if ((*step)++, testIncrementalEval && st->psq != compute_psq_score()) + if ((*step)++, testCheckerCount && popcount(st->checkersBB) > 2) return false; if ((*step)++, testPieceCounts) diff --git a/src/position.h b/src/position.h index ded55d7b..935d86b2 100644 --- a/src/position.h +++ b/src/position.h @@ -171,9 +171,7 @@ private: // 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; + void set_state(StateInfo* si) const; // Helper functions void do_castling(Square kfrom, Square kto, Square rfrom, Square rto); -- 2.39.2