X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=8b3b8fb4864436c17c6964a24151a85db92f873f;hp=0db8f6c2f9978ebf7935a9d8422f5115f3cfd8c1;hb=b53239d6410cfc87bf454370671390b04879ef05;hpb=87452f3a8c913cb795f04db132ff0f56ee471a62 diff --git a/src/search.cpp b/src/search.cpp index 0db8f6c2..8b3b8fb4 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -96,8 +96,6 @@ namespace { Move best = MOVE_NONE; }; - Value DrawValue[COLOR_NB]; - template Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode, bool skipEarlyPruning); @@ -202,8 +200,9 @@ void MainThread::search() { TT.new_search(); int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns - DrawValue[ us] = VALUE_DRAW - Value(contempt); - DrawValue[~us] = VALUE_DRAW + Value(contempt); + + Eval::Contempt = (us == WHITE ? make_score(contempt, contempt / 2) + : -make_score(contempt, contempt / 2)); if (rootMoves.empty()) { @@ -444,7 +443,7 @@ void Thread::search() { int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1])); Color us = rootPos.side_to_move(); - bool thinkHard = DrawValue[us] == bestValue + bool thinkHard = bestValue == VALUE_DRAW && Limits.time[us] - Time.elapsed() > Limits.time[~us] && ::pv_is_draw(rootPos); @@ -532,8 +531,7 @@ namespace { { // Step 2. Check for aborted search and immediate draw if (Threads.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()]; + return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos) : VALUE_DRAW; // Step 3. Mate distance pruning. Even if we mate at the next move our score // would be at best mate_in(ss->ply+1), but if alpha is already bigger because @@ -656,7 +654,7 @@ namespace { ss->staticEval, TT.generation()); } - if (skipEarlyPruning) + if (skipEarlyPruning || !pos.non_pawn_material(pos.side_to_move())) goto moves_loop; // Step 6. Razoring (skipped when in check) @@ -677,15 +675,14 @@ namespace { if ( !rootNode && depth < 7 * ONE_PLY && eval - futility_margin(depth) >= beta - && eval < VALUE_KNOWN_WIN // Do not return unproven wins - && pos.non_pawn_material(pos.side_to_move())) + && eval < VALUE_KNOWN_WIN) // Do not return unproven wins return eval; // Step 8. Null move search with verification search (is omitted in PV nodes) if ( !PvNode && eval >= beta && ss->staticEval >= beta - 36 * depth / ONE_PLY + 225 - && pos.non_pawn_material(pos.side_to_move())) + && (ss->ply >= thisThread->nmp_ply || ss->ply % 2 == thisThread->pair)) { assert(eval - beta >= 0); @@ -711,8 +708,17 @@ namespace { return nullValue; // Do verification search at high depths + R += ONE_PLY; + // disable null move pruning for side to move for the first part of the remaining search tree + int nmp_ply = thisThread->nmp_ply; + int pair = thisThread->pair; + thisThread->nmp_ply = ss->ply + 3 * (depth-R) / 4; + thisThread->pair = (ss->ply % 2) == 0; + Value v = depth-R < ONE_PLY ? qsearch(pos, ss, beta-1, beta) : search(pos, ss, beta-1, beta, depth-R, false, true); + thisThread->pair = pair; + thisThread->nmp_ply = nmp_ply; if (v >= beta) return nullValue; @@ -812,7 +818,7 @@ moves_loop: // When in check search starts from here movedPiece = pos.moved_piece(move); givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates() - ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move) + ? pos.check_squares(type_of(movedPiece)) & to_sq(move) : pos.gives_check(move); moveCountPruning = depth < 16 * ONE_PLY @@ -1076,7 +1082,7 @@ moves_loop: // When in check search starts from here if (!moveCount) bestValue = excludedMove ? alpha - : inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()]; + : inCheck ? mated_in(ss->ply) : VALUE_DRAW; else if (bestMove) { // Quiet best move: update move sorting heuristics @@ -1115,7 +1121,7 @@ moves_loop: // When in check search starts from here const bool PvNode = NT == PV; - assert(InCheck == !!pos.checkers()); + assert(InCheck == bool(pos.checkers())); assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE); assert(PvNode || (alpha == beta - 1)); assert(depth <= DEPTH_ZERO); @@ -1144,8 +1150,7 @@ moves_loop: // When in check search starts from here // Check for an instant draw or if the maximum ply has been reached if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) - return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos) - : DrawValue[pos.side_to_move()]; + return ss->ply >= MAX_PLY && !InCheck ? evaluate(pos) : VALUE_DRAW; assert(0 <= ss->ply && ss->ply < MAX_PLY); @@ -1196,7 +1201,7 @@ moves_loop: // When in check search starts from here if (bestValue >= beta) { if (!ttHit) - tte->save(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER, + tte->save(posKey, value_to_tt(bestValue, ss->ply), BOUND_LOWER, DEPTH_NONE, MOVE_NONE, ss->staticEval, TT.generation()); return bestValue; @@ -1220,7 +1225,7 @@ moves_loop: // When in check search starts from here assert(is_ok(move)); givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates() - ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move) + ? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move) : pos.gives_check(move); moveCount++; @@ -1375,7 +1380,7 @@ moves_loop: // When in check search starts from here CapturePieceToHistory& captureHistory = pos.this_thread()->captureHistory; Piece moved_piece = pos.moved_piece(move); PieceType captured = type_of(pos.piece_on(to_sq(move))); - captureHistory.update(moved_piece,to_sq(move), captured, bonus); + captureHistory.update(moved_piece, to_sq(move), captured, bonus); // Decrease all the other played capture moves for (int i = 0; i < captureCnt; ++i)