]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Rewrite do_null_move()
[stockfish] / src / position.cpp
index 8dab668bd90e1fb392338e7d933e6e6aa5647d96..2cdcb4aecca934f237adec65f63dc628d85f2908 100644 (file)
@@ -358,16 +358,16 @@ const string Position::fen() const {
   ss << (sideToMove == WHITE ? " w " : " b ");
 
   if (can_castle(WHITE_OO))
-      ss << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE, KING_SIDE))))) : 'K');
+      ss << (chess960 ? file_to_char(file_of(castle_rook_square(WHITE,  KING_SIDE)), false) : 'K');
 
   if (can_castle(WHITE_OOO))
-      ss << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE, QUEEN_SIDE))))) : 'Q');
+      ss << (chess960 ? file_to_char(file_of(castle_rook_square(WHITE, QUEEN_SIDE)), false) : 'Q');
 
   if (can_castle(BLACK_OO))
-      ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, KING_SIDE))) : 'k');
+      ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK,  KING_SIDE)),  true) : 'k');
 
   if (can_castle(BLACK_OOO))
-      ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, QUEEN_SIDE))) : 'q');
+      ss << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, QUEEN_SIDE)),  true) : 'q');
 
   if (st->castleRights == CASTLES_NONE)
       ss << '-';
@@ -802,9 +802,10 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       pieceList[them][capture][index[lastSquare]] = lastSquare;
       pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
 
-      // Update hash keys
+      // Update material hash key and prefetch access to materialTable
       k ^= Zobrist::psq[them][capture][capsq];
       st->materialKey ^= Zobrist::psq[them][capture][pieceCount[them][capture]];
+      prefetch((char*)thisThread->materialTable[st->materialKey]);
 
       // Update incremental scores
       st->psqScore -= pieceSquareTable[make_piece(them, capture)][capsq];
@@ -831,7 +832,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       st->castleRights &= ~cr;
   }
 
-  // Prefetch TT access as soon as we know key is updated
+  // Prefetch TT access as soon as we know the new hash key
   prefetch((char*)TT.first_entry(k));
 
   // Move the piece
@@ -894,17 +895,14 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
           st->npMaterial[us] += PieceValue[MG][promotion];
       }
 
-      // Update pawn hash key
+      // Update pawn hash key and prefetch access to pawnsTable
       st->pawnKey ^= Zobrist::psq[us][PAWN][from] ^ Zobrist::psq[us][PAWN][to];
+      prefetch((char*)thisThread->pawnsTable[st->pawnKey]);
 
       // Reset rule 50 draw counter
       st->rule50 = 0;
   }
 
-  // Prefetch pawn and material hash tables
-  prefetch((char*)thisThread->pawnsTable[st->pawnKey]);
-  prefetch((char*)thisThread->materialTable[st->materialKey]);
-
   // Update incremental scores
   st->psqScore += psq_delta(piece, from, to);
 
