X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=c54c1269089ed9237558f4adb18595573235b4ea;hp=57f636535ba89ac192a87196494f748457da3993;hb=e0504ab876a997321102f040ab88203cb893db12;hpb=1b62d413c137bfa669922b6d52b92262d60020f1 diff --git a/src/search.cpp b/src/search.cpp index 57f63653..c54c1269 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -153,11 +153,11 @@ namespace { {1, 0, 0, 0, 0, 1, 1 ,1}, }; + const size_t HalfDensitySize = std::extent::value; + Value bonus(Depth depth) { int d = depth / ONE_PLY ; return Value(d * d + 2 * d - 2); } Value penalty(Depth depth) { int d = depth / ONE_PLY ; return -Value(d * d + 4 * d + 1); } - const size_t HalfDensitySize = std::extent::value; - EasyMoveManager EasyMove; Value DrawValue[COLOR_NB]; @@ -165,7 +165,7 @@ namespace { Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode, bool skipEarlyPruning); template - Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth); + Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth = DEPTH_ZERO); Value value_to_tt(Value v, int ply); Value value_from_tt(Value v, int ply); @@ -211,7 +211,6 @@ void Search::clear() { for (Thread* th : Threads) { - th->history.clear(); th->counterMoves.clear(); th->fromTo.clear(); th->counterMoveHistory.clear(); @@ -312,9 +311,13 @@ void MainThread::search() { && rootMoves[0].pv[0] != MOVE_NONE) { for (Thread* th : Threads) - if ( th->completedDepth > bestThread->completedDepth - && th->rootMoves[0].score > bestThread->rootMoves[0].score) + { + Depth depthDiff = th->completedDepth - bestThread->completedDepth; + Value scoreDiff = th->rootMoves[0].score - bestThread->rootMoves[0].score; + + if (scoreDiff > 0 && depthDiff >= 0) bestThread = th; + } } previousScore = bestThread->rootMoves[0].score; @@ -597,7 +600,7 @@ namespace { if (!rootNode) { // Step 2. Check for aborted search and immediate draw - if (Signals.stop.load(std::memory_order_relaxed) || pos.is_draw() || ss->ply >= MAX_PLY) + if (Signals.stop.load(std::memory_order_relaxed) || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos) : DrawValue[pos.side_to_move()]; @@ -638,7 +641,7 @@ namespace { && (ttValue >= beta ? (tte->bound() & BOUND_LOWER) : (tte->bound() & BOUND_UPPER))) { - // If ttMove is quiet, update killers, history, counter move on TT hit + // If ttMove is quiet, update move sorting heuristics on TT hit if (ttValue >= beta && ttMove) { if (!pos.capture_or_promotion(ttMove)) @@ -654,10 +657,10 @@ namespace { // Step 4a. Tablebase probe if (!rootNode && TB::Cardinality) { - int piecesCnt = pos.count(WHITE) + pos.count(BLACK); + int piecesCount = pos.count(WHITE) + pos.count(BLACK); - if ( piecesCnt <= TB::Cardinality - && (piecesCnt < TB::Cardinality || depth >= TB::ProbeDepth) + if ( piecesCount <= TB::Cardinality + && (piecesCount < TB::Cardinality || depth >= TB::ProbeDepth) && pos.rule50_count() == 0 && !pos.can_castle(ANY_CASTLING)) { @@ -721,10 +724,10 @@ namespace { && eval + razor_margin[depth / ONE_PLY] <= alpha) { if (depth <= ONE_PLY) - return qsearch(pos, ss, alpha, beta, DEPTH_ZERO); + return qsearch(pos, ss, alpha, alpha+1); Value ralpha = alpha - razor_margin[depth / ONE_PLY]; - Value v = qsearch(pos, ss, ralpha, ralpha+1, DEPTH_ZERO); + Value v = qsearch(pos, ss, ralpha, ralpha+1); if (v <= ralpha) return v; } @@ -752,7 +755,7 @@ namespace { Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY; pos.do_null_move(st); - nullValue = depth-R < ONE_PLY ? -qsearch(pos, ss+1, -beta, -beta+1, DEPTH_ZERO) + nullValue = depth-R < ONE_PLY ? -qsearch(pos, ss+1, -beta, -beta+1) : - search(pos, ss+1, -beta, -beta+1, depth-R, !cutNode, true); pos.undo_null_move(); @@ -766,7 +769,7 @@ namespace { return nullValue; // Do verification search at high depths - Value v = depth-R < ONE_PLY ? qsearch(pos, ss, beta-1, beta, DEPTH_ZERO) + Value v = depth-R < ONE_PLY ? qsearch(pos, ss, beta-1, beta) : search(pos, ss, beta-1, beta, depth-R, false, true); if (v >= beta) @@ -934,16 +937,10 @@ moves_loop: // When in check search starts from here && !pos.see_ge(move, Value(-35 * lmrDepth * lmrDepth))) continue; } - else if (depth < 7 * ONE_PLY && !extension) - { - Value v = -Value(399 + 35 * depth / ONE_PLY * depth / ONE_PLY); - - if (PvNode) - v += beta - alpha - 1; - - if (!pos.see_ge(move, v)) + else if ( depth < 7 * ONE_PLY + && !extension + && !pos.see_ge(move, -PawnValueEg * (depth / ONE_PLY))) continue; - } } // Speculative prefetch as early as possible @@ -985,12 +982,11 @@ moves_loop: // When in check search starts from here && !pos.see_ge(make_move(to_sq(move), from_sq(move)), VALUE_ZERO)) r -= 2 * ONE_PLY; - ss->history = thisThread->history[moved_piece][to_sq(move)] - + (cmh ? (*cmh )[moved_piece][to_sq(move)] : VALUE_ZERO) - + (fmh ? (*fmh )[moved_piece][to_sq(move)] : VALUE_ZERO) - + (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO) - + thisThread->fromTo.get(~pos.side_to_move(), move) - - 8000; // Correction factor + ss->history = (cmh ? (*cmh )[moved_piece][to_sq(move)] : VALUE_ZERO) + + (fmh ? (*fmh )[moved_piece][to_sq(move)] : VALUE_ZERO) + + (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO) + + thisThread->fromTo.get(~pos.side_to_move(), move) + - 8000; // Correction factor // Decrease/increase reduction by comparing opponent's stat score if (ss->history > VALUE_ZERO && (ss-1)->history < VALUE_ZERO) @@ -1015,8 +1011,8 @@ moves_loop: // When in check search starts from here // Step 16. Full depth search when LMR is skipped or fails high if (doFullDepthSearch) value = newDepth < ONE_PLY ? - givesCheck ? -qsearch(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO) - : -qsearch(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO) + givesCheck ? -qsearch(pos, ss+1, -(alpha+1), -alpha) + : -qsearch(pos, ss+1, -(alpha+1), -alpha) : - search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode, false); // For PV nodes only, do a full PV search on the first move or after a fail @@ -1028,8 +1024,8 @@ moves_loop: // When in check search starts from here (ss+1)->pv[0] = MOVE_NONE; value = newDepth < ONE_PLY ? - givesCheck ? -qsearch(pos, ss+1, -beta, -alpha, DEPTH_ZERO) - : -qsearch(pos, ss+1, -beta, -alpha, DEPTH_ZERO) + givesCheck ? -qsearch(pos, ss+1, -beta, -alpha) + : -qsearch(pos, ss+1, -beta, -alpha) : - search(pos, ss+1, -beta, -alpha, newDepth, false, false); } @@ -1080,13 +1076,6 @@ moves_loop: // When in check search starts from here if (value > alpha) { - // If there is an easy move for this position, clear it if unstable - if ( PvNode - && thisThread == Threads.main() - && EasyMove.get(pos.key()) - && (move != EasyMove.get(pos.key()) || moveCount > 1)) - EasyMove.clear(); - bestMove = move; if (PvNode && !rootNode) // Update pv even in fail-high case @@ -1127,7 +1116,7 @@ moves_loop: // When in check search starts from here else if (bestMove) { - // Quiet best move: update killers, history and countermoves + // Quiet best move: update move sorting heuristics if (!pos.capture_or_promotion(bestMove)) update_stats(pos, ss, bestMove, quietsSearched, quietCount, bonus(depth)); @@ -1153,8 +1142,7 @@ moves_loop: // When in check search starts from here // qsearch() is the quiescence search function, which is called by the main - // search function when the remaining depth is zero (or, to be more precise, - // less than ONE_PLY). + // search function with depth zero, or recursively with depth less than ONE_PLY. template Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) { @@ -1187,7 +1175,7 @@ moves_loop: // When in check search starts from here ss->ply = (ss-1)->ply + 1; // Check for an instant draw or if the maximum ply has been reached - if (pos.is_draw() || ss->ply >= MAX_PLY) + if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos) : DrawValue[pos.side_to_move()]; @@ -1414,8 +1402,7 @@ moves_loop: // When in check search starts from here } - // update_stats() updates killers, history, countermove and countermove plus - // follow-up move history when a new quiet best move is found. + // update_stats() updates move sorting heuristics when a new quiet best move is found void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, Value bonus) { @@ -1429,7 +1416,6 @@ moves_loop: // When in check search starts from here Color c = pos.side_to_move(); Thread* thisThread = pos.this_thread(); thisThread->fromTo.update(c, move, bonus); - thisThread->history.update(pos.moved_piece(move), to_sq(move), bonus); update_cm_stats(ss, pos.moved_piece(move), to_sq(move), bonus); if ((ss-1)->counterMoves) @@ -1442,7 +1428,6 @@ moves_loop: // When in check search starts from here for (int i = 0; i < quietsCnt; ++i) { thisThread->fromTo.update(c, quiets[i], -bonus); - thisThread->history.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus); update_cm_stats(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus); } }