X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=8ce9c56e42d0849e2caf9b2528d463faf524fe21;hb=21d6b69f7c8d0c0a71fe627714913a59d39a3b57;hp=5d54a15d628070707d6f08db5b7e6483635b3d27;hpb=b36d39de3d61b8f31c11d85233631aafaf760ee1;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 5d54a15d..8ce9c56e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -288,20 +288,10 @@ void Thread::search() { ss->pv = pv; - bestValue = delta = alpha = -VALUE_INFINITE; - beta = VALUE_INFINITE; - optimism[WHITE] = optimism[BLACK] = VALUE_ZERO; + bestValue = -VALUE_INFINITE; if (mainThread) { - - if (!rootPos.checkers()) - { - int rootComplexity; - Eval::evaluate(rootPos, &rootComplexity); - mainThread->complexity = std::min(1.03 + (rootComplexity - 241) / 1552.0, 1.45); - } - if (mainThread->bestPreviousScore == VALUE_INFINITE) for (int i = 0; i < 4; ++i) mainThread->iterValue[i] = VALUE_ZERO; @@ -357,18 +347,15 @@ void Thread::search() { selDepth = 0; // Reset aspiration window starting size - if (rootDepth >= 4) - { - Value prev = rootMoves[pvIdx].averageScore; - delta = Value(10) + int(prev) * prev / 16502; - alpha = std::max(prev - delta,-VALUE_INFINITE); - beta = std::min(prev + delta, VALUE_INFINITE); - - // Adjust optimism based on root move's previousScore - int opt = 120 * prev / (std::abs(prev) + 161); - optimism[ us] = Value(opt); - optimism[~us] = -optimism[us]; - } + Value prev = rootMoves[pvIdx].averageScore; + delta = Value(10) + int(prev) * prev / 16502; + alpha = std::max(prev - delta,-VALUE_INFINITE); + beta = std::min(prev + delta, VALUE_INFINITE); + + // Adjust optimism based on root move's previousScore + int opt = 102 * prev / (std::abs(prev) + 147); + optimism[ us] = Value(opt); + optimism[~us] = -optimism[us]; // Start with a small aspiration window and, in the case of a fail // high/low, re-search with a bigger window until we don't fail @@ -478,7 +465,7 @@ void Thread::search() { double reduction = (1.4 + mainThread->previousTimeReduction) / (2.08 * timeReduction); double bestMoveInstability = 1 + 1.8 * totBestMoveChanges / Threads.size(); - double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * mainThread->complexity; + double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability; // Cap used time in case of a single legal move for a better viewer experience in tournaments // yielding correct scores and sufficiently fast moves. @@ -561,7 +548,7 @@ namespace { bool givesCheck, improving, priorCapture, singularQuietLMR; bool capture, moveCountPruning, ttCapture; Piece movedPiece; - int moveCount, captureCount, quietCount, improvement, complexity; + int moveCount, captureCount, quietCount, improvement; // Step 1. Initialize node Thread* thisThread = pos.this_thread(); @@ -723,7 +710,6 @@ namespace { ss->staticEval = eval = VALUE_NONE; improving = false; improvement = 0; - complexity = 0; goto moves_loop; } else if (excludedMove) @@ -731,17 +717,15 @@ namespace { // Providing the hint that this node's accumulator will be used often brings significant Elo gain (13 Elo) Eval::NNUE::hint_common_parent_position(pos); eval = ss->staticEval; - complexity = abs(ss->staticEval - pos.psq_eg_stm()); } else if (ss->ttHit) { // Never assume anything about values stored in TT ss->staticEval = eval = tte->eval(); if (eval == VALUE_NONE) - ss->staticEval = eval = evaluate(pos, &complexity); - else // Fall back to (semi)classical complexity for TT hits, the NNUE complexity is lost + ss->staticEval = eval = evaluate(pos); + else { - complexity = abs(ss->staticEval - pos.psq_eg_stm()); if (PvNode) Eval::NNUE::hint_common_parent_position(pos); } @@ -753,7 +737,7 @@ namespace { } else { - ss->staticEval = eval = evaluate(pos, &complexity); + ss->staticEval = eval = evaluate(pos); // Save static evaluation into transposition table tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval); } @@ -799,15 +783,15 @@ namespace { && (ss-1)->statScore < 18755 && eval >= beta && eval >= ss->staticEval - && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 + complexity / 25 + && ss->staticEval >= beta - 20 * depth - improvement / 13 + 253 && !excludedMove && pos.non_pawn_material(us) - && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) + && (ss->ply >= thisThread->nmpMinPly)) { assert(eval - beta >= 0); - // Null move dynamic reduction based on depth, eval and complexity of position - Depth R = std::min(int(eval - beta) / 172, 6) + depth / 3 + 4 - (complexity > 825); + // Null move dynamic reduction based on depth and eval + Depth R = std::min(int(eval - beta) / 172, 6) + depth / 3 + 4; ss->currentMove = MOVE_NULL; ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0]; @@ -830,9 +814,8 @@ namespace { assert(!thisThread->nmpMinPly); // Recursive verification is not allowed // Do verification search at high depths, with null move pruning disabled - // for us, until ply exceeds nmpMinPly. + // until ply exceeds nmpMinPly. thisThread->nmpMinPly = ss->ply + 3 * (depth-R) / 4; - thisThread->nmpColor = us; Value v = search(pos, ss, beta-1, beta, depth-R, false); @@ -1018,16 +1001,16 @@ moves_loop: // When in check, search starts here { if (depth < 2 - capture) continue; - // don't prune move if a heavy enemy piece (KQR) is under attack after the exchanges - Bitboard leftEnemies = (pos.pieces(~us, QUEEN, ROOK) | pos.pieces(~us, KING)) & occupied; + // Don't prune the move if opp. King/Queen/Rook gets a discovered attack during or after the exchanges + Bitboard leftEnemies = pos.pieces(~us, KING, QUEEN, ROOK); Bitboard attacks = 0; occupied |= to_sq(move); while (leftEnemies && !attacks) { Square sq = pop_lsb(leftEnemies); - attacks |= pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; - // exclude Queen/Rook(s) which were already threatened before SEE - if (attacks && (sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us)))) + attacks = pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied; + // Exclude Queen/Rook(s) which were already threatened before SEE (opp King can't be in check when it's our turn) + if (attacks && sq != pos.square(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))) attacks = 0; } if (!attacks) @@ -1186,9 +1169,7 @@ moves_loop: // When in check, search starts here if ((ss+1)->cutoffCnt > 3) r++; - // Decrease reduction if move is a killer and we have a good history (~1 Elo) - if (move == ss->killers[0] - && (*contHist[0])[movedPiece][to_sq(move)] >= 3722) + else if (move == ttMove) r--; ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] @@ -1233,8 +1214,9 @@ moves_loop: // When in check, search starts here if (newDepth > d) value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); - int bonus = value > alpha ? stat_bonus(newDepth) - : -stat_bonus(newDepth); + int bonus = value <= alpha ? -stat_bonus(newDepth) + : value >= beta ? stat_bonus(newDepth) + : 0; update_continuation_histories(ss, movedPiece, to_sq(move), bonus); } @@ -1259,9 +1241,6 @@ moves_loop: // When in check, search starts here (ss+1)->pv[0] = MOVE_NONE; value = -search(pos, ss+1, -beta, -alpha, newDepth, false); - - if (moveCount > 1 && newDepth >= depth && !capture) - update_continuation_histories(ss, movedPiece, to_sq(move), -stat_bonus(newDepth)); } // Step 19. Undo move @@ -1335,15 +1314,11 @@ moves_loop: // When in check, search starts here if (PvNode && value < beta) // Update alpha! Always alpha < beta { - // Reduce other moves if we have found at least one score improvement (~1 Elo) if ( depth > 1 - && ((improving && complexity > 971) || (value < (5 * alpha + 75 * beta) / 87) || depth < 6) && beta < 12535 - && value > -12535) { - bool extraReduction = depth > 2 && alpha > -12535 && bestValue != -VALUE_INFINITE && (value - bestValue) > (7 * (beta - alpha)) / 8; - depth -= 1 + extraReduction; - } + && value > -12535) + depth -= 1; assert(depth > 0); alpha = value;