+ // 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 calling update_gains()
+ 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.
+ if (value > alpha && value < beta)
+ sort<RootMove>(Rml.begin(), Rml.end());
+ else
+ // In MultiPV mode, sort only the tail of the list
+ // until all fail-highs and fail-lows have been resolved
+ sort<RootMove>(Rml.begin() + MultiPVIteration, Rml.end());
+
+ // 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, (int)Rml.size()); i++)
+ {
+ bool updated = (i <= MultiPVIteration);
+ bool match = (i == MultiPVIteration);
+
+ if (!updated && depth == 1)
+ continue;
+
+ cout << "info"
+ << depth_to_uci((updated ? depth : depth - 1) * ONE_PLY)
+ << score_to_uci(updated ? Rml[i].pv_score : prevValues[i],
+ match ? alpha : -VALUE_INFINITE,
+ match ? beta : VALUE_INFINITE)
+ << speed_to_uci(pos.nodes_searched())
+ << pv_to_uci(updated ? Rml[i].pv : Rml.find(prevMoves[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.
+ 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);
+ }