+ // Start with a small aspiration window and, in case of fail high/low,
+ // research with bigger window until not failing high/low anymore.
+ do {
+ // Search starting from ss+1 to allow referencing (ss-1). This is
+ // needed by update_gains() and ss copy when splitting at Root.
+ value = search<Root>(pos, ss+1, alpha, beta, depth * ONE_PLY);
+
+ // It is critical that sorting is done with a stable algorithm
+ // because all the values but the first are usually set to
+ // -VALUE_INFINITE and we want to keep the same order for all
+ // the moves but the new PV that goes to head.
+ sort<RootMove>(Rml.begin() + MultiPVIteration, Rml.end());
+
+ // In case we have found an exact score reorder the PV moves
+ // before leaving the fail high/low loop, otherwise leave the
+ // last PV move in its position so to be searched again.
+ if (value > alpha && value < beta)
+ sort<RootMove>(Rml.begin(), Rml.begin() + MultiPVIteration);
+
+ // Write PV back to transposition table in case the relevant entries
+ // have been overwritten during the search.
+ for (int i = 0; i <= MultiPVIteration; i++)
+ Rml[i].insert_pv_in_tt(pos);
+
+ // Value cannot be trusted. Break out immediately!
+ if (StopRequest)
+ break;
+
+ // Send full PV info to GUI if we are going to leave the loop or
+ // if we have a fail high/low and we are deep in the search.
+ if ((value > alpha && value < beta) || current_search_time() > 2000)
+ for (int i = 0; i < Min(UCIMultiPV, MultiPVIteration + 1); i++)
+ cout << "info"
+ << depth_to_uci(depth * ONE_PLY)
+ << (i == MultiPVIteration ? score_to_uci(Rml[i].score, alpha, beta) :
+ score_to_uci(Rml[i].score))
+ << speed_to_uci(pos.nodes_searched())
+ << pv_to_uci(&Rml[i].pv[0], i + 1, pos.is_chess960())
+ << endl;
+
+ // In case of failing high/low increase aspiration window and research,
+ // otherwise exit the fail high/low loop.
+ if (value >= beta)
+ {
+ beta = Min(beta + aspirationDelta, VALUE_INFINITE);
+ aspirationDelta += aspirationDelta / 2;
+ }
+ else if (value <= alpha)
+ {
+ AspirationFailLow = true;
+ StopOnPonderhit = false;
+
+ alpha = Max(alpha - aspirationDelta, -VALUE_INFINITE);
+ aspirationDelta += aspirationDelta / 2;
+ }
+ else
+ break;
+
+ } while (abs(value) < VALUE_KNOWN_WIN);
+ }