+ // Start with a small aspiration window and, in the case of a fail
+ // high/low, re-search with a bigger window until we're not failing
+ // high/low anymore.
+ while (true)
+ {
+ bestValue = ::search<PV>(rootPos, ss, alpha, beta, rootDepth, false);
+
+ // Bring the best move to the front. It is critical that sorting
+ // is done with a stable algorithm because all the values but the
+ // first and eventually the new best one are set to -VALUE_INFINITE
+ // and we want to keep the same order for all the moves except the
+ // new PV that goes to the front. Note that in case of MultiPV
+ // search the already searched PV lines are preserved.
+ std::stable_sort(rootMoves.begin() + PVIdx, rootMoves.end());
+
+ // Write PV back to the transposition table in case the relevant
+ // entries have been overwritten during the search.
+ for (size_t i = 0; i <= PVIdx; ++i)
+ rootMoves[i].insert_pv_in_tt(rootPos);
+
+ // If search has been stopped, break immediately. Sorting and
+ // writing PV back to TT is safe because RootMoves is still
+ // valid, although it refers to the previous iteration.
+ if (Signals.stop)
+ break;
+
+ // When failing high/low give some update (without cluttering
+ // the UI) before a re-search.
+ if ( mainThread
+ && multiPV == 1
+ && (bestValue <= alpha || bestValue >= beta)
+ && Time.elapsed() > 3000)
+ sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
+
+ // In case of failing low/high increase aspiration window and
+ // re-search, otherwise exit the loop.
+ if (bestValue <= alpha)
+ {
+ beta = (alpha + beta) / 2;
+ alpha = std::max(bestValue - delta, -VALUE_INFINITE);
+
+ if (mainThread)
+ {
+ mainThread->failedLow = true;
+ Signals.stopOnPonderhit = false;
+ }
+ }
+ else if (bestValue >= beta)
+ {
+ alpha = (alpha + beta) / 2;
+ beta = std::min(bestValue + delta, VALUE_INFINITE);
+ }
+ else
+ break;
+
+ delta += delta / 4 + 5;
+
+ assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
+ }
+
+ // Sort the PV lines searched so far and update the GUI
+ std::stable_sort(rootMoves.begin(), rootMoves.begin() + PVIdx + 1);
+
+ if (!mainThread)
+ break;
+
+ if (Signals.stop)
+ sync_cout << "info nodes " << Threads.nodes_searched()
+ << " time " << Time.elapsed() << sync_endl;
+
+ else if (PVIdx + 1 == multiPV || Time.elapsed() > 3000)
+ sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl;
+ }
+
+ if (!Signals.stop)
+ completedDepth = rootDepth;
+
+ if (!mainThread)
+ continue;
+
+ // If skill level is enabled and time is up, pick a sub-optimal best move
+ if (skill.enabled() && skill.time_to_pick(rootDepth))
+ skill.pick_best(multiPV);
+
+ // Have we found a "mate in x"?
+ if ( Limits.mate
+ && bestValue >= VALUE_MATE_IN_MAX_PLY
+ && VALUE_MATE - bestValue <= 2 * Limits.mate)
+ Signals.stop = true;
+
+ // Do we have time for the next iteration? Can we stop searching now?
+ if (Limits.use_time_management())
+ {
+ if (!Signals.stop && !Signals.stopOnPonderhit)
+ {
+ // Stop the search if only one legal move is available, or if all
+ // of the available time has been used, or if we matched an easyMove
+ // from the previous search and just did a fast verification.
+ const bool F[] = { !mainThread->failedLow,
+ bestValue >= mainThread->previousScore };
+
+ int improvingFactor = 640 - 160*F[0] - 126*F[1] - 124*F[0]*F[1];
+ double unstablePvFactor = 1 + mainThread->bestMoveChanges;
+
+ bool doEasyMove = rootMoves[0].pv[0] == easyMove
+ && mainThread->bestMoveChanges < 0.03
+ && Time.elapsed() > Time.optimum() * 25 / 204;
+
+ if ( rootMoves.size() == 1
+ || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 634
+ || (mainThread->easyMovePlayed = doEasyMove))
+ {
+ // If we are allowed to ponder do not stop the search now but
+ // keep pondering until the GUI sends "ponderhit" or "stop".
+ if (Limits.ponder)
+ Signals.stopOnPonderhit = true;
+ else
+ Signals.stop = true;
+ }
+ }
+
+ if (rootMoves[0].pv.size() >= 3)
+ EasyMove.update(rootPos, rootMoves[0].pv);
+ else
+ EasyMove.clear();
+ }