]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Detach the state when copying a position
[stockfish] / src / position.cpp
index ec86f35ce73ebecb16c6394604d150c28e8e53e1..480a92ec9cfcd1a7e3850aea8fbc94f61c570ece 100644 (file)
@@ -27,6 +27,7 @@
 #include <fstream>
 #include <iostream>
 
+#include "bitcount.h"
 #include "mersenne.h"
 #include "movegen.h"
 #include "movepick.h"
@@ -314,9 +315,10 @@ void Position::print(Move m) const {
 
 /// Position::copy() creates a copy of the input position.
 
-void Position::copy(const Position &pos) {
+void Position::copy(const Positionpos) {
 
   memcpy(this, &pos, sizeof(Position));
+  saveState(); // detach and copy state info
 }
 
 
@@ -741,12 +743,11 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
       do_capture_move(st->capture, them, to);
 
     // Move the piece
-    clear_bit(&(byColorBB[us]), from);
-    clear_bit(&(byTypeBB[piece]), from);
-    clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
-    set_bit(&(byColorBB[us]), to);
-    set_bit(&(byTypeBB[piece]), to);
-    set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
+    Bitboard move_bb = make_move_bb(from, to);
+    do_move_bb(&(byColorBB[us]), move_bb);
+    do_move_bb(&(byTypeBB[piece]), move_bb);
+    do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
+
     board[to] = board[from];
     board[from] = EMPTY;
 
@@ -838,6 +839,7 @@ void Position::do_capture_move(PieceType capture, Color them, Square to) {
     // Remove captured piece
     clear_bit(&(byColorBB[them]), to);
     clear_bit(&(byTypeBB[capture]), to);
+    clear_bit(&(byTypeBB[0]), to);
 
     // Update hash key
     st->key ^= zobrist[them][capture][to];
@@ -1080,21 +1082,17 @@ void Position::do_ep_move(Move m) {
   assert(piece_on(from) == piece_of_color_and_type(us, PAWN));
   assert(piece_on(capsq) == piece_of_color_and_type(them, PAWN));
 
-  // Remove captured piece
+  // Remove captured pawn
   clear_bit(&(byColorBB[them]), capsq);
   clear_bit(&(byTypeBB[PAWN]), capsq);
   clear_bit(&(byTypeBB[0]), capsq); // HACK: byTypeBB[0] == occupied squares
   board[capsq] = EMPTY;
 
-  // Remove moving piece from source square
-  clear_bit(&(byColorBB[us]), from);
-  clear_bit(&(byTypeBB[PAWN]), from);
-  clear_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
-
-  // Put moving piece on destination square
-  set_bit(&(byColorBB[us]), to);
-  set_bit(&(byTypeBB[PAWN]), to);
-  set_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
+  // Move capturing pawn
+  Bitboard move_bb = make_move_bb(from, to);
+  do_move_bb(&(byColorBB[us]), move_bb);
+  do_move_bb(&(byTypeBB[PAWN]), move_bb);
+  do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
   board[to] = board[from];
   board[from] = EMPTY;
 
@@ -1170,17 +1168,13 @@ void Position::undo_move(Move m) {
       assert(color_of_piece_on(to) == us);
 
       // Put the piece back at the source square
+      Bitboard move_bb = make_move_bb(to, from);
       piece = type_of_piece_on(to);
-      set_bit(&(byColorBB[us]), from);
-      set_bit(&(byTypeBB[piece]), from);
-      set_bit(&(byTypeBB[0]), from); // HACK: byTypeBB[0] == occupied squares
+      do_move_bb(&(byColorBB[us]), move_bb);
+      do_move_bb(&(byTypeBB[piece]), move_bb);
+      do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
       board[from] = piece_of_color_and_type(us, piece);
 
-      // Clear the destination square
-      clear_bit(&(byColorBB[us]), to);
-      clear_bit(&(byTypeBB[piece]), to);
-      clear_bit(&(byTypeBB[0]), to); // HACK: byTypeBB[0] == occupied squares
-
       // If the moving piece was a king, update the king square
       if (piece == KING)
           kingSquare[us] = from;
@@ -1193,7 +1187,7 @@ void Position::undo_move(Move m) {
       {
           assert(st->capture != KING);
 
-          // Replace the captured piece
+          // Restore the captured piece
           set_bit(&(byColorBB[them]), to);
           set_bit(&(byTypeBB[st->capture]), to);
           set_bit(&(byTypeBB[0]), to);
@@ -1375,22 +1369,18 @@ void Position::undo_ep_move(Move m) {
   assert(piece_on(from) == EMPTY);
   assert(piece_on(capsq) == EMPTY);
 
-  // Replace captured piece
+  // Restore captured pawn
   set_bit(&(byColorBB[them]), capsq);
   set_bit(&(byTypeBB[PAWN]), capsq);
   set_bit(&(byTypeBB[0]), capsq);
   board[capsq] = piece_of_color_and_type(them, PAWN);
 
-  // Remove moving piece from destination square
-  clear_bit(&(byColorBB[us]), to);
-  clear_bit(&(byTypeBB[PAWN]), to);
-  clear_bit(&(byTypeBB[0]), to);
+  // Move capturing pawn back to source square
+  Bitboard move_bb = make_move_bb(to, from);
+  do_move_bb(&(byColorBB[us]), move_bb);
+  do_move_bb(&(byTypeBB[PAWN]), move_bb);
+  do_move_bb(&(byTypeBB[0]), move_bb);
   board[to] = EMPTY;
-
-  // Replace moving piece at source square
-  set_bit(&(byColorBB[us]), from);
-  set_bit(&(byTypeBB[PAWN]), from);
-  set_bit(&(byTypeBB[0]), from);
   board[from] = piece_of_color_and_type(us, PAWN);
 
   // Update piece list
@@ -1413,11 +1403,13 @@ void Position::do_null_move(StateInfo& backupSt) {
   assert(!is_check());
 
   // Back up the information necessary to undo the null move to the supplied
-  // StateInfo object. In the case of a null move, the only thing we need to
-  // remember is the en passant square.
+  // StateInfo object.
   // Note that differently from normal case here backupSt is actually used as
   // a backup storage not as a new state to be used.
   backupSt.epSquare = st->epSquare;
+  backupSt.key = st->key;
+  backupSt.mgValue = st->mgValue;
+  backupSt.egValue = st->egValue;
   backupSt.previous = st->previous;
   st->previous = &backupSt;
 
@@ -1451,19 +1443,15 @@ void Position::undo_null_move() {
 
   // Restore information from the our backup StateInfo object
   st->epSquare = st->previous->epSquare;
+  st->key = st->previous->key;
+  st->mgValue = st->previous->mgValue;
+  st->egValue = st->previous->egValue;
   st->previous = st->previous->previous;
 
-  if (st->epSquare != SQ_NONE)
-      st->key ^= zobEp[st->epSquare];
-
   // Update the necessary information
   sideToMove = opposite_color(sideToMove);
   st->rule50--;
   gamePly--;
-  st->key ^= zobSideToMove;
-
-  st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
-  st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame;
 
   assert(is_ok());
 }
@@ -1620,15 +1608,16 @@ int Position::see(Square from, Square to) const {
 }
 
 
-/// Position::setStartState() copies the content of the argument
+/// Position::saveState() copies the content of the current state
 /// inside startState and makes st point to it. This is needed
 /// when the st pointee could become stale, as example because
 /// the caller is about to going out of scope.
 
-void Position::setStartState(const StateInfo& s) {
+void Position::saveState() {
 
-  startState = s;
+  startState = *st;
   st = &startState;
+  st->previous = NULL; // as a safe guard
 }
 
 
@@ -1979,7 +1968,7 @@ void Position::init_piece_square_tables() {
 /// the white and black sides reversed. This is only useful for debugging,
 /// especially for finding evaluation symmetry bugs.
 
-void Position::flipped_copy(const Position &pos) {
+void Position::flipped_copy(const Positionpos) {
 
   assert(pos.is_ok());