int current_search_time(int set = 0);
std::string score_to_uci(Value v, Value alpha, Value beta);
std::string speed_to_uci(int64_t nodes);
- std::string pv_to_uci(Move pv[], int pvNum);
+ std::string pv_to_uci(Move pv[], int pvNum, bool chess960);
std::string depth_to_uci(Depth depth);
void poll(const Position& pos);
void wait_for_stop_or_ponderhit();
<< depth_to_uci(depth * ONE_PLY)
<< score_to_uci(Rml[i].pv_score, alpha, beta)
<< speed_to_uci(pos.nodes_searched())
- << pv_to_uci(Rml[i].pv, i + 1) << endl;
+ << pv_to_uci(Rml[i].pv, i + 1, pos.is_chess960()) << endl;
// In case of failing high/low increase aspiration window and research,
// otherwise exit the fail high/low loop.
// Check for some early stop condition
if (!StopRequest && Limits.useTimeManagement())
{
- // Stop search early when the last two iterations returned a mate score
- if ( depth >= 5
- && abs(bestValues[depth]) >= VALUE_MATE_IN_PLY_MAX
- && abs(bestValues[depth - 1]) >= VALUE_MATE_IN_PLY_MAX)
- StopRequest = true;
-
// Stop search early if one move seems to be much better than the
// others or if there is only a single legal move. Also in the latter
// case we search up to some depth anyway to get a proper score.
if (PvNode && thread.maxPly < ss->ply)
thread.maxPly = ss->ply;
- // Step 1. Initialize node.
+ // Step 1. Initialize node and poll. Polling can abort search
if (!SpNode)
{
ss->currentMove = ss->bestMove = threatMove = (ss+1)->excludedMove = MOVE_NONE;
goto split_point_start;
}
+ if (pos.thread() == 0 && ++NodesSincePoll > NodesBetweenPolls)
+ {
+ NodesSincePoll = 0;
+ poll(pos);
+ }
+
+ // Step 2. Check for aborted search and immediate draw
+ if (( StopRequest
+ || pos.is_draw<false>()
+ || ss->ply > PLY_MAX) && !RootNode)
+ return VALUE_DRAW;
+
// Step 3. Mate distance pruning
if (!RootNode)
{
if (pos.pl_move_is_legal(move, ci.pinned))
{
pos.do_move(move, st, ci, pos.move_gives_check(move, ci));
-
- if (pos.is_draw<false>() || ss->ply + 1 > PLY_MAX)
- value = VALUE_DRAW;
- else
- value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth);
-
+ value = -search<NonPV>(pos, ss+1, -rbeta, -rbeta+1, rdepth);
pos.undo_move(move);
if (value >= rbeta)
return value;
// Step 14. Make the move
pos.do_move(move, st, ci, givesCheck);
- // Step XX. Poll. Check if search should be aborted.
- if (pos.thread() == 0 && ++NodesSincePoll > NodesBetweenPolls)
- {
- NodesSincePoll = 0;
- poll(pos);
- }
-
- // Step XX. Check for aborted search and immediate draw
- if ( StopRequest
- || pos.is_draw<false>()
- || ss->ply + 1 > PLY_MAX)
- {
- value = VALUE_DRAW;
- goto undo;
- }
-
// Step extra. pv search (only in PV nodes)
// The first move in list is the expected PV
if (isPvMove)
}
// Step 17. Undo move
-undo:
pos.undo_move(move);
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
ss->bestMove = ss->currentMove = MOVE_NONE;
ss->ply = (ss-1)->ply + 1;
+ // Check for an instant draw or maximum ply reached
+ if (pos.is_draw<true>() || ss->ply > PLY_MAX)
+ return VALUE_DRAW;
+
// Decide whether or not to include checks, this fixes also the type of
// TT entry depth that we are going to use. Note that in qsearch we use
// only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
// Make and search the move
pos.do_move(move, st, ci, givesCheck);
-
- if (pos.is_draw<true>() || ss->ply+1 > PLY_MAX)
- value = VALUE_DRAW;
- else
- value = -qsearch<NT>(pos, ss+1, -beta, -alpha, depth-ONE_PLY);
-
+ value = -qsearch<NT>(pos, ss+1, -beta, -alpha, depth-ONE_PLY);
pos.undo_move(move);
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
// pv_to_uci() returns a string with information on the current PV line
// formatted according to UCI specification.
- std::string pv_to_uci(Move pv[], int pvNum) {
+ std::string pv_to_uci(Move pv[], int pvNum, bool chess960) {
std::stringstream s;
- s << " multipv " << pvNum << " pv ";
+ s << " multipv " << pvNum << " pv " << set960(chess960);
for ( ; *pv != MOVE_NONE; pv++)
s << *pv << " ";