]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Another see() shortcut
[stockfish] / src / position.cpp
index e0e9aa3a9b37b316dc1b55f02b00755a3305c42b..1fe723aec461e20a303582484349b9696ca9c552 100644 (file)
@@ -703,7 +703,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
   // pointer to point to the new, ready to be updated, state.
   struct ReducedStateInfo {
     Key key, pawnKey, materialKey;
-    int castleRights, rule50;
+    int castleRights, rule50, pliesFromNull;
     Square epSquare;
     Value mgValue, egValue;
     Value npMaterial[2];
@@ -724,6 +724,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
   // Increment the 50 moves rule draw counter. Resetting it to zero in the
   // case of non-reversible moves is taken care of later.
   st->rule50++;
+  st->pliesFromNull++;
 
   if (move_is_castle(m))
   {
@@ -1242,6 +1243,7 @@ void Position::do_null_move(StateInfo& backupSt) {
   backupSt.mgValue  = st->mgValue;
   backupSt.egValue  = st->egValue;
   backupSt.previous = st->previous;
+  backupSt.pliesFromNull = st->pliesFromNull;
   st->previous = &backupSt;
 
   // Save the current key to the history[] array, in order to be able to
@@ -1258,6 +1260,7 @@ void Position::do_null_move(StateInfo& backupSt) {
   sideToMove = opposite_color(sideToMove);
   st->epSquare = SQ_NONE;
   st->rule50++;
+  st->pliesFromNull = 0;
   gamePly++;
 
   st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
@@ -1279,6 +1282,7 @@ void Position::undo_null_move() {
   st->mgValue  = backupSt->mgValue;
   st->egValue  = backupSt->egValue;
   st->previous = backupSt->previous;
+  st->pliesFromNull = backupSt->pliesFromNull;
 
   // Update the necessary information
   sideToMove = opposite_color(sideToMove);
@@ -1296,13 +1300,13 @@ void Position::undo_null_move() {
 int Position::see(Square to) const {
 
   assert(square_is_ok(to));
-  return see(SQ_NONE, to);
+  return see(SQ_NONE, to, false);
 }
 
 int Position::see(Move m) const {
 
   assert(move_is_ok(m));
-  return see(move_from(m), move_to(m));
+  return see(move_from(m), move_to(m), false);
 }
 
 int Position::see_sign(Move m) const {
@@ -1318,10 +1322,10 @@ int Position::see_sign(Move m) const {
       && type_of_piece_on(from) != KING)
          return 1;
 
-  return see(from, to);
+  return see(from, to, true);
 }
 
-int Position::see(Square from, Square to) const {
+int Position::see(Square from, Square to, bool shortcut) const {
 
   // Material values
   static const int seeValues[18] = {
@@ -1333,7 +1337,9 @@ int Position::see(Square from, Square to) const {
   };
 
   Bitboard attackers, stmAttackers, b;
+  int pieceDiff = 0;
 
+  assert(!shortcut || from != SQ_NONE);
   assert(square_is_ok(from) || from == SQ_NONE);
   assert(square_is_ok(to));
 
@@ -1346,6 +1352,26 @@ int Position::see(Square from, Square to) const {
   Piece capture = piece_on(to);
   Bitboard occ = occupied_squares();
 
+  // King cannot be recaptured
+  if (type_of_piece(piece) == KING)
+      return seeValues[capture];
+
+  // If captured piece is defended by enemy pawns or knights then SEE is negative
+  // when captured piece value does not compensate the lost of capturing one.
+  if (shortcut)
+  {
+      pieceDiff = seeValues[piece] - seeValues[capture];
+
+      if (   pieceDiff > seeValues[PAWN]
+          &&(attacks_from<PAWN>(to, us) & pieces(PAWN, them)))
+          return -(pieceDiff - seeValues[PAWN] / 2);
+
+      if (   pieceDiff > seeValues[KNIGHT]
+          && pieces(KNIGHT, them)
+          &&(pieces(KNIGHT, them) & attacks_from<KNIGHT>(to)))
+          return -(pieceDiff - seeValues[KNIGHT] / 2);
+  }
+
   // Handle en passant moves
   if (st->epSquare == to && type_of_piece_on(from) == PAWN)
   {
@@ -1416,6 +1442,15 @@ int Position::see(Square from, Square to) const {
       for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
           assert(pt < KING);
 
+      // If captured piece is defended by an enemy piece then SEE is negative
+      // if captured piece value does not compensate the lost of capturing one.
+      if (pieceDiff > seeValues[pt])
+      {
+          assert(shortcut);
+          return -(pieceDiff - seeValues[pt] / 2);
+      } else
+          pieceDiff = 0; // Only first cycle
+
       // Remove the attacker we just found from the 'attackers' bitboard,
       // and scan for new X-ray attacks behind the attacker.
       b = stmAttackers & pieces(pt);
@@ -1484,8 +1519,8 @@ void Position::clear() {
   for (int i = 0; i < 64; i++)
       board[i] = EMPTY;
 
-  for (int i = 0; i < 7; i++)
-      for (int j = 0; j < 8; j++)
+  for (int i = 0; i < 8; i++)
+      for (int j = 0; j < 16; j++)
           pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE;
 
   sideToMove = WHITE;
@@ -1683,7 +1718,7 @@ bool Position::is_draw() const {
       return true;
 
   // Draw by repetition?
-  for (int i = 2; i < Min(gamePly, st->rule50); i += 2)
+  for (int i = 2; i < Min(Min(gamePly, st->rule50), st->pliesFromNull); i += 2)
       if (history[gamePly - i] == st->key)
           return true;