// Add a small random component to draw evaluations to avoid 3fold-blindness
Value value_draw(Depth depth, Thread* thisThread) {
- return depth < 4 ? VALUE_DRAW
- : VALUE_DRAW + Value(2 * (thisThread->nodes & 1) - 1);
+ return depth < 4 * ONE_PLY ? VALUE_DRAW
+ : VALUE_DRAW + Value(2 * (thisThread->nodes & 1) - 1);
}
// Skill structure is used to implement strength limit
// Use part of the gained time from a previous stable move for the current move
for (Thread* th : Threads)
+ {
totBestMoveChanges += th->bestMoveChanges;
-
+ th->bestMoveChanges = 0;
+ }
double bestMoveInstability = 1 + totBestMoveChanges / Threads.size();
// Stop the search if we have only one legal move, or if available time elapsed
: ttHit ? tte->move() : MOVE_NONE;
ttPv = (ttHit && tte->is_pv()) || (PvNode && depth > 4 * ONE_PLY);
- // if position has been searched at higher depths and we are shuffling, return value_draw
- if (pos.rule50_count() > 36
- && ss->ply > 36
- && depth < 3 * ONE_PLY
- && ttHit
- && tte->depth() > depth
- && pos.count<PAWN>() > 0)
- return VALUE_DRAW;
-
// At non-PV nodes we check for an early TT cutoff
if ( !PvNode
&& ttHit
// Do verification search at high depths, with null move pruning disabled
// for us, until ply exceeds nmpMinPly.
- thisThread->nmpMinPly = ss->ply + 3 * (depth-R) / 4;
+ thisThread->nmpMinPly = ss->ply + 3 * (depth-R) / (4 * ONE_PLY);
thisThread->nmpColor = us;
Value v = search<NonPV>(pos, ss, beta-1, beta, depth-R, false);
&& pos.legal(move))
{
Value singularBeta = ttValue - 2 * depth / ONE_PLY;
+ Depth halfDepth = depth / (2 * ONE_PLY) * ONE_PLY; // ONE_PLY invariant
ss->excludedMove = move;
- value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, depth / 2, cutNode);
+ value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, halfDepth, cutNode);
ss->excludedMove = MOVE_NONE;
if (value < singularBeta)
&& (pos.blockers_for_king(~us) & from_sq(move) || pos.see_ge(move)))
extension = ONE_PLY;
- // Shuffle extension
- else if(pos.rule50_count() > 14 && ss->ply > 14 && depth < 3 * ONE_PLY && PvNode)
- extension = ONE_PLY;
-
// Castling extension
else if (type_of(move) == CASTLING)
extension = ONE_PLY;
+ // Passed pawn extension
+ else if ( move == ss->killers[0]
+ && pos.advanced_pawn_push(move)
+ && pos.pawn_passed(us, to_sq(move)))
+ extension = ONE_PLY;
+
// Calculate new depth for this move
newDepth = depth - ONE_PLY + extension;
continue;
// Reduced depth of the next LMR search
- int lmrDepth = std::max(newDepth - reduction<PvNode>(improving, depth, moveCount), DEPTH_ZERO) / ONE_PLY;
+ int lmrDepth = std::max(newDepth - reduction<PvNode>(improving, depth, moveCount), DEPTH_ZERO);
+ lmrDepth /= ONE_PLY;
// Countermoves based pruning (~20 Elo)
if ( lmrDepth < 3 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)