- // 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());
-
- // Save the current node count before the move is searched
- nodes = pos.nodes_searched();
-
- // If it's time to send nodes info, do it here where we have the
- // correct accumulated node counts searched by each thread.
- if (SendSearchedNodes)
- {
- SendSearchedNodes = false;
- cout << "info nodes " << nodes
- << " nps " << nps(pos)
- << " time " << current_search_time() << endl;
- }
-
- // Pick the next root move, and print the move and the move number to
- // the standard output.
- move = ss->currentMove = rm->pv[0];
- movesSearched[moveCount++] = move;
- isPvMove = (moveCount <= MultiPV);
-
- if (current_search_time() >= 1000)
- cout << "info currmove " << move
- << " currmovenumber " << moveCount << endl;
-
- moveIsCheck = pos.move_is_check(move);
- captureOrPromotion = pos.move_is_capture_or_promotion(move);
-
- // Step 11. Decide the new search depth
- ext = extension<PV>(pos, move, captureOrPromotion, moveIsCheck, false, false, &dangerous);
- newDepth = depth + ext;
-
- // Step 12. Futility pruning (omitted at root)
-
- // Step extra. Fail high loop
- // If move fails high, we research with bigger window until we are not failing
- // high anymore.
- value = -VALUE_INFINITE;
-
- while (1)
- {
- // Step 13. Make the move
- pos.do_move(move, st, ci, moveIsCheck);
-
- // Step extra. pv search
- // We do pv search for PV moves and when failing high
- if (isPvMove || value > alpha)
- {
- // Aspiration window is disabled in multi-pv case
- if (MultiPV > 1)
- alpha = -VALUE_INFINITE;
-
- // Full depth PV search, done on first move or after a fail high
- value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, 1);
- }
- else
- {
- // Step 14. Reduced search
- // if the move fails high will be re-searched at full depth
- bool doFullDepthSearch = true;
-
- if ( depth >= 3 * ONE_PLY
- && !dangerous
- && !captureOrPromotion
- && !move_is_castle(move))
- {
- ss->reduction = reduction<PV>(depth, moveCount - MultiPV + 1);
- if (ss->reduction)
- {
- assert(newDepth-ss->reduction >= ONE_PLY);
-
- // Reduced depth non-pv search using alpha as upperbound
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth-ss->reduction, 1);
- doFullDepthSearch = (value > alpha);
- }
- ss->reduction = DEPTH_ZERO; // Restore original reduction
- }
-
- // Step 15. Full depth search
- if (doFullDepthSearch)
- {
- // Full depth non-pv search using alpha as upperbound
- value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, 1);
-
- // If we are above alpha then research at same depth but as PV
- // to get a correct score or eventually a fail high above beta.
- if (value > alpha)
- value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, 1);
- }
- }
-
- // Step 16. Undo move
- pos.undo_move(move);
-
- // Can we exit fail high loop ?
- if (StopRequest || 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.
- ss->bestMove = move;
- rm->pv_score = value;
- rm->extract_pv_from_tt(pos);
-
- // Update killers and history only for non capture moves that fails high
- if (!pos.move_is_capture_or_promotion(move))
- {
- update_history(pos, move, depth, movesSearched, moveCount);
- update_killers(move, ss->killers);
- }
-
- // Inform GUI that PV has changed
- cout << rm->pv_info_to_uci(pos, alpha, beta) << endl;
-
- // Prepare for a research after a fail high, each time with a wider window
- 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 (StopRequest)
- break;
-
- // Remember searched nodes counts for this move
- rm->nodes += pos.nodes_searched() - nodes;
-
- assert(value >= -VALUE_INFINITE && value <= VALUE_INFINITE);
- assert(value < beta);
-
- // Step 17. Check for new best move
- if (!isPvMove && value <= alpha)
- rm->pv_score = -VALUE_INFINITE;
- else
- {
- // PV move or new best move!