Reintroduce gains
authorJoona Kiiski <joona.kiiski@gmail.com>
Sun, 10 Nov 2013 14:53:23 +0000 (14:53 +0000)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 11 Nov 2013 07:46:11 +0000 (08:46 +0100)
This seems a die hard idea :-)

Passed both short TC
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 17485 W: 3307 L: 3156 D: 11022

And long TC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 38181 W: 6002 L: 5729 D: 26450

bench: 8659830

src/movepick.h
src/search.cpp

index 93061ee6fc6a81c8aaf277b817dab41a0d02dd34..c444615f5b9f2e8ab4a0952ff47e3c97bf642079 100644 (file)
 
 
 /// The Stats struct stores moves statistics. According to the template parameter
-/// the class can store History and Countermoves. History records how often
+/// the class can store History, Gains and Countermoves. History records how often
 /// different moves have been successful or unsuccessful during the current search
-/// and is used for reduction and move ordering decisions.
+/// and is used for reduction and move ordering decisions. Gains records the move's
+/// best evaluation gain from one ply to the next and is used for pruning decisions.
 /// Countermoves store the move that refute a previous one. Entries are stored
 /// according only to moving piece and destination square, hence two moves with
 /// different origin but same destination and piece will be considered identical.
-template<typename T>
+template<bool Gain, typename T>
 struct Stats {
 
   static const Value Max = Value(2000);
@@ -55,7 +56,10 @@ struct Stats {
 
   void update(Piece p, Square to, Value v) {
 
-    if (abs(table[p][to] + v) < Max)
+    if (Gain)
+        table[p][to] = std::max(v, table[p][to] - 1);
+
+    else if (abs(table[p][to] + v) < Max)
         table[p][to] +=  v;
   }
 
@@ -63,8 +67,9 @@ private:
   T table[PIECE_NB][SQUARE_NB];
 };
 
-typedef Stats<Value> HistoryStats;
-typedef Stats<std::pair<Move, Move> > CountermovesStats;
+typedef Stats< true, Value> GainsStats;
+typedef Stats<false, Value> HistoryStats;
+typedef Stats<false, std::pair<Move, Move> > CountermovesStats;
 
 
 /// MovePicker class is used to pick one pseudo legal move at a time from the
index 02aea53827f39eff2977258b10ef175bfe49b164..f1ab80f29294e20401fb93e9736b3b2b679668de 100644 (file)
@@ -82,6 +82,7 @@ namespace {
   double BestMoveChanges;
   Value DrawValue[COLOR_NB];
   HistoryStats History;
+  GainsStats Gains;
   CountermovesStats Countermoves;
 
   template <NodeType NT>
@@ -293,6 +294,7 @@ namespace {
     Value bestValue, alpha, beta, delta;
 
     std::memset(ss-2, 0, 5 * sizeof(Stack));
+    (ss-1)->currentMove = MOVE_NULL; // Hack to skip update gains
 
     depth = 0;
     BestMoveChanges = 0;
@@ -301,6 +303,7 @@ namespace {
 
     TT.new_search();
     History.clear();
+    Gains.clear();
     Countermoves.clear();
 
     PVSize = Options["MultiPV"];
@@ -487,9 +490,8 @@ namespace {
     SplitPoint* splitPoint;
     Key posKey;
     Move ttMove, move, excludedMove, bestMove, threatMove;
-    Depth ext, newDepth;
-    Value bestValue, value, ttValue;
-    Value eval, nullValue;
+    Depth ext, newDepth, predictedDepth;
+    Value bestValue, value, ttValue, eval, nullValue, futilityValue;
     bool inCheck, givesCheck, pvMove, singularExtensionNode, improving;
     bool captureOrPromotion, dangerous, doFullDepthSearch;
     int moveCount, quietCount;
@@ -601,6 +603,16 @@ namespace {
         TT.store(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, ss->staticEval);
     }
 
+    if (   !pos.captured_piece_type()
+        &&  ss->staticEval != VALUE_NONE
+        && (ss-1)->staticEval != VALUE_NONE
+        && (move = (ss-1)->currentMove) != MOVE_NULL
+        &&  type_of(move) == NORMAL)
+    {
+        Square to = to_sq(move);
+        Gains.update(pos.piece_on(to), to, -(ss-1)->staticEval - ss->staticEval);
+    }
+
     // Step 6. Razoring (skipped when in check)
     if (   !PvNode
         &&  depth < 4 * ONE_PLY
@@ -847,12 +859,13 @@ moves_loop: // When in check and at SpNode search starts from here
               continue;
           }
 
-          Depth predictedDepth = newDepth - reduction<PvNode>(improving, depth, moveCount);
+          predictedDepth = newDepth - reduction<PvNode>(improving, depth, moveCount);
 
           // Futility pruning: parent node
           if (predictedDepth < 7 * ONE_PLY)
           {
-              Value futilityValue = ss->staticEval + futility_margin(predictedDepth) + Value(128);
+              futilityValue = ss->staticEval + futility_margin(predictedDepth)
+                            + Value(128) + Gains[pos.moved_piece(move)][to_sq(move)];
 
               if (futilityValue <= alpha)
               {
@@ -869,8 +882,7 @@ moves_loop: // When in check and at SpNode search starts from here
           }
 
           // Prune moves with negative SEE at low depths
-          if (   predictedDepth < 4 * ONE_PLY
-              && pos.see_sign(move) < 0)
+          if (predictedDepth < 4 * ONE_PLY && pos.see_sign(move) < 0)
           {
               if (SpNode)
                   splitPoint->mutex.lock();
@@ -883,7 +895,7 @@ moves_loop: // When in check and at SpNode search starts from here
       // Check for legality only before to do the move
       if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
       {
-          --moveCount;
+          moveCount--;
           continue;
       }