X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=50dfcc0ced1dc210acb6bf8cb23ffe9c7e6458e7;hp=c2168bbbddd6171ed6632798d1f779e23dfa3b5c;hb=72760c05c64d1fb2bb71c2ac54acfbeecf513b87;hpb=fca0a2dd881e6bde0a01d3342dd385600e01730b diff --git a/src/search.cpp b/src/search.cpp index c2168bbb..50dfcc0c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -243,9 +243,6 @@ namespace { template Value qsearch(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth); - template - Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool* dangerous); - bool check_is_dangerous(Position &pos, Move move, Value futilityBase, Value beta, Value *bValue); bool connected_moves(const Position& pos, Move m1, Move m2); Value value_to_tt(Value v, int ply); @@ -285,6 +282,51 @@ namespace { return os; } + // extension() decides whether a move should be searched with normal depth, + // or with extended depth. Certain classes of moves (checking moves, in + // particular) are searched with bigger depth than ordinary moves and in + // any case are marked as 'dangerous'. Note that also if a move is not + // extended, as example because the corresponding UCI option is set to zero, + // the move is marked as 'dangerous' so, at least, we avoid to prune it. + template + FORCE_INLINE Depth extension(const Position& pos, Move m, bool captureOrPromotion, + bool moveIsCheck, bool* dangerous) { + assert(m != MOVE_NONE); + + Depth result = DEPTH_ZERO; + *dangerous = moveIsCheck; + + if (moveIsCheck && pos.see_sign(m) >= 0) + result += CheckExtension[PvNode]; + + if (pos.type_of_piece_on(move_from(m)) == PAWN) + { + Color c = pos.side_to_move(); + if (relative_rank(c, move_to(m)) == RANK_7) + { + result += PawnPushTo7thExtension[PvNode]; + *dangerous = true; + } + if (pos.pawn_is_passed(c, move_to(m))) + { + result += PassedPawnExtension[PvNode]; + *dangerous = true; + } + } + + if ( captureOrPromotion + && pos.type_of_piece_on(move_to(m)) != PAWN + && ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) + - pos.midgame_value_of_piece_on(move_to(m)) == VALUE_ZERO) + && !move_is_special(m)) + { + result += PawnEndgameExtension[PvNode]; + *dangerous = true; + } + + return Min(result, ONE_PLY); + } + } // namespace @@ -685,7 +727,7 @@ namespace { Value refinedValue, nullValue, futilityBase, futilityValueScaled; // Non-PV specific bool isPvMove, inCheck, singularExtensionNode, givesCheck, captureOrPromotion, dangerous; int moveCount = 0, playedMoveCount = 0; - int threadID = pos.thread(); + Thread& thread = Threads[pos.thread()]; SplitPoint* sp = NULL; refinedValue = bestValue = value = -VALUE_INFINITE; @@ -694,8 +736,8 @@ namespace { ss->ply = (ss-1)->ply + 1; // Used to send selDepth info to GUI - if (PvNode && Threads[threadID].maxPly < ss->ply) - Threads[threadID].maxPly = ss->ply; + if (PvNode && thread.maxPly < ss->ply) + thread.maxPly = ss->ply; if (SpNode) { @@ -713,7 +755,7 @@ namespace { (ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO; (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE; - if (threadID == 0 && ++NodesSincePoll > NodesBetweenPolls) + if (pos.thread() == 0 && ++NodesSincePoll > NodesBetweenPolls) { NodesSincePoll = 0; poll(pos); @@ -721,8 +763,7 @@ namespace { // Step 2. Check for aborted search and immediate draw if (( StopRequest - || Threads[threadID].cutoff_occurred() - || pos.is_draw() + || pos.is_draw() || ss->ply > PLY_MAX) && !RootNode) return VALUE_DRAW; @@ -744,10 +785,8 @@ namespace { // At PV nodes we check for exact scores, while at non-PV nodes we check for // a fail high/low. Biggest advantage at probing at PV nodes is to have a // smooth experience in analysis mode. - if ( !RootNode - && tte - && (PvNode ? tte->depth() >= depth && tte->type() == VALUE_TYPE_EXACT - : ok_to_use_TT(tte, depth, beta, ss->ply))) + if (tte && (PvNode ? tte->depth() >= depth && tte->type() == VALUE_TYPE_EXACT + : ok_to_use_TT(tte, depth, beta, ss->ply))) { TT.refresh(tte); ss->bestMove = ttMove; // Can be MOVE_NONE @@ -933,7 +972,7 @@ split_point_start: // At split points actual search starts from here // Loop through all pseudo-legal moves until no moves remain or a beta cutoff occurs while ( bestValue < beta && (move = mp.get_next_move()) != MOVE_NONE - && !Threads[threadID].cutoff_occurred()) + && !thread.cutoff_occurred()) { assert(move_is_ok(move)); @@ -1095,7 +1134,7 @@ split_point_start: // At split points actual search starts from here bool doFullDepthSearch = true; alpha = SpNode ? sp->alpha : alpha; - if ( depth >= 3 * ONE_PLY + if ( depth > 3 * ONE_PLY && !captureOrPromotion && !dangerous && !move_is_castle(move) @@ -1142,7 +1181,7 @@ split_point_start: // At split points actual search starts from here alpha = sp->alpha; } - if (value > bestValue && !(SpNode && Threads[threadID].cutoff_occurred())) + if (value > bestValue && !(SpNode && thread.cutoff_occurred())) { bestValue = value; @@ -1214,9 +1253,9 @@ split_point_start: // At split points actual search starts from here && !SpNode && depth >= Threads.min_split_depth() && bestValue < beta - && Threads.available_slave_exists(threadID) + && Threads.available_slave_exists(pos.thread()) && !StopRequest - && !Threads[threadID].cutoff_occurred()) + && !thread.cutoff_occurred()) Threads.split(pos, ss, &alpha, beta, &bestValue, depth, threatMove, moveCount, &mp, PvNode); } @@ -1231,7 +1270,7 @@ split_point_start: // At split points actual search starts from here // Step 21. Update tables // If the search is not aborted, update the transposition table, // history counters, and killer moves. - if (!SpNode && !StopRequest && !Threads[threadID].cutoff_occurred()) + if (!SpNode && !StopRequest && !thread.cutoff_occurred()) { move = bestValue <= oldAlpha ? MOVE_NONE : ss->bestMove; vt = bestValue <= oldAlpha ? VALUE_TYPE_UPPER @@ -1256,7 +1295,7 @@ split_point_start: // At split points actual search starts from here if (SpNode) { // Here we have the lock still grabbed - sp->is_slave[threadID] = false; + sp->is_slave[pos.thread()] = false; sp->nodes += pos.nodes_searched(); lock_release(&(sp->lock)); } @@ -1294,7 +1333,7 @@ split_point_start: // At split points actual search starts from here ss->ply = (ss-1)->ply + 1; // Check for an instant draw or maximum ply reached - if (ss->ply > PLY_MAX || pos.is_draw()) + if (pos.is_draw() || ss->ply > PLY_MAX) return VALUE_DRAW; // Decide whether or not to include checks, this fixes also the type of @@ -1333,8 +1372,6 @@ split_point_start: // At split points actual search starts from here else ss->eval = bestValue = evaluate(pos, evalMargin); - update_gains(pos, (ss-1)->currentMove, (ss-1)->eval, ss->eval); - // Stand pat. Return immediately if static value is at least beta if (bestValue >= beta) { @@ -1356,7 +1393,7 @@ split_point_start: // At split points actual search starts from here // 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. - MovePicker mp(pos, ttMove, depth, H); + MovePicker mp(pos, ttMove, depth, H, move_to((ss-1)->currentMove)); CheckInfo ci(pos); Bitboard pinned = pos.pinned_pieces(pos.side_to_move()); @@ -1608,53 +1645,6 @@ split_point_start: // At split points actual search starts from here } - // extension() decides whether a move should be searched with normal depth, - // or with extended depth. Certain classes of moves (checking moves, in - // particular) are searched with bigger depth than ordinary moves and in - // any case are marked as 'dangerous'. Note that also if a move is not - // extended, as example because the corresponding UCI option is set to zero, - // the move is marked as 'dangerous' so, at least, we avoid to prune it. - template - Depth extension(const Position& pos, Move m, bool captureOrPromotion, - bool moveIsCheck, bool* dangerous) { - - assert(m != MOVE_NONE); - - Depth result = DEPTH_ZERO; - *dangerous = moveIsCheck; - - if (moveIsCheck && pos.see_sign(m) >= 0) - result += CheckExtension[PvNode]; - - if (pos.type_of_piece_on(move_from(m)) == PAWN) - { - Color c = pos.side_to_move(); - if (relative_rank(c, move_to(m)) == RANK_7) - { - result += PawnPushTo7thExtension[PvNode]; - *dangerous = true; - } - if (pos.pawn_is_passed(c, move_to(m))) - { - result += PassedPawnExtension[PvNode]; - *dangerous = true; - } - } - - if ( captureOrPromotion - && pos.type_of_piece_on(move_to(m)) != PAWN - && ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) - - pos.midgame_value_of_piece_on(move_to(m)) == VALUE_ZERO) - && !move_is_special(m)) - { - result += PawnEndgameExtension[PvNode]; - *dangerous = true; - } - - return Min(result, ONE_PLY); - } - - // connected_threat() tests whether it is safe to forward prune a move or if // is somehow connected to the threat move returned by null search. @@ -2027,7 +2017,7 @@ split_point_start: // At split points actual search starts from here && pos.move_is_pl(tte->move()) && pos.pl_move_is_legal(tte->move(), pos.pinned_pieces(pos.side_to_move())) && ply < PLY_MAX - && (!pos.is_draw() || ply < 2)) + && (!pos.is_draw() || ply < 2)) { pv[ply] = tte->move(); pos.do_move(pv[ply++], *st++);