X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=06cc9b60fc97155cf6687422ad5d2b8b2de1eb5b;hp=d93493c29d40757b0341f8523b23b8a68d4a450b;hb=24cc3a97a480afdd5587ab9b2d75c1426acc3133;hpb=9e4befe3f1ea324bece88aee2e97b38659411c52 diff --git a/src/search.cpp b/src/search.cpp index d93493c2..06cc9b60 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -916,7 +916,7 @@ namespace { else { if ( newDepth >= 3*OnePly - && i >= MultiPV + LMRPVMoves - 2 // Remove -2 and decrease LMRPVMoves instead ? + && i >= MultiPV + LMRPVMoves && !dangerous && !moveIsCapture && !move_is_promotion(move) @@ -1091,16 +1091,16 @@ namespace { // Initialize a MovePicker object for the current position, and prepare // to search all moves - MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]); - Move move, movesSearched[256]; int moveCount = 0; Value value, bestValue = -VALUE_INFINITE; - Bitboard dcCandidates = mp.discovered_check_candidates(); Color us = pos.side_to_move(); bool isCheck = pos.is_check(); bool mateThreat = pos.has_mate_threat(opposite_color(us)); + MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]); + Bitboard dcCandidates = mp.discovered_check_candidates(); + // Loop through all legal moves until no moves remain or a beta cutoff // occurs. while ( alpha < beta @@ -1109,7 +1109,7 @@ namespace { { assert(move_is_ok(move)); - bool singleReply = (isCheck && mp.number_of_moves() == 1); + bool singleReply = (isCheck && mp.number_of_evasions() == 1); bool moveIsCheck = pos.move_is_check(move, dcCandidates); bool moveIsCapture = pos.move_is_capture(move); @@ -1281,21 +1281,57 @@ namespace { bool mateThreat = false; bool isCheck = pos.is_check(); - bool useNullMove = ( allowNullmove - && depth > OnePly - && !isCheck - && !value_is_mate(beta) - && ok_to_do_nullmove(pos) - && approximateEval >= beta - NullMoveMargin); + // Null move search + if ( allowNullmove + && depth > OnePly + && !isCheck + && !value_is_mate(beta) + && ok_to_do_nullmove(pos) + && approximateEval >= beta - NullMoveMargin) + { + ss[ply].currentMove = MOVE_NULL; + + StateInfo st; + pos.do_null_move(st); + int R = (depth >= 5 * OnePly ? 4 : 3); // Null move dynamic reduction + + Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID); + + pos.undo_null_move(); + if (nullValue >= beta) + { + if (depth < 6 * OnePly) + return beta; + + // Do zugzwang verification search + Value v = search(pos, ss, beta, depth-5*OnePly, ply, false, threadID); + if (v >= beta) + return beta; + } else { + // The null move failed low, which means that we may be faced with + // some kind of threat. If the previous move was reduced, check if + // the move that refuted the null move was somehow connected to the + // move which was reduced. If a connection is found, return a fail + // low score (which will cause the reduced move to fail high in the + // parent node, which will trigger a re-search with full depth). + if (nullValue == value_mated_in(ply + 2)) + mateThreat = true; + + ss[ply].threatMove = ss[ply + 1].currentMove; + if ( depth < ThreatDepth + && ss[ply - 1].reduction + && connected_moves(pos, ss[ply - 1].currentMove, ss[ply].threatMove)) + return beta - 1; + } + } // Null move search not allowed, try razoring - if ( !useNullMove - && !value_is_mate(beta) - && depth < RazorDepth - && approximateEval < beta - RazorApprMargins[int(depth) - 2] - && ss[ply - 1].currentMove != MOVE_NULL - && ttMove == MOVE_NONE - && !pos.has_pawn_on_7th(pos.side_to_move())) + else if ( !value_is_mate(beta) + && depth < RazorDepth + && approximateEval < beta - RazorApprMargins[int(depth) - 2] + && ss[ply - 1].currentMove != MOVE_NULL + && ttMove == MOVE_NONE + && !pos.has_pawn_on_7th(pos.side_to_move())) { Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID); if (v < beta - RazorMargins[int(depth) - 2]) @@ -1312,7 +1348,7 @@ namespace { // Initialize a MovePicker object for the current position, and prepare // to search all moves. - MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply], useNullMove); + MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]); Move move, movesSearched[256]; int moveCount = 0; @@ -1328,51 +1364,9 @@ namespace { && (move = mp.get_next_move()) != MOVE_NONE && !thread_should_stop(threadID)) { - - // Null move search - if (move == MOVE_NULL) - { - ss[ply].currentMove = MOVE_NULL; - - StateInfo st; - pos.do_null_move(st); - int R = (depth >= 5 * OnePly ? 4 : 3); // Null move dynamic reduction - - Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID); - - pos.undo_null_move(); - - if (nullValue >= beta) - { - if (depth < 6 * OnePly) - return beta; - - // Do zugzwang verification search - Value v = search(pos, ss, beta, depth-5*OnePly, ply, false, threadID); - if (v >= beta) - return beta; - } else { - // The null move failed low, which means that we may be faced with - // some kind of threat. If the previous move was reduced, check if - // the move that refuted the null move was somehow connected to the - // move which was reduced. If a connection is found, return a fail - // low score (which will cause the reduced move to fail high in the - // parent node, which will trigger a re-search with full depth). - if (nullValue == value_mated_in(ply + 2)) - mateThreat = true; - - ss[ply].threatMove = ss[ply + 1].currentMove; - if ( depth < ThreatDepth - && ss[ply - 1].reduction - && connected_moves(pos, ss[ply - 1].currentMove, ss[ply].threatMove)) - return beta - 1; - } - continue; - } - assert(move_is_ok(move)); - bool singleReply = (isCheck && mp.number_of_moves() == 1); + bool singleReply = (isCheck && mp.number_of_evasions() == 1); bool moveIsCheck = pos.move_is_check(move, dcCandidates); bool moveIsCapture = pos.move_is_capture(move); @@ -1546,10 +1540,10 @@ namespace { // Use the cached evaluation score if possible assert(ei.futilityMargin == Value(0)); - staticValue = tte->value(); + staticValue = tte->value() + 7; } else - staticValue = evaluate(pos, ei, threadID); + staticValue = evaluate(pos, ei, threadID) + 7; if (ply == PLY_MAX - 1) return evaluate(pos, ei, threadID); @@ -2159,7 +2153,9 @@ namespace { // the second move is assumed to be a move from the current position. bool connected_moves(const Position& pos, Move m1, Move m2) { + Square f1, t1, f2, t2; + Piece p; assert(move_is_ok(m1)); assert(move_is_ok(m2)); @@ -2185,31 +2181,32 @@ namespace { return true; // Case 4: The destination square for m2 is attacked by the moving piece in m1 - if (pos.piece_attacks_square(pos.piece_on(t1), t1, t2)) + p = pos.piece_on(t1); + if (bit_is_set(pos.attacks_from(p, t1), t2)) return true; // Case 5: Discovered check, checking piece is the piece moved in m1 - if ( piece_is_slider(pos.piece_on(t1)) + if ( piece_is_slider(p) && bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), f2) - && !bit_is_set(squares_between(t2, pos.king_square(pos.side_to_move())), t2)) + && !bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), t2)) { Bitboard occ = pos.occupied_squares(); Color us = pos.side_to_move(); Square ksq = pos.king_square(us); clear_bit(&occ, f2); - if (pos.type_of_piece_on(t1) == BISHOP) + if (type_of_piece(p) == BISHOP) { if (bit_is_set(bishop_attacks_bb(ksq, occ), t1)) return true; } - else if (pos.type_of_piece_on(t1) == ROOK) + else if (type_of_piece(p) == ROOK) { if (bit_is_set(rook_attacks_bb(ksq, occ), t1)) return true; } else { - assert(pos.type_of_piece_on(t1) == QUEEN); + assert(type_of_piece(p) == QUEEN); if (bit_is_set(queen_attacks_bb(ksq, occ), t1)) return true; } @@ -2445,8 +2442,9 @@ namespace { n = Slowdown; for (i = 0; i < n; i++) { Square s = Square(i&63); - if (count_1s(pos.attacks_to(s)) > 63) - std::cout << "This can't happen, but I put this string here anyway, in order to prevent the compiler from optimizing away the useless computation." << std::endl; + if (count_1s(pos.attackers_to(s)) > 63) + std::cout << "This can't happen, but I put this string here anyway, in order to " + "prevent the compiler from optimizing away the useless computation." << std::endl; } }