// and near frontier nodes.
const Value FutilityMarginQS = Value(0x80);
+ // Each move futility margin is decreased
+ const Value IncrementalFutilityMargin = Value(0xA);
+
// Remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply
const Value FutilityMargins[12] = { Value(0x100), Value(0x120), Value(0x200), Value(0x220), Value(0x250), Value(0x270),
// 4 ply 4.5 ply 5 ply 5.5 ply 6 ply 6.5 ply
const TTEntry* tte;
Move ttMove, move;
Depth ext, newDepth;
- Value approximateEval, nullValue, value, futilityValue;
+ Value approximateEval, nullValue, value, futilityValue, futilityValueScaled;
bool isCheck, useFutilityPruning, singleReply, moveIsCheck, captureOrPromotion, dangerous;
bool mateThreat = false;
int moveCount = 0;
ss[ply].currentMove = MOVE_NULL;
pos.do_null_move(st);
- int R = (depth >= 5 * OnePly ? 4 : 3); // Null move dynamic reduction
+
+ // Null move dynamic reduction based on depth
+ int R = (depth >= 5 * OnePly ? 4 : 3);
+
+ // Null move dynamic reduction based on value
+ if (approximateEval - beta > PawnValueMidgame)
+ R++;
nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
&& ttMove == MOVE_NONE
&& !pos.has_pawn_on_7th(pos.side_to_move()))
{
- Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
- if (v < beta - RazorMargins[int(depth) - 2])
+ Value rbeta = beta - RazorMargins[int(depth) - 2];
+ Value v = qsearch(pos, ss, rbeta-1, rbeta, Depth(0), ply, threadID);
+ if (v < rbeta)
return v;
}
{
if (futilityValue == VALUE_NONE)
futilityValue = evaluate(pos, ei, threadID)
- + FutilityMargins[int(depth) - 2];
+ + FutilityMargins[int(depth) - 2]
+ + 4*IncrementalFutilityMargin;
+
+ futilityValueScaled = futilityValue - moveCount * IncrementalFutilityMargin;
- if (futilityValue < beta)
+ if (futilityValueScaled < beta)
{
- if (futilityValue > bestValue)
- bestValue = futilityValue;
+ if (futilityValueScaled > bestValue)
+ bestValue = futilityValueScaled;
continue;
}
}