X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=6ec4d80322372332e10f909a5c574dbf6be5f3d9;hb=33f3cfae0093b934563e1eca78486261f18e4650;hp=1e2980cb0cda1138dd35118e3b1ab603bfe909f5;hpb=ab5cd8340f2f7f8730aa7c77476edf4a98a166e4;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 1e2980cb..6ec4d803 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -263,10 +263,10 @@ void MainThread::search() { Thread* bestThread = this; - if (int(Options["MultiPV"]) == 1 && - !Limits.depth && - !(Skill(Options["Skill Level"]).enabled() || int(Options["UCI_LimitStrength"])) && - rootMoves[0].pv[0] != MOVE_NONE) + if ( int(Options["MultiPV"]) == 1 + && !Limits.depth + && !(Skill(Options["Skill Level"]).enabled() || int(Options["UCI_LimitStrength"])) + && rootMoves[0].pv[0] != MOVE_NONE) bestThread = Threads.get_best_thread(); bestPreviousScore = bestThread->rootMoves[0].score; @@ -596,7 +596,7 @@ namespace { Key posKey; Move ttMove, move, excludedMove, bestMove; Depth extension, newDepth; - Value bestValue, value, ttValue, eval, maxValue; + Value bestValue, value, ttValue, eval, maxValue, probcutBeta; bool ttHit, ttPv, formerPv, givesCheck, improving, didLMR, priorCapture; bool captureOrPromotion, doFullDepthSearch, moveCountPruning, ttCapture, singularQuietLMR; @@ -662,7 +662,7 @@ namespace { // search to overwrite a previous full search TT value, so we use a different // position key in case of an excluded move. excludedMove = ss->excludedMove; - posKey = pos.key() ^ (Key(excludedMove) << 48); // Isn't a very good hash + posKey = excludedMove == MOVE_NONE ? pos.key() : pos.key() ^ make_key(excludedMove); tte = TT.probe(posKey, ttHit); ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE; ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0] @@ -670,7 +670,11 @@ namespace { ttPv = PvNode || (ttHit && tte->is_pv()); formerPv = ttPv && !PvNode; - if (ttPv && depth > 12 && ss->ply - 1 < MAX_LPH && !priorCapture && is_ok((ss-1)->currentMove)) + if ( ttPv + && depth > 12 + && ss->ply - 1 < MAX_LPH + && !priorCapture + && is_ok((ss-1)->currentMove)) thisThread->lowPlyHistory[ss->ply - 1][from_to((ss-1)->currentMove)] << stat_bonus(depth - 5); // thisThread->ttHitAverage can be used to approximate the running average of ttHit @@ -867,23 +871,33 @@ namespace { } } + probcutBeta = beta + 176 - 49 * improving; + // Step 10. ProbCut (~10 Elo) // If we have a good enough capture and a reduced search returns a value // much above beta, we can (almost) safely prune the previous move. if ( !PvNode && depth > 4 - && abs(beta) < VALUE_TB_WIN_IN_MAX_PLY) + && abs(beta) < VALUE_TB_WIN_IN_MAX_PLY + && !( ttHit + && tte->depth() >= depth - 3 + && ttValue != VALUE_NONE + && ttValue < probcutBeta)) { - Value raisedBeta = beta + 176 - 49 * improving; - assert(raisedBeta < VALUE_INFINITE); - MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &captureHistory); + if ( ttHit + && tte->depth() >= depth - 3 + && ttValue != VALUE_NONE + && ttValue >= probcutBeta + && ttMove + && pos.capture_or_promotion(ttMove)) + return probcutBeta; + + assert(probcutBeta < VALUE_INFINITE); + MovePicker mp(pos, ttMove, probcutBeta - ss->staticEval, &captureHistory); int probCutCount = 0; while ( (move = mp.next_move()) != MOVE_NONE - && probCutCount < 2 + 2 * cutNode - && !( move == ttMove - && tte->depth() >= depth - 4 - && ttValue < raisedBeta)) + && probCutCount < 2 + 2 * cutNode) if (move != excludedMove && pos.legal(move)) { assert(pos.capture_or_promotion(move)); @@ -901,16 +915,24 @@ namespace { pos.do_move(move, st); // Perform a preliminary qsearch to verify that the move holds - value = -qsearch(pos, ss+1, -raisedBeta, -raisedBeta+1); + value = -qsearch(pos, ss+1, -probcutBeta, -probcutBeta+1); // If the qsearch held, perform the regular search - if (value >= raisedBeta) - value = -search(pos, ss+1, -raisedBeta, -raisedBeta+1, depth - 4, !cutNode); + if (value >= probcutBeta) + value = -search(pos, ss+1, -probcutBeta, -probcutBeta+1, depth - 4, !cutNode); pos.undo_move(move); - if (value >= raisedBeta) + if (value >= probcutBeta) + { + if ( !(ttHit + && tte->depth() >= depth - 3 + && ttValue != VALUE_NONE)) + tte->save(posKey, value_to_tt(value, ss->ply), ttPv, + BOUND_LOWER, + depth - 3, move, ss->staticEval); return value; + } } } @@ -1045,7 +1067,7 @@ moves_loop: // When in check, search starts from here // 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 on all the other moves but the ttMove and if the - // result is lower than ttValue minus a margin then we will extend the ttMove. + // result is lower than ttValue minus a margin, then we will extend the ttMove. if ( depth >= 6 && move == ttMove && !rootNode @@ -1109,12 +1131,6 @@ moves_loop: // When in check, search starts from here if (type_of(move) == CASTLING) extension = 1; - // Late irreversible move extension - if ( move == ttMove - && pos.rule50_count() > 80 - && (captureOrPromotion || type_of(movedPiece) == PAWN)) - extension = 2; - // Add extension to new depth newDepth += extension; @@ -1486,8 +1502,8 @@ moves_loop: // When in check, search starts from here // Initialize a MovePicker object for the current position, and prepare // to search the moves. Because the depth is <= 0 here, only captures, - // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will - // be generated. + // queen and checking knight promotions, and other checks(only if depth >= DEPTH_QS_CHECKS) + // will be generated. MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory, &thisThread->captureHistory, contHist, @@ -1835,6 +1851,9 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { << " multipv " << i + 1 << " score " << UCI::value(v); + if (Options["UCI_ShowWDL"]) + ss << UCI::wdl(v, pos.game_ply()); + if (!tb && i == pvIdx) ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");