if (!rootNode)
(ss+2)->statScore = 0;
- // Step 4. Transposition table lookup. We don't want the score of a partial
- // search to overwrite a previous full search TT value, so we use a different
- // position key in case of an excluded move.
+ // Step 4. Transposition table lookup.
excludedMove = ss->excludedMove;
- posKey = excludedMove == MOVE_NONE ? pos.key() : pos.key() ^ make_key(excludedMove);
+ posKey = pos.key();
tte = TT.probe(posKey, ss->ttHit);
ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
: ss->ttHit ? tte->move() : MOVE_NONE;
ttCapture = ttMove && pos.capture(ttMove);
+
+ // At this point, if excluded, skip straight to step 6, static eval. However,
+ // to save indentation, we list the condition in all code between here and there.
if (!excludedMove)
ss->ttPv = PvNode || (ss->ttHit && tte->is_pv());
// At non-PV nodes we check for an early TT cutoff
if ( !PvNode
&& ss->ttHit
+ && !excludedMove
&& tte->depth() > depth - (tte->bound() == BOUND_EXACT)
&& ttValue != VALUE_NONE // Possible in case of TT access race
&& (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER)))
}
// Step 5. Tablebases probe
- if (!rootNode && TB::Cardinality)
+ if (!rootNode && !excludedMove && TB::Cardinality)
{
int piecesCount = pos.count<ALL_PIECES>();
complexity = 0;
goto moves_loop;
}
+ else if (excludedMove) {
+ // excludeMove implies that we had a ttHit on the containing non-excluded search with ss->staticEval filled from TT
+ // However static evals from the TT aren't good enough (-13 elo), presumably due to changing optimism context
+ // Recalculate value with current optimism (without updating thread avgComplexity)
+ ss->staticEval = eval = evaluate(pos, &complexity);
+ }
else if (ss->ttHit)
{
// Never assume anything about values stored in TT
ss->staticEval = eval = evaluate(pos, &complexity);
else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost
complexity = abs(ss->staticEval - pos.psq_eg_stm());
+ thisThread->complexityAverage.update(complexity);
// ttValue can be used as a better position evaluation (~7 Elo)
if ( ttValue != VALUE_NONE
else
{
ss->staticEval = eval = evaluate(pos, &complexity);
+ thisThread->complexityAverage.update(complexity);
// Save static evaluation into transposition table
- if (!excludedMove)
- tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
+ tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
}
- thisThread->complexityAverage.update(complexity);
-
// Use static evaluation difference to improve quiet move ordering (~4 Elo)
if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture)
{
Depth singularDepth = (depth - 1) / 2;
ss->excludedMove = move;
+ // the search with excludedMove will update ss->staticEval
value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode);
ss->excludedMove = MOVE_NONE;