- init_ss_array(ss, PLY_MAX_PLUS_2);
- pv[0] = pv[1] = MOVE_NONE;
- ValueByIteration[1] = rml.move_score(0);
- Iteration = 1;
-
- // Is one move significantly better than others after initial scoring ?
- if ( rml.move_count() == 1
- || rml.move_score(0) > rml.move_score(1) + EasyMoveMargin)
- EasyMove = rml.move(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);
- }
-
- // Search to the current depth, rml is updated and sorted, alpha and beta could change
- value = root_search(p, ss, pv, rml, &alpha, &beta);
-
- // Write PV to transposition table, in case the relevant entries have
- // been overwritten during the search.
- insert_pv_in_tt(p, pv);
-
- 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 (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.move_count() == 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
- int64_t nodes = ThreadsMgr.nodes_searched();
- if ( Iteration >= 8
- && EasyMove == pv[0]
- && ( ( rml.move_nodes(0) > (nodes * 85) / 100
- && current_search_time() > TimeMgr.available_time() / 16)
- ||( rml.move_nodes(0) > (nodes * 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 " << ThreadsMgr.nodes_searched()
- << " nps " << nps()
- << " time " << current_search_time() << endl;
-
- // Print the best move and the ponder move to the standard output
- if (pv[0] == MOVE_NONE)
- {
- pv[0] = rml.move(0);
- pv[1] = MOVE_NONE;
- }
-
- assert(pv[0] != MOVE_NONE);
-
- cout << "bestmove " << pv[0];