Use TT for pruning also in PV nodes
authorMarco Costalba <mcostalba@gmail.com>
Mon, 31 Jan 2011 12:05:01 +0000 (13:05 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 31 Jan 2011 12:07:26 +0000 (13:07 +0100)
Biggest advantage is be able to analize positions
without "loss of memory" when goind back/forth in
a position.

Patch has proven to fix analysys problems and is even
worths some elo points.

After 5811 games Mod- Orig:
1037 - 902 - 3872 +8 ELO  (+- 3.6) LOS 97%

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

index eb19b51d9c994c5d11e8c9c7abfb195806e475af..791cbc6fb580901a567296d23a0eeed08f892969 100644 (file)
@@ -297,6 +297,7 @@ namespace {
   Value value_to_tt(Value v, int ply);
   Value value_from_tt(Value v, int ply);
   bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
+  bool ok_to_use_TT_PV(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply);
   bool connected_threat(const Position& pos, Move m, Move threat);
   Value refine_eval(const TTEntry* tte, Value defaultEval, int ply);
   void update_history(const Position& pos, Move move, Depth depth, Move movesSearched[], int moveCount);
@@ -838,14 +839,10 @@ namespace {
     tte = TT.retrieve(posKey);
     ttMove = tte ? tte->move() : MOVE_NONE;
 
-    // At PV nodes, we don't use the TT for pruning, but only for move ordering.
-    // This is to avoid problems in the following areas:
-    //
-    // * Repetition draw detection
-    // * Fifty move rule detection
-    // * Searching for a mate
-    // * Printing of full PV line
-    if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
+    // At PV nodes we check for exact scores within (alha, beta) range, while
+    // at non-PV nodes we check for and return a fail high/low. Biggest advantage
+    // at probing at PV nodes is to have a smooth experience in analysis mode.
+    if (!Root && tte && (PvNode ? ok_to_use_TT_PV(tte, depth, alpha, beta, ply) : ok_to_use_TT(tte, depth, beta, ply)))
     {
         TT.refresh(tte);
         ss->bestMove = ttMove; // Can be MOVE_NONE
@@ -1797,7 +1794,9 @@ split_point_start: // At split points actual search starts from here
 
 
   // ok_to_use_TT() returns true if a transposition table score
-  // can be used at a given point in search.
+  // can be used at a given point in search. There are two versions
+  // one to be used in non-PV nodes and one in PV nodes where we look
+  // for an exact score that falls between (alha, beta) boundaries.
 
   bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply) {
 
@@ -1811,6 +1810,17 @@ split_point_start: // At split points actual search starts from here
               || ((tte->type() & VALUE_TYPE_UPPER) && v < beta));
   }
 
+  bool ok_to_use_TT_PV(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply) {
+
+    Value v = value_from_tt(tte->value(), ply);
+
+     return   tte->depth() >= depth
+           && tte->type() == VALUE_TYPE_EXACT
+           && tte->move() != MOVE_NONE
+           && v < beta
+           && v > alpha;
+  }
+
 
   // refine_eval() returns the transposition table score if
   // possible otherwise falls back on static position evaluation.
index 20ac1608e2fee1eb0e1338c3dbbe940275cc9f36..773f03ccbac463929faf254ec4cb8e591d42c224 100644 (file)
@@ -122,7 +122,7 @@ void TranspositionTable::store(const Key posKey, Value v, ValueType t, Depth d,
           continue;
 
       c1 = (replace->generation() == generation ?  2 : 0);
-      c2 = (tte->generation() == generation ? -2 : 0);
+      c2 = (tte->generation() == generation || tte->type() == VALUE_TYPE_EXACT ? -2 : 0);
       c3 = (tte->depth() < replace->depth() ?  1 : 0);
 
       if (c1 + c2 + c3 > 0)