X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=7efb3928bf4a86c2efca25b7ead1b4d766eb461d;hp=b47e26a1c974f73e627adf73754aa4ccc5c70b90;hb=8b3fdec7ecf330968dae2339e5c1b9a664bda51d;hpb=b599da01fa008e5f274a96c948f8346991bfd050 diff --git a/src/search.cpp b/src/search.cpp index b47e26a1..7efb3928 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -172,12 +172,15 @@ namespace { const bool PruneDefendingMoves = false; const bool PruneBlockingMoves = false; + // Only move margin + const Value OnlyMoveMargin = Value(100); + // Margins for futility pruning in the quiescence search, and at frontier // and near frontier nodes. const Value FutilityMarginQS = Value(0x80); // Each move futility margin is decreased - const Value IncrementalFutilityMargin = Value(0xA); + const Value IncrementalFutilityMargin = Value(0x8); // Remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply const Value FutilityMargins[12] = { Value(0x100), Value(0x120), Value(0x200), Value(0x220), Value(0x250), Value(0x270), @@ -277,7 +280,7 @@ namespace { Value id_loop(const Position& pos, Move searchMoves[]); Value root_search(Position& pos, SearchStack ss[], RootMoveList& rml, Value alpha, Value beta); Value search_pv(Position& pos, SearchStack ss[], Value alpha, Value beta, Depth depth, int ply, int threadID); - Value search(Position& pos, SearchStack ss[], Value beta, Depth depth, int ply, bool allowNullmove, int threadID); + Value search(Position& pos, SearchStack ss[], Value beta, Depth depth, int ply, bool allowNullmove, int threadID, Move forbiddenMove = MOVE_NONE); Value qsearch(Position& pos, SearchStack ss[], Value alpha, Value beta, Depth depth, int ply, int threadID); void sp_search(SplitPoint* sp, int threadID); void sp_search_pv(SplitPoint* sp, int threadID); @@ -1132,12 +1135,34 @@ namespace { moveIsCheck = pos.move_is_check(move, ci); captureOrPromotion = pos.move_is_capture_or_promotion(move); - movesSearched[moveCount++] = ss[ply].currentMove = move; + movesSearched[moveCount++] = move; // Decide the new search depth ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, singleReply, mateThreat, &dangerous); + + // Only move extension + if ( moveCount == 1 + && ext < OnePly + && depth >= 4 * OnePly + && tte + && (tte->type() & VALUE_TYPE_LOWER) + && tte->move() != MOVE_NONE + && tte->depth() >= depth - 3 * OnePly) + { + Value ttValue = value_from_tt(tte->value(), ply); + if (abs(ttValue) < VALUE_KNOWN_WIN) + { + Value excValue = search(pos, ss, ttValue - OnlyMoveMargin, Max(Min(depth / 2, depth - 4 * OnePly), OnePly), ply, false, threadID, tte->move()); + if (excValue < ttValue - OnlyMoveMargin) + ext = OnePly; + } + } + newDepth = depth - OnePly + ext; + // Update current move + ss[ply].currentMove = move; + // Make and search the move pos.do_move(move, st, ci, moveIsCheck); @@ -1251,7 +1276,7 @@ namespace { // search() is the search function for zero-width nodes. Value search(Position& pos, SearchStack ss[], Value beta, Depth depth, - int ply, bool allowNullmove, int threadID) { + int ply, bool allowNullmove, int threadID, Move forbiddenMove) { assert(beta >= -VALUE_INFINITE && beta <= VALUE_INFINITE); assert(ply >= 0 && ply < PLY_MAX); @@ -1293,8 +1318,14 @@ namespace { if (value_mate_in(ply + 1) < beta) return beta - 1; + // Position key calculation + Key posKey = pos.get_key(); + + if (forbiddenMove != MOVE_NONE) + posKey ^= Position::zobExclusion; + // Transposition table lookup - tte = TT.retrieve(pos.get_key()); + tte = TT.retrieve(posKey); ttMove = (tte ? tte->move() : MOVE_NONE); if (tte && ok_to_use_TT(tte, depth, beta, ply)) @@ -1399,16 +1430,42 @@ namespace { { assert(move_is_ok(move)); + if (move == forbiddenMove) + continue; + singleReply = (isCheck && mp.number_of_evasions() == 1); moveIsCheck = pos.move_is_check(move, ci); captureOrPromotion = pos.move_is_capture_or_promotion(move); - movesSearched[moveCount++] = ss[ply].currentMove = move; + movesSearched[moveCount++] = move; // Decide the new search depth ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, singleReply, mateThreat, &dangerous); + + // Only move extension + if ( forbiddenMove == MOVE_NONE + && moveCount == 1 + && ext < OnePly + && depth >= 4 * OnePly + && tte + && (tte->type() & VALUE_TYPE_LOWER) + && tte->move() != MOVE_NONE + && tte->depth() >= depth - 3 * OnePly) + { + Value ttValue = value_from_tt(tte->value(), ply); + if (abs(ttValue) < VALUE_KNOWN_WIN) + { + Value excValue = search(pos, ss, ttValue - OnlyMoveMargin, Max(Min(depth / 2, depth - 4 * OnePly), OnePly), ply, false, threadID, tte->move()); + if (excValue < ttValue - OnlyMoveMargin) + ext = (depth >= 8 * OnePly)? OnePly : ext + OnePly / 2; + } + } + newDepth = depth - OnePly + ext; + // Update current move + ss[ply].currentMove = move; + // Futility pruning if ( useFutilityPruning && !dangerous @@ -1417,10 +1474,25 @@ namespace { { //std::cout << std::endl; //for (int d = 2; d < 14; d++) - // std::cout << d << ", " << 300 + 2*(1 << (3*d/4)) << std::endl; + // std::cout << d << ", " << 64*(1+bitScanReverse32(d*d)) << std::endl; //std::cout << std::endl; /* + 64*(1+bitScanReverse32(d*d)) + + 2 -> 256 - 256 + 3 -> 288 - 320 + 4 -> 512 - 384 + 5 -> 544 - 384 + 6 -> 592 - 448 + 7 -> 624 - 448 + 8 -> 672 - 512 + 9 -> 704 - 512 + 10 -> 832 - 512 + 11 -> 864 - 512 + 12 -> 928 - 576 + 13 -> 960 - 576 + 300 + 2*(1 << (3*d/4)) 2 -> 256 - 304 @@ -1458,8 +1530,7 @@ namespace { { if (futilityValue == VALUE_NONE) futilityValue = evaluate(pos, ei, threadID) - + (300 + 2 * (1 << (3 * int(depth) /4))) - + 4*IncrementalFutilityMargin; + + 64*(2+bitScanReverse32(int(depth) * int(depth))); futilityValueScaled = futilityValue - moveCount * IncrementalFutilityMargin; @@ -1526,7 +1597,7 @@ namespace { // All legal moves have been searched. A special case: If there were // no legal moves, it must be mate or stalemate. if (moveCount == 0) - return (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW); + return (forbiddenMove == MOVE_NONE ? (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW) : beta - 1); // If the search is not aborted, update the transposition table, // history counters, and killer moves. @@ -1534,7 +1605,7 @@ namespace { return bestValue; if (bestValue < beta) - TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, depth, MOVE_NONE); + TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_UPPER, depth, MOVE_NONE); else { BetaCounter.add(pos.side_to_move(), depth, threadID); @@ -1544,7 +1615,7 @@ namespace { update_history(pos, move, depth, movesSearched, moveCount); update_killers(move, ss[ply]); } - TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move); + TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move); } assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);