@@ -955,10 +953,7 @@ void Position::undo_move(Move m) {
   sideToMove = ~sideToMove;
 
   if (type_of(m) == CASTLE)
-  {
-      do_castle_move<false>(m);
-      return;
-  }
+      return do_castle_move<false>(m);
 
   Color us = sideToMove;
   Color them = ~us;
@@ -1054,30 +1049,24 @@ void Position::do_castle_move(Move m) {
   assert(is_ok(m));
   assert(type_of(m) == CASTLE);
 
-  Square kto, kfrom, rfrom, rto, kAfter, rAfter;
-
   Color us = sideToMove;
-  Square kBefore = from_sq(m);
-  Square rBefore = to_sq(m);
+  Square kfrom, kto, rfrom, rto;
 
-  // Find after-castle squares for king and rook
-  if (rBefore > kBefore) // O-O
+  bool kingSide = to_sq(m) > from_sq(m);
+  kfrom = kto = from_sq(m);
+  rfrom = rto = to_sq(m);
+
+  if (Do)
   {
-      kAfter = relative_square(us, SQ_G1);
-      rAfter = relative_square(us, SQ_F1);
+      kto = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
+      rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
   }
-  else // O-O-O
+  else
   {
-      kAfter = relative_square(us, SQ_C1);
-      rAfter = relative_square(us, SQ_D1);
+      kfrom = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
+      rfrom = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
   }
 
-  kfrom = Do ? kBefore : kAfter;
-  rfrom = Do ? rBefore : rAfter;
-
-  kto = Do ? kAfter : kBefore;
-  rto = Do ? rAfter : rBefore;
-
   assert(piece_on(kfrom) == make_piece(us, KING));
   assert(piece_on(rfrom) == make_piece(us, ROOK));
 
@@ -1090,11 +1079,9 @@ void Position::do_castle_move(Move m) {
   byColorBB[us] ^= k_from_to_bb ^ r_from_to_bb;
 
   // Update board
-  Piece king = make_piece(us, KING);
-  Piece rook = make_piece(us, ROOK);
   board[kfrom] = board[rfrom] = NO_PIECE;
-  board[kto] = king;
-  board[rto] = rook;
+  board[kto] = make_piece(us, KING);
+  board[rto] = make_piece(us, ROOK);
 
   // Update piece lists
   pieceList[us][KING][index[kfrom]] = kto;
@@ -1109,8 +1096,8 @@ void Position::do_castle_move(Move m) {
       st->capturedType = NO_PIECE_TYPE;
 
       // Update incremental scores
-      st->psqScore += psq_delta(king, kfrom, kto);
-      st->psqScore += psq_delta(rook, rfrom, rto);
+      st->psqScore += psq_delta(make_piece(us, KING), kfrom, kto);
+      st->psqScore += psq_delta(make_piece(us, ROOK), rfrom, rto);
 
       // Update hash key
       st->key ^= Zobrist::psq[us][KING][kfrom] ^ Zobrist::psq[us][KING][kto];
@@ -1140,47 +1127,42 @@ void Position::do_castle_move(Move m) {
 }
 
 
-/// Position::do_null_move() is used to do/undo a "null move": It flips the side
-/// to move and updates the hash key without executing any move on the board.
-template<bool Do>
-void Position::do_null_move(StateInfo& backupSt) {
+/// Position::do(undo)_null_move() is used to do(undo) a "null move": It flips
+/// the side to move without executing any move on the board.
 
-  assert(!checkers());
+void Position::do_null_move(StateInfo& newSt) {
 
-  // Back up the information necessary to undo the null move to the supplied
-  // StateInfo object. Note that differently from normal case here backupSt
-  // is actually used as a backup storage not as the new state. This reduces
-  // the number of fields to be copied.
-  StateInfo* src = Do ? st : &backupSt;
-  StateInfo* dst = Do ? &backupSt : st;
+  assert(!checkers());
 
-  dst->key      = src->key;
-  dst->epSquare = src->epSquare;
-  dst->psqScore = src->psqScore;
-  dst->rule50   = src->rule50;
-  dst->pliesFromNull = src->pliesFromNull;
+  memcpy(&newSt, st, sizeof(StateInfo)); // Fully copy here
 
-  sideToMove = ~sideToMove;
+  newSt.previous = st;
+  st = &newSt;
 
-  if (Do)
+  if (st->epSquare != SQ_NONE)
   {
-      if (st->epSquare != SQ_NONE)
-          st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
-
-      st->key ^= Zobrist::side;
-      prefetch((char*)TT.first_entry(st->key));
-
+      st->key ^= Zobrist::enpassant[file_of(st->epSquare)];
       st->epSquare = SQ_NONE;
-      st->rule50++;
-      st->pliesFromNull = 0;
   }
 
+  st->key ^= Zobrist::side;
+  prefetch((char*)TT.first_entry(st->key));
+
+  st->rule50++;
+  st->pliesFromNull = 0;
+
+  sideToMove = ~sideToMove;
+
   assert(pos_is_ok());
 }
 
-// Explicit template instantiations
-template void Position::do_null_move<false>(StateInfo& backupSt);
-template void Position::do_null_move<true>(StateInfo& backupSt);
+void Position::undo_null_move() {
+
+  assert(!checkers());
+
+  st = st->previous;
+  sideToMove = ~sideToMove;
+}
 
 
 /// Position::see() is a static exchange evaluator: It tries to estimate the