static Book book; // Defined static to initialize the PRNG only once
- Move bm;
Position& pos = RootPosition;
Chess960 = pos.is_chess960();
elapsed_time(true);
goto finalize;
}
- if ( Options["OwnBook"]
- && (bm = book.probe(pos, Options["Book File"], Options["Best Book Move"])) != MOVE_NONE
- && count(RootMoves.begin(), RootMoves.end(), bm))
+ if (Options["OwnBook"])
{
- std::swap(RootMoves[0], *find(RootMoves.begin(), RootMoves.end(), bm));
- goto finalize;
+ Move bookMove = book.probe(pos, Options["Book File"], Options["Best Book Move"]);
+
+ if (bookMove && count(RootMoves.begin(), RootMoves.end(), bookMove))
+ {
+ std::swap(RootMoves[0], *find(RootMoves.begin(), RootMoves.end(), bookMove));
+ goto finalize;
+ }
}
// Read UCI options: GUI could change UCI parameters during the game
const bool RootNode = (NT == Root || NT == SplitPointRoot);
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
- assert(PvNode == (alpha != beta - 1));
+ assert((alpha == beta - 1) || PvNode);
assert(depth > DEPTH_ZERO);
assert(pos.thread() >= 0 && pos.thread() < Threads.size());
}
// Step 2. Check for aborted search and immediate draw
+ // Enforce node limit here. FIXME: This only works with 1 search thread.
+ if (Limits.maxNodes && pos.nodes_searched() >= Limits.maxNodes)
+ Signals.stop = true;
+
if (( Signals.stop
|| pos.is_draw<false>()
|| ss->ply > MAX_PLY) && !RootNode)
Depth rdepth = depth - ONE_PLY - 3 * ONE_PLY;
assert(rdepth >= ONE_PLY);
+ assert((ss-1)->currentMove != MOVE_NONE);
MovePicker mp(pos, ttMove, H, pos.captured_piece_type());
CheckInfo ci(pos);
while ((move = mp.next_move()) != MOVE_NONE)
if (pos.pl_move_is_legal(move, ci.pinned))
{
+ 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);
pos.undo_move(move);
// Step 15. Reduced depth search (LMR). If the move fails high will be
// re-searched at full depth.
- if ( depth > 3 * ONE_PLY
+ if ( depth > 4 * ONE_PLY
&& !isPvMove
&& !captureOrPromotion
&& !dangerous
&& ss->killers[1] != move)
{
ss->reduction = reduction<PvNode>(depth, moveCount);
- Depth d = newDepth - ss->reduction;
+ Depth d = std::max(newDepth - ss->reduction, ONE_PLY);
alpha = SpNode ? sp->alpha : alpha;
- value = d < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO)
- : - search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d);
+ value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d);
doFullDepthSearch = (value > alpha && ss->reduction != DEPTH_ZERO);
ss->reduction = DEPTH_ZERO;
alpha = sp->alpha;
}
- // Finished searching the move. If StopRequest is true, the search
+ // Finished searching the move. If Signals.stop is true, the search
// was aborted because the user interrupted the search or because we
// ran out of time. In this case, the return value of the search cannot
// be trusted, and we don't update the best move and/or PV.
// Step 20. Check for mate and stalemate
// All legal moves have been searched and if there are no legal moves, it
// must be mate or stalemate. Note that we can have a false positive in
- // case of StopRequest or thread.cutoff_occurred() are set, but this is
+ // case of Signals.stop or thread.cutoff_occurred() are set, but this is
// harmless because return value is discarded anyhow in the parent nodes.
// If we are in a singular extension search then return a fail low score.
if (!moveCount)
assert(NT == PV || NT == NonPV);
assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE);
- assert(PvNode == (alpha != beta - 1));
+ assert((alpha == beta - 1) || PvNode);
assert(depth <= DEPTH_ZERO);
assert(pos.thread() >= 0 && pos.thread() < Threads.size());
|| stillAtFirstMove;
if ( (Limits.use_time_management() && noMoreTime)
- || (Limits.maxTime && e >= Limits.maxTime)
- /* missing nodes limit */ ) // FIXME
+ || (Limits.maxTime && e >= Limits.maxTime))
Signals.stop = true;
}