Another see() shortcut
authorMarco Costalba <mcostalba@gmail.com>
Sat, 31 Oct 2009 10:16:40 +0000 (11:16 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sun, 1 Nov 2009 20:06:26 +0000 (21:06 +0100)
Because we only generate legal moves we can assume
a king cannot be recaptured, so we can safely return
immediately with the captured piece score. If the move
turns out to be illegal it will be pruned anyhow,
independently from SEE value. This gives a good speed up
especially now that we SEE-test all the evasions that
are always legal and very often are king moves.

Another optimization catches almost 15% of cases, unfortunatly
we have already calculated the very expensive attacks, so
benefits are not so big anyway.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/position.cpp

index b6a8d7465d5911a84b06f52e5e48edfec5e86965..1fe723aec461e20a303582484349b9696ca9c552 100644 (file)
@@ -1337,6 +1337,7 @@ int Position::see(Square from, Square to, bool shortcut) const {
   };
 
   Bitboard attackers, stmAttackers, b;
   };
 
   Bitboard attackers, stmAttackers, b;
+  int pieceDiff = 0;
 
   assert(!shortcut || from != SQ_NONE);
   assert(square_is_ok(from) || from == SQ_NONE);
 
   assert(!shortcut || from != SQ_NONE);
   assert(square_is_ok(from) || from == SQ_NONE);
@@ -1351,20 +1352,24 @@ int Position::see(Square from, Square to, bool shortcut) const {
   Piece capture = piece_on(to);
   Bitboard occ = occupied_squares();
 
   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
   // If captured piece is defended by enemy pawns or knights then SEE is negative
-  // when captured piece value is not enough to compensate the lost of capturing one.
+  // when captured piece value does not compensate the lost of capturing one.
   if (shortcut)
   {
   if (shortcut)
   {
-      int diff = seeValues[piece] - seeValues[capture];
+      pieceDiff = seeValues[piece] - seeValues[capture];
 
 
-      if (   diff > seeValues[PAWN]
+      if (   pieceDiff > seeValues[PAWN]
           &&(attacks_from<PAWN>(to, us) & pieces(PAWN, them)))
           &&(attacks_from<PAWN>(to, us) & pieces(PAWN, them)))
-          return -(diff - seeValues[PAWN] / 2);
+          return -(pieceDiff - seeValues[PAWN] / 2);
 
 
-      if (   diff > seeValues[KNIGHT]
+      if (   pieceDiff > seeValues[KNIGHT]
           && pieces(KNIGHT, them)
           &&(pieces(KNIGHT, them) & attacks_from<KNIGHT>(to)))
           && pieces(KNIGHT, them)
           &&(pieces(KNIGHT, them) & attacks_from<KNIGHT>(to)))
-          return -(diff - seeValues[KNIGHT] / 2);
+          return -(pieceDiff - seeValues[KNIGHT] / 2);
   }
 
   // Handle en passant moves
   }
 
   // Handle en passant moves
@@ -1437,6 +1442,15 @@ int Position::see(Square from, Square to, bool shortcut) const {
       for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
           assert(pt < KING);
 
       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);
       // Remove the attacker we just found from the 'attackers' bitboard,
       // and scan for new X-ray attacks behind the attacker.
       b = stmAttackers & pieces(pt);