const int skipPhase[] = { 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7 };
// Razoring and futility margin based on depth
- // razor_margin[0] is unused as long as depth >= ONE_PLY in search
- const int razor_margin[] = { 0, 570, 603, 554 };
+ const int razor_margin = 600;
Value futility_margin(Depth d) { return Value(150 * d / ONE_PLY); }
// Futility and reductions lookup tables, initialized at startup
Key posKey;
Move ttMove, move, excludedMove, bestMove;
Depth extension, newDepth;
- Value bestValue, value, ttValue, eval;
+ Value bestValue, value, ttValue, eval, maxValue;
bool ttHit, inCheck, givesCheck, singularExtensionNode, improving;
bool captureOrPromotion, doFullDepthSearch, moveCountPruning, skipQuiets, ttCapture, pvExact;
Piece movedPiece;
moveCount = captureCount = quietCount = ss->moveCount = 0;
ss->statScore = 0;
bestValue = -VALUE_INFINITE;
+ maxValue = VALUE_INFINITE;
// Check for the available remaining time
if (thisThread == Threads.main())
&& !pos.can_castle(ANY_CASTLING))
{
TB::ProbeState err;
- TB::WDLScore v = Tablebases::probe_wdl(pos, &err);
+ TB::WDLScore wdl = Tablebases::probe_wdl(pos, &err);
if (err != TB::ProbeState::FAIL)
{
int drawScore = TB::UseRule50 ? 1 : 0;
- value = v < -drawScore ? -VALUE_MATE + MAX_PLY + ss->ply + 1
- : v > drawScore ? VALUE_MATE - MAX_PLY - ss->ply - 1
- : VALUE_DRAW + 2 * v * drawScore;
+ value = wdl < -drawScore ? -VALUE_MATE + MAX_PLY + ss->ply + 1
+ : wdl > drawScore ? VALUE_MATE - MAX_PLY - ss->ply - 1
+ : VALUE_DRAW + 2 * wdl * drawScore;
- tte->save(posKey, value_to_tt(value, ss->ply), BOUND_EXACT,
- std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY),
- MOVE_NONE, VALUE_NONE, TT.generation());
+ Bound b = wdl < -drawScore ? BOUND_UPPER
+ : wdl > drawScore ? BOUND_LOWER : BOUND_EXACT;
- return value;
+ if ( b == BOUND_EXACT
+ || (b == BOUND_LOWER ? value >= beta : value <= alpha))
+ {
+ tte->save(posKey, value_to_tt(value, ss->ply), b,
+ std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY),
+ MOVE_NONE, VALUE_NONE, TT.generation());
+
+ return value;
+ }
+
+ if (PvNode)
+ {
+ if (b == BOUND_LOWER)
+ bestValue = value, alpha = std::max(alpha, bestValue);
+ else
+ maxValue = value;
+ }
}
}
}
// Step 6. Razoring (skipped when in check)
if ( !PvNode
&& depth < 4 * ONE_PLY
- && eval + razor_margin[depth / ONE_PLY] <= alpha)
+ && eval + razor_margin <= alpha)
{
if (depth <= ONE_PLY)
return qsearch<NonPV, false>(pos, ss, alpha, alpha+1);
- Value ralpha = alpha - razor_margin[depth / ONE_PLY];
+ Value ralpha = alpha - razor_margin;
Value v = qsearch<NonPV, false>(pos, ss, ralpha, ralpha+1);
if (v <= ralpha)
return v;
&& is_ok((ss-1)->currentMove))
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth));
+ if (PvNode)
+ bestValue = std::min(bestValue, maxValue);
+
if (!excludedMove)
tte->save(posKey, value_to_tt(bestValue, ss->ply),
bestValue >= beta ? BOUND_LOWER :
TB::Score = TB::Score > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1
: TB::Score < VALUE_DRAW ? -VALUE_MATE + MAX_PLY + 1
: VALUE_DRAW;
+
+ // Since root_probe() and root_probe_wdl() dirty the root move scores,
+ // we reset them to -VALUE_INFINITE
+ for (RootMove& rm : rootMoves)
+ rm.score = -VALUE_INFINITE;
}