X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=4745da0210a921112852c3a3cb69192200660481;hp=04e4dded86474e507fd88974648e01888ea1d37b;hb=c8773c720af6fd5c3a8f84550ee36e5eb89f929e;hpb=4b53bb02f69bd838b271b7919d1070580d6f73a7 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 04e4dded..4745da02 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -58,15 +58,17 @@ namespace { // weights read from UCI parameters. The purpose is to be able to change // the evaluation weights while keeping the default values of the UCI // parameters at 100, which looks prettier. - const int WeightMobilityMidgameInternal = 0x100; - const int WeightMobilityEndgameInternal = 0x100; - const int WeightPawnStructureMidgameInternal = 0x100; - const int WeightPawnStructureEndgameInternal = 0x100; - const int WeightPassedPawnsMidgameInternal = 0x100; - const int WeightPassedPawnsEndgameInternal = 0x100; - const int WeightKingSafetyInternal = 0x110; - const int WeightKingOppSafetyInternal = 0x110; - const int WeightSpaceInternal = 0x30; + // + // Values modified by Joona Kiiski + const int WeightMobilityMidgameInternal = 0x0FA; + const int WeightMobilityEndgameInternal = 0x10A; + const int WeightPawnStructureMidgameInternal = 0x0EC; + const int WeightPawnStructureEndgameInternal = 0x0CD; + const int WeightPassedPawnsMidgameInternal = 0x108; + const int WeightPassedPawnsEndgameInternal = 0x109; + const int WeightKingSafetyInternal = 0x0F7; + const int WeightKingOppSafetyInternal = 0x101; + const int WeightSpaceInternal = 0x02F; // Visually better to define tables constants typedef Value V; @@ -167,18 +169,19 @@ namespace { V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0) // 8 }; - // Bonus for unstoppable passed pawns: + // Bonus for unstoppable passed pawns const Value UnstoppablePawnValue = Value(0x500); - // Rooks and queens on the 7th rank: - const Value MidgameRookOn7thBonus = Value(50); - const Value EndgameRookOn7thBonus = Value(100); - const Value MidgameQueenOn7thBonus = Value(25); - const Value EndgameQueenOn7thBonus = Value(50); + // Rooks and queens on the 7th rank + const Value MidgameRookOn7thBonus = Value(47); + const Value EndgameRookOn7thBonus = Value(98); + const Value MidgameQueenOn7thBonus = Value(27); + const Value EndgameQueenOn7thBonus = Value(54); - // Rooks on open files: - const Value RookOpenFileBonus = Value(40); - const Value RookHalfOpenFileBonus = Value(20); + + // Rooks on open files + const Value RookOpenFileBonus = Value(43); + const Value RookHalfOpenFileBonus = Value(19); // Penalty for rooks trapped inside a friendly king which has lost the // right to castle: @@ -272,11 +275,11 @@ namespace { uint8_t BitCount8Bit[256]; // Function prototypes - void evaluate_knight(const Position &p, Square s, Color us, EvalInfo &ei); - void evaluate_bishop(const Position &p, Square s, Color us, EvalInfo &ei); - void evaluate_rook(const Position &p, Square s, Color us, EvalInfo &ei); - void evaluate_queen(const Position &p, Square s, Color us, EvalInfo &ei); - void evaluate_king(const Position &p, Square s, Color us, EvalInfo &ei); + template + void evaluate_pieces(const Position& p, Color us, EvalInfo& ei); + + template<> + void evaluate_pieces(const Position& p, Color us, EvalInfo &ei); void evaluate_passed_pawns(const Position &pos, EvalInfo &ei); void evaluate_trapped_bishop_a7h7(const Position &pos, Square s, Color us, @@ -286,7 +289,6 @@ namespace { void evaluate_space(const Position &p, Color us, EvalInfo &ei); inline Value apply_weight(Value v, int w); - Value scale_by_game_phase(Value mv, Value ev, Phase ph, const ScaleFactor sf[]); int count_1s_8bit(Bitboard b); @@ -352,52 +354,22 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) { // Evaluate pieces for (Color c = WHITE; c <= BLACK; c++) { - // Knights - for (int i = 0; i < pos.piece_count(c, KNIGHT); i++) - evaluate_knight(pos, pos.piece_list(c, KNIGHT, i), c, ei); - - // Bishops - for (int i = 0; i < pos.piece_count(c, BISHOP); i++) - evaluate_bishop(pos, pos.piece_list(c, BISHOP, i), c, ei); - - // Rooks - for (int i = 0; i < pos.piece_count(c, ROOK); i++) - evaluate_rook(pos, pos.piece_list(c, ROOK, i), c, ei); - - // Queens - for(int i = 0; i < pos.piece_count(c, QUEEN); i++) - evaluate_queen(pos, pos.piece_list(c, QUEEN, i), c, ei); - - // Special pattern: trapped bishops on a7/h7/a2/h2 - Bitboard b = pos.bishops(c) & MaskA7H7[c]; - while (b) - { - Square s = pop_1st_bit(&b); - evaluate_trapped_bishop_a7h7(pos, s, c, ei); - } - - // Special pattern: trapped bishops on a1/h1/a8/h8 in Chess960: - if (Chess960) - { - b = pos.bishops(c) & MaskA1H1[c]; - while (b) - { - Square s = pop_1st_bit(&b); - evaluate_trapped_bishop_a1h1(pos, s, c, ei); - } - } - - // Sum up all attacked squares - ei.attackedBy[c][0] = ei.attackedBy[c][PAWN] | ei.attackedBy[c][KNIGHT] - | ei.attackedBy[c][BISHOP] | ei.attackedBy[c][ROOK] - | ei.attackedBy[c][QUEEN] | ei.attackedBy[c][KING]; + evaluate_pieces(pos, c, ei); + evaluate_pieces(pos, c, ei); + evaluate_pieces(pos, c, ei); + evaluate_pieces(pos, c, ei); + + // Sum up all attacked squares + ei.attackedBy[c][0] = ei.attackedBy[c][PAWN] | ei.attackedBy[c][KNIGHT] + | ei.attackedBy[c][BISHOP] | ei.attackedBy[c][ROOK] + | ei.attackedBy[c][QUEEN] | ei.attackedBy[c][KING]; } // Kings. Kings are evaluated after all other pieces for both sides, // because we need complete attack information for all pieces when computing // the king safety evaluation. for (Color c = WHITE; c <= BLACK; c++) - evaluate_king(pos, pos.king_square(c), c, ei); + evaluate_pieces(pos, c, ei); // Evaluate passed pawns. We evaluate passed pawns for both sides at once, // because we need to know which side promotes first in positions where @@ -555,6 +527,22 @@ void read_weights(Color us) { } +/// scale_by_game_phase() interpolates between a middle game and an endgame +/// score, based on game phase. It also scales the return value by a +/// ScaleFactor array. + +Value scale_by_game_phase(Value mv, Value ev, Phase ph, const ScaleFactor sf[]) { + + assert(mv > -VALUE_INFINITE && mv < VALUE_INFINITE); + assert(ev > -VALUE_INFINITE && ev < VALUE_INFINITE); + assert(ph >= PHASE_ENDGAME && ph <= PHASE_MIDGAME); + + ev = apply_scale_factor(ev, sf[(ev > Value(0) ? WHITE : BLACK)]); + + Value result = Value(int((mv * ph + ev * (128 - ph)) / 128)); + return Value(int(result) & ~(GrainSize - 1)); +} + namespace { // evaluate_common() computes terms common to all pieces attack @@ -616,109 +604,102 @@ namespace { } - // evaluate_knight() assigns bonuses and penalties to a knight of a given - // color on a given square. + // evaluate_pieces<>() assigns bonuses and penalties to the pieces of a given + // color. - void evaluate_knight(const Position& p, Square s, Color us, EvalInfo& ei) { + template + void evaluate_pieces(const Position& pos, Color us, EvalInfo& ei) { - // Attacks, mobility and outposts - evaluate_common(p, p.piece_attacks(s), us, ei, s); - } + Bitboard b; + Square s, ksq; + Color them; + int mob; + File f; + for (int i = 0, e = pos.piece_count(us, Piece); i < e; i++) + { + s = pos.piece_list(us, Piece, i); - // evaluate_bishop() assigns bonuses and penalties to a bishop of a given - // color on a given square. + if (Piece == KNIGHT || Piece == QUEEN) + b = pos.piece_attacks(s); + else if (Piece == BISHOP) + b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.queens(us)); + else if (Piece == ROOK) + b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.rooks_and_queens(us)); - void evaluate_bishop(const Position& p, Square s, Color us, EvalInfo& ei) { + // Attacks, mobility and outposts + mob = evaluate_common(pos, b, us, ei, s); - Bitboard b = bishop_attacks_bb(s, p.occupied_squares() & ~p.queens(us)); + // Special patterns: trapped bishops on a7/h7/a2/h2 + // and trapped bishops on a1/h1/a8/h8 in Chess960. + if (Piece == BISHOP) + { + if (bit_is_set(MaskA7H7[us], s)) + evaluate_trapped_bishop_a7h7(pos, s, us, ei); - // Attacks, mobility and outposts - evaluate_common(p, b, us, ei, s); - } + if (Chess960 && bit_is_set(MaskA1H1[us], s)) + evaluate_trapped_bishop_a1h1(pos, s, us, ei); + } + if (Piece != ROOK && Piece != QUEEN) + continue; - // evaluate_rook() assigns bonuses and penalties to a rook of a given - // color on a given square. + // Queen or rook on 7th rank + them = opposite_color(us); - void evaluate_rook(const Position& p, Square s, Color us, EvalInfo& ei) { + if ( relative_rank(us, s) == RANK_7 + && relative_rank(us, pos.king_square(them)) == RANK_8) + { + ei.mgValue += Sign[us] * (Piece == ROOK ? MidgameRookOn7thBonus : MidgameQueenOn7thBonus); + ei.egValue += Sign[us] * (Piece == ROOK ? EndgameRookOn7thBonus : EndgameQueenOn7thBonus); + } - Bitboard b = rook_attacks_bb(s, p.occupied_squares() & ~p.rooks_and_queens(us)); + // Special extra evaluation for rooks + if (Piece != ROOK) + continue; - // Attacks and mobility - int mob = evaluate_common(p, b, us, ei); + // Open and half-open files + f = square_file(s); + if (ei.pi->file_is_half_open(us, f)) + { + if (ei.pi->file_is_half_open(them, f)) + { + ei.mgValue += Sign[us] * RookOpenFileBonus; + ei.egValue += Sign[us] * RookOpenFileBonus; + } + else + { + ei.mgValue += Sign[us] * RookHalfOpenFileBonus; + ei.egValue += Sign[us] * RookHalfOpenFileBonus; + } + } - // Rook on 7th rank - Color them = opposite_color(us); + // Penalize rooks which are trapped inside a king. Penalize more if + // king has lost right to castle. + if (mob > 6 || ei.pi->file_is_half_open(us, f)) + continue; - if ( relative_rank(us, s) == RANK_7 - && relative_rank(us, p.king_square(them)) == RANK_8) - { - ei.mgValue += Sign[us] * MidgameRookOn7thBonus; - ei.egValue += Sign[us] * EndgameRookOn7thBonus; - } + ksq = pos.king_square(us); - // Open and half-open files - File f = square_file(s); - if (ei.pi->file_is_half_open(us, f)) - { - if (ei.pi->file_is_half_open(them, f)) + if ( square_file(ksq) >= FILE_E + && square_file(s) > square_file(ksq) + && (relative_rank(us, ksq) == RANK_1 || square_rank(ksq) == square_rank(s))) { - ei.mgValue += Sign[us] * RookOpenFileBonus; - ei.egValue += Sign[us] * RookOpenFileBonus; + // Is there a half-open file between the king and the edge of the board? + if (!ei.pi->has_open_file_to_right(us, square_file(ksq))) + ei.mgValue -= pos.can_castle(us)? Sign[us] * ((TrappedRookPenalty - mob * 16) / 2) + : Sign[us] * (TrappedRookPenalty - mob * 16); } - else + else if ( square_file(ksq) <= FILE_D + && square_file(s) < square_file(ksq) + && (relative_rank(us, ksq) == RANK_1 || square_rank(ksq) == square_rank(s))) { - ei.mgValue += Sign[us] * RookHalfOpenFileBonus; - ei.egValue += Sign[us] * RookHalfOpenFileBonus; + // Is there a half-open file between the king and the edge of the board? + if (!ei.pi->has_open_file_to_left(us, square_file(ksq))) + ei.mgValue -= pos.can_castle(us)? Sign[us] * ((TrappedRookPenalty - mob * 16) / 2) + : Sign[us] * (TrappedRookPenalty - mob * 16); } } - - // Penalize rooks which are trapped inside a king. Penalize more if - // king has lost right to castle - if (mob > 6 || ei.pi->file_is_half_open(us, f)) - return; - - Square ksq = p.king_square(us); - - if ( square_file(ksq) >= FILE_E - && square_file(s) > square_file(ksq) - && (relative_rank(us, ksq) == RANK_1 || square_rank(ksq) == square_rank(s))) - { - // Is there a half-open file between the king and the edge of the board? - if (!ei.pi->has_open_file_to_right(us, square_file(ksq))) - ei.mgValue -= p.can_castle(us)? Sign[us] * ((TrappedRookPenalty - mob * 16) / 2) - : Sign[us] * (TrappedRookPenalty - mob * 16); - } - else if ( square_file(ksq) <= FILE_D - && square_file(s) < square_file(ksq) - && (relative_rank(us, ksq) == RANK_1 || square_rank(ksq) == square_rank(s))) - { - // Is there a half-open file between the king and the edge of the board? - if (!ei.pi->has_open_file_to_left(us, square_file(ksq))) - ei.mgValue -= p.can_castle(us)? Sign[us] * ((TrappedRookPenalty - mob * 16) / 2) - : Sign[us] * (TrappedRookPenalty - mob * 16); - } - } - - - // evaluate_queen() assigns bonuses and penalties to a queen of a given - // color on a given square. - - void evaluate_queen(const Position& p, Square s, Color us, EvalInfo& ei) { - - // Attacks and mobility - evaluate_common(p, p.piece_attacks(s), us, ei); - - // Queen on 7th rank - Color them = opposite_color(us); - - if ( relative_rank(us, s) == RANK_7 - && relative_rank(us, p.king_square(them)) == RANK_8) - { - ei.mgValue += Sign[us] * MidgameQueenOn7thBonus; - ei.egValue += Sign[us] * EndgameQueenOn7thBonus; - } } inline Bitboard shiftRowsDown(const Bitboard& b, int num) { @@ -726,12 +707,14 @@ namespace { return b >> (num << 3); } - // evaluate_king() assigns bonuses and penalties to a king of a given - // color on a given square. + // evaluate_pieces() assigns bonuses and penalties to a king of a given + // color. - void evaluate_king(const Position& p, Square s, Color us, EvalInfo& ei) { + template<> + void evaluate_pieces(const Position& p, Color us, EvalInfo& ei) { int shelter = 0, sign = Sign[us]; + Square s = p.king_square(us); // King shelter if (relative_rank(us, s) <= RANK_4) @@ -918,7 +901,7 @@ namespace { { Square s = pop_1st_bit(&b); - assert(pos.piece_on(s) == pawn_of_color(us)); + assert(pos.piece_on(s) == piece_of_color_and_type(us, PAWN)); assert(pos.pawn_is_passed(us, s)); int r = int(relative_rank(us, s) - RANK_2); @@ -1069,12 +1052,12 @@ namespace { void evaluate_trapped_bishop_a7h7(const Position &pos, Square s, Color us, EvalInfo &ei) { assert(square_is_ok(s)); - assert(pos.piece_on(s) == bishop_of_color(us)); + assert(pos.piece_on(s) == piece_of_color_and_type(us, BISHOP)); Square b6 = relative_square(us, (square_file(s) == FILE_A) ? SQ_B6 : SQ_G6); Square b8 = relative_square(us, (square_file(s) == FILE_A) ? SQ_B8 : SQ_G8); - if ( pos.piece_on(b6) == pawn_of_color(opposite_color(us)) + if ( pos.piece_on(b6) == piece_of_color_and_type(opposite_color(us), PAWN) && pos.see(s, b6) < 0 && pos.see(s, b8) < 0) { @@ -1091,12 +1074,12 @@ namespace { void evaluate_trapped_bishop_a1h1(const Position &pos, Square s, Color us, EvalInfo &ei) { - Piece pawn = pawn_of_color(us); + Piece pawn = piece_of_color_and_type(us, PAWN); Square b2, b3, c3; assert(Chess960); assert(square_is_ok(s)); - assert(pos.piece_on(s) == bishop_of_color(us)); + assert(pos.piece_on(s) == piece_of_color_and_type(us, BISHOP)); if (square_file(s) == FILE_A) { @@ -1176,23 +1159,6 @@ namespace { } - // scale_by_game_phase() interpolates between a middle game and an endgame - // score, based on game phase. It also scales the return value by a - // ScaleFactor array. - - Value scale_by_game_phase(Value mv, Value ev, Phase ph, const ScaleFactor sf[]) { - - assert(mv > -VALUE_INFINITE && mv < VALUE_INFINITE); - assert(ev > -VALUE_INFINITE && ev < VALUE_INFINITE); - assert(ph >= PHASE_ENDGAME && ph <= PHASE_MIDGAME); - - ev = apply_scale_factor(ev, sf[(ev > Value(0) ? WHITE : BLACK)]); - - Value result = Value(int((mv * ph + ev * (128 - ph)) / 128)); - return Value(int(result) & ~(GrainSize - 1)); - } - - // count_1s_8bit() counts the number of nonzero bits in the 8 least // significant bits of a Bitboard. This function is used by the king // shield evaluation.