- else { // MultiPV > 1
- rml.sort_multipv(i);
- for(int j = 0; j < Min(MultiPV, rml.move_count()); j++) {
- int k;
- std::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 " << nodes_searched()
- << " nps " << nps()
- << " pv ";
- for(k = 0; rml.get_move_pv(j, k) != MOVE_NONE && k < PLY_MAX; k++)
- std::cout << rml.get_move_pv(j, k) << " ";
- std::cout << std::endl;
- }
- alpha = rml.get_move_score(Min(i, MultiPV-1));
+ else
+ {
+ value = -search(pos, ss, -alpha, newDepth, 1, true, 0);
+ if (value > alpha)
+ {
+ // Fail high! Set the boolean variable FailHigh to true, and
+ // re-search the move with a big window. The variable FailHigh is
+ // used for time managment: We try to avoid aborting the search
+ // prematurely during a fail high research.
+ FailHigh = true;
+ value = -search_pv(pos, ss, -beta, -alpha, newDepth, 1, 0);
+ }
+ }
+
+ pos.undo_move(move);
+
+ // 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 the node count for this move. The node counts are used to
+ // sort the root moves at the next iteration.
+ rml.set_move_nodes(i, nodes_searched() - nodes);
+
+ // Remember the beta-cutoff statistics
+ int64_t our, their;
+ BetaCounter.read(pos.side_to_move(), our, their);
+ rml.set_beta_counters(i, our, their);
+
+ assert(value >= -VALUE_INFINITE && value <= VALUE_INFINITE);
+
+ if (value <= alpha && i >= MultiPV)
+ rml.set_move_score(i, -VALUE_INFINITE);
+ else
+ {
+ // New best move!
+
+ // Update PV
+ rml.set_move_score(i, value);
+ update_pv(ss, 0);
+ 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 search information to the standard output:
+ std::cout << "info depth " << Iteration
+ << " score " << value_to_string(value)
+ << " time " << current_search_time()
+ << " nodes " << nodes_searched()
+ << " nps " << nps()
+ << " pv ";
+
+ for (int j = 0; ss[0].pv[j] != MOVE_NONE && j < PLY_MAX; j++)
+ std::cout << ss[0].pv[j] << " ";
+
+ std::cout << std::endl;
+
+ if (UseLogFile)
+ LogFile << pretty_pv(pos, current_search_time(), Iteration, nodes_searched(), value, ss[0].pv)
+ << std::endl;
+
+ alpha = value;
+
+ // Reset the global variable Problem to false if the value isn't too
+ // far below the final value from the last iteration.
+ if (value > ValueByIteration[Iteration - 1] - NoProblemMargin)
+ Problem = false;
+ }
+ else // MultiPV > 1
+ {
+ rml.sort_multipv(i);
+ for (int j = 0; j < Min(MultiPV, rml.move_count()); j++)
+ {
+ int k;
+ std::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 " << nodes_searched()
+ << " nps " << nps()
+ << " pv ";
+
+ for (k = 0; rml.get_move_pv(j, k) != MOVE_NONE && k < PLY_MAX; k++)
+ std::cout << rml.get_move_pv(j, k) << " ";
+
+ std::cout << std::endl;
+ }
+ alpha = rml.get_move_score(Min(i, MultiPV-1));
+ }