- // 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 (Pondering)
- StopOnPonderhit = true;
- else
- break;
- }
- }
-
- if (MaxDepth && Iteration >= MaxDepth)
- break;
- }
-
- *ponderMove = rml[0].pv[1];
- return rml[0].pv[0];
- }
-
-
- // root_search() is the function which searches the root node. It is
- // similar to search_pv except that it prints some information to the
- // standard output and handles the fail low/high loops.
-
- Value root_search(Position& pos, SearchStack* ss, Value alpha,
- Value beta, Depth depth, RootMoveList& rml) {
- StateInfo st;
- Move movesSearched[MOVES_MAX];
- CheckInfo ci(pos);
- int64_t nodes;
- Move move;
- Depth ext, newDepth;
- Value value, oldAlpha;
- RootMoveList::iterator rm;
- bool isCheck, moveIsCheck, captureOrPromotion, dangerous, isPvMove;
- int moveCount, researchCountFH, researchCountFL;
-
- researchCountFH = researchCountFL = 0;
- oldAlpha = alpha;
- isCheck = pos.is_check();
-
- // Step 1. Initialize node (polling is omitted at root)
- ss->currentMove = ss->bestMove = MOVE_NONE;
-
- // Step 2. Check for aborted search (omitted at root)
- // Step 3. Mate distance pruning (omitted at root)
- // Step 4. Transposition table lookup (omitted at root)
-
- // Step 5. Evaluate the position statically
- // At root we do this only to get reference value for child nodes
- ss->evalMargin = VALUE_NONE;
- ss->eval = isCheck ? VALUE_NONE : evaluate(pos, ss->evalMargin);
-
- // Step 6. Razoring (omitted at root)
- // Step 7. Static null move pruning (omitted at root)
- // Step 8. Null move search with verification search (omitted at root)
- // Step 9. Internal iterative deepening (omitted at root)
-
- // Step extra. Fail low loop
- // We start with small aspiration window and in case of fail low, we research
- // with bigger window until we are not failing low anymore.
- while (1)
- {
- // Sort the moves before to (re)search
- rml.set_non_pv_scores(pos, rml[0].pv[0], ss);
- rml.sort();
- moveCount = 0;
-
- // Step 10. Loop through all moves in the root move list
- for (rm = rml.begin(); rm != rml.end() && !StopRequest; ++rm)
- {
- // This is used by time management
- FirstRootMove = (rm == rml.begin());