CountermovesStats Countermoves;
template <NodeType NT>
- Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth);
+ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode);
template <NodeType NT, bool InCheck>
Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth);
// research with bigger window until not failing high/low anymore.
while (true)
{
- bestValue = search<Root>(pos, ss, alpha, beta, depth * ONE_PLY);
+ bestValue = search<Root>(pos, ss, alpha, beta, depth * ONE_PLY, false);
// Bring to front the best move. It is critical that sorting is
// done with a stable algorithm because all the values but the first
rm = *std::find(RootMoves.begin(), RootMoves.end(), skill.best);
Log log(Options["Search Log Filename"]);
- log << pretty_pv(pos, depth, rm.score, Time::now() - SearchTime, rm.pv.data())
+ log << pretty_pv(pos, depth, rm.score, Time::now() - SearchTime, &rm.pv[0])
<< std::endl;
}
Value rBeta = bestValue - 2 * PawnValueMg;
ss->excludedMove = RootMoves[0].pv[0];
ss->skipNullMove = true;
- Value v = search<NonPV>(pos, ss, rBeta - 1, rBeta, (depth - 3) * ONE_PLY);
+ Value v = search<NonPV>(pos, ss, rBeta - 1, rBeta, (depth - 3) * ONE_PLY, true);
ss->skipNullMove = false;
ss->excludedMove = MOVE_NONE;
// here: This is taken care of after we return from the split point.
template <NodeType NT>
- Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) {
+ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode) {
const bool PvNode = (NT == PV || NT == Root || NT == SplitPointPV || NT == SplitPointRoot);
const bool SpNode = (NT == SplitPointPV || NT == SplitPointNonPV || NT == SplitPointRoot);
pos.do_null_move(st);
(ss+1)->skipNullMove = true;
nullValue = depth-R < ONE_PLY ? -qsearch<NonPV, false>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
- : - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R);
+ : - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R, !cutNode);
(ss+1)->skipNullMove = false;
pos.undo_null_move();
// Do verification search at high depths
ss->skipNullMove = true;
- Value v = search<NonPV>(pos, ss, alpha, beta, depth-R);
+ Value v = search<NonPV>(pos, ss, alpha, beta, depth-R, false);
ss->skipNullMove = false;
if (v >= beta)
&& depth >= 5 * ONE_PLY
&& !inCheck
&& !ss->skipNullMove
- && excludedMove == MOVE_NONE
&& abs(beta) < VALUE_MATE_IN_MAX_PLY)
{
Value rbeta = beta + 200;
{
ss->currentMove = move;
pos.do_move(move, st, ci, pos.move_gives_check(move, ci));
- value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth);
+ value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode);
pos.undo_move(move);
if (value >= rbeta)
return value;
Depth d = depth - 2 * ONE_PLY - (PvNode ? DEPTH_ZERO : depth / 4);
ss->skipNullMove = true;
- search<PvNode ? PV : NonPV>(pos, ss, alpha, beta, d);
+ search<PvNode ? PV : NonPV>(pos, ss, alpha, beta, d, true);
ss->skipNullMove = false;
tte = TT.probe(posKey);
Value rBeta = ttValue - int(depth);
ss->excludedMove = move;
ss->skipNullMove = true;
- value = search<NonPV>(pos, ss, rBeta - 1, rBeta, depth / 2);
+ value = search<NonPV>(pos, ss, rBeta - 1, rBeta, depth / 2, cutNode);
ss->skipNullMove = false;
ss->excludedMove = MOVE_NONE;
&& move != ss->killers[1])
{
ss->reduction = reduction<PvNode>(depth, moveCount);
+
+ if (!PvNode && cutNode)
+ ss->reduction += ONE_PLY;
+
if (move == countermoves[0] || move == countermoves[1])
ss->reduction = std::max(DEPTH_ZERO, ss->reduction-ONE_PLY);
if (SpNode)
alpha = splitPoint->alpha;
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
doFullDepthSearch = (value > alpha && ss->reduction != DEPTH_ZERO);
ss->reduction = DEPTH_ZERO;
value = newDepth < ONE_PLY ?
givesCheck ? -qsearch<NonPV, true>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
: -qsearch<NonPV, false>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
- : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth);
+ : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
}
// Only for PV nodes do a full PV search on the first move or after a fail
value = newDepth < ONE_PLY ?
givesCheck ? -qsearch<PV, true>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
: -qsearch<PV, false>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
- : - search<PV>(pos, ss+1, -beta, -alpha, newDepth);
+ : - search<PV>(pos, ss+1, -beta, -alpha, newDepth, false);
// Step 17. Undo move
pos.undo_move(move);
assert(bestValue < beta);
thisThread->split<FakeSplit>(pos, ss, alpha, beta, &bestValue, &bestMove,
- depth, threatMove, moveCount, &mp, NT);
+ depth, threatMove, moveCount, &mp, NT, cutNode);
if (bestValue >= beta)
break;
}
switch (sp->nodeType) {
case Root:
- search<SplitPointRoot>(pos, ss, sp->alpha, sp->beta, sp->depth);
+ search<SplitPointRoot>(pos, ss, sp->alpha, sp->beta, sp->depth, sp->cutNode);
break;
case PV:
- search<SplitPointPV>(pos, ss, sp->alpha, sp->beta, sp->depth);
+ search<SplitPointPV>(pos, ss, sp->alpha, sp->beta, sp->depth, sp->cutNode);
break;
case NonPV:
- search<SplitPointNonPV>(pos, ss, sp->alpha, sp->beta, sp->depth);
+ search<SplitPointNonPV>(pos, ss, sp->alpha, sp->beta, sp->depth, sp->cutNode);
break;
default:
assert(false);