]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Explicitly use delta psqt values when possible
[stockfish] / src / position.cpp
index ec86f35ce73ebecb16c6394604d150c28e8e53e1..1179f6f98a8aa61733cb81df7cdecae906c4a042 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
 }
 
 
@@ -553,12 +555,12 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
           && (direction_between_squares(from, ksq) != direction_between_squares(to, ksq)))
           return true;
 
-      if (move_promotion(m)) // Promotion with check?
+      if (move_is_promotion(m)) // Promotion with check?
       {
           Bitboard b = occupied_squares();
           clear_bit(&b, from);
 
-          switch (move_promotion(m))
+          switch (move_promotion_piece(m))
           {
           case KNIGHT:
               return bit_is_set(piece_attacks<KNIGHT>(to), ksq);
@@ -719,7 +721,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
 
   if (move_is_castle(m))
       do_castle_move(m);
-  else if (move_promotion(m))
+  else if (move_is_promotion(m))
       do_promotion_move(m);
   else if (move_is_ep(m))
       do_ep_move(m);
@@ -733,7 +735,8 @@ 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);
 
@@ -741,26 +744,23 @@ 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[pt]), 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];
+    st->key ^= zobrist[us][pt][from] ^ zobrist[us][pt][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);
+    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 (piece == KING)
+    if (pt == KING)
         kingSquare[us] = to;
 
     // Reset en passant square
@@ -771,7 +771,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
     }
 
     // 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;
@@ -792,19 +792,22 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
     }
 
     // Update piece lists
-    pieceList[us][piece][index[from]] = to;
+    pieceList[us][pt][index[from]] = to;
     index[to] = index[from];
 
-    // Update castle rights
-    st->key ^= zobCastle[st->castleRights];
-    st->castleRights &= castleRightsMask[from];
-    st->castleRights &= castleRightsMask[to];
-    st->key ^= zobCastle[st->castleRights];
+    // 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;
@@ -838,6 +841,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];
@@ -918,9 +922,11 @@ void Position::do_castle_move(Move m) {
   set_bit(&(byTypeBB[0]), rto); // 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;
@@ -933,14 +939,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];
@@ -977,7 +979,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);
@@ -1000,7 +1002,7 @@ void Position::do_promotion_move(Move m) {
   board[from] = EMPTY;
 
   // Insert promoted piece
-  promotion = move_promotion(m);
+  promotion = move_promotion_piece(m);
   assert(promotion >= KNIGHT && promotion <= QUEEN);
   set_bit(&(byColorBB[us]), to);
   set_bit(&(byTypeBB[promotion]), 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;
 
@@ -1120,12 +1118,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;
@@ -1151,7 +1148,7 @@ void Position::undo_move(Move m) {
 
   if (move_is_castle(m))
       undo_castle_move(m);
-  else if (move_promotion(m))
+  else if (move_is_promotion(m))
       undo_promotion_move(m);
   else if (move_is_ep(m))
       undo_ep_move(m);
@@ -1170,17 +1167,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 +1186,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);
@@ -1293,7 +1286,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,
@@ -1307,7 +1300,7 @@ void Position::undo_promotion_move(Move m) {
   assert(piece_on(from) == EMPTY);
 
   // Remove promoted piece
-  promotion = move_promotion(m);
+  promotion = move_promotion_piece(m);
   assert(piece_on(to)==piece_of_color_and_type(us, promotion));
   assert(promotion >= KNIGHT && promotion <= QUEEN);
   clear_bit(&(byColorBB[us]), to);
@@ -1375,22 +1368,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 +1402,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 +1442,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());
 }
@@ -1606,7 +1593,7 @@ int Position::see(Square from, Square to) const {
       if (pt == KING && stmAttackers)
       {
           assert(n < 32);
-          swapList[n++] = 100;
+          swapList[n++] = QueenValueMidgame*10;
           break;
       }
   } while (stmAttackers);
@@ -1620,15 +1607,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 +1967,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());