X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=6f4de561fd42aa68156a4df42e25ec54f1b7790a;hp=46ddfe5c80046933bc018bf5c26ff92ba2d8e927;hb=853ce65f178204f0c88098f937d759dd40c4c3c9;hpb=2f5012a3eb560049fb1a0b6977d0895b845d104e diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 46ddfe5c..6f4de561 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -6,12 +6,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + Glaurung is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -44,123 +44,136 @@ namespace { const int GrainSize = 4; // Evaluation weights - int WeightMobilityMidgame = 0x100; - int WeightMobilityEndgame = 0x100; + int WeightMobilityMidgame = 0x100; + int WeightMobilityEndgame = 0x100; int WeightPawnStructureMidgame = 0x100; int WeightPawnStructureEndgame = 0x100; - int WeightPassedPawnsMidgame = 0x100; - int WeightPassedPawnsEndgame = 0x100; + int WeightPassedPawnsMidgame = 0x100; + int WeightPassedPawnsEndgame = 0x100; int WeightKingSafety[2] = { 0x100, 0x100 }; // Internal evaluation weights. These are applied on top of the evaluation // 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 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 = 0x100; + const int WeightPassedPawnsMidgameInternal = 0x100; + const int WeightPassedPawnsEndgameInternal = 0x100; + const int WeightKingSafetyInternal = 0x100; + + // Visually better to define tables constants + typedef Value V; // Knight mobility bonus in middle game and endgame, indexed by the number // of attacked squares not occupied by friendly piecess. const Value MidgameKnightMobilityBonus[] = { - Value(-30), Value(-20), Value(-10), Value(0), Value(10), - Value(20), Value(25), Value(30), Value(30) + // 0 1 2 3 4 5 6 7 8 + V(-30), V(-20),V(-10), V(0), V(10), V(20), V(25), V(30), V(30) }; const Value EndgameKnightMobilityBonus[] = { - Value(-30), Value(-20), Value(-10), Value(0), Value(10), - Value(20), Value(25), Value(30), Value(30) + // 0 1 2 3 4 5 6 7 8 + V(-30), V(-20),V(-10), V(0), V(10), V(20), V(25), V(30), V(30) }; // Bishop mobility bonus in middle game and endgame, indexed by the number // of attacked squares not occupied by friendly pieces. X-ray attacks through // queens are also included. const Value MidgameBishopMobilityBonus[] = { - Value(-30), Value(-15), Value(0), Value(15), Value(30), Value(45), - Value(58), Value(66), Value(72), Value(76), Value(78), Value(80), - Value(81), Value(82), Value(83), Value(83) + // 0 1 2 3 4 5 6 7 + V(-30), V(-15), V(0), V(15), V(30), V(45), V(58), V(66), + // 8 9 10 11 12 13 14 15 + V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83) }; const Value EndgameBishopMobilityBonus[] = { - Value(-30), Value(-15), Value(0), Value(15), Value(30), Value(45), - Value(58), Value(66), Value(72), Value(76), Value(78), Value(80), - Value(81), Value(82), Value(83), Value(83) + // 0 1 2 3 4 5 6 7 + V(-30), V(-15), V(0), V(15), V(30), V(45), V(58), V(66), + // 8 9 10 11 12 13 14 15 + V( 72), V( 76), V(78), V(80), V(81), V(82), V(83), V(83) }; // Rook mobility bonus in middle game and endgame, indexed by the number // of attacked squares not occupied by friendly pieces. X-ray attacks through // queens and rooks are also included. const Value MidgameRookMobilityBonus[] = { - Value(-18), Value(-12), Value(-6), Value(0), Value(6), Value(12), - Value(16), Value(21), Value(24), Value(27), Value(28), Value(29), - Value(30), Value(31), Value(32), Value(33) + // 0 1 2 3 4 5 6 7 + V(-18), V(-12), V(-6), V(0), V(6), V(12), V(16), V(21), + // 8 9 10 11 12 13 14 15 + V( 24), V( 27), V(28), V(29), V(30), V(31), V(32), V(33) }; - + const Value EndgameRookMobilityBonus[] = { - Value(-30), Value(-18), Value(-6), Value(6), Value(18), Value(30), - Value(42), Value(54), Value(66), Value(74), Value(78), Value(80), - Value(81), Value(82), Value(83), Value(83) + // 0 1 2 3 4 5 6 7 + V(-30), V(-18), V(-6), V(6), V(18), V(30), V(42), V(54), + // 8 9 10 11 12 13 14 15 + V( 66), V( 74), V(78), V(80), V(81), V(82), V(83), V(83) }; // Queen mobility bonus in middle game and endgame, indexed by the number // of attacked squares not occupied by friendly pieces. const Value MidgameQueenMobilityBonus[] = { - Value(-10), Value(-8), Value(-6), Value(-4), Value(-2), Value(0), Value(2), - Value(4), Value(6), Value(8), Value(10), Value(12), Value(13), Value(14), - Value(15), Value(16), Value(16), Value(16), Value(16), Value(16), - Value(16), Value(16), Value(16), Value(16), Value(16), Value(16), - Value(16), Value(16), Value(16), Value(16), Value(16), Value(16) + // 0 1 2 3 4 5 6 7 + V(-10), V(-8), V(-6), V(-4), V(-2), V( 0), V( 2), V( 4), + // 8 9 10 11 12 13 14 15 + V( 6), V( 8), V(10), V(12), V(13), V(14), V(15), V(16), + // 16 17 18 19 20 21 22 23 + V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16), + // 24 25 26 27 28 29 30 31 + V( 16), V(16), V(16), V(16), V(16), V(16), V(16), V(16) }; const Value EndgameQueenMobilityBonus[] = { - Value(-20), Value(-15), Value(-10), Value(-5), Value(0), Value(5), - Value(10), Value(15), Value(19), Value(23), Value(27), Value(29), - Value(30), Value(30), Value(30), Value(30), Value(30), Value(30), - Value(30), Value(30), Value(30), Value(30), Value(30), Value(30), - Value(30), Value(30), Value(30), Value(30), Value(30), Value(30), - Value(30), Value(30) + // 0 1 2 3 4 5 6 7 + V(-20),V(-15),V(-10), V(-5), V( 0), V( 5), V(10), V(15), + // 8 9 10 11 12 13 14 15 + V( 19), V(23), V(27), V(29), V(30), V(30), V(30), V(30), + // 16 17 18 19 20 21 22 23 + V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30), + // 24 25 26 27 28 29 30 31 + V( 30), V(30), V(30), V(30), V(30), V(30), V(30), V(30) }; - // Outpost bonuses for knights and bishops, indexed by square (from white's // point of view). const Value KnightOutpostBonus[64] = { - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0), - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0), - Value(0),Value(0),Value(5),Value(10),Value(10),Value(5),Value(0),Value(0), - Value(0),Value(5),Value(20),Value(30),Value(30),Value(20),Value(5),Value(0), - Value(0),Value(10),Value(30),Value(40),Value(40),Value(30),Value(10),Value(0), - Value(0),Value(5),Value(20),Value(20),Value(20),Value(20),Value(5),Value(0), - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0), - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0) + // A B C D E F G H + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 1 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 2 + V(0), V(0), V(5),V(10),V(10), V(5), V(0), V(0), // 3 + V(0), V(5),V(20),V(30),V(30),V(20), V(5), V(0), // 4 + V(0),V(10),V(30),V(40),V(40),V(30),V(10), V(0), // 5 + V(0), V(5),V(20),V(20),V(20),V(20), V(5), V(0), // 6 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 7 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0) // 8 }; const Value BishopOutpostBonus[64] = { - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0), - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0), - Value(0),Value(0),Value(5),Value(5),Value(5),Value(5),Value(0),Value(0), - Value(0),Value(5),Value(10),Value(10),Value(10),Value(10),Value(5),Value(0), - Value(0),Value(10),Value(20),Value(20),Value(20),Value(20),Value(10),Value(0), - Value(0),Value(5),Value(8),Value(8),Value(8),Value(8),Value(5),Value(0), - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0), - Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0) + // A B C D E F G H + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 1 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 2 + V(0), V(0), V(5), V(5), V(5), V(5), V(0), V(0), // 3 + V(0), V(5),V(10),V(10),V(10),V(10), V(5), V(0), // 4 + V(0),V(10),V(20),V(20),V(20),V(20),V(10), V(0), // 5 + V(0), V(5), V(8), V(8), V(8), V(8), V(5), V(0), // 6 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // 7 + V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0) // 8 }; // 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 MidgameRookOn7thBonus = Value(50); + const Value EndgameRookOn7thBonus = Value(100); const Value MidgameQueenOn7thBonus = Value(25); const Value EndgameQueenOn7thBonus = Value(50); // Rooks on open files: - const Value RookOpenFileBonus = Value(40); + const Value RookOpenFileBonus = Value(40); const Value RookHalfOpenFileBonus = Value(20); // Penalty for rooks trapped inside a friendly king which has lost the @@ -188,26 +201,25 @@ namespace { ((1ULL << SQ_A8) | (1ULL << SQ_H8)) }; - /// King safety constants and variables. The king safety scores are taken /// from the array SafetyTable[]. Various little "meta-bonuses" measuring /// the strength of the attack are added up into an integer, which is used /// as an index to SafetyTable[]. // Attack weights for each piece type. - const int QueenAttackWeight = 5; - const int RookAttackWeight = 3; + const int QueenAttackWeight = 5; + const int RookAttackWeight = 3; const int BishopAttackWeight = 2; const int KnightAttackWeight = 2; - // Bonuses for safe checks for each piece type. + // Bonuses for safe checks for each piece type. int QueenContactCheckBonus = 4; - int RookContactCheckBonus = 2; - int QueenCheckBonus = 2; - int RookCheckBonus = 1; - int BishopCheckBonus = 1; - int KnightCheckBonus = 1; - int DiscoveredCheckBonus = 3; + int RookContactCheckBonus = 2; + int QueenCheckBonus = 2; + int RookCheckBonus = 1; + int BishopCheckBonus = 1; + int KnightCheckBonus = 1; + int DiscoveredCheckBonus = 3; // Scan for queen contact mates? const bool QueenContactMates = true; @@ -218,20 +230,20 @@ namespace { // InitKingDanger[] contains bonuses based on the position of the defending // king. const int InitKingDanger[64] = { - 2, 0, 2, 5, 5, 2, 0, 2, - 2, 2, 4, 8, 8, 4, 2, 2, - 7, 10, 12, 12, 12, 12, 10, 7, + 2, 0, 2, 5, 5, 2, 0, 2, + 2, 2, 4, 8, 8, 4, 2, 2, + 7, 10, 12, 12, 12, 12, 10, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15 }; // SafetyTable[] contains the actual king safety scores. It is initialized // in init_safety(). Value SafetyTable[100]; - // Pawn and material hash tables, indexed by the current thread id: PawnInfoTable *PawnTable[8] = {0, 0, 0, 0, 0, 0, 0, 0}; MaterialInfoTable *MaterialTable[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -256,7 +268,7 @@ namespace { void evaluate_trapped_bishop_a1h1(const Position &pos, Square s, Color us, EvalInfo &ei); - Value apply_weight(Value v, int w); + inline Value apply_weight(Value v, int w); Value scale_by_game_phase(Value mv, Value ev, Phase ph, ScaleFactor sf[]); int count_1s_8bit(Bitboard b); @@ -340,7 +352,7 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) { s = pos.knight_list(c, i); evaluate_knight(pos, s, c, ei); } - + // Bishops for(int i = 0; i < pos.bishop_count(c); i++) { s = pos.bishop_list(c, i); @@ -378,8 +390,8 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) { } ei.attackedBy[c][0] = - ei.attackedBy[c][PAWN] | ei.attackedBy[c][KNIGHT] - | ei.attackedBy[c][BISHOP] | ei.attackedBy[c][ROOK] + ei.attackedBy[c][PAWN] | ei.attackedBy[c][KNIGHT] + | ei.attackedBy[c][BISHOP] | ei.attackedBy[c][ROOK] | ei.attackedBy[c][QUEEN] | ei.attackedBy[c][KING]; } @@ -408,7 +420,7 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) { ei.pi->kingside_storm_value(BLACK); else if(square_file(pos.king_square(WHITE)) <= FILE_D && square_file(pos.king_square(BLACK)) >= FILE_E) - ei.mgValue += + ei.mgValue += ei.pi->kingside_storm_value(WHITE) - ei.pi->queenside_storm_value(BLACK); } @@ -471,7 +483,7 @@ Value quick_evaluate(const Position &pos) { Value mgValue, egValue; ScaleFactor factor[2] = {SCALE_FACTOR_NORMAL, SCALE_FACTOR_NORMAL}; Phase phase; - + assert(pos.is_ok()); stm = pos.side_to_move(); @@ -484,32 +496,32 @@ Value quick_evaluate(const Position &pos) { return Sign[stm] * value; } - + /// init_eval() initializes various tables used by the evaluation function. void init_eval(int threads) { + assert(threads <= THREAD_MAX); - - for(int i = 0; i < threads; i++) { - if(PawnTable[i] == NULL) - PawnTable[i] = new PawnInfoTable(PawnTableSize); - if(MaterialTable[i] == NULL) - MaterialTable[i] = new MaterialInfoTable(MaterialTableSize); - } - for(int i = threads; i < THREAD_MAX; i++) { - if(PawnTable[i] != NULL) { - delete PawnTable[i]; - PawnTable[i] = NULL; - } - if(MaterialTable[i] != NULL) { - delete MaterialTable[i]; - MaterialTable[i] = NULL; + + for (int i = 0; i < THREAD_MAX; i++) + { + if (i >= threads) + { + delete PawnTable[i]; + delete MaterialTable[i]; + PawnTable[i] = NULL; + MaterialTable[i] = NULL; + continue; } + if (!PawnTable[i]) + PawnTable[i] = new PawnInfoTable(PawnTableSize); + if (!MaterialTable[i]) + MaterialTable[i] = new MaterialInfoTable(MaterialTableSize); } - for(Bitboard b = 0ULL; b < 256ULL; b++) - BitCount8Bit[b] = count_1s(b); + for (Bitboard b = 0ULL; b < 256ULL; b++) + BitCount8Bit[b] = count_1s(b); } @@ -559,32 +571,46 @@ void read_weights(Color sideToMove) { namespace { - // evaluate_knight() assigns bonuses and penalties to a knight of a given - // color on a given square. - - void evaluate_knight(const Position &p, Square s, Color us, EvalInfo &ei) { + // evaluate_common() computes terms common to all pieces attack + + int evaluate_common(const Position&p, const Bitboard& b, Color us, EvalInfo& ei, + int AttackWeight, const Value* mgBonus, const Value* egBonus) { Color them = opposite_color(us); - Bitboard b = p.knight_attacks(s); - ei.attackedBy[us][KNIGHT] |= b; // King attack if(b & ei.attackZone[us]) { ei.attackCount[us]++; - ei.attackWeight[us] += KnightAttackWeight; + ei.attackWeight[us] += AttackWeight; Bitboard bb = (b & ei.attackedBy[them][KING]); if(bb) ei.attacked[us] += count_1s_max_15(bb); } - + // Mobility int mob = count_1s_max_15(b & ~p.pieces_of_color(us)); - ei.mgMobility += Sign[us] * MidgameKnightMobilityBonus[mob]; - ei.egMobility += Sign[us] * EndgameKnightMobilityBonus[mob]; + ei.mgMobility += Sign[us] * mgBonus[mob]; + ei.egMobility += Sign[us] * egBonus[mob]; + + return mob; + } + + // evaluate_knight() assigns bonuses and penalties to a knight of a given + // color on a given square. + + void evaluate_knight(const Position &p, Square s, Color us, EvalInfo &ei) { + + Color them = opposite_color(us); + Bitboard b = p.knight_attacks(s); + ei.attackedBy[us][KNIGHT] |= b; + + // King attack and mobility + evaluate_common(p, b, us, ei, KnightAttackWeight, + MidgameKnightMobilityBonus, EndgameKnightMobilityBonus); // Knight outposts: if(p.square_is_weak(s, them)) { Value v, bonus; - + // Initial bonus based on square: v = bonus = KnightOutpostBonus[relative_square(us, s)]; @@ -607,32 +633,23 @@ namespace { // evaluate_bishop() assigns bonuses and penalties to a bishop of a given // color on a given square. - + void evaluate_bishop(const Position &p, Square s, Color us, EvalInfo &ei) { Color them = opposite_color(us); Bitboard b = bishop_attacks_bb(s, p.occupied_squares() & ~p.queens(us)); - - ei.attackedBy[us][BISHOP] |= b; - // King attack - if(b & ei.attackZone[us]) { - ei.attackCount[us]++; - ei.attackWeight[us] += BishopAttackWeight; - Bitboard bb = (b & ei.attackedBy[them][KING]); - if(bb) ei.attacked[us] += count_1s_max_15(bb); - } + ei.attackedBy[us][BISHOP] |= b; - // Mobility: - int mob = count_1s_max_15(b & ~p.pieces_of_color(us)); - ei.mgMobility += Sign[us] * MidgameBishopMobilityBonus[mob]; - ei.egMobility += Sign[us] * EndgameBishopMobilityBonus[mob]; + // King attack and mobility + evaluate_common(p, b, us, ei, BishopAttackWeight, + MidgameBishopMobilityBonus, EndgameBishopMobilityBonus); // Bishop outposts: if(p.square_is_weak(s, them)) { Value v, bonus; - + // Initial bonus based on square: v = bonus = BishopOutpostBonus[relative_square(us, s)]; @@ -649,17 +666,17 @@ namespace { ei.mgValue += Sign[us] * bonus; ei.egValue += Sign[us] * bonus; - } + } } - + // evaluate_rook() assigns bonuses and penalties to a rook of a given // color on a given square. - + void evaluate_rook(const Position &p, Square s, Color us, EvalInfo &ei) { Color them = opposite_color(us); - + // Open and half-open files: File f = square_file(s); if(ei.pi->file_is_half_open(us, f)) { @@ -685,18 +702,9 @@ namespace { rook_attacks_bb(s, p.occupied_squares() & ~p.rooks_and_queens(us)); ei.attackedBy[us][ROOK] |= b; - // King attack - if(b & ei.attackZone[us]) { - ei.attackCount[us]++; - ei.attackWeight[us] += RookAttackWeight; - Bitboard bb = (b & ei.attackedBy[them][KING]); - if(bb) ei.attacked[us] += count_1s_max_15(bb); - } - - // Mobility - int mob = count_1s_max_15(b & ~p.pieces_of_color(us)); - ei.mgMobility += Sign[us] * MidgameRookMobilityBonus[mob]; - ei.egMobility += Sign[us] * EndgameRookMobilityBonus[mob]; + // King attack and mobility + int mob = evaluate_common(p, b, us, ei, RookAttackWeight, + MidgameRookMobilityBonus, EndgameRookMobilityBonus); // Penalize rooks which are trapped inside a king which has lost the // right to castle: @@ -729,7 +737,7 @@ namespace { // 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) { Color them = opposite_color(us); @@ -744,26 +752,17 @@ namespace { Bitboard b = p.queen_attacks(s); ei.attackedBy[us][QUEEN] |= b; - // King attack - if(b & ei.attackZone[us]) { - ei.attackCount[us]++; - ei.attackWeight[us] += QueenAttackWeight; - Bitboard bb = (b & ei.attackedBy[them][KING]); - if(bb) ei.attacked[us] += count_1s_max_15(bb); - } - - // Mobility - int mob = count_1s(b & ~p.pieces_of_color(us)); - ei.mgMobility += Sign[us] * MidgameQueenMobilityBonus[mob]; - ei.egMobility += Sign[us] * EndgameQueenMobilityBonus[mob]; + // King attack and mobility + evaluate_common(p, b, us, ei, QueenAttackWeight, + MidgameQueenMobilityBonus, EndgameQueenMobilityBonus); } // evaluate_king() assigns bonuses and penalties to a king of a given // color on a given square. - + void evaluate_king(const Position &p, Square s, Color us, EvalInfo &ei) { - + int shelter = 0, sign = Sign[us]; // King shelter. @@ -776,7 +775,7 @@ namespace { } // King safety. This is quite complicated, and is almost certainly far - // from optimally tuned. + // from optimally tuned. Color them = opposite_color(us); if(p.queen_count(them) >= 1 && ei.attackCount[them] >= 2 && p.non_pawn_material(them) >= QueenValueMidgame + RookValueMidgame @@ -784,7 +783,7 @@ namespace { // Is it the attackers turn to move? bool sente = (them == p.side_to_move()); - + // Find the attacked squares around the king which has no defenders // apart from the king itself: Bitboard undefended = @@ -857,7 +856,7 @@ namespace { } } } - + // Analyse safe distance checks: if(QueenCheckBonus > 0 || RookCheckBonus > 0) { b = p.rook_attacks(s) & ~p.pieces_of_color(them) & ~ei.attacked_by(us); @@ -1067,7 +1066,7 @@ namespace { // evaluate_trapped_bishop_a7h7() determines whether a bishop on a7/h7 // (a2/h2 for black) is trapped by enemy pawns, and assigns a penalty // if it is. - + void evaluate_trapped_bishop_a7h7(const Position &pos, Square s, Color us, EvalInfo &ei) { Piece pawn = pawn_of_color(opposite_color(us)); @@ -1097,7 +1096,7 @@ namespace { // (a8/h8 for black) is trapped by a friendly pawn on b2/g2 (b7/g7 for // black), and assigns a penalty if it is. This pattern can obviously // only occur in Chess960 games. - + void evaluate_trapped_bishop_a1h1(const Position &pos, Square s, Color us, EvalInfo &ei) { Piece pawn = pawn_of_color(us); @@ -1127,7 +1126,7 @@ namespace { penalty = TrappedBishopA1H1Penalty; else penalty = TrappedBishopA1H1Penalty / 2; - + ei.mgValue -= Sign[us] * penalty; ei.egValue -= Sign[us] * penalty; } @@ -1145,7 +1144,7 @@ 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, ScaleFactor sf[]) { assert(mv > -VALUE_INFINITE && mv < VALUE_INFINITE); assert(ev > -VALUE_INFINITE && ev < VALUE_INFINITE); @@ -1156,7 +1155,12 @@ namespace { else ev = apply_scale_factor(ev, sf[BLACK]); - Value result = Value(int((mv * ph + ev * (128 - ph)) / 128)); + // Superlinear interpolator + int sli_ph = int(ph); + sli_ph -= (64 - sli_ph) / 4; + sli_ph = Min(PHASE_MIDGAME, Max(PHASE_ENDGAME, sli_ph)); // ceiling + + Value result = Value(int((mv * sli_ph + ev * (128 - sli_ph)) / 128)); return Value(int(result) & ~(GrainSize - 1)); } @@ -1164,7 +1168,7 @@ namespace { // 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. - + int count_1s_8bit(Bitboard b) { return int(BitCount8Bit[b & 0xFF]); } @@ -1177,15 +1181,15 @@ namespace { uciWeight = (uciWeight * 0x100) / 100; return (uciWeight * internalWeight) / 0x100; } - + // init_safety() initizes the king safety evaluation, based on UCI // parameters. It is called from read_weights(). - + void init_safety() { double a, b; int maxSlope, peak, i, j; - + QueenContactCheckBonus = get_option_value_int("Queen Contact Check Bonus"); RookContactCheckBonus = get_option_value_int("Rook Contact Check Bonus"); QueenCheckBonus = get_option_value_int("Queen Check Bonus"); @@ -1199,7 +1203,7 @@ namespace { b = get_option_value_int("King Safety X Intercept") * 1.0; maxSlope = get_option_value_int("King Safety Max Slope"); peak = (get_option_value_int("King Safety Max Value") * 256) / 100; - + for(i = 0; i < 100; i++) { if(i < b) SafetyTable[i] = Value(0); else if(get_option_value_string("King Safety Curve") == "Quadratic") @@ -1217,5 +1221,5 @@ namespace { if(SafetyTable[i] > Value(peak)) SafetyTable[i] = Value(peak); } - + }