Try only recaptures in qsearch if depth is very low
authorMarco Costalba <mcostalba@gmail.com>
Sun, 12 Jun 2011 06:25:51 +0000 (07:25 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Wed, 15 Jun 2011 11:17:49 +0000 (12:17 +0100)
This avoids search explosion in qsearch for some
patological cases like:

r1n1n1b1/1P1P1P1P/1N1N1N2/2RnQrRq/2pKp3/3BNQbQ/k7/4Bq2 w - - 0 1

After 9078 games 20"+0.1 QUAD:
Mod vs Orig 1413 - 1319 - 6346 ELO +3 (+- 4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/movepick.cpp
src/movepick.h
src/search.cpp
src/types.h

index 04fa40d..71c9810 100644 (file)
@@ -37,6 +37,7 @@ namespace {
     PH_BAD_CAPTURES,  // Queen promotions and captures with SEE values < captureThreshold (captureThreshold <= 0)
     PH_EVASIONS,      // Check evasions
     PH_QCAPTURES,     // Captures in quiescence search
+    PH_QRECAPTURES,   // Recaptures in quiescence search
     PH_QCHECKS,       // Non-capture checks in quiescence search
     PH_STOP
   };
@@ -46,6 +47,7 @@ namespace {
   const uint8_t EvasionTable[] = { PH_TT_MOVE, PH_EVASIONS, PH_STOP };
   const uint8_t QsearchWithChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_QCHECKS, PH_STOP };
   const uint8_t QsearchWithoutChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_STOP };
+  const uint8_t QsearchRecapturesTable[] = { PH_TT_MOVE, PH_QRECAPTURES, PH_STOP };
   const uint8_t ProbCutTable[] = { PH_TT_MOVE, PH_GOOD_PROBCUT, PH_STOP };
 }
 
@@ -85,7 +87,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h,
   go_next_phase();
 }
 
-MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h)
+MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h, Square recaptureSq)
                       : pos(p), H(h) {
 
   assert(d <= DEPTH_ZERO);
@@ -94,7 +96,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h)
       phasePtr = EvasionTable;
   else if (d >= DEPTH_QS_CHECKS)
       phasePtr = QsearchWithChecksTable;
-  else
+  else if (d >= DEPTH_QS_RECAPTURES)
   {
       phasePtr = QsearchWithoutChecksTable;
 
@@ -104,6 +106,12 @@ MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h)
       if (ttm != MOVE_NONE && !pos.move_is_capture(ttm) && !move_is_promotion(ttm))
           ttm = MOVE_NONE;
   }
+  else
+  {
+      phasePtr = QsearchRecapturesTable;
+      recaptureSquare = recaptureSq;
+      ttm = MOVE_NONE;
+  }
 
   ttMove = (ttm && pos.move_is_pl(ttm) ? ttm : MOVE_NONE);
   phasePtr += int(ttMove == MOVE_NONE) - 1;
@@ -184,6 +192,10 @@ void MovePicker::go_next_phase() {
       score_captures();
       return;
 
+  case PH_QRECAPTURES:
+      lastMove = generate<MV_CAPTURE>(pos, moves);
+      return;
+
   case PH_QCHECKS:
       lastMove = generate<MV_NON_CAPTURE_CHECK>(pos, moves);
       return;
@@ -347,6 +359,12 @@ Move MovePicker::get_next_move() {
               return move;
           break;
 
+      case PH_QRECAPTURES:
+          move = (curMove++)->move;
+          if (move_to(move) == recaptureSquare)
+              return move;
+          break;
+
       case PH_QCHECKS:
           move = (curMove++)->move;
           if (move != ttMove)
index d0ced04..1316e7c 100644 (file)
@@ -41,7 +41,7 @@ class MovePicker {
 
 public:
   MovePicker(const Position&, Move, Depth, const History&, SearchStack*, Value);
-  MovePicker(const Position&, Move, Depth, const History&);
+  MovePicker(const Position&, Move, Depth, const History&, Square recaptureSq);
   MovePicker(const Position&, Move, const History&, int parentCapture);
   Move get_next_move();
 
@@ -56,6 +56,7 @@ private:
   Depth depth;
   Move ttMove;
   MoveStack killers[2];
+  Square recaptureSquare;
   int captureThreshold, phase;
   const uint8_t* phasePtr;
   MoveStack *curMove, *lastMove, *lastNonCapture, *badCaptures;
index 3862e27..50dfcc0 100644 (file)
@@ -1393,7 +1393,7 @@ split_point_start: // At split points actual search starts from here
     // to search the moves. Because the depth is <= 0 here, only captures,
     // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
     // be generated.
-    MovePicker mp(pos, ttMove, depth, H);
+    MovePicker mp(pos, ttMove, depth, H, move_to((ss-1)->currentMove));
     CheckInfo ci(pos);
     Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
 
index 3457514..d02755c 100644 (file)
@@ -201,9 +201,10 @@ enum Depth {
 
   ONE_PLY = 2,
 
-  DEPTH_ZERO         =  0 * ONE_PLY,
-  DEPTH_QS_CHECKS    = -1 * ONE_PLY,
-  DEPTH_QS_NO_CHECKS = -2 * ONE_PLY,
+  DEPTH_ZERO          =  0 * ONE_PLY,
+  DEPTH_QS_CHECKS     = -1 * ONE_PLY,
+  DEPTH_QS_NO_CHECKS  = -2 * ONE_PLY,
+  DEPTH_QS_RECAPTURES = -4 * ONE_PLY,
 
   DEPTH_NONE = -127 * ONE_PLY
 };