void Search::init() {
for (int i = 1; i < MAX_MOVES; ++i)
- Reductions[i] = int(21.9 * std::log(i));
+ Reductions[i] = int((21.9 + std::log(Threads.size()) / 2) * std::log(i));
}
return singularBeta;
// If the eval of ttMove is greater than beta we try also if there is another
- // move that pushes it over beta, if so also produce a cutoff.
+ // move that pushes it over beta, if so the position also has probably multiple
+ // moves giving fail highs. We will then reduce the ttMove (negative extension).
else if (ttValue >= beta)
{
ss->excludedMove = move;
ss->excludedMove = MOVE_NONE;
if (value >= beta)
- return beta;
+ extension = -2;
}
}
// Check extensions
else if ( givesCheck
&& depth > 6
- && abs(ss->staticEval) > Value(100))
+ && abs(ss->staticEval) > 100)
+ extension = 1;
+
+ // Quiet ttMove extensions
+ else if ( PvNode
+ && move == ttMove
+ && move == ss->killers[0]
+ && (*contHist[0])[movedPiece][to_sq(move)] >= 10000)
extension = 1;
// Add extension to new depth
// Decrease/increase reduction for moves with a good/bad history (~30 Elo)
r -= ss->statScore / 14721;
- // In general we want to cap the LMR depth search at newDepth. But if
- // reductions are really negative and movecount is low, we allow this move
- // to be searched deeper than the first move in specific cases (note that
- // this may lead to hidden double extensions if newDepth got it own extension
- // before).
+ // In general we want to cap the LMR depth search at newDepth. But if reductions
+ // are really negative and movecount is low, we allow this move to be searched
+ // deeper than the first move (this may lead to hidden double extensions if
+ // newDepth got its own extension before).
int deeper = r >= -1 ? 0
: noLMRExtension ? 0
: moveCount <= 5 ? 1
for (Move* m = (ss+1)->pv; *m != MOVE_NONE; ++m)
rm.pv.push_back(*m);
- // We record how often the best move has been changed in each
- // iteration. This information is used for time management and LMR
- if (moveCount > 1)
+ // We record how often the best move has been changed in each iteration.
+ // This information is used for time management and LMR. In MultiPV mode,
+ // we must take care to only do this for the first PV line.
+ if ( moveCount > 1
+ && !thisThread->pvIdx)
++thisThread->bestMoveChanges;
}
else