X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=2720edb373d8bba025b51cb431e160240d8f9fd8;hp=48cb4d6bdd9df3a36bacff4d04b3ce0dfd5dac34;hb=3d937e1e901c59c04cd5d602c05f72892222ded8;hpb=103b368ab7f5fd696e0c6925917344d15a3c2d9c diff --git a/src/search.cpp b/src/search.cpp index 48cb4d6b..2720edb3 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -249,7 +249,6 @@ void Search::think() { static Book book; // Defined static to initialize the PRNG only once - Move bm; Position& pos = RootPosition; Chess960 = pos.is_chess960(); elapsed_time(true); @@ -266,12 +265,15 @@ void Search::think() { goto finalize; } - if ( Options["OwnBook"] - && (bm = book.probe(pos, Options["Book File"], Options["Best Book Move"])) != MOVE_NONE - && count(RootMoves.begin(), RootMoves.end(), bm)) + if (Options["OwnBook"]) { - std::swap(RootMoves[0], *find(RootMoves.begin(), RootMoves.end(), bm)); - goto finalize; + Move bookMove = book.probe(pos, Options["Book File"], Options["Best Book Move"]); + + if (bookMove && count(RootMoves.begin(), RootMoves.end(), bookMove)) + { + std::swap(RootMoves[0], *find(RootMoves.begin(), RootMoves.end(), bookMove)); + goto finalize; + } } // Read UCI options: GUI could change UCI parameters during the game @@ -542,7 +544,7 @@ namespace { const bool RootNode = (NT == Root || NT == SplitPointRoot); assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE); - assert(PvNode == (alpha != beta - 1)); + assert((alpha == beta - 1) || PvNode); assert(depth > DEPTH_ZERO); assert(pos.thread() >= 0 && pos.thread() < Threads.size()); @@ -587,6 +589,10 @@ namespace { } // Step 2. Check for aborted search and immediate draw + // Enforce node limit here. FIXME: This only works with 1 search thread. + if (Limits.maxNodes && pos.nodes_searched() >= Limits.maxNodes) + Signals.stop = true; + if (( Signals.stop || pos.is_draw() || ss->ply > MAX_PLY) && !RootNode) @@ -769,6 +775,7 @@ namespace { Depth rdepth = depth - ONE_PLY - 3 * ONE_PLY; assert(rdepth >= ONE_PLY); + assert((ss-1)->currentMove != MOVE_NONE); MovePicker mp(pos, ttMove, H, pos.captured_piece_type()); CheckInfo ci(pos); @@ -776,6 +783,7 @@ namespace { while ((move = mp.next_move()) != MOVE_NONE) if (pos.pl_move_is_legal(move, ci.pinned)) { + ss->currentMove = move; pos.do_move(move, st, ci, pos.move_gives_check(move, ci)); value = -search(pos, ss+1, -rbeta, -rbeta+1, rdepth); pos.undo_move(move); @@ -814,7 +822,7 @@ split_point_start: // At split points actual search starts from here && tte->depth() >= depth - 3 * ONE_PLY; if (SpNode) { - lock_grab(&(sp->lock)); + lock_grab(sp->lock); bestValue = sp->bestValue; moveCount = sp->moveCount; @@ -846,7 +854,7 @@ split_point_start: // At split points actual search starts from here if (SpNode) { moveCount = ++sp->moveCount; - lock_release(&(sp->lock)); + lock_release(sp->lock); } else moveCount++; @@ -917,7 +925,7 @@ split_point_start: // At split points actual search starts from here && (!threatMove || !connected_threat(pos, move, threatMove))) { if (SpNode) - lock_grab(&(sp->lock)); + lock_grab(sp->lock); continue; } @@ -932,7 +940,7 @@ split_point_start: // At split points actual search starts from here if (futilityValue < beta) { if (SpNode) - lock_grab(&(sp->lock)); + lock_grab(sp->lock); continue; } @@ -942,7 +950,7 @@ split_point_start: // At split points actual search starts from here && pos.see_sign(move) < 0) { if (SpNode) - lock_grab(&(sp->lock)); + lock_grab(sp->lock); continue; } @@ -964,7 +972,7 @@ split_point_start: // At split points actual search starts from here // Step 15. Reduced depth search (LMR). If the move fails high will be // re-searched at full depth. - if ( depth > 3 * ONE_PLY + if ( depth > 4 * ONE_PLY && !isPvMove && !captureOrPromotion && !dangerous @@ -973,11 +981,10 @@ split_point_start: // At split points actual search starts from here && ss->killers[1] != move) { ss->reduction = reduction(depth, moveCount); - Depth d = newDepth - ss->reduction; + Depth d = std::max(newDepth - ss->reduction, ONE_PLY); alpha = SpNode ? sp->alpha : alpha; - value = d < ONE_PLY ? -qsearch(pos, ss+1, -(alpha+1), -alpha, DEPTH_ZERO) - : - search(pos, ss+1, -(alpha+1), -alpha, d); + value = -search(pos, ss+1, -(alpha+1), -alpha, d); doFullDepthSearch = (value > alpha && ss->reduction != DEPTH_ZERO); ss->reduction = DEPTH_ZERO; @@ -1008,12 +1015,12 @@ split_point_start: // At split points actual search starts from here // Step 18. Check for new best move if (SpNode) { - lock_grab(&(sp->lock)); + lock_grab(sp->lock); bestValue = sp->bestValue; alpha = sp->alpha; } - // Finished searching the move. If StopRequest is true, the search + // Finished searching the move. If Signals.stop is true, the search // was aborted because the user interrupted the search or because we // ran out of time. In this case, the return value of the search cannot // be trusted, and we don't update the best move and/or PV. @@ -1074,7 +1081,7 @@ split_point_start: // At split points actual search starts from here // Step 20. Check for mate and stalemate // All legal moves have been searched and if there are no legal moves, it // must be mate or stalemate. Note that we can have a false positive in - // case of StopRequest or thread.cutoff_occurred() are set, but this is + // case of Signals.stop or thread.cutoff_occurred() are set, but this is // harmless because return value is discarded anyhow in the parent nodes. // If we are in a singular extension search then return a fail low score. if (!moveCount) @@ -1127,7 +1134,7 @@ split_point_start: // At split points actual search starts from here // Here we have the lock still grabbed sp->is_slave[pos.thread()] = false; sp->nodes += pos.nodes_searched(); - lock_release(&(sp->lock)); + lock_release(sp->lock); } assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1147,7 +1154,7 @@ split_point_start: // At split points actual search starts from here assert(NT == PV || NT == NonPV); assert(alpha >= -VALUE_INFINITE && alpha < beta && beta <= VALUE_INFINITE); - assert(PvNode == (alpha != beta - 1)); + assert((alpha == beta - 1) || PvNode); assert(depth <= DEPTH_ZERO); assert(pos.thread() >= 0 && pos.thread() < Threads.size()); @@ -1851,12 +1858,12 @@ void Thread::idle_loop(SplitPoint* sp) { } // Grab the lock to avoid races with Thread::wake_up() - lock_grab(&sleepLock); + lock_grab(sleepLock); // If we are master and all slaves have finished don't go to sleep if (sp && Threads.split_point_finished(sp)) { - lock_release(&sleepLock); + lock_release(sleepLock); break; } @@ -1865,9 +1872,9 @@ void Thread::idle_loop(SplitPoint* sp) { // in the meanwhile, allocated us and sent the wake_up() call before we // had the chance to grab the lock. if (do_sleep || !is_searching) - cond_wait(&sleepCond, &sleepLock); + cond_wait(sleepCond, sleepLock); - lock_release(&sleepLock); + lock_release(sleepLock); } // If this thread has been assigned work, launch a search @@ -1910,8 +1917,8 @@ void Thread::idle_loop(SplitPoint* sp) { { // Because sp->is_slave[] is reset under lock protection, // be sure sp->lock has been released before to return. - lock_grab(&(sp->lock)); - lock_release(&(sp->lock)); + lock_grab(sp->lock); + lock_release(sp->lock); return; } } @@ -1944,7 +1951,6 @@ void check_time() { || stillAtFirstMove; if ( (Limits.use_time_management() && noMoreTime) - || (Limits.maxTime && e >= Limits.maxTime) - /* missing nodes limit */ ) // FIXME + || (Limits.maxTime && e >= Limits.maxTime)) Signals.stop = true; }