Remove Threat Extension
authorLucas Braesch <lucas.braesch@gmail.com>
Tue, 1 Jan 2013 03:51:35 +0000 (11:51 +0800)
committerMarco Costalba <mcostalba@gmail.com>
Tue, 15 Jan 2013 16:03:56 +0000 (17:03 +0100)
Great code simplification: - instead do not futility
prune threat refutations. allows_move() is therefore removed.

4000 games at 50,000 nodes/move:
1085-989-1926 [51.2%] LOS=98.3%

4000 games in 10"+0.1"
756-751-2493 [50.1%] LOS=55.1%

EDIT: I have retested the patch of Lucas in a slightly different form
(without pruning in PvNode) and test mre or less confirms that
60 lines of code are totally unuseful:

After 6195 games at 15"+0.05"
1333 - 1325 - 3537 ELO 0

bench 5140990

src/search.cpp

index 0be6912..4eaf2e5 100644 (file)
@@ -99,7 +99,6 @@ namespace {
   Value value_to_tt(Value v, int ply);
   Value value_from_tt(Value v, int ply);
   bool check_is_dangerous(Position& pos, Move move, Value futilityBase, Value beta);
-  bool allows_move(const Position& pos, Move first, Move second);
   bool prevents_move(const Position& pos, Move first, Move second);
   string uci_pv(const Position& pos, int depth, Value alpha, Value beta);
 
@@ -499,13 +498,12 @@ namespace {
     Value bestValue, value, ttValue;
     Value eval, nullValue, futilityValue;
     bool inCheck, givesCheck, pvMove, singularExtensionNode;
-    bool captureOrPromotion, dangerous, doFullDepthSearch, threatExtension;
+    bool captureOrPromotion, dangerous, doFullDepthSearch;
     int moveCount, playedMoveCount;
 
     // Step 1. Initialize node
     Thread* thisThread = pos.this_thread();
     moveCount = playedMoveCount = 0;
-    threatExtension = false;
     inCheck = pos.checkers();
 
     if (SpNode)
@@ -694,20 +692,9 @@ namespace {
                 return nullValue;
         }
         else
-        {
             // The null move failed low, which means that we may be faced with
-            // some kind of threat. If the previous move was reduced, check if
-            // the move that refuted the null move was somehow connected to the
-            // move which was reduced. If a connection is found extend moves that
-            // defend against threat.
+            // some kind of threat.
             threatMove = (ss+1)->currentMove;
-
-            if (   depth < 5 * ONE_PLY
-                && (ss-1)->reduction
-                && threatMove != MOVE_NONE
-                && allows_move(pos, (ss-1)->currentMove, threatMove))
-                threatExtension = true;
-        }
     }
 
     // Step 9. ProbCut (is omitted in PV nodes)
@@ -824,9 +811,6 @@ split_point_start: // At split points actual search starts from here
       if (PvNode && dangerous)
           ext = ONE_PLY;
 
-      else if (threatExtension && prevents_move(pos, move, threatMove))
-          ext = ONE_PLY;
-
       else if (givesCheck && pos.see_sign(move) >= 0)
           ext = ONE_PLY / 2;
 
@@ -863,13 +847,12 @@ split_point_start: // At split points actual search starts from here
           && !inCheck
           && !dangerous
           &&  move != ttMove
+          && (!threatMove || !prevents_move(pos, move, threatMove))
           && (bestValue > VALUE_MATED_IN_MAX_PLY || (   bestValue == -VALUE_INFINITE
                                                      && alpha > VALUE_MATED_IN_MAX_PLY)))
       {
           // Move count based pruning
-          if (   depth < 16 * ONE_PLY
-              && moveCount >= FutilityMoveCounts[depth]
-              && (!threatMove || !prevents_move(pos, move, threatMove)))
+          if (depth < 16 * ONE_PLY && moveCount >= FutilityMoveCounts[depth])
           {
               if (SpNode)
                   sp->mutex.lock();
@@ -1368,47 +1351,6 @@ split_point_start: // At split points actual search starts from here
   }
 
 
-  // allows_move() tests whether the move at previous ply (first) somehow makes a
-  // second move possible, for instance if the moving piece is the same in both
-  // moves. Normally the second move is the threat move (the best move returned
-  // from a null search that fails low).
-
-  bool allows_move(const Position& pos, Move first, Move second) {
-
-    assert(is_ok(first));
-    assert(is_ok(second));
-    assert(color_of(pos.piece_on(from_sq(second))) == ~pos.side_to_move());
-    assert(color_of(pos.piece_on(to_sq(first))) == ~pos.side_to_move());
-
-    Square m1from = from_sq(first);
-    Square m2from = from_sq(second);
-    Square m1to = to_sq(first);
-    Square m2to = to_sq(second);
-
-    // The piece is the same or second's destination was vacated by the first move
-    if (m1to == m2from || m2to == m1from)
-        return true;
-
-    // Second one moves through the square vacated by first one
-    if (between_bb(m2from, m2to) & m1from)
-      return true;
-
-    // Second's destination is defended by the first move's piece
-    Bitboard m1att = pos.attacks_from(pos.piece_on(m1to), m1to, pos.pieces() ^ m2from);
-    if (m1att & m2to)
-        return true;
-
-    // Second move gives a discovered check through the first's checking piece
-    if (m1att & pos.king_square(pos.side_to_move()))
-    {
-        assert(between_bb(m1to, pos.king_square(pos.side_to_move())) & m2from);
-        return true;
-    }
-
-    return false;
-  }
-
-
   // prevents_move() tests whether a move (first) is able to defend against an
   // opponent's move (second). In this case will not be pruned. Normally the
   // second move is the threat move (the best move returned from a null search