From: Fabian Fichter Date: Mon, 1 Jun 2020 08:53:27 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=ddd48695abe9a8559d1f8761162ba4329e80ce93;p=fairystockfish.git Merge official-stockfish/master bench: 4968875 --- ddd48695abe9a8559d1f8761162ba4329e80ce93 diff --cc src/endgame.cpp index 14ef2d4,74e16fa..5bc23c2 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@@ -163,15 -136,8 +163,15 @@@ Value Endgame::operator()(const Po || pos.count(strongSide) ||(pos.count(strongSide) && pos.count(strongSide)) || ( (pos.pieces(strongSide, BISHOP) & ~DarkSquares) - && (pos.pieces(strongSide, BISHOP) & DarkSquares))) + && (pos.pieces(strongSide, BISHOP) & DarkSquares)) + || pos.count(strongSide) >= 2 + ||(pos.count(strongSide) && pos.count(strongSide)) + ||(pos.count(strongSide) && pos.count(strongSide)) + ||(pos.count(strongSide) && pos.count(strongSide) >= 2) + ||(pos.count(strongSide) >= 3 + && ( DarkSquares & pos.pieces(strongSide, FERS)) + && (~DarkSquares & pos.pieces(strongSide, FERS)))) - result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1); + result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1); return strongSide == pos.side_to_move() ? result : -result; } @@@ -194,9 -160,9 +194,9 @@@ Value Endgame::operator()(const P Value result = VALUE_KNOWN_WIN + PushClose[distance(winnerKSq, loserKSq)] - + PushToCorners[opposite_colors(bishopSq, SQ_A1) ? ~loserKSq : loserKSq]; + + PushToCorners[map_to_standard_board(pos, relative_square(opposite_colors(bishopSq, SQ_A1) ? BLACK : WHITE, loserKSq, pos.max_rank()))]; - assert(abs(result) < VALUE_MATE_IN_MAX_PLY); + assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY); return strongSide == pos.side_to_move() ? result : -result; } @@@ -362,9 -318,9 +363,9 @@@ Value Endgame::operator()(const assert(verify_material(pos, strongSide, 2 * KnightValueMg, 0)); assert(verify_material(pos, weakSide, VALUE_ZERO, 1)); - Value result = 2 * KnightValueEg - - PawnValueEg - + PushToEdges[map_to_standard_board(pos, pos.square(weakSide))]; + Value result = PawnValueEg - + 2 * PushToEdges[pos.square(weakSide)] ++ + 2 * PushToEdges[map_to_standard_board(pos, pos.square(weakSide))] + - 10 * relative_rank(weakSide, pos.square(weakSide)); return strongSide == pos.side_to_move() ? result : -result; } @@@ -374,150 -330,6 +375,150 @@@ template<> Value Endgame::operator()(const Position&) const { return VALUE_DRAW; } +/// KFsPs vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = pos.non_pawn_material(strongSide) + + pos.count(strongSide) * PawnValueEg + + PushToEdges[map_to_standard_board(pos, loserKSq)] + + PushClose[distance(winnerKSq, loserKSq)]; + + if ( pos.count(strongSide) >= 3 + && ( DarkSquares & pos.pieces(strongSide, FERS)) + && (~DarkSquares & pos.pieces(strongSide, FERS))) - result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1); ++ result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1); + else if (pos.count(strongSide) + pos.count(strongSide) < 3) + return VALUE_DRAW; + else + { + bool dark = DarkSquares & pos.pieces(strongSide, FERS); + bool light = ~DarkSquares & pos.pieces(strongSide, FERS); + + // Determine the color of ferzes from promoting pawns + Bitboard b = pos.pieces(strongSide, PAWN); + while (b && (!dark || !light)) + { + if (file_of(pop_lsb(&b)) % 2 != relative_rank(strongSide, pos.promotion_rank(), pos.max_rank()) % 2) + light = true; + else + dark = true; + } + if (!dark || !light) + return VALUE_DRAW; // we can not checkmate with same colored ferzes + } + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// Mate with KNS vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg, 0)); + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = VALUE_KNOWN_WIN + + PushClose[distance(winnerKSq, loserKSq)] + + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// KNF vs K. Can only be won if the weaker side's king +/// is close to a corner of the same color as the fers. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, KnightValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + Square fersSq = pos.square(strongSide); + + // tries to drive toward corners A1 or H8. If we have a + // fers that cannot reach the above squares, we flip the kings in order + // to drive the enemy toward corners A8 or H1. + if (opposite_colors(fersSq, SQ_A1)) + { + winnerKSq = relative_square(BLACK, winnerKSq, pos.max_rank()); + loserKSq = relative_square(BLACK, loserKSq, pos.max_rank()); + } + + Value result = Value(PushClose[distance(winnerKSq, loserKSq)]) + + (PushToCorners[map_to_standard_board(pos, loserKSq)] - 3000) / 10; + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// KNSFKR vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, RookValueMg, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = KnightValueEg + SilverValueEg + FersValueEg - RookValueEg + + PushClose[distance(winnerKSq, loserKSq)] + + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// Mate with KSF vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = VALUE_KNOWN_WIN + + PushClose[distance(winnerKSq, loserKSq)] + + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// Mate with KSF vs KF. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, FersValueMg, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + Square fersSq = pos.square(weakSide); + + Value result = SilverValueEg + + PushClose[distance(winnerKSq, loserKSq)] + + PushAway[distance(fersSq, loserKSq)] + + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; + + return strongSide == pos.side_to_move() ? result : -result; +} + + /// KB and one or more pawns vs K. It checks for draws with rook pawns and /// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW /// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling diff --cc src/search.cpp index c99b510,c3ebf9a..0233446 --- a/src/search.cpp +++ b/src/search.cpp @@@ -960,10 -891,9 +961,10 @@@ namespace // much above beta, we can (almost) safely prune the previous move. if ( !PvNode && depth >= 5 + && (pos.pieces() ^ pos.pieces(CLOBBER_PIECE)) - && abs(beta) < VALUE_MATE_IN_MAX_PLY) + && abs(beta) < VALUE_TB_WIN_IN_MAX_PLY) { - Value raisedBeta = std::min(beta + 189 - 45 * improving, VALUE_INFINITE); + Value raisedBeta = std::min(beta + (189 + 20 * !!pos.capture_the_flag_piece()) * (1 + pos.check_counting() + (pos.extinction_value() != VALUE_NONE)) - 45 * improving, VALUE_INFINITE); MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &thisThread->captureHistory); int probCutCount = 0; @@@ -1066,16 -996,14 +1067,16 @@@ moves_loop: // When in check, search st // Step 13. Pruning at shallow depth (~200 Elo) if ( !rootNode - && pos.non_pawn_material(us) + && (pos.non_pawn_material(us) || !(pos.pieces(us) ^ pos.pieces(us, PAWN))) - && bestValue > VALUE_MATED_IN_MAX_PLY) + && bestValue > VALUE_TB_LOSS_IN_MAX_PLY) { // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold - moveCountPruning = moveCount >= futility_move_count(improving, depth); + moveCountPruning = moveCount >= futility_move_count(improving, depth) + || (pos.must_capture() && (moveCountPruning || (pos.capture(move) && pos.legal(move)))); if ( !captureOrPromotion - && !givesCheck) + && !givesCheck + && (!pos.must_capture() || !pos.attackers_to(to_sq(move), ~us))) { // Reduced depth of the next LMR search int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), 0);