- init_ss_array(ss, PLY_MAX_PLUS_2);
- ValueByIteration[1] = rml[0].pv_score;
- Iteration = 1;
-
- // Send initial RootMoveList scoring (iteration 1)
- cout << set960(pos.is_chess960()) // Is enough to set once at the beginning
- << "info depth " << Iteration
- << "\n" << rml[0].pv_info_to_uci(pos, alpha, beta) << endl;
-
- // Is one move significantly better than others after initial scoring ?
- if ( rml.size() == 1
- || rml[0].pv_score > rml[1].pv_score + EasyMoveMargin)
- EasyMove = rml[0].pv[0];
-
- // Iterative deepening loop
- while (Iteration < PLY_MAX)
- {
- // Initialize iteration
- Iteration++;
- BestMoveChangesByIteration[Iteration] = 0;
-
- cout << "info depth " << Iteration << endl;
-
- // Calculate dynamic aspiration window based on previous iterations
- if (MultiPV == 1 && Iteration >= 6 && abs(ValueByIteration[Iteration - 1]) < VALUE_KNOWN_WIN)
- {
- int prevDelta1 = ValueByIteration[Iteration - 1] - ValueByIteration[Iteration - 2];
- int prevDelta2 = ValueByIteration[Iteration - 2] - ValueByIteration[Iteration - 3];
-
- AspirationDelta = Max(abs(prevDelta1) + abs(prevDelta2) / 2, 16);
- AspirationDelta = (AspirationDelta + 7) / 8 * 8; // Round to match grainSize
-
- alpha = Max(ValueByIteration[Iteration - 1] - AspirationDelta, -VALUE_INFINITE);
- beta = Min(ValueByIteration[Iteration - 1] + AspirationDelta, VALUE_INFINITE);
- }
-
- depth = (Iteration - 2) * ONE_PLY + InitialDepth;
-
- // Search to the current depth, rml is updated and sorted
- value = root_search(pos, ss, alpha, beta, depth, rml);
-
- if (AbortSearch)
- break; // Value cannot be trusted. Break out immediately!
-
- //Save info about search result
- ValueByIteration[Iteration] = value;
-
- // Drop the easy move if differs from the new best move
- if (rml[0].pv[0] != EasyMove)
- EasyMove = MOVE_NONE;
-
- if (UseTimeManagement)
- {
- // Time to stop?
- bool stopSearch = false;
-
- // Stop search early if there is only a single legal move,
- // we search up to Iteration 6 anyway to get a proper score.
- if (Iteration >= 6 && rml.size() == 1)
- stopSearch = true;
-
- // Stop search early when the last two iterations returned a mate score
- if ( Iteration >= 6
- && abs(ValueByIteration[Iteration]) >= abs(VALUE_MATE) - 100
- && abs(ValueByIteration[Iteration-1]) >= abs(VALUE_MATE) - 100)
- stopSearch = true;
-
- // Stop search early if one move seems to be much better than the others
- if ( Iteration >= 8
- && EasyMove == rml[0].pv[0]
- && ( ( rml[0].nodes > (pos.nodes_searched() * 85) / 100
- && current_search_time() > TimeMgr.available_time() / 16)
- ||( rml[0].nodes > (pos.nodes_searched() * 98) / 100
- && current_search_time() > TimeMgr.available_time() / 32)))
- stopSearch = true;
-
- // Add some extra time if the best move has changed during the last two iterations
- if (Iteration > 5 && Iteration <= 50)
- TimeMgr.pv_instability(BestMoveChangesByIteration[Iteration],
- BestMoveChangesByIteration[Iteration-1]);
-
- // Stop search if most of MaxSearchTime is consumed at the end of the
- // iteration. We probably don't have enough time to search the first
- // move at the next iteration anyway.
- if (current_search_time() > (TimeMgr.available_time() * 80) / 128)
- stopSearch = true;
-
- if (stopSearch)
- {
- if (PonderSearch)
- StopOnPonderhit = true;
- else
- break;
- }
- }
-
- if (MaxDepth && Iteration >= MaxDepth)
- break;
- }
-
- // If we are pondering or in infinite search, we shouldn't print the
- // best move before we are told to do so.
- if (!AbortSearch && (PonderSearch || InfiniteSearch))
- wait_for_stop_or_ponderhit();
- else
- // Print final search statistics
- cout << "info nodes " << pos.nodes_searched()
- << " nps " << nps(pos)
- << " time " << current_search_time() << endl;