// 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.
// Recursive singular search is avoided.
}
// 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 currnet 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;
}
if ((ss + 1)->cutoffCnt > 3)
r++;
- // Decrease reduction for first generated move (ttMove)
+ // Set reduction to 0 for first generated move (ttMove)
+ // 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)]
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