}
// History and stats update bonus, based on depth
-int stat_bonus(Depth d) { return std::min(364 * d - 438, 1501); }
+int stat_bonus(Depth d) { return std::min(291 * d - 350, 1200); }
// History and stats update malus, based on depth
-int stat_malus(Depth d) { return std::min(452 * d - 452, 1478); }
+int stat_malus(Depth d) { return std::min(361 * d - 361, 1182); }
// Add a small random component to draw evaluations to avoid 3-fold blindness
Value value_draw(const Thread* thisThread) {
// Use static evaluation difference to improve quiet move ordering (~4 Elo)
if (is_ok((ss - 1)->currentMove) && !(ss - 1)->inCheck && !priorCapture)
{
- int bonus = std::clamp(-18 * int((ss - 1)->staticEval + ss->staticEval), -1812, 1812);
+ int bonus = std::clamp(-14 * int((ss - 1)->staticEval + ss->staticEval), -1449, 1449);
thisThread->mainHistory[~us][from_to((ss - 1)->currentMove)] << bonus;
if (type_of(pos.piece_on(prevSq)) != PAWN && type_of((ss - 1)->currentMove) != PROMOTION)
thisThread->pawnHistory[pawn_structure(pos)][pos.piece_on(prevSq)][prevSq] << bonus / 4;
if (depth <= 0)
return qsearch<PV>(pos, ss, alpha, beta);
- // For cutNodes without a ttMove, we decrease depth by 2
- // if current depth >= 8.
+ // For cutNodes without a ttMove, we decrease depth by 2 if depth is high enough.
if (cutNode && depth >= 8 && !ttMove)
depth -= 2;
// Note: the depth margin and singularBeta margin are known for having non-linear
// scaling. Their values are optimized to time controls of 180+1.8 and longer
- // so changing them requires tests at this type of time controls.
+ // so changing them requires tests at these types of time controls.
// Recursive singular search is avoided.
if (!rootNode && move == ttMove && !excludedMove
&& depth >= 4 - (thisThread->completedDepth > 24) + 2 * (PvNode && tte->is_pv())
// we do not know if the ttMove is singular or can do a multi-cut,
// so we reduce the ttMove in favor of other moves based on some conditions:
- // If the ttMove is assumed to fail high over currnet beta (~7 Elo)
+ // If the ttMove is assumed to fail high over current beta (~7 Elo)
else if (ttValue >= beta)
extension = -2 - !PvNode;
if ((ss + 1)->cutoffCnt > 3)
r++;
- // Set reduction to 0 for first generated move (ttMove)
+ // Set reduction to 0 for first picked move (ttMove) (~2 Elo)
// Nullifies all previous reduction adjustments to ttMove and leaves only history to do them
else if (move == ttMove)
r = 0;
+ (*contHist[3])[movedPiece][to_sq(move)] - 3848;
// Decrease/increase reduction for moves with a good/bad history (~25 Elo)
- r -= ss->statScore / (10216 + 3855 * (depth > 5 && depth < 23));
+ r -= ss->statScore / 14200;
// Step 17. Late moves reduction / extension (LMR, ~117 Elo)
// We use various heuristics for the sons of a node after the first son has
{
// Adjust full-depth search based on LMR results - if the result
// was good enough search deeper, if it was bad enough search shallower.
- const bool doDeeperSearch = value > (bestValue + 51 + 10 * (newDepth - d));
- const bool doShallowerSearch = value < bestValue + newDepth;
+ const bool doDeeperSearch =
+ value > (bestValue + 51 + 10 * (newDepth - d)); // (~1 Elo)
+ const bool doShallowerSearch = value < bestValue + newDepth; // (~2 Elo)
newDepth += doDeeperSearch - doShallowerSearch;
bestValue = ttValue;
}
else
- // In case of null move search use previous static eval with a different sign
+ // In case of null move search, use previous static eval with a different sign
ss->staticEval = bestValue =
(ss - 1)->currentMove != MOVE_NULL ? evaluate(pos) : -(ss - 1)->staticEval;