]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Try to prefetch as soon as position key is ready
[stockfish] / src / position.cpp
index 64b833857b9976080db3b587715e8319f5da8e39..874c7545bf4dc31b1745a920ba6f7bcbef2106d6 100644 (file)
@@ -34,6 +34,7 @@
 #include "position.h"
 #include "psqtab.h"
 #include "san.h"
+#include "tt.h"
 #include "ucioption.h"
 
 using std::string;
@@ -71,6 +72,14 @@ Position::Position(const string& fen) {
 }
 
 
+/// Position::setTranspositionTable() is used by search functions to pass
+/// the pointer to the used TT so that do_move() will prefetch TT access.
+
+void Position::setTranspositionTable(TranspositionTable* tt) {
+  TT = tt;
+}
+
+
 /// Position::from_fen() 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).
@@ -735,34 +744,17 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
     assert(color_of_piece_on(from) == us);
     assert(color_of_piece_on(to) == them || piece_on(to) == EMPTY);
 
-    PieceType piece = type_of_piece_on(from);
+    Piece piece = piece_on(from);
+    PieceType pt = type_of_piece(piece);
 
     st->capture = type_of_piece_on(to);
 
     if (st->capture)
       do_capture_move(st->capture, them, to);
 
-    // Move the piece
-    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;
-
     // Update hash key
-    st->key ^= zobrist[us][piece][from] ^ zobrist[us][piece][to];
-
-    // Update incremental scores
-    st->mgValue -= pst<MidGame>(us, piece, from);
-    st->mgValue += pst<MidGame>(us, piece, to);
-    st->egValue -= pst<EndGame>(us, piece, from);
-    st->egValue += pst<EndGame>(us, piece, to);
-
-    // If the moving piece was a king, update the king square
-    if (piece == KING)
-        kingSquare[us] = to;
+    st->key ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
+    st->key ^= zobSideToMove;
 
     // Reset en passant square
     if (st->epSquare != SQ_NONE)
@@ -771,8 +763,32 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
         st->epSquare = SQ_NONE;
     }
 
+    // Update castle rights, try to shortcut a common case
+    if ((castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
+    {
+        st->key ^= zobCastle[st->castleRights];
+        st->castleRights &= castleRightsMask[from];
+        st->castleRights &= castleRightsMask[to];
+        st->key ^= zobCastle[st->castleRights];
+    }
+
+    bool checkEpSquare = (pt == PAWN && abs(int(to) - int(from)) == 16);
+
+    // Prefetch TT access as soon as we know key is updated
+    if (!checkEpSquare && TT)
+        TT->prefetch(st->key);
+
+    // Move the piece
+    Bitboard move_bb = make_move_bb(from, to);
+    do_move_bb(&(byColorBB[us]), move_bb);
+    do_move_bb(&(byTypeBB[pt]), move_bb);
+    do_move_bb(&(byTypeBB[0]), move_bb); // HACK: byTypeBB[0] == occupied squares
+
+    board[to] = board[from];
+    board[from] = EMPTY;
+
     // If the moving piece was a pawn do some special extra work
-    if (piece == PAWN)
+    if (pt == PAWN)
     {
         // Reset rule 50 draw counter
         st->rule50 = 0;
@@ -781,7 +797,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
         st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
 
         // Set en passant square, only if moved pawn can be captured
-        if (abs(int(to) - int(from)) == 16)
+        if (checkEpSquare)
         {
             if (   (us == WHITE && (pawn_attacks(WHITE, from + DELTA_N) & pawns(BLACK)))
                 || (us == BLACK && (pawn_attacks(BLACK, from + DELTA_S) & pawns(WHITE))))
@@ -792,23 +808,26 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
         }
     }
 
+    // Prefetch only here in the few cases we needed zobEp[] to update the key
+    if (checkEpSquare && TT)
+        TT->prefetch(st->key);
+
+    // Update incremental scores
+    st->mgValue += pst_delta<MidGame>(piece, from, to);
+    st->egValue += pst_delta<EndGame>(piece, from, to);
+
+    // If the moving piece was a king, update the king square
+    if (pt == KING)
+        kingSquare[us] = to;
+
     // Update piece lists
-    pieceList[us][piece][index[from]] = to;
+    pieceList[us][pt][index[from]] = to;
     index[to] = index[from];
 
-    // Update castle rights, try to shortcut a common case
-    if ((castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
-    {
-        st->key ^= zobCastle[st->castleRights];
-        st->castleRights &= castleRightsMask[from];
-        st->castleRights &= castleRightsMask[to];
-        st->key ^= zobCastle[st->castleRights];
-    }
-
     // Update checkers bitboard, piece must be already moved
     st->checkersBB = EmptyBoardBB;
     Square ksq = king_square(them);
-    switch (piece)
+    switch (pt)
     {
     case PAWN:   update_checkers<PAWN>(&(st->checkersBB), ksq, from, to, dcCandidates);   break;
     case KNIGHT: update_checkers<KNIGHT>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
@@ -821,7 +840,6 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
   }
 
   // Finish
-  st->key ^= zobSideToMove;
   sideToMove = opposite_color(sideToMove);
   gamePly++;
 
@@ -906,26 +924,23 @@ void Position::do_castle_move(Move m) {
       rto = relative_square(us, SQ_D1);
   }
 
-  // Remove pieces from source squares
-  clear_bit(&(byColorBB[us]), kfrom);
-  clear_bit(&(byTypeBB[KING]), kfrom);
-  clear_bit(&(byTypeBB[0]), kfrom); // HACK: byTypeBB[0] == occupied squares
-  clear_bit(&(byColorBB[us]), rfrom);
-  clear_bit(&(byTypeBB[ROOK]), rfrom);
-  clear_bit(&(byTypeBB[0]), rfrom); // HACK: byTypeBB[0] == occupied squares
-
-  // Put pieces on destination squares
-  set_bit(&(byColorBB[us]), kto);
-  set_bit(&(byTypeBB[KING]), kto);
-  set_bit(&(byTypeBB[0]), kto); // HACK: byTypeBB[0] == occupied squares
-  set_bit(&(byColorBB[us]), rto);
-  set_bit(&(byTypeBB[ROOK]), rto);
-  set_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares
+  // Move the pieces
+  Bitboard kmove_bb = make_move_bb(kfrom, kto);
+  do_move_bb(&(byColorBB[us]), kmove_bb);
+  do_move_bb(&(byTypeBB[KING]), kmove_bb);
+  do_move_bb(&(byTypeBB[0]), kmove_bb); // HACK: byTypeBB[0] == occupied squares
+
+  Bitboard rmove_bb = make_move_bb(rfrom, rto);
+  do_move_bb(&(byColorBB[us]), rmove_bb);
+  do_move_bb(&(byTypeBB[ROOK]), rmove_bb);
+  do_move_bb(&(byTypeBB[0]), rmove_bb); // HACK: byTypeBB[0] == occupied squares
 
   // Update board array
+  Piece king = piece_of_color_and_type(us, KING);
+  Piece rook = piece_of_color_and_type(us, ROOK);
   board[kfrom] = board[rfrom] = EMPTY;
-  board[kto] = piece_of_color_and_type(us, KING);
-  board[rto] = piece_of_color_and_type(us, ROOK);
+  board[kto] = king;
+  board[rto] = rook;
 
   // Update king square
   kingSquare[us] = kto;
@@ -938,14 +953,10 @@ void Position::do_castle_move(Move m) {
   index[rto] = tmp;
 
   // Update incremental scores
-  st->mgValue -= pst<MidGame>(us, KING, kfrom);
-  st->mgValue += pst<MidGame>(us, KING, kto);
-  st->egValue -= pst<EndGame>(us, KING, kfrom);
-  st->egValue += pst<EndGame>(us, KING, kto);
-  st->mgValue -= pst<MidGame>(us, ROOK, rfrom);
-  st->mgValue += pst<MidGame>(us, ROOK, rto);
-  st->egValue -= pst<EndGame>(us, ROOK, rfrom);
-  st->egValue += pst<EndGame>(us, ROOK, rto);
+  st->mgValue += pst_delta<MidGame>(king, kfrom, kto);
+  st->egValue += pst_delta<EndGame>(king, kfrom, kto);
+  st->mgValue += pst_delta<MidGame>(rook, rfrom, rto);
+  st->egValue += pst_delta<EndGame>(rook, rfrom, rto);
 
   // Update hash key
   st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto];
@@ -968,6 +979,8 @@ void Position::do_castle_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
+
+  st->key ^= zobSideToMove;
 }
 
 
@@ -982,7 +995,7 @@ void Position::do_promotion_move(Move m) {
 
   assert(is_ok());
   assert(move_is_ok(m));
-  assert(move_promotion(m));
+  assert(move_is_promotion(m));
 
   us = side_to_move();
   them = opposite_color(us);
@@ -1058,6 +1071,8 @@ void Position::do_promotion_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
+
+  st->key ^= zobSideToMove;
 }
 
 
@@ -1121,12 +1136,11 @@ void Position::do_ep_move(Move m) {
   st->pawnKey ^= zobrist[them][PAWN][capsq];
 
   // Update incremental scores
+  Piece pawn = piece_of_color_and_type(us, PAWN);
+  st->mgValue += pst_delta<MidGame>(pawn, from, to);
+  st->egValue += pst_delta<EndGame>(pawn, from, to);
   st->mgValue -= pst<MidGame>(them, PAWN, capsq);
-  st->mgValue -= pst<MidGame>(us, PAWN, from);
-  st->mgValue += pst<MidGame>(us, PAWN, to);
   st->egValue -= pst<EndGame>(them, PAWN, capsq);
-  st->egValue -= pst<EndGame>(us, PAWN, from);
-  st->egValue += pst<EndGame>(us, PAWN, to);
 
   // Reset en passant square
   st->epSquare = SQ_NONE;
@@ -1136,6 +1150,8 @@ void Position::do_ep_move(Move m) {
 
   // Update checkers BB
   st->checkersBB = attacks_to(king_square(them), us);
+
+  st->key ^= zobSideToMove;
 }
 
 
@@ -1246,21 +1262,16 @@ void Position::undo_castle_move(Move m) {
   assert(piece_on(kto) == piece_of_color_and_type(us, KING));
   assert(piece_on(rto) == piece_of_color_and_type(us, ROOK));
 
-  // Remove pieces from destination squares
-  clear_bit(&(byColorBB[us]), kto);
-  clear_bit(&(byTypeBB[KING]), kto);
-  clear_bit(&(byTypeBB[0]), kto); // HACK: byTypeBB[0] == occupied squares
-  clear_bit(&(byColorBB[us]), rto);
-  clear_bit(&(byTypeBB[ROOK]), rto);
-  clear_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares
-
-  // Put pieces on source squares
-  set_bit(&(byColorBB[us]), kfrom);
-  set_bit(&(byTypeBB[KING]), kfrom);
-  set_bit(&(byTypeBB[0]), kfrom); // HACK: byTypeBB[0] == occupied squares
-  set_bit(&(byColorBB[us]), rfrom);
-  set_bit(&(byTypeBB[ROOK]), rfrom);
-  set_bit(&(byTypeBB[0]), rfrom); // HACK: byTypeBB[0] == occupied squares
+  // Put the pieces back at the source square
+  Bitboard kmove_bb = make_move_bb(kto, kfrom);
+  do_move_bb(&(byColorBB[us]), kmove_bb);
+  do_move_bb(&(byTypeBB[KING]), kmove_bb);
+  do_move_bb(&(byTypeBB[0]), kmove_bb); // HACK: byTypeBB[0] == occupied squares
+
+  Bitboard rmove_bb = make_move_bb(rto, rfrom);
+  do_move_bb(&(byColorBB[us]), rmove_bb);
+  do_move_bb(&(byTypeBB[ROOK]), rmove_bb);
+  do_move_bb(&(byTypeBB[0]), rmove_bb); // HACK: byTypeBB[0] == occupied squares
 
   // Update board
   board[rto] = board[kto] = EMPTY;
@@ -1290,7 +1301,7 @@ void Position::undo_promotion_move(Move m) {
   PieceType promotion;
 
   assert(move_is_ok(m));
-  assert(move_promotion(m));
+  assert(move_is_promotion(m));
 
   // When we have arrived here, some work has already been done by
   // Position::undo_move.  In particular, the side to move has been switched,
@@ -1421,14 +1432,15 @@ void Position::do_null_move(StateInfo& backupSt) {
   history[gamePly] = st->key;
 
   // Update the necessary information
-  sideToMove = opposite_color(sideToMove);
   if (st->epSquare != SQ_NONE)
       st->key ^= zobEp[st->epSquare];
 
+  st->key ^= zobSideToMove;
+  TT->prefetch(st->key);
+  sideToMove = opposite_color(sideToMove);
   st->epSquare = SQ_NONE;
   st->rule50++;
   gamePly++;
-  st->key ^= zobSideToMove;
 
   st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
   st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame;
@@ -1478,6 +1490,22 @@ int Position::see(Move m) const {
   return see(move_from(m), move_to(m));
 }
 
+int Position::see_sign(Move m) const {
+
+  assert(move_is_ok(m));
+
+  Square from = move_from(m);
+  Square to = move_to(m);
+
+  // Early return if SEE cannot be negative because capturing piece value
+  // is not bigger then captured one.
+  if (   midgame_value_of_piece_on(from) <= midgame_value_of_piece_on(to)
+      && type_of_piece_on(from) != KING)
+         return 1;
+
+  return see(from, to);
+}
+
 int Position::see(Square from, Square to) const {
 
   // Material values
@@ -1652,6 +1680,7 @@ void Position::clear() {
   initialKFile = FILE_E;
   initialKRFile = FILE_H;
   initialQRFile = FILE_A;
+  TT = NULL;
 }