&& !Threads.stop
&& !Threads.stopOnPonderhit)
{
- const int F[] = { failedLow,
- bestValue - mainThread->previousScore };
-
- int improvingFactor = std::max(246, std::min(832, 306 + 119 * F[0] - 6 * F[1]));
+ double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
+ fallingEval = std::max(0.5, std::min(1.5, fallingEval));
// If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = 1.0;
// Stop the search if we have only one legal move, or if available time elapsed
if ( rootMoves.size() == 1
- || Time.elapsed() > Time.optimum() * bestMoveInstability * improvingFactor / 581)
+ || Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval)
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
&& depth >= 5 * ONE_PLY
&& abs(beta) < VALUE_MATE_IN_MAX_PLY)
{
- Value rbeta = std::min(beta + 216 - 48 * improving, VALUE_INFINITE);
- MovePicker mp(pos, ttMove, rbeta - ss->staticEval, &thisThread->captureHistory);
+ Value raisedBeta = std::min(beta + 216 - 48 * improving, VALUE_INFINITE);
+ MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &thisThread->captureHistory);
int probCutCount = 0;
while ( (move = mp.next_move()) != MOVE_NONE
pos.do_move(move, st);
// Perform a preliminary qsearch to verify that the move holds
- value = -qsearch<NonPV>(pos, ss+1, -rbeta, -rbeta+1);
+ value = -qsearch<NonPV>(pos, ss+1, -raisedBeta, -raisedBeta+1);
// If the qsearch held perform the regular search
- if (value >= rbeta)
- value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, depth - 4 * ONE_PLY, !cutNode);
+ if (value >= raisedBeta)
+ value = -search<NonPV>(pos, ss+1, -raisedBeta, -raisedBeta+1, depth - 4 * ONE_PLY, !cutNode);
pos.undo_move(move);
- if (value >= rbeta)
+ if (value >= raisedBeta)
return value;
}
}
if ( depth >= 8 * ONE_PLY
&& move == ttMove
&& !rootNode
- && !excludedMove // Recursive singular search is not allowed
+ && !excludedMove // Avoid recursive singular search
&& ttValue != VALUE_NONE
&& (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 3 * ONE_PLY
&& pos.legal(move))
{
- Value rBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE);
+ Value reducedBeta = std::max(ttValue - 2 * depth / ONE_PLY, -VALUE_MATE);
ss->excludedMove = move;
- value = search<NonPV>(pos, ss, rBeta - 1, rBeta, depth / 2, cutNode);
+ value = search<NonPV>(pos, ss, reducedBeta - 1, reducedBeta, depth / 2, cutNode);
ss->excludedMove = MOVE_NONE;
- if (value < rBeta)
+ if (value < reducedBeta)
extension = ONE_PLY;
}
else if ( givesCheck // Check extension (~2 Elo)
int lmrDepth = std::max(newDepth - reduction<PvNode>(improving, depth, moveCount), DEPTH_ZERO) / ONE_PLY;
// Countermoves based pruning (~20 Elo)
- if ( lmrDepth < 3 + ((ss-1)->statScore > 0)
+ if ( lmrDepth < 3 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)
&& (*contHist[0])[movedPiece][to_sq(move)] < CounterMovePruneThreshold
&& (*contHist[1])[movedPiece][to_sq(move)] < CounterMovePruneThreshold)
continue;
update_capture_stats(pos, bestMove, capturesSearched, captureCount, stat_bonus(depth + ONE_PLY));
- // Extra penalty for a quiet TT move in previous ply when it gets refuted
- if ((ss-1)->moveCount == 1 && !pos.captured_piece())
- update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
+ // Extra penalty for a quiet TT or main killer move in previous ply when it gets refuted
+ if ( (ss-1)->moveCount == 1
+ || ((ss-1)->currentMove == (ss-1)->killers[0] && (ss-1)->killers[0]))
+ if (!pos.captured_piece())
+ update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
- // Extra penalty for killer move in previous ply when it gets refuted
- else if ( (ss-1)->killers[0]
- && (ss-1)->currentMove == (ss-1)->killers[0]
- && !pos.captured_piece())
- update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth));
}
// Bonus for prior countermove that caused the fail low
else if ( (depth >= 3 * ONE_PLY || PvNode)