pvLast = 0;
if (!Threads.increaseDepth)
- searchAgainCounter++;
+ searchAgainCounter++;
// MultiPV loop. We perform a full root search for each PV line
for (pvIdx = 0; pvIdx < multiPV && !Threads.stop; ++pvIdx)
if (!Threads.stop)
completedDepth = rootDepth;
- if (rootMoves[0].pv[0] != lastBestMove) {
- lastBestMove = rootMoves[0].pv[0];
- lastBestMoveDepth = rootDepth;
+ if (rootMoves[0].pv[0] != lastBestMove)
+ {
+ lastBestMove = rootMoves[0].pv[0];
+ lastBestMoveDepth = rootDepth;
}
// Have we found a "mate in x"?
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);
+ ttCapture = ttMove && pos.capture_stage(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.
complexity = 0;
goto moves_loop;
}
- else if (excludedMove) {
+ else if (excludedMove)
+ {
// Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 elo)
Eval::NNUE::hint_common_parent_position(pos);
eval = ss->staticEval;
if (eval == VALUE_NONE)
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());
+ if (PvNode)
+ Eval::NNUE::hint_common_parent_position(pos);
+ }
// ttValue can be used as a better position evaluation (~7 Elo)
if ( ttValue != VALUE_NONE
// Save static evaluation into transposition table
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)
probCutBeta = beta + 186 - 54 * improving;
// Step 10. ProbCut (~10 Elo)
- // If we have a good enough capture and a reduced search returns a value
+ // If we have a good enough capture (or queen promotion) and a reduced search returns a value
// much above beta, we can (almost) safely prune the previous move.
if ( !PvNode
&& depth > 4
while ((move = mp.next_move()) != MOVE_NONE)
if (move != excludedMove && pos.legal(move))
{
- assert(pos.capture(move) || promotion_type(move) == QUEEN);
+ assert(pos.capture_stage(move));
ss->currentMove = move;
ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck]
return value;
}
}
+
+ Eval::NNUE::hint_common_parent_position(pos);
}
// Step 11. If the position is not in TT, decrease depth by 3.
&& tte->depth() >= depth - 3
&& ttValue >= probCutBeta
&& abs(ttValue) <= VALUE_KNOWN_WIN
- && abs(beta) <= VALUE_KNOWN_WIN
- )
+ && abs(beta) <= VALUE_KNOWN_WIN)
return probCutBeta;
-
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
nullptr , (ss-4)->continuationHistory,
nullptr , (ss-6)->continuationHistory };
(ss+1)->pv = nullptr;
extension = 0;
- capture = pos.capture(move);
+ capture = pos.capture_stage(move);
movedPiece = pos.moved_piece(move);
givesCheck = pos.gives_check(move);
&& (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 3)
{
- Value singularBeta = ttValue - (2 + (ss->ttPv && !PvNode)) * depth;
+ Value singularBeta = ttValue - (3 + 2 * (ss->ttPv && !PvNode)) * depth / 2;
Depth singularDepth = (depth - 1) / 2;
ss->excludedMove = move;
// If the eval of ttMove is greater than beta, we reduce it (negative extension)
else if (ttValue >= beta)
- extension = -2;
+ extension = -2 - !PvNode;
- // If the eval of ttMove is less than alpha and value, we reduce it (negative extension)
- else if (ttValue <= alpha && ttValue <= value)
+ // If the eval of ttMove is less than value, we reduce it (negative extension)
+ else if (ttValue <= value)
+ extension = -1;
+
+ // If the eval of ttMove is less than alpha, we reduce it (negative extension)
+ else if (ttValue <= alpha)
extension = -1;
}
// Step 18. Full depth search when LMR is skipped. If expected reduction is high, reduce its depth by 1.
else if (!PvNode || moveCount > 1)
{
- // Increase reduction for cut nodes and not ttMove (~1 Elo)
- if (!ttMove && cutNode)
- r += 2;
+ // Increase reduction for cut nodes and not ttMove (~1 Elo)
+ if (!ttMove && cutNode)
+ r += 2;
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 4), !cutNode);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth - (r > 4), !cutNode);
}
// For PV nodes only, do a full PV search on the first move or after a fail
rm.selDepth = thisThread->selDepth;
rm.scoreLowerbound = rm.scoreUpperbound = false;
- if (value >= beta) {
- rm.scoreLowerbound = true;
- rm.uciScore = beta;
+ if (value >= beta)
+ {
+ rm.scoreLowerbound = true;
+ rm.uciScore = beta;
}
- else if (value <= alpha) {
- rm.scoreUpperbound = true;
- rm.uciScore = alpha;
+ else if (value <= alpha)
+ {
+ rm.scoreUpperbound = true;
+ rm.uciScore = alpha;
}
+
rm.pv.resize(1);
assert((ss+1)->pv);
// Bonus for prior countermove that caused the fail low
else if (!priorCapture)
{
- // Extra bonuses for PV/Cut nodes or bad fail lows
- int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth);
+ int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth) + ((ss-1)->moveCount > 10);
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus);
}
// TT entry depth that we are going to use. Note that in qsearch we use
// only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
ttDepth = ss->inCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS
- : DEPTH_QS_NO_CHECKS;
+ : DEPTH_QS_NO_CHECKS;
+
// Step 3. Transposition table lookup
posKey = pos.key();
tte = TT.probe(posKey, ss->ttHit);
continue;
givesCheck = pos.gives_check(move);
- capture = pos.capture(move);
+ capture = pos.capture_stage(move);
moveCount++;
// Do not search moves with bad enough SEE values (~5 Elo)
if (!pos.see_ge(move, Value(-110)))
continue;
-
}
// Speculative prefetch as early as possible
PieceType captured = type_of(pos.piece_on(to_sq(bestMove)));
int bonus1 = stat_bonus(depth + 1);
- if (!pos.capture(bestMove))
+ if (!pos.capture_stage(bestMove))
{
int bonus2 = bestValue > beta + 153 ? bonus1 // larger bonus
: stat_bonus(depth); // smaller bonus