+ // Can we exit fail high loop ?
+ if (AbortSearch || value < beta)
+ break;
+
+ // We are failing high and going to do a research. It's important to update
+ // the score before research in case we run out of time while researching.
+ rml.set_move_score(i, value);
+ update_pv(ss, 0);
+ TT.extract_pv(pos, ss[0].pv, PLY_MAX);
+ rml.set_move_pv(i, ss[0].pv);
+
+ // Print information to the standard output
+ print_pv_info(pos, ss, alpha, beta, value);
+
+ // Prepare for a research after a fail high, each time with a wider window
+ *betaPtr = beta = Min(beta + AspirationDelta * (1 << researchCountFH), VALUE_INFINITE);
+ researchCountFH++;
+
+ } // End of fail high loop
+
+ // Finished searching the move. If AbortSearch 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 break out of the loop without updating the best
+ // move and/or PV.
+ if (AbortSearch)
+ break;
+
+ // Remember beta-cutoff and searched nodes counts for this move. The
+ // info is used to sort the root moves for the next iteration.
+ int64_t our, their;
+ TM.get_beta_counters(pos.side_to_move(), our, their);
+ rml.set_beta_counters(i, our, their);
+ rml.set_move_nodes(i, TM.nodes_searched() - nodes);
+
+ assert(value >= -VALUE_INFINITE && value <= VALUE_INFINITE);
+ assert(value < beta);
+
+ // Step 17. Check for new best move
+ if (value <= alpha && i >= MultiPV)
+ rml.set_move_score(i, -VALUE_INFINITE);
+ else
+ {
+ // PV move or new best move!
+
+ // Update PV
+ rml.set_move_score(i, value);
+ update_pv(ss, 0);
+ TT.extract_pv(pos, ss[0].pv, PLY_MAX);
+ rml.set_move_pv(i, ss[0].pv);
+
+ if (MultiPV == 1)
+ {
+ // We record how often the best move has been changed in each
+ // iteration. This information is used for time managment: When
+ // the best move changes frequently, we allocate some more time.
+ if (i > 0)
+ BestMoveChangesByIteration[Iteration]++;
+
+ // Print information to the standard output
+ print_pv_info(pos, ss, alpha, beta, value);
+
+ // Raise alpha to setup proper non-pv search upper bound
+ if (value > alpha)
+ alpha = value;
+ }
+ else // MultiPV > 1
+ {
+ rml.sort_multipv(i);
+ for (int j = 0; j < Min(MultiPV, rml.move_count()); j++)
+ {
+ cout << "info multipv " << j + 1
+ << " score " << value_to_string(rml.get_move_score(j))
+ << " depth " << (j <= i ? Iteration : Iteration - 1)
+ << " time " << current_search_time()
+ << " nodes " << TM.nodes_searched()
+ << " nps " << nps()
+ << " pv ";
+
+ for (int k = 0; rml.get_move_pv(j, k) != MOVE_NONE && k < PLY_MAX; k++)
+ cout << rml.get_move_pv(j, k) << " ";
+
+ cout << endl;
+ }
+ alpha = rml.get_move_score(Min(i, MultiPV - 1));
+ }
+ } // PV move or new best move