X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=39e4be3d8ae0bb1f8958b8647704a4deb0875858;hp=f64f55f0a129a4b4292891140ebd9eb1ad818af5;hb=917944e9c5324cc9659e630570e1852270b22bd4;hpb=738c5595adefe397d8389fb315908e7d2f6ab40c diff --git a/src/search.cpp b/src/search.cpp index f64f55f0..39e4be3d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -55,9 +56,6 @@ namespace { // Set to true to force running with one thread. Used for debugging const bool FakeSplit = false; - // This is the minimum interval in msec between two check_time() calls - const int TimerResolution = 5; - // Different node types, used as template parameter enum NodeType { Root, PV, NonPV, SplitPointRoot, SplitPointPV, SplitPointNonPV }; @@ -65,13 +63,10 @@ namespace { inline Value razor_margin(Depth d) { return Value(512 + 16 * int(d)); } // Futility lookup tables (initialized at startup) and their access functions - Value FutilityMargins[16][64]; // [depth][moveNumber] int FutilityMoveCounts[2][32]; // [improving][depth] - inline Value futility_margin(Depth d, int mn) { - - return d < 7 * ONE_PLY ? FutilityMargins[std::max(int(d), 1)][std::min(mn, 63)] - : 2 * VALUE_INFINITE; + inline Value futility_margin(Depth d) { + return Value(100 * int(d)); } // Reduction lookup tables (initialized at startup) and their access function @@ -84,7 +79,7 @@ namespace { size_t PVSize, PVIdx; TimeManager TimeMgr; - float BestMoveChanges; + double BestMoveChanges; Value DrawValue[COLOR_NB]; HistoryStats History; GainsStats Gains; @@ -131,7 +126,7 @@ void Search::init() { int mc; // moveCount // Init reductions array - for (hd = 1; hd < 64; hd++) for (mc = 1; mc < 64; mc++) + for (hd = 1; hd < 64; ++hd) for (mc = 1; mc < 64; ++mc) { double pvRed = log(double(hd)) * log(double(mc)) / 3.0; double nonPVRed = 0.33 + log(double(hd)) * log(double(mc)) / 2.25; @@ -143,17 +138,16 @@ void Search::init() { if (Reductions[0][0][hd][mc] > 2 * ONE_PLY) Reductions[0][0][hd][mc] += ONE_PLY; - } - // Init futility margins array - for (d = 1; d < 16; d++) for (mc = 0; mc < 64; mc++) - FutilityMargins[d][mc] = Value(112 * int(log(double(d * d) / 2) / log(2.0) + 1.001) - 8 * mc + 45); + else if (Reductions[0][0][hd][mc] > 1 * ONE_PLY) + Reductions[0][0][hd][mc] += ONE_PLY / 2; + } // Init futility move count array - for (d = 0; d < 32; d++) + for (d = 0; d < 32; ++d) { - FutilityMoveCounts[0][d] = int(3 + 0.3 * pow(double(d ), 1.8)) * 3/4 + (2 < d && d < 5); - FutilityMoveCounts[1][d] = int(3 + 0.3 * pow(double(d + 0.98), 1.8)); + FutilityMoveCounts[0][d] = int(2.4 + 0.222 * pow(d + 0.0, 1.8)); + FutilityMoveCounts[1][d] = int(3.0 + 0.3 * pow(d + 0.98, 1.8)); } } @@ -170,7 +164,7 @@ static size_t perft(Position& pos, Depth depth) { for (MoveList it(pos); *it; ++it) { - pos.do_move(*it, st, ci, pos.move_gives_check(*it, ci)); + pos.do_move(*it, st, ci, pos.gives_check(*it, ci)); cnt += leaf ? MoveList(pos).size() : ::perft(pos, depth - ONE_PLY); pos.undo_move(*it); } @@ -236,21 +230,16 @@ void Search::think() { } // Reset the threads, still sleeping: will be wake up at split time - for (size_t i = 0; i < Threads.size(); i++) + for (size_t i = 0; i < Threads.size(); ++i) Threads[i]->maxPly = 0; Threads.sleepWhileIdle = Options["Idle Threads Sleep"]; - - // Set best timer interval to avoid lagging under time pressure. Timer is - // used to check for remaining available thinking time. Timer will be started - // at the end of first iteration to avoid returning with a random move. - Threads.timer->msec = - Limits.use_time_management() ? std::min(100, std::max(TimeMgr.available_time() / 16, TimerResolution)) : - Limits.nodes ? 2 * TimerResolution : 100; + Threads.timer->run = true; + Threads.timer->notify_one(); // Wake up the recurring timer id_loop(RootPos); // Let's start searching ! - Threads.timer->msec = 0; // Stop the timer + Threads.timer->run = false; // Stop the timer Threads.sleepWhileIdle = true; // Send idle threads to sleep if (Options["Write Search Log"]) @@ -331,15 +320,15 @@ namespace { while (++depth <= MAX_PLY && !Signals.stop && (!Limits.depth || depth <= Limits.depth)) { // Age out PV variability metric - BestMoveChanges *= 0.8f; + BestMoveChanges *= 0.8; // Save last iteration's scores before first PV line is searched and all // the move scores but the (new) PV are set to -VALUE_INFINITE. - for (size_t i = 0; i < RootMoves.size(); i++) + for (size_t i = 0; i < RootMoves.size(); ++i) RootMoves[i].prevScore = RootMoves[i].score; // MultiPV loop. We perform a full root search for each PV line - for (PVIdx = 0; PVIdx < PVSize; PVIdx++) + for (PVIdx = 0; PVIdx < PVSize && !Signals.stop; ++PVIdx) { // Reset aspiration window starting size if (depth >= 5) @@ -365,14 +354,14 @@ namespace { // Write PV back to transposition table in case the relevant // entries have been overwritten during the search. - for (size_t i = 0; i <= PVIdx; i++) + for (size_t i = 0; i <= PVIdx; ++i) RootMoves[i].insert_pv_in_tt(pos); - // If search has been stopped return immediately. Sorting and + // If search has been stopped break immediately. Sorting and // writing PV back to TT is safe becuase RootMoves is still // valid, although refers to previous iteration. if (Signals.stop) - return; + break; // When failing high/low give some update (without cluttering // the UI) before to research. @@ -400,10 +389,6 @@ namespace { assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE); } - // Wake up the recurring timer after first iteration is finished - if (depth == 1) - Threads.timer->notify_one(); - // Sort the PV lines searched so far and update the GUI std::stable_sort(RootMoves.begin(), RootMoves.begin() + PVIdx + 1); @@ -433,7 +418,7 @@ namespace { Signals.stop = true; // Do we have time for the next iteration? Can we stop searching now? - if (Limits.use_time_management() && !Signals.stopOnPonderhit) + if (Limits.use_time_management() && !Signals.stop && !Signals.stopOnPonderhit) { bool stop = false; // Local variable, not the volatile Signals.stop @@ -449,6 +434,7 @@ namespace { // Stop search early if one move seems to be much better than others if ( depth >= 12 + && BestMoveChanges <= DBL_EPSILON && !stop && PVSize == 1 && bestValue > VALUE_MATED_IN_MAX_PLY @@ -498,18 +484,16 @@ namespace { assert(PvNode || (alpha == beta - 1)); assert(depth > DEPTH_ZERO); - Move quietsSearched[64]; StateInfo st; const TTEntry *tte; SplitPoint* splitPoint; Key posKey; Move ttMove, move, excludedMove, bestMove, threatMove; - Depth ext, newDepth; - Value bestValue, value, ttValue; - Value eval, nullValue, futilityValue; + Depth ext, newDepth, predictedDepth; + Value bestValue, value, ttValue, eval, nullValue, futilityValue; bool inCheck, givesCheck, pvMove, singularExtensionNode, improving; bool captureOrPromotion, dangerous, doFullDepthSearch; - int moveCount, quietCount; + int moveCount; // Step 1. Initialize node Thread* thisThread = pos.this_thread(); @@ -530,11 +514,10 @@ namespace { goto moves_loop; } - moveCount = quietCount = 0; + moveCount = 0; bestValue = -VALUE_INFINITE; ss->currentMove = threatMove = (ss+1)->excludedMove = bestMove = MOVE_NONE; ss->ply = (ss-1)->ply + 1; - ss->futilityMoveCount = 0; (ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO; (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE; @@ -586,7 +569,7 @@ namespace { if ( ttValue >= beta && ttMove - && !pos.is_capture_or_promotion(ttMove) + && !pos.capture_or_promotion(ttMove) && ttMove != ss->killers[0]) { ss->killers[1] = ss->killers[0]; @@ -598,32 +581,27 @@ namespace { // Step 5. Evaluate the position statically and update parent's gain statistics if (inCheck) { - ss->staticEval = ss->evalMargin = eval = VALUE_NONE; + ss->staticEval = eval = VALUE_NONE; goto moves_loop; } else if (tte) { // Never assume anything on values stored in TT - if ( (ss->staticEval = eval = tte->eval_value()) == VALUE_NONE - ||(ss->evalMargin = tte->eval_margin()) == VALUE_NONE) - eval = ss->staticEval = evaluate(pos, ss->evalMargin); + if ((ss->staticEval = eval = tte->eval_value()) == VALUE_NONE) + eval = ss->staticEval = evaluate(pos); // Can ttValue be used as a better position evaluation? if (ttValue != VALUE_NONE) - if ( ((tte->bound() & BOUND_LOWER) && ttValue > eval) - || ((tte->bound() & BOUND_UPPER) && ttValue < eval)) + if (tte->bound() & (ttValue > eval ? BOUND_LOWER : BOUND_UPPER)) eval = ttValue; } else { - eval = ss->staticEval = evaluate(pos, ss->evalMargin); - TT.store(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, - ss->staticEval, ss->evalMargin); + eval = ss->staticEval = evaluate(pos); + TT.store(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, ss->staticEval); } - // Update gain for the parent non-capture move given the static position - // evaluation before and after the move. if ( !pos.captured_piece_type() && ss->staticEval != VALUE_NONE && (ss-1)->staticEval != VALUE_NONE @@ -650,17 +628,15 @@ namespace { return v; } - // Step 7. Static null move pruning (skipped when in check) - // We're betting that the opponent doesn't have a move that will reduce - // the score by more than futility_margin(depth) if we do a null move. + // Step 7. Futility pruning: child node (skipped when in check) if ( !PvNode && !ss->skipNullMove - && depth < 4 * ONE_PLY - && eval - futility_margin(depth, (ss-1)->futilityMoveCount) >= beta + && depth < 7 * ONE_PLY + && eval - futility_margin(depth) >= beta && abs(beta) < VALUE_MATE_IN_MAX_PLY && abs(eval) < VALUE_KNOWN_WIN && pos.non_pawn_material(pos.side_to_move())) - return eval - futility_margin(depth, (ss-1)->futilityMoveCount); + return eval - futility_margin(depth); // Step 8. Null move search with verification search (is omitted in PV nodes) if ( !PvNode @@ -741,10 +717,10 @@ namespace { CheckInfo ci(pos); while ((move = mp.next_move()) != MOVE_NONE) - if (pos.pl_move_is_legal(move, ci.pinned)) + if (pos.legal(move, ci.pinned)) { ss->currentMove = move; - pos.do_move(move, st, ci, pos.move_gives_check(move, ci)); + pos.do_move(move, st, ci, pos.gives_check(move, ci)); value = -search(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode); pos.undo_move(move); if (value >= rbeta) @@ -806,14 +782,14 @@ moves_loop: // When in check and at SpNode search starts from here if (SpNode) { // Shared counter cannot be decremented later if move turns out to be illegal - if (!pos.pl_move_is_legal(move, ci.pinned)) + if (!pos.legal(move, ci.pinned)) continue; moveCount = ++splitPoint->moveCount; splitPoint->mutex.unlock(); } else - moveCount++; + ++moveCount; if (RootNode) { @@ -826,19 +802,16 @@ moves_loop: // When in check and at SpNode search starts from here } ext = DEPTH_ZERO; - captureOrPromotion = pos.is_capture_or_promotion(move); - givesCheck = pos.move_gives_check(move, ci); + captureOrPromotion = pos.capture_or_promotion(move); + givesCheck = pos.gives_check(move, ci); dangerous = givesCheck - || pos.is_passed_pawn_push(move) + || pos.passed_pawn_push(move) || type_of(move) == CASTLE; - // Step 12. Extend checks and, in PV nodes, also dangerous moves - if (PvNode && dangerous) + // Step 12. Extend checks + if (givesCheck && pos.see_sign(move) >= 0) ext = ONE_PLY; - else if (givesCheck && pos.see_sign(move) >= 0) - ext = inCheck || ss->staticEval < VALUE_ZERO ? ONE_PLY : ONE_PLY / 2; - // Singular extension search. If all moves but one fail low on a search of // (alpha-s, beta-s), and just one fails high on (alpha, beta), then that move // is singular and should be extended. To verify this we do a reduced search @@ -847,7 +820,7 @@ moves_loop: // When in check and at SpNode search starts from here if ( singularExtensionNode && move == ttMove && !ext - && pos.pl_move_is_legal(move, ci.pinned) + && pos.legal(move, ci.pinned) && abs(ttValue) < VALUE_KNOWN_WIN) { assert(ttValue != VALUE_NONE); @@ -866,7 +839,7 @@ moves_loop: // When in check and at SpNode search starts from here // Update current move (this must be done after singular extension search) newDepth = depth - ONE_PLY + ext; - // Step 13. Futility pruning (is omitted in PV nodes) + // Step 13. Pruning at shallow depth (exclude PV nodes) if ( !PvNode && !captureOrPromotion && !inCheck @@ -885,29 +858,30 @@ moves_loop: // When in check and at SpNode search starts from here continue; } - // Value based pruning - // We illogically ignore reduction condition depth >= 3*ONE_PLY for predicted depth, - // but fixing this made program slightly weaker. - Depth predictedDepth = newDepth - reduction(improving, depth, moveCount); - futilityValue = ss->staticEval + ss->evalMargin + futility_margin(predictedDepth, moveCount) - + Gains[pos.piece_moved(move)][to_sq(move)]; + predictedDepth = newDepth - reduction(improving, depth, moveCount); - if (futilityValue < beta) + // Futility pruning: parent node + if (predictedDepth < 7 * ONE_PLY) { - bestValue = std::max(bestValue, futilityValue); + futilityValue = ss->staticEval + futility_margin(predictedDepth) + + Value(128) + Gains[pos.moved_piece(move)][to_sq(move)]; - if (SpNode) + if (futilityValue <= alpha) { - splitPoint->mutex.lock(); - if (bestValue > splitPoint->bestValue) - splitPoint->bestValue = bestValue; + bestValue = std::max(bestValue, futilityValue); + + if (SpNode) + { + splitPoint->mutex.lock(); + if (bestValue > splitPoint->bestValue) + splitPoint->bestValue = bestValue; + } + continue; } - continue; } // Prune moves with negative SEE at low depths - if ( predictedDepth < 4 * ONE_PLY - && pos.see_sign(move) < 0) + if (predictedDepth < 4 * ONE_PLY && pos.see_sign(move) < 0) { if (SpNode) splitPoint->mutex.lock(); @@ -915,15 +889,10 @@ moves_loop: // When in check and at SpNode search starts from here continue; } - // We have not pruned the move that will be searched, but remember how - // far in the move list we are to be more aggressive in the child node. - ss->futilityMoveCount = moveCount; } - else - ss->futilityMoveCount = 0; // Check for legality only before to do the move - if (!RootNode && !SpNode && !pos.pl_move_is_legal(move, ci.pinned)) + if (!RootNode && !SpNode && !pos.legal(move, ci.pinned)) { moveCount--; continue; @@ -931,8 +900,6 @@ moves_loop: // When in check and at SpNode search starts from here pvMove = PvNode && moveCount == 1; ss->currentMove = move; - if (!SpNode && !captureOrPromotion && quietCount < 64) - quietsSearched[quietCount++] = move; // Step 14. Make the move pos.do_move(move, st, ci, givesCheck); @@ -951,8 +918,11 @@ moves_loop: // When in check and at SpNode search starts from here if (!PvNode && cutNode) ss->reduction += ONE_PLY; + else if (History[pos.piece_on(to_sq(move))][to_sq(move)] < 0) + ss->reduction += ONE_PLY / 2; + if (move == countermoves[0] || move == countermoves[1]) - ss->reduction = std::max(DEPTH_ZERO, ss->reduction-ONE_PLY); + ss->reduction = std::max(DEPTH_ZERO, ss->reduction - ONE_PLY); Depth d = std::max(newDepth - ss->reduction, ONE_PLY); if (SpNode) @@ -1020,7 +990,7 @@ moves_loop: // When in check and at SpNode search starts from here // iteration. This information is used for time management: When // the best move changes frequently, we allocate some more time. if (!pvMove) - BestMoveChanges++; + ++BestMoveChanges; } else // All other moves but the PV are set to the lowest value, this @@ -1087,11 +1057,11 @@ moves_loop: // When in check and at SpNode search starts from here TT.store(posKey, value_to_tt(bestValue, ss->ply), bestValue >= beta ? BOUND_LOWER : PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER, - depth, bestMove, ss->staticEval, ss->evalMargin); + depth, bestMove, ss->staticEval); // Quiet best move: update killers, history and countermoves if ( bestValue >= beta - && !pos.is_capture_or_promotion(bestMove) + && !pos.capture_or_promotion(bestMove) && !inCheck) { if (ss->killers[0] != bestMove) @@ -1103,12 +1073,10 @@ moves_loop: // When in check and at SpNode search starts from here // Increase history value of the cut-off move and decrease all the other // played non-capture moves. Value bonus = Value(int(depth) * int(depth)); - History.update(pos.piece_moved(bestMove), to_sq(bestMove), bonus); - for (int i = 0; i < quietCount - 1; i++) - { - Move m = quietsSearched[i]; - History.update(pos.piece_moved(m), to_sq(m), -bonus); - } + History.update(pos.moved_piece(bestMove), to_sq(bestMove), bonus); + + for (const ExtMove* em = mp.quiet_moves(); em && em->move != bestMove; ++em) + History.update(pos.moved_piece(em->move), to_sq(em->move), -bonus); if (is_ok((ss-1)->currentMove)) Countermoves.update(pos.piece_on(prevMoveSq), prevMoveSq, bestMove); @@ -1180,7 +1148,7 @@ moves_loop: // When in check and at SpNode search starts from here // Evaluate the position statically if (InCheck) { - ss->staticEval = ss->evalMargin = VALUE_NONE; + ss->staticEval = VALUE_NONE; bestValue = futilityBase = -VALUE_INFINITE; } else @@ -1188,19 +1156,23 @@ moves_loop: // When in check and at SpNode search starts from here if (tte) { // Never assume anything on values stored in TT - if ( (ss->staticEval = bestValue = tte->eval_value()) == VALUE_NONE - ||(ss->evalMargin = tte->eval_margin()) == VALUE_NONE) - ss->staticEval = bestValue = evaluate(pos, ss->evalMargin); + if ((ss->staticEval = bestValue = tte->eval_value()) == VALUE_NONE) + ss->staticEval = bestValue = evaluate(pos); + + // Can ttValue be used as a better position evaluation? + if (ttValue != VALUE_NONE) + if (tte->bound() & (ttValue > bestValue ? BOUND_LOWER : BOUND_UPPER)) + bestValue = ttValue; } else - ss->staticEval = bestValue = evaluate(pos, ss->evalMargin); + ss->staticEval = bestValue = evaluate(pos); // Stand pat. Return immediately if static value is at least beta if (bestValue >= beta) { if (!tte) TT.store(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER, - DEPTH_NONE, MOVE_NONE, ss->staticEval, ss->evalMargin); + DEPTH_NONE, MOVE_NONE, ss->staticEval); return bestValue; } @@ -1208,7 +1180,7 @@ moves_loop: // When in check and at SpNode search starts from here if (PvNode && bestValue > alpha) alpha = bestValue; - futilityBase = ss->staticEval + ss->evalMargin + Value(128); + futilityBase = bestValue + Value(128); } // Initialize a MovePicker object for the current position, and prepare @@ -1223,7 +1195,7 @@ moves_loop: // When in check and at SpNode search starts from here { assert(is_ok(move)); - givesCheck = pos.move_gives_check(move, ci); + givesCheck = pos.gives_check(move, ci); // Futility pruning if ( !PvNode @@ -1232,7 +1204,7 @@ moves_loop: // When in check and at SpNode search starts from here && move != ttMove && type_of(move) != PROMOTION && futilityBase > -VALUE_KNOWN_WIN - && !pos.is_passed_pawn_push(move)) + && !pos.passed_pawn_push(move)) { futilityValue = futilityBase + PieceValue[EG][pos.piece_on(to_sq(move))] @@ -1257,7 +1229,7 @@ moves_loop: // When in check and at SpNode search starts from here // Detect non-capture evasions that are candidate to be pruned evasionPrunable = InCheck && bestValue > VALUE_MATED_IN_MAX_PLY - && !pos.is_capture(move) + && !pos.capture(move) && !pos.can_castle(pos.side_to_move()); // Don't search moves with negative SEE values @@ -1269,7 +1241,7 @@ moves_loop: // When in check and at SpNode search starts from here continue; // Check for legality only before to do the move - if (!pos.pl_move_is_legal(move, ci.pinned)) + if (!pos.legal(move, ci.pinned)) continue; ss->currentMove = move; @@ -1297,7 +1269,7 @@ moves_loop: // When in check and at SpNode search starts from here else // Fail high { TT.store(posKey, value_to_tt(value, ss->ply), BOUND_LOWER, - ttDepth, move, ss->staticEval, ss->evalMargin); + ttDepth, move, ss->staticEval); return value; } @@ -1312,7 +1284,7 @@ moves_loop: // When in check and at SpNode search starts from here TT.store(posKey, value_to_tt(bestValue, ss->ply), PvNode && bestValue > oldAlpha ? BOUND_EXACT : BOUND_UPPER, - ttDepth, bestMove, ss->staticEval, ss->evalMargin); + ttDepth, bestMove, ss->staticEval); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1366,7 +1338,7 @@ moves_loop: // When in check and at SpNode search starts from here // We exclude the trivial case where a sliding piece does in two moves what // it could do in one move: eg. Ra1a2, Ra2a3. if ( m2to == m1from - || (m1to == m2from && !squares_aligned(m1from, m2from, m2to))) + || (m1to == m2from && !aligned(m1from, m2from, m2to))) return true; // Second one moves through the square vacated by first one @@ -1409,7 +1381,7 @@ moves_loop: // When in check and at SpNode search starts from here // If the threatened piece has value less than or equal to the value of the // threat piece, don't prune moves which defend it. - if ( pos.is_capture(second) + if ( pos.capture(second) && ( PieceValue[MG][pos.piece_on(m2from)] >= PieceValue[MG][pos.piece_on(m2to)] || type_of(pos.piece_on(m2from)) == KING)) { @@ -1446,7 +1418,7 @@ moves_loop: // When in check and at SpNode search starts from here static RKISS rk; // PRNG sequence should be not deterministic - for (int i = Time::now() % 50; i > 0; i--) + for (int i = Time::now() % 50; i > 0; --i) rk.rand(); // RootMoves are already sorted by score in descending order @@ -1458,7 +1430,7 @@ moves_loop: // When in check and at SpNode search starts from here // Choose best move. For each move score we add two terms both dependent on // weakness, one deterministic and bigger for weaker moves, and one random, // then we choose the move with the resulting highest score. - for (size_t i = 0; i < PVSize; i++) + for (size_t i = 0; i < PVSize; ++i) { int s = RootMoves[i].score; @@ -1491,11 +1463,11 @@ moves_loop: // When in check and at SpNode search starts from here size_t uciPVSize = std::min((size_t)Options["MultiPV"], RootMoves.size()); int selDepth = 0; - for (size_t i = 0; i < Threads.size(); i++) + for (size_t i = 0; i < Threads.size(); ++i) if (Threads[i]->maxPly > selDepth) selDepth = Threads[i]->maxPly; - for (size_t i = 0; i < uciPVSize; i++) + for (size_t i = 0; i < uciPVSize; ++i) { bool updated = (i <= PVIdx); @@ -1517,7 +1489,7 @@ moves_loop: // When in check and at SpNode search starts from here << " multipv " << i + 1 << " pv"; - for (size_t j = 0; RootMoves[i].pv[j] != MOVE_NONE; j++) + for (size_t j = 0; RootMoves[i].pv[j] != MOVE_NONE; ++j) s << " " << move_to_uci(RootMoves[i].pv[j], pos.is_chess960()); } @@ -1550,8 +1522,8 @@ void RootMove::extract_pv_from_tt(Position& pos) { tte = TT.probe(pos.key()); } while ( tte - && pos.is_pseudo_legal(m = tte->move()) // Local copy, TT could change - && pos.pl_move_is_legal(m, pos.pinned_pieces()) + && pos.pseudo_legal(m = tte->move()) // Local copy, TT could change + && pos.legal(m, pos.pinned_pieces(pos.side_to_move())) && ply < MAX_PLY && (!pos.is_draw() || ply < 2)); @@ -1575,7 +1547,7 @@ void RootMove::insert_pv_in_tt(Position& pos) { tte = TT.probe(pos.key()); if (!tte || tte->move() != pv[ply]) // Don't overwrite correct entries - TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply], VALUE_NONE, VALUE_NONE); + TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply], VALUE_NONE); assert(MoveList(pos).contains(pv[ply])); @@ -1732,8 +1704,8 @@ void check_time() { // Loop across all split points and sum accumulated SplitPoint nodes plus // all the currently active positions nodes. - for (size_t i = 0; i < Threads.size(); i++) - for (int j = 0; j < Threads[i]->splitPointsSize; j++) + for (size_t i = 0; i < Threads.size(); ++i) + for (int j = 0; j < Threads[i]->splitPointsSize; ++j) { SplitPoint& sp = Threads[i]->splitPoints[j]; @@ -1759,7 +1731,7 @@ void check_time() { && !Signals.failedLowAtRoot && elapsed > TimeMgr.available_time(); - bool noMoreTime = elapsed > TimeMgr.maximum_time() - 2 * TimerResolution + bool noMoreTime = elapsed > TimeMgr.maximum_time() - 2 * TimerThread::Resolution || stillAtFirstMove; if ( (Limits.use_time_management() && noMoreTime)