]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Fix compilation after recent merge.
[stockfish] / src / position.cpp
index f7354b3d77cef78c1fda19b1137a312cd4f31ccb..c45dd7b2e22a0000a439513e6f9687dde5bb6ad7 100644 (file)
@@ -49,7 +49,7 @@ namespace Zobrist {
 Key psq[PIECE_NB][SQUARE_NB];
 Key enpassant[FILE_NB];
 Key castling[CASTLING_RIGHT_NB];
-Key side;
+Key side, noPawns;
 }
 
 namespace {
@@ -61,8 +61,7 @@ constexpr Piece Pieces[] = {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
 }  // namespace
 
 
-// operator<<(Position) returns an ASCII representation of the position
-
+// Returns an ASCII representation of the position
 std::ostream& operator<<(std::ostream& os, const Position& pos) {
 
     os << "\n +---+---+---+---+---+---+---+---+\n";
@@ -114,8 +113,7 @@ Key  cuckoo[8192];
 Move cuckooMove[8192];
 
 
-// Position::init() initializes at startup the various arrays used to compute hash keys
-
+// Initializes at startup the various arrays used to compute hash keys
 void Position::init() {
 
     PRNG rng(1070372);
@@ -130,7 +128,8 @@ void Position::init() {
     for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr)
         Zobrist::castling[cr] = rng.rand<Key>();
 
-    Zobrist::side = rng.rand<Key>();
+    Zobrist::side    = rng.rand<Key>();
+    Zobrist::noPawns = rng.rand<Key>();
 
     // Prepare the cuckoo tables
     std::memset(cuckoo, 0, sizeof(cuckoo));
@@ -158,10 +157,9 @@ void Position::init() {
 }
 
 
-// Position::set() initializes the position object with the given FEN string.
+// 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.
-
 Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Thread* th) {
     /*
    A FEN string defines a particular position using only the ASCII character set.
@@ -298,9 +296,8 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
 }
 
 
-// Position::set_castling_right() is a helper function used to set castling
+// Helper function used to set castling
 // rights given the corresponding color and the rook starting square.
-
 void Position::set_castling_right(Color c, Square rfrom) {
 
     Square         kfrom = square<KING>(c);
@@ -318,8 +315,7 @@ void Position::set_castling_right(Color c, Square rfrom) {
 }
 
 
-// Position::set_check_info() sets king attacks to detect if a move gives check
-
+// Sets king attacks to detect if a move gives check
 void Position::set_check_info() const {
 
     update_slider_blockers(WHITE);
@@ -336,13 +332,13 @@ void Position::set_check_info() const {
 }
 
 
-// Position::set_state() computes the hash keys of the position, and other
+// 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
-
 void Position::set_state() const {
 
     st->key = st->materialKey  = 0;
+    st->pawnKey                = Zobrist::noPawns;
     st->nonPawnMaterial[WHITE] = st->nonPawnMaterial[BLACK] = VALUE_ZERO;
     st->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
 
@@ -354,7 +350,10 @@ void Position::set_state() const {
         Piece  pc = piece_on(s);
         st->key ^= Zobrist::psq[pc][s];
 
-        if (type_of(pc) != KING && type_of(pc) != PAWN)
+        if (type_of(pc) == PAWN)
+            st->pawnKey ^= Zobrist::psq[pc][s];
+
+        else if (type_of(pc) != KING)
             st->nonPawnMaterial[color_of(pc)] += PieceValue[pc];
     }
 
@@ -372,10 +371,8 @@ void Position::set_state() const {
 }
 
 
-// Position::set() is an overload to initialize the position object with
-// the given endgame code string like "KBPKN". It is mainly a helper to
-// get the material key out of an endgame code.
-
+// Overload to initialize the position object with the given endgame code string
+// like "KBPKN". It's mainly a helper to get the material key out of an endgame code.
 Position& Position::set(const string& code, Color c, StateInfo* si) {
 
     assert(code[0] == 'K');
@@ -395,9 +392,8 @@ Position& Position::set(const string& code, Color c, StateInfo* si) {
 }
 
 
-// Position::fen() returns a FEN representation of the position. In case of
+// Returns a FEN representation of the position. In case of
 // Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
-
 string Position::fen() const {
 
     int                emptyCnt;
@@ -444,7 +440,7 @@ string Position::fen() const {
     return ss.str();
 }
 
-// update_slider_blockers() calculates st->blockersForKing[c] and st->pinners[~c],
+// Calculates st->blockersForKing[c] and st->pinners[~c],
 // which store respectively the pieces preventing king of color c from being in check
 // and the slider pieces of color ~c pinning pieces of color c to the king.
 void Position::update_slider_blockers(Color c) const {
@@ -475,9 +471,8 @@ void Position::update_slider_blockers(Color c) const {
 }
 
 
-// Position::attackers_to() computes a bitboard of all pieces which attack a
-// given square. Slider attacks use the occupied bitboard to indicate occupancy.
-
+// Computes a bitboard of all pieces which attack a given square.
+// Slider attacks use the occupied bitboard to indicate occupancy.
 Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
 
     return (pawn_attacks_bb(BLACK, s) & pieces(WHITE, PAWN))
@@ -489,8 +484,7 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
 }
 
 
-// Position::legal() tests whether a pseudo-legal move is legal
-
+// Tests whether a pseudo-legal move is legal
 bool Position::legal(Move m) const {
 
     assert(is_ok(m));
@@ -549,10 +543,9 @@ bool Position::legal(Move m) const {
 }
 
 
-// Position::pseudo_legal() takes a random move and tests whether the move is
+// Takes a random move and tests whether the move is
 // pseudo-legal. It is used to validate moves from TT that can be corrupted
 // due to SMP concurrent access or hash position key aliasing.
-
 bool Position::pseudo_legal(const Move m) const {
 
     Color  us   = sideToMove;
@@ -581,8 +574,7 @@ bool Position::pseudo_legal(const Move m) const {
     // Handle the special case of a pawn move
     if (type_of(pc) == PAWN)
     {
-        // We have already handled promotion moves, so destination
-        // cannot be on the 8th/1st rank.
+        // We have already handled promotion moves, so destination cannot be on the 8th/1st rank
         if ((Rank8BB | Rank1BB) & to)
             return false;
 
@@ -620,8 +612,7 @@ bool Position::pseudo_legal(const Move m) const {
 }
 
 
-// Position::gives_check() tests whether a pseudo-legal move gives a check
-
+// Tests whether a pseudo-legal move gives a check
 bool Position::gives_check(Move m) const {
 
     assert(is_ok(m));
@@ -646,10 +637,9 @@ bool Position::gives_check(Move m) const {
     case PROMOTION :
         return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove);
 
-    // En passant capture with check? We have already handled the case
-    // of direct checks and ordinary discovered check, so the only case we
-    // need to handle is the unusual case of a discovered check through
-    // the captured pawn.
+    // En passant capture with check? We have already handled the case of direct
+    // checks and ordinary discovered check, so the only case we need to handle
+    // is the unusual case of a discovered check through the captured pawn.
     case EN_PASSANT : {
         Square   capsq = make_square(file_of(to), rank_of(from));
         Bitboard b     = (pieces() ^ from ^ capsq) | to;
@@ -669,10 +659,9 @@ bool Position::gives_check(Move m) const {
 }
 
 
-// Position::do_move() makes a move, and saves all information necessary
+// Makes a move, and saves all information necessary
 // to a StateInfo object. The move is assumed to be legal. Pseudo-legal
 // moves should be filtered out before this function is called.
-
 void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
 
     assert(is_ok(m));
@@ -741,6 +730,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
                 assert(piece_on(to) == NO_PIECE);
                 assert(piece_on(capsq) == make_piece(them, PAWN));
             }
+
+            st->pawnKey ^= Zobrist::psq[captured][capsq];
         }
         else
             st->nonPawnMaterial[them] -= PieceValue[captured];
@@ -819,6 +810,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
 
             // Update hash keys
             k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
+            st->pawnKey ^= Zobrist::psq[pc][to];
             st->materialKey ^=
               Zobrist::psq[promotion][pieceCount[promotion] - 1] ^ Zobrist::psq[pc][pieceCount[pc]];
 
@@ -826,6 +818,9 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
             st->nonPawnMaterial[us] += PieceValue[promotion];
         }
 
+        // Update pawn hash key
+        st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
+
         // Reset rule 50 draw counter
         st->rule50 = 0;
     }
@@ -867,9 +862,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
 }
 
 
-// Position::undo_move() unmakes a move. When it returns, the position should
+// Unmakes a move. When it returns, the position should
 // be restored to exactly the same state as before the move was made.
-
 void Position::undo_move(Move m) {
 
     assert(is_ok(m));
@@ -931,8 +925,8 @@ void Position::undo_move(Move m) {
 }
 
 
-// Position::do_castling() is a helper used to do/undo a castling move. This
-// is a bit tricky in Chess960 where from/to squares can overlap.
+// Helper used to do/undo a castling move. This is a bit
+// tricky in Chess960 where from/to squares can overlap.
 template<bool Do>
 void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
 
@@ -963,9 +957,8 @@ void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Squ
 }
 
 
-// Position::do_null_move() is used to do a "null move": it flips
+// Used to do a "null move": it flips
 // the side to move without executing any move on the board.
-
 void Position::do_null_move(StateInfo& newSt) {
 
     assert(!checkers());
@@ -1003,8 +996,7 @@ void Position::do_null_move(StateInfo& newSt) {
 }
 
 
-// Position::undo_null_move() must be used to undo a "null move"
-
+// Must be used to undo a "null move"
 void Position::undo_null_move() {
 
     assert(!checkers());
@@ -1014,10 +1006,9 @@ void Position::undo_null_move() {
 }
 
 
-// Position::key_after() computes the new hash key after the given move. Needed
+// Computes the new hash key after the given move. Needed
 // for speculative prefetch. It doesn't recognize special moves like castling,
 // en passant and promotions.
-
 Key Position::key_after(Move m) const {
 
     Square from     = from_sq(m);
@@ -1035,10 +1026,9 @@ Key Position::key_after(Move m) const {
 }
 
 
-// Position::see_ge (Static Exchange Evaluation Greater or Equal) tests if the
-// SEE value of move is greater or equal to the given threshold. We'll use an
+// Tests if the SEE (Static Exchange Evaluation)
+// value of move is greater or equal to the given threshold. We'll use an
 // algorithm similar to alpha-beta pruning with a null window.
-
 bool Position::see_ge(Move m, Value threshold) const {
 
     assert(is_ok(m));
@@ -1140,9 +1130,8 @@ bool Position::see_ge(Move m, Value threshold) const {
     return bool(res);
 }
 
-// Position::is_draw() tests whether the position is drawn by 50-move rule
+// Tests whether the position is drawn by 50-move rule
 // or by repetition. It does not detect stalemates.
-
 bool Position::is_draw(int ply) const {
 
     if (st->rule50 > 99 && (!checkers() || MoveList<LEGAL>(*this).size()))
@@ -1154,9 +1143,8 @@ bool Position::is_draw(int ply) const {
 }
 
 
-// Position::has_repeated() tests whether there has been at least one repetition
+// Tests whether there has been at least one repetition
 // of positions since the last capture or pawn move.
-
 bool Position::has_repeated() const {
 
     StateInfo* stc = st;
@@ -1172,9 +1160,8 @@ bool Position::has_repeated() const {
 }
 
 
-// Position::has_game_cycle() tests if the position has a move which draws by repetition,
+// Tests if the position has a move which draws by repetition,
 // or an earlier position has a move that directly reaches the current position.
-
 bool Position::has_game_cycle(int ply) const {
 
     int j;
@@ -1220,9 +1207,8 @@ bool Position::has_game_cycle(int ply) const {
 }
 
 
-// Position::flip() flips position with the white and black sides reversed. This
+// Flips position with the white and black sides reversed. This
 // is only useful for debugging e.g. for finding evaluation symmetry bugs.
-
 void Position::flip() {
 
     string            f, token;
@@ -1255,10 +1241,9 @@ void Position::flip() {
 }
 
 
-// Position::pos_is_ok() performs some consistency checks for the
-// position object and raise an assert if something wrong is detected.
+// Performs some consistency checks for the position object
+// and raise an assert if something wrong is detected.
 // This is meant to be helpful when debugging.
-
 bool Position::pos_is_ok() const {
 
     constexpr bool Fast = true;  // Quick (default) or full check?