// Futility margin
Value futility_margin(Depth d, bool noTtCutNode, bool improving) {
- return Value((125 - 43 * noTtCutNode) * (d - improving));
+ return Value((116 - 44 * noTtCutNode) * (d - improving));
}
// Reductions lookup table initialized at startup
Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
int reductionScale = Reductions[d] * Reductions[mn];
- return (reductionScale + 1487 - int(delta) * 976 / int(rootDelta)) / 1024
- + (!i && reductionScale > 808);
+ return (reductionScale + 1346 - int(delta) * 896 / int(rootDelta)) / 1024
+ + (!i && reductionScale > 880);
}
constexpr int futility_move_count(bool improving, Depth depth) {
}
// History and stats update bonus, based on depth
-int stat_bonus(Depth d) { return std::min(357 * d - 483, 1511); }
+int stat_bonus(Depth d) { return std::min(268 * d - 352, 1153); }
+
+// History and stats update malus, based on depth
+int stat_malus(Depth d) { return std::min(400 * d - 354, 1201); }
// Add a small random component to draw evaluations to avoid 3-fold blindness
Value value_draw(const Thread* thisThread) {
// Reset aspiration window starting size
Value avg = rootMoves[pvIdx].averageScore;
- delta = Value(10) + int(avg) * avg / 15335;
+ delta = Value(9) + int(avg) * avg / 14847;
alpha = std::max(avg - delta, -VALUE_INFINITE);
beta = std::min(avg + delta, VALUE_INFINITE);
// Adjust optimism based on root move's averageScore (~4 Elo)
- optimism[us] = 103 * (avg + 33) / (std::abs(avg + 34) + 119);
- optimism[~us] = -116 * (avg + 40) / (std::abs(avg + 12) + 123);
+ optimism[us] = 121 * avg / (std::abs(avg) + 109);
+ optimism[~us] = -optimism[us];
// Start with a small aspiration window and, in the case of a fail
// high/low, re-search with a bigger window until we don't fail
// the previous ply (~0 Elo on STC, ~2 Elo on LTC).
if (prevSq != SQ_NONE && (ss - 1)->moveCount <= 2 && !priorCapture)
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
- -stat_bonus(depth + 1));
+ -stat_malus(depth + 1));
}
// Penalty for a quiet ttMove that fails low (~1 Elo)
else if (!ttCapture)
{
- int penalty = -stat_bonus(depth);
+ int penalty = -stat_malus(depth);
thisThread->mainHistory[us][from_to(ttMove)] << penalty;
update_continuation_histories(ss, pos.moved_piece(ttMove), to_sq(ttMove), penalty);
}
int drawScore = TB::UseRule50 ? 1 : 0;
- // use the range VALUE_MATE_IN_MAX_PLY to VALUE_TB_WIN_IN_MAX_PLY to score
- value = wdl < -drawScore ? VALUE_MATED_IN_MAX_PLY + ss->ply + 1
- : wdl > drawScore ? VALUE_MATE_IN_MAX_PLY - ss->ply - 1
+ Value tbValue = VALUE_TB - ss->ply;
+
+ // use the range VALUE_TB to VALUE_TB_WIN_IN_MAX_PLY to score
+ value = wdl < -drawScore ? -tbValue
+ : wdl > drawScore ? tbValue
: VALUE_DRAW + 2 * wdl * drawScore;
Bound b = wdl < -drawScore ? BOUND_UPPER
// 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(-13 * int((ss - 1)->staticEval + ss->staticEval), -1555, 1452);
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;
}
// Set up the improving flag, which is true if current static evaluation is
// If eval is really low check with qsearch if it can exceed alpha, if it can't,
// return a fail low.
// Adjust razor margin according to cutoffCnt. (~1 Elo)
- if (eval < alpha - 474 - (270 - 174 * ((ss + 1)->cutoffCnt > 3)) * depth * depth)
+ if (eval < alpha - 472 - (284 - 165 * ((ss + 1)->cutoffCnt > 3)) * depth * depth)
{
value = qsearch<NonPV>(pos, ss, alpha - 1, alpha);
if (value < alpha)
- {
- if (!priorCapture && prevSq != SQ_NONE)
- {
- int bonus = (depth > 6) + (PvNode || cutNode) + (value < alpha - 658)
- + ((ss - 1)->moveCount > 11);
- update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
- stat_bonus(depth) * bonus);
- thisThread->mainHistory[~us][from_to((ss - 1)->currentMove)]
- << stat_bonus(depth) * bonus * 57 / 100;
- }
return value;
- }
}
// Step 8. Futility pruning: child node (~40 Elo)
// The depth condition is important for mate finding.
if (!ss->ttPv && depth < 9
&& eval - futility_margin(depth, cutNode && !ss->ttHit, improving)
- - (ss - 1)->statScore / 321
+ - (ss - 1)->statScore / 337
>= beta
- && eval >= beta && eval < 29462 // smaller than TB wins
+ && eval >= beta && eval < 29008 // smaller than TB wins
&& (!ttMove || ttCapture))
- return eval;
+ return (eval + beta) / 2;
// Step 9. Null move search with verification search (~35 Elo)
- if (!PvNode && (ss - 1)->currentMove != MOVE_NULL && (ss - 1)->statScore < 17257 && eval >= beta
- && eval >= ss->staticEval && ss->staticEval >= beta - 24 * depth + 281 && !excludedMove
+ if (!PvNode && (ss - 1)->currentMove != MOVE_NULL && (ss - 1)->statScore < 17496 && eval >= beta
+ && eval >= ss->staticEval && ss->staticEval >= beta - 23 * depth + 304 && !excludedMove
&& pos.non_pawn_material(us) && ss->ply >= thisThread->nmpMinPly
&& beta > VALUE_TB_LOSS_IN_MAX_PLY)
{
assert(eval - beta >= 0);
// Null move dynamic reduction based on depth and eval
- Depth R = std::min(int(eval - beta) / 152, 6) + depth / 3 + 4;
+ Depth R = std::min(int(eval - beta) / 144, 6) + depth / 3 + 4;
ss->currentMove = MOVE_NULL;
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
// Do not return unproven mate or TB scores
if (nullValue >= beta && nullValue < VALUE_TB_WIN_IN_MAX_PLY)
{
- if (thisThread->nmpMinPly || depth < 14)
+ if (thisThread->nmpMinPly || depth < 15)
return nullValue;
assert(!thisThread->nmpMinPly); // Recursive verification is not allowed
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;
- probCutBeta = beta + 168 - 70 * improving;
+ probCutBeta = beta + 163 - 67 * improving;
// Step 11. ProbCut (~10 Elo)
// If we have a good enough capture (or queen promotion) and a reduced search returns a value
{
assert(probCutBeta < VALUE_INFINITE);
- MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory,
- thisThread->pawnHistory);
+ MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory);
while ((move = mp.next_move()) != MOVE_NONE)
if (move != excludedMove && pos.legal(move))
moves_loop: // When in check, search starts here
// Step 12. A small Probcut idea, when we are in check (~4 Elo)
- probCutBeta = beta + 416;
+ probCutBeta = beta + 425;
if (ss->inCheck && !PvNode && ttCapture && (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 4 && ttValue >= probCutBeta
&& abs(ttValue) < VALUE_TB_WIN_IN_MAX_PLY && abs(beta) < VALUE_TB_WIN_IN_MAX_PLY)
prevSq != SQ_NONE ? thisThread->counterMoves[pos.piece_on(prevSq)][prevSq] : MOVE_NONE;
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, &captureHistory, contHist,
- thisThread->pawnHistory, countermove, ss->killers);
+ &thisThread->pawnHistory, countermove, ss->killers);
value = bestValue;
moveCountPruning = singularQuietLMR = false;
{
Piece capturedPiece = pos.piece_on(to_sq(move));
int futilityEval =
- ss->staticEval + 239 + 291 * lmrDepth + PieceValue[capturedPiece]
+ ss->staticEval + 238 + 305 * lmrDepth + PieceValue[capturedPiece]
+ captureHistory[movedPiece][to_sq(move)][type_of(capturedPiece)] / 7;
if (futilityEval < alpha)
continue;
}
// SEE based pruning for captures and checks (~11 Elo)
- if (!pos.see_ge(move, Value(-185) * depth))
+ if (!pos.see_ge(move, Value(-187) * depth))
continue;
}
else
+ thisThread->pawnHistory[pawn_structure(pos)][movedPiece][to_sq(move)];
// Continuation history based pruning (~2 Elo)
- if (lmrDepth < 6 && history < -3645 * depth)
+ if (lmrDepth < 6 && history < -3752 * depth)
continue;
history += 2 * thisThread->mainHistory[us][from_to(move)];
- lmrDepth += history / 7836;
+ lmrDepth += history / 7838;
lmrDepth = std::max(lmrDepth, -1);
// Futility pruning: parent node (~13 Elo)
- if (!ss->inCheck && lmrDepth < 13 && ss->staticEval + 77 + 124 * lmrDepth <= alpha)
+ if (!ss->inCheck && lmrDepth < 14
+ && ss->staticEval + (bestValue < ss->staticEval - 57 ? 124 : 71)
+ + 118 * lmrDepth
+ <= alpha)
continue;
lmrDepth = std::max(lmrDepth, 0);
// Singular extension search (~94 Elo). If all moves but one fail low on a
// search of (alpha-s, beta-s), and just one fails high on (alpha, beta),
// then that move is singular and should be extended. To verify this we do
- // a reduced search on all the other moves but the ttMove and if the result
- // is lower than ttValue minus a margin, then we will extend the ttMove. Note
- // that depth margin and singularBeta margin are known for having non-linear
+ // a reduced search on the position excluding the ttMove and if the result
+ // is lower than ttValue minus a margin, then we will extend the ttMove.
+
+ // 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())
+ && depth >= 4 - (thisThread->completedDepth > 27) + 2 * (PvNode && tte->is_pv())
&& abs(ttValue) < VALUE_TB_WIN_IN_MAX_PLY && (tte->bound() & BOUND_LOWER)
&& tte->depth() >= depth - 3)
{
- Value singularBeta = ttValue - (64 + 57 * (ss->ttPv && !PvNode)) * depth / 64;
- Depth singularDepth = (depth - 1) / 2;
+ Value singularBeta = ttValue - (66 + 58 * (ss->ttPv && !PvNode)) * depth / 64;
+ Depth singularDepth = newDepth / 2;
ss->excludedMove = move;
value =
singularQuietLMR = !ttCapture;
// Avoid search explosion by limiting the number of double extensions
- if (!PvNode && value < singularBeta - 18 && ss->doubleExtensions <= 11)
+ if (!PvNode && value < singularBeta - 17 && ss->doubleExtensions <= 11)
{
extension = 2;
depth += depth < 15;
}
// Multi-cut pruning
- // Our ttMove is assumed to fail high, and now we failed high also on a
- // reduced search without the ttMove. So we assume this expected cut-node
- // is not singular, that multiple moves fail high, and we can prune the
- // whole subtree by returning a softbound.
+ // Our ttMove is assumed to fail high based on the bound of the TT entry,
+ // and if after excluding the ttMove with a reduced search we fail high over the original beta,
+ // we assume this expected cut-node is not singular (multiple moves fail high),
+ // and we can prune the whole subtree by returning a softbound.
else if (singularBeta >= beta)
return singularBeta;
- // If the eval of ttMove is greater than beta, reduce it (negative extension) (~7 Elo)
+ // Negative extensions
+ // If other moves failed high over (ttValue - margin) without the ttMove on a reduced search,
+ // but we cannot do multi-cut because (ttValue - margin) is lower than the original beta,
+ // 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 current beta (~7 Elo)
else if (ttValue >= beta)
extension = -2 - !PvNode;
- // If we are on a cutNode, reduce it based on depth (negative extension) (~1 Elo)
+ // If we are on a cutNode but the ttMove is not assumed to fail high over current beta (~1 Elo)
else if (cutNode)
extension = depth < 19 ? -2 : -1;
- // If the eval of ttMove is less than value, reduce it (negative extension) (~1 Elo)
+ // If the ttMove is assumed to fail low over the value of the reduced search (~1 Elo)
else if (ttValue <= value)
extension = -1;
}
// Check extensions (~1 Elo)
- else if (givesCheck && depth > 9)
+ else if (givesCheck && depth > 10)
extension = 1;
// Quiet ttMove extensions (~1 Elo)
else if (PvNode && move == ttMove && move == ss->killers[0]
- && (*contHist[0])[movedPiece][to_sq(move)] >= 4194)
+ && (*contHist[0])[movedPiece][to_sq(move)] >= 4325)
+ extension = 1;
+
+ // Recapture extensions (~1 Elo)
+ else if (PvNode && move == ttMove && to_sq(move) == prevSq
+ && captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))]
+ > 4146)
extension = 1;
}
if ((ss + 1)->cutoffCnt > 3)
r++;
- // Decrease reduction 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--;
+ r = 0;
ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)]
+ (*contHist[0])[movedPiece][to_sq(move)]
+ (*contHist[1])[movedPiece][to_sq(move)]
- + (*contHist[3])[movedPiece][to_sq(move)] - 3848;
+ + (*contHist[3])[movedPiece][to_sq(move)] - 3817;
// Decrease/increase reduction for moves with a good/bad history (~25 Elo)
- r -= ss->statScore / (10216 + 3855 * (depth > 5 && depth < 23));
+ r -= ss->statScore / 14767;
// Step 17. Late moves reduction / extension (LMR, ~117 Elo)
// We use various heuristics for the sons of a node after the first son has
// been searched. In general, we would like to reduce them, but there are many
// cases where we extend a son if it has good chances to be "interesting".
- if (depth >= 2 && moveCount > 1 + (PvNode && ss->ply <= 1)
+ if (depth >= 2 && moveCount > 1 + rootNode
&& (!ss->ttPv || !capture || (cutNode && (ss - 1)->moveCount > 1)))
{
// In general we want to cap the LMR depth search at newDepth, but when
// reduction is negative, we allow this move a limited search extension
// beyond the first move depth. This may lead to hidden double extensions.
- Depth d = std::clamp(newDepth - r, 1, newDepth + 1);
+ // To prevent problems when the max value is less than the min value,
+ // std::clamp has been replaced by a more robust implementation.
+ Depth d = std::max(1, std::min(newDepth - r, newDepth + 1));
value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha, d, true);
{
// 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 doEvenDeeperSearch = value > alpha + 700 && ss->doubleExtensions <= 6;
- const bool doShallowerSearch = value < bestValue + newDepth;
+ const bool doDeeperSearch = value > (bestValue + 53 + 2 * newDepth); // (~1 Elo)
+ const bool doShallowerSearch = value < bestValue + newDepth; // (~2 Elo)
- ss->doubleExtensions = ss->doubleExtensions + doEvenDeeperSearch;
-
- newDepth += doDeeperSearch - doShallowerSearch + doEvenDeeperSearch;
+ newDepth += doDeeperSearch - doShallowerSearch;
if (newDepth > d)
value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha, newDepth, !cutNode);
- int bonus = value <= alpha ? -stat_bonus(newDepth)
+ int bonus = value <= alpha ? -stat_malus(newDepth)
: value >= beta ? stat_bonus(newDepth)
: 0;
// Step 18. Full-depth search when LMR is skipped
else if (!PvNode || moveCount > 1)
{
- // Increase reduction for cut nodes without ttMove (~1 Elo)
- if (!ttMove && cutNode)
+ // Increase reduction if ttMove is not present (~1 Elo)
+ if (!ttMove)
r += 2;
// Note that if expected reduction is high, we reduce search depth by 1 here
else
{
// Reduce other moves if we have found at least one score improvement (~2 Elo)
- if (depth > 2 && depth < 12 && beta < 13828 && value > -11369)
+ if (depth > 2 && depth < 12 && beta < 13782 && value > -11541)
depth -= 2;
assert(depth > 0);
// Bonus for prior countermove that caused the fail low
else if (!priorCapture && prevSq != SQ_NONE)
{
- int bonus = (depth > 6) + (PvNode || cutNode) + (bestValue < alpha - 657)
+ int bonus = (depth > 6) + (PvNode || cutNode) + (bestValue < alpha - 656)
+ ((ss - 1)->moveCount > 10);
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
stat_bonus(depth) * bonus);
thisThread->mainHistory[~us][from_to((ss - 1)->currentMove)]
- << stat_bonus(depth) * bonus * 61 / 100;
+ << stat_bonus(depth) * bonus / 2;
}
if (PvNode)
ss->inCheck = pos.checkers();
moveCount = 0;
+ // Used to send selDepth info to GUI (selDepth counts from 1, ply from 0)
+ if (PvNode && thisThread->selDepth < ss->ply + 1)
+ thisThread->selDepth = ss->ply + 1;
+
// Step 2. Check for an immediate draw or maximum ply reached
if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY)
return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) : VALUE_DRAW;
assert(0 <= ss->ply && ss->ply < MAX_PLY);
- // Decide whether or not to include checks: this fixes also the type of
- // 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.
+ // Decide the replacement and cutoff priority of the qsearch TT entries
ttDepth = ss->inCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS : DEPTH_QS_NO_CHECKS;
// Step 3. Transposition table lookup
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;
- // Stand pat. Return immediately if static value is at least beta
+ // Stand pat. Return immediately if bestValue is at least beta at non-Pv nodes.
+ // At PvNodes set bestValue between alpha and beta instead
if (bestValue >= beta)
{
- if (!ss->ttHit)
- tte->save(posKey, value_to_tt(bestValue, ss->ply), false, BOUND_LOWER, DEPTH_NONE,
- MOVE_NONE, ss->staticEval);
+ if (!PvNode || abs(bestValue) >= VALUE_TB_WIN_IN_MAX_PLY)
+ {
+ if (!ss->ttHit)
+ tte->save(posKey, value_to_tt(bestValue, ss->ply), false, BOUND_LOWER,
+ DEPTH_NONE, MOVE_NONE, ss->staticEval);
- return bestValue;
+ return bestValue;
+ }
+ bestValue = std::min((alpha + beta) / 2, beta - 1);
}
if (bestValue > alpha)
alpha = bestValue;
- futilityBase = ss->staticEval + 200;
+ futilityBase = ss->staticEval + 182;
}
const PieceToHistory* contHist[] = {(ss - 1)->continuationHistory,
// will be generated.
Square prevSq = is_ok((ss - 1)->currentMove) ? to_sq((ss - 1)->currentMove) : SQ_NONE;
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, &thisThread->captureHistory,
- contHist, thisThread->pawnHistory, prevSq);
+ contHist, &thisThread->pawnHistory);
int quietCheckEvasions = 0;
continue;
// Do not search moves with bad enough SEE values (~5 Elo)
- if (!pos.see_ge(move, Value(-90)))
+ if (!pos.see_ge(move, Value(-77)))
continue;
}
// Inverse of value_to_tt(): it adjusts a mate or TB score
// from the transposition table (which refers to the plies to mate/be mated from
// current position) to "plies to mate/be mated (TB win/loss) from the root".
-// However, to avoid potentially false mate scores related to the 50 moves rule
-// and the graph history interaction problem, we return an optimal TB score instead.
+// However, to avoid potentially false mate or TB scores related to the 50 moves rule
+// and the graph history interaction, we return highest non-TB score instead.
+
Value value_from_tt(Value v, int ply, int r50c) {
if (v == VALUE_NONE)
return VALUE_NONE;
- if (v >= VALUE_TB_WIN_IN_MAX_PLY) // TB win or better
+ // handle TB win or better
+ if (v >= VALUE_TB_WIN_IN_MAX_PLY)
{
- if (v >= VALUE_MATE_IN_MAX_PLY && VALUE_MATE - v > 99 - r50c)
- return VALUE_MATE_IN_MAX_PLY - 1; // do not return a potentially false mate score
+ // Downgrade a potentially false mate score
+ if (v >= VALUE_MATE_IN_MAX_PLY && VALUE_MATE - v > 100 - r50c)
+ return VALUE_TB_WIN_IN_MAX_PLY - 1;
+
+ // Downgrade a potentially false TB score.
+ if (VALUE_TB - v > 100 - r50c)
+ return VALUE_TB_WIN_IN_MAX_PLY - 1;
return v - ply;
}
- if (v <= VALUE_TB_LOSS_IN_MAX_PLY) // TB loss or worse
+ // handle TB loss or worse
+ if (v <= VALUE_TB_LOSS_IN_MAX_PLY)
{
- if (v <= VALUE_MATED_IN_MAX_PLY && VALUE_MATE + v > 99 - r50c)
- return VALUE_MATED_IN_MAX_PLY + 1; // do not return a potentially false mate score
+ // Downgrade a potentially false mate score.
+ if (v <= VALUE_MATED_IN_MAX_PLY && VALUE_MATE + v > 100 - r50c)
+ return VALUE_TB_LOSS_IN_MAX_PLY + 1;
+
+ // Downgrade a potentially false TB score.
+ if (VALUE_TB + v > 100 - r50c)
+ return VALUE_TB_LOSS_IN_MAX_PLY + 1;
return v + ply;
}
PieceType captured;
int quietMoveBonus = stat_bonus(depth + 1);
+ int quietMoveMalus = stat_malus(depth);
if (!pos.capture_stage(bestMove))
{
- int bestMoveBonus = bestValue > beta + 168 ? quietMoveBonus // larger bonus
+ int bestMoveBonus = bestValue > beta + 173 ? quietMoveBonus // larger bonus
: stat_bonus(depth); // smaller bonus
// Increase stats for the best move in case it was a quiet move
{
thisThread->pawnHistory[pawn_structure(pos)][pos.moved_piece(quietsSearched[i])]
[to_sq(quietsSearched[i])]
- << -bestMoveBonus;
- thisThread->mainHistory[us][from_to(quietsSearched[i])] << -bestMoveBonus;
+ << -quietMoveMalus;
+ thisThread->mainHistory[us][from_to(quietsSearched[i])] << -quietMoveMalus;
update_continuation_histories(ss, pos.moved_piece(quietsSearched[i]),
- to_sq(quietsSearched[i]), -bestMoveBonus);
+ to_sq(quietsSearched[i]), -quietMoveMalus);
}
}
else
&& ((ss - 1)->moveCount == 1 + (ss - 1)->ttHit
|| ((ss - 1)->currentMove == (ss - 1)->killers[0]))
&& !pos.captured_piece())
- update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -quietMoveBonus);
+ update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -quietMoveMalus);
// Decrease stats for all non-best capture moves
for (int i = 0; i < captureCount; ++i)
{
moved_piece = pos.moved_piece(capturesSearched[i]);
captured = type_of(pos.piece_on(to_sq(capturesSearched[i])));
- captureHistory[moved_piece][to_sq(capturesSearched[i])][captured] << -quietMoveBonus;
+ captureHistory[moved_piece][to_sq(capturesSearched[i])][captured] << -quietMoveMalus;
}
}
if (v == -VALUE_INFINITE)
v = VALUE_ZERO;
- bool tb = TB::RootInTB && abs(v) < VALUE_MATE_IN_MAX_PLY;
+ bool tb = TB::RootInTB && abs(v) <= VALUE_TB;
v = tb ? rootMoves[i].tbScore : v;
if (ss.rdbuf()->in_avail()) // Not at first line
}
-// Called in case we have no ponder move
-// before exiting the search, for instance, in case we stop the search during a
-// fail high at root. We try hard to have a ponder move to return to the GUI,
+// Called in case we have no ponder move before exiting the search,
+// for instance, in case we stop the search during a fail high at root.
+// We try hard to have a ponder move to return to the GUI,
// otherwise in case of 'ponder on' we have nothing to think about.
bool RootMove::extract_ponder_from_tt(Position& pos) {