Ok. Let's do electricity providers happy. I'm going to add in test queue this one:I try to confirm the result with 60000 10'' games now.
My electricity provider will be glad
Code: Select all
Subject: Use TT in PV also in qsearch()
Patch from Fruity:
http://www.open-chess.org/viewtopic.php?f=5&t=1042&start=160
Slightly reshuffled by me.
---
diff --git a/src/search.cpp b/src/search.cpp
--- a/src/search.cpp
+++ b/src/search.cpp
@@ -293,6 +293,20 @@ namespace {
}
template <NodeType PvNode>
+ inline bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value alpha, Value beta, int ply) {
+
+ Value v = value_from_tt(tte->value(), ply);
+
+ return ( tte->depth() >= depth
+ || v >= Max(value_mate_in(PLY_MAX), beta)
+ || v <= Min(value_mated_in(PLY_MAX), alpha))
+ &&
+ (PvNode ? tte->type() == VALUE_TYPE_EXACT
+ : ( ((tte->type() & VALUE_TYPE_LOWER) && v >= beta)
+ || ((tte->type() & VALUE_TYPE_UPPER) && v <= alpha)));
+ }
+
+ template <NodeType PvNode>
Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool singleEvasion, bool mateThreat, bool* dangerous);
bool check_is_dangerous(Position &pos, Move move, Value futilityBase, Value beta, Value *bValue);
@@ -300,7 +314,6 @@ namespace {
bool value_is_mate(Value value);
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 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);
@@ -991,14 +1004,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, 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 (tte && ok_to_use_TT<PvNode>(tte, depth, alpha, beta, ply))
{
TT.refresh(tte);
ss->bestMove = ttMove; // Can be MOVE_NONE
@@ -1443,7 +1452,7 @@ split_point_start: // At split points actual search starts from here
tte = TT.retrieve(pos.get_key());
ttMove = (tte ? tte->move() : MOVE_NONE);
- if (!PvNode && tte && ok_to_use_TT(tte, ttDepth, beta, ply))
+ if (tte && ok_to_use_TT<PvNode>(tte, ttDepth, alpha, beta, ply))
{
ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
@@ -1849,22 +1858,6 @@ 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.
-
- bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply) {
-
- Value v = value_from_tt(tte->value(), ply);
-
- return ( tte->depth() >= depth
- || v >= Max(value_mate_in(PLY_MAX), beta)
- || v < Min(value_mated_in(PLY_MAX), beta))
-
- && ( ((tte->type() & VALUE_TYPE_LOWER) && v >= beta)
- || ((tte->type() & VALUE_TYPE_UPPER) && v < beta));
- }
-
-
// refine_eval() returns the transposition table score if
// possible otherwise falls back on static position evaluation.
diff --git a/src/tt.cpp b/src/tt.cpp
--- a/src/tt.cpp
+++ b/src/tt.cpp
@@ -121,7 +121,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)
BTW I have thought a bit about your result because was unexpected. It is true that leaf nodes are the most but PV leaf nodes are a real rarity and also in that case the advantage of returning from TT instead of performing the actual searching is minimal. But I have found a possible side effect that could be more important. At the beginning of the search we perform a qsearch<PvNode>() on the root position to have a startup scoring and so a startup ordering. It can happen that the startup ordering plays a role and in this case also your patch that uses TT hits in qsearch().