X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=inline;f=src%2Fevaluate.cpp;h=f44173445bac916afc72090d68d5a217b0d4cc2d;hb=3ee3cdc09b2d52a17f5db4b7ecb0fcc64c27ccd6;hp=f4b7fb757dfc3c340ef03229e70dcabd3bdf93b1;hpb=f56af8e84db25c0d26fe762fbe171ec5518177bb;p=stockfish diff --git a/src/evaluate.cpp b/src/evaluate.cpp index f4b7fb75..f4417344 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -63,6 +63,7 @@ namespace { const int WeightPassedPawnsMidgameInternal = 0x100; const int WeightPassedPawnsEndgameInternal = 0x100; const int WeightKingSafetyInternal = 0x100; + const int WeightKingOppSafetyInternal = 0x100; // Visually better to define tables constants typedef Value V; @@ -274,6 +275,7 @@ namespace { int count_1s_8bit(Bitboard b); int compute_weight(int uciWeight, int internalWeight); + int weight_option(const std::string& opt, int weight); void init_safety(); } @@ -328,19 +330,19 @@ Value evaluate(const Position &pos, EvalInfo &ei, int threadID) { // Initialize king attack bitboards and king attack zones for both sides: ei.attackedBy[WHITE][KING] = pos.king_attacks(pos.king_square(WHITE)); ei.attackedBy[BLACK][KING] = pos.king_attacks(pos.king_square(BLACK)); - ei.attackZone[WHITE] = + ei.kingZone[WHITE] = ei.attackedBy[BLACK][KING] | (ei.attackedBy[BLACK][KING] >> 8); - ei.attackZone[BLACK] = + ei.kingZone[BLACK] = ei.attackedBy[WHITE][KING] | (ei.attackedBy[WHITE][KING] << 8); // Initialize pawn attack bitboards for both sides: ei.attackedBy[WHITE][PAWN] = ((pos.pawns(WHITE) << 9) & ~FileABB) | ((pos.pawns(WHITE) << 7) & ~FileHBB); - ei.attackCount[WHITE] += + ei.kingAttackersCount[WHITE] += count_1s_max_15(ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING])/2; ei.attackedBy[BLACK][PAWN] = ((pos.pawns(BLACK) >> 7) & ~FileABB) | ((pos.pawns(BLACK) >> 9) & ~FileHBB); - ei.attackCount[BLACK] += + ei.kingAttackersCount[BLACK] += count_1s_max_15(ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING])/2; // Evaluate pieces: @@ -538,32 +540,19 @@ void quit_eval() { /// read_weights() reads evaluation weights from the corresponding UCI /// parameters. -void read_weights(Color sideToMove) { - WeightMobilityMidgame = - compute_weight(get_option_value_int("Mobility (Middle Game)"), - WeightMobilityMidgameInternal); - WeightMobilityEndgame = - compute_weight(get_option_value_int("Mobility (Endgame)"), - WeightMobilityEndgameInternal); - WeightPawnStructureMidgame = - compute_weight(get_option_value_int("Pawn Structure (Middle Game)"), - WeightPawnStructureMidgameInternal); - WeightPawnStructureEndgame = - compute_weight(get_option_value_int("Pawn Structure (Endgame)"), - WeightPawnStructureEndgameInternal); - WeightPassedPawnsMidgame = - compute_weight(get_option_value_int("Passed Pawns (Middle Game)"), - WeightPassedPawnsMidgameInternal); - WeightPassedPawnsEndgame = - compute_weight(get_option_value_int("Passed Pawns (Endgame)"), - WeightPassedPawnsEndgameInternal); - WeightKingSafety[sideToMove] = - compute_weight(get_option_value_int("Cowardice"), WeightKingSafetyInternal); - WeightKingSafety[opposite_color(sideToMove)] = - compute_weight(get_option_value_int("Aggressiveness"), - WeightKingSafetyInternal); - WeightKingSafety[opposite_color(sideToMove)] = - (get_option_value_int("Aggressiveness") * 0x100) / 100; +void read_weights(Color us) { + + WeightMobilityMidgame = weight_option("Mobility (Middle Game)", WeightMobilityMidgameInternal); + WeightMobilityEndgame = weight_option("Mobility (Endgame)", WeightMobilityEndgameInternal); + WeightPawnStructureMidgame = weight_option("Pawn Structure (Middle Game)", WeightPawnStructureMidgameInternal); + WeightPawnStructureEndgame = weight_option("Pawn Structure (Endgame)", WeightPawnStructureEndgameInternal); + WeightPassedPawnsMidgame = weight_option("Passed Pawns (Middle Game)", WeightPassedPawnsMidgameInternal); + WeightPassedPawnsEndgame = weight_option("Passed Pawns (Endgame)", WeightPassedPawnsEndgameInternal); + + Color them = opposite_color(us); + + WeightKingSafety[us] = weight_option("Cowardice", WeightKingSafetyInternal); + WeightKingSafety[them] = weight_option("Aggressiveness", WeightKingOppSafetyInternal); init_safety(); } @@ -580,13 +569,13 @@ namespace { Color them = opposite_color(us); // King attack - if (b & ei.attackZone[us]) + if (b & ei.kingZone[us]) { - ei.attackCount[us]++; - ei.attackWeight[us] += AttackWeight; + ei.kingAttackersCount[us]++; + ei.kingAttackersWeight[us] += AttackWeight; Bitboard bb = (b & ei.attackedBy[them][KING]); if (bb) - ei.attacked[us] += count_1s_max_15(bb); + ei.kingZoneAttacksCount[us] += count_1s_max_15(bb); } // Mobility @@ -688,8 +677,9 @@ namespace { // 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))) @@ -754,9 +744,9 @@ namespace { // King safety. This is quite complicated, and is almost certainly far // from optimally tuned. Color them = opposite_color(us); - if(p.queen_count(them) >= 1 && ei.attackCount[them] >= 2 + if(p.queen_count(them) >= 1 && ei.kingAttackersCount[them] >= 2 && p.non_pawn_material(them) >= QueenValueMidgame + RookValueMidgame - && ei.attacked[them]) { + && ei.kingZoneAttacksCount[them]) { // Is it the attackers turn to move? bool sente = (them == p.side_to_move()); @@ -776,8 +766,8 @@ namespace { // undefended squares around the king, the square of the king, and the // quality of the pawn shelter. int attackUnits = - Min((ei.attackCount[them] * ei.attackWeight[them]) / 2, 25) - + (ei.attacked[them] + count_1s_max_15(undefended)) * 3 + Min((ei.kingAttackersCount[them] * ei.kingAttackersWeight[them]) / 2, 25) + + (ei.kingZoneAttacksCount[them] + count_1s_max_15(undefended)) * 3 + InitKingDanger[relative_square(us, s)] - shelter / 32; // Analyse safe queen contact checks: @@ -1046,26 +1036,20 @@ namespace { void evaluate_trapped_bishop_a7h7(const Position &pos, Square s, Color us, EvalInfo &ei) { - Piece pawn = pawn_of_color(opposite_color(us)); - Square b6, b8; assert(square_is_ok(s)); assert(pos.piece_on(s) == bishop_of_color(us)); - if(square_file(s) == FILE_A) { - b6 = relative_square(us, SQ_B6); - b8 = relative_square(us, SQ_B8); - } - else { - b6 = relative_square(us, SQ_G6); - b8 = relative_square(us, SQ_G8); - } + 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 && pos.see(s, b6) < 0 && pos.see(s, b8) < 0) { - ei.mgValue -= Sign[us] * TrappedBishopA7H7Penalty; - ei.egValue -= Sign[us] * TrappedBishopA7H7Penalty; + if ( pos.piece_on(b6) == pawn_of_color(opposite_color(us)) + && pos.see(s, b6) < 0 + && pos.see(s, b8) < 0) + { + ei.mgValue -= Sign[us] * TrappedBishopA7H7Penalty; + ei.egValue -= Sign[us] * TrappedBishopA7H7Penalty; } - } @@ -1123,21 +1107,20 @@ namespace { // 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); assert(ph >= PHASE_ENDGAME && ph <= PHASE_MIDGAME); - if(ev > Value(0)) - ev = apply_scale_factor(ev, sf[WHITE]); - else - ev = apply_scale_factor(ev, sf[BLACK]); + ev = apply_scale_factor(ev, sf[(ev > Value(0) ? WHITE : BLACK)]); + + // Linearized sigmoid interpolator + int sph = int(ph); + sph -= (64 - sph) / 4; + sph = Min(PHASE_MIDGAME, Max(PHASE_ENDGAME, sph)); - // 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 * sph + ev * (128 - sph)) / 128)); - Value result = Value(int((mv * sli_ph + ev * (128 - sli_ph)) / 128)); return Value(int(result) & ~(GrainSize - 1)); } @@ -1160,43 +1143,53 @@ namespace { } + // helper used in read_weights() + int weight_option(const std::string& opt, int weight) { + + return compute_weight(get_option_value_int(opt), weight); + } + + // 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"); - RookCheckBonus = get_option_value_int("Rook Check Bonus"); - BishopCheckBonus = get_option_value_int("Bishop Check Bonus"); - KnightCheckBonus = get_option_value_int("Knight Check Bonus"); - DiscoveredCheckBonus = get_option_value_int("Discovered Check Bonus"); - MateThreatBonus = get_option_value_int("Mate Threat Bonus"); - - a = get_option_value_int("King Safety Coefficient") / 100.0; - 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") - SafetyTable[i] = Value((int)(a * (i - b) * (i - b))); - else if(get_option_value_string("King Safety Curve") == "Linear") - SafetyTable[i] = Value((int)(100 * a * (i - b))); + RookContactCheckBonus = get_option_value_int("Rook Contact Check Bonus"); + QueenCheckBonus = get_option_value_int("Queen Check Bonus"); + RookCheckBonus = get_option_value_int("Rook Check Bonus"); + BishopCheckBonus = get_option_value_int("Bishop Check Bonus"); + KnightCheckBonus = get_option_value_int("Knight Check Bonus"); + DiscoveredCheckBonus = get_option_value_int("Discovered Check Bonus"); + MateThreatBonus = get_option_value_int("Mate Threat Bonus"); + + int maxSlope = get_option_value_int("King Safety Max Slope"); + int peak = get_option_value_int("King Safety Max Value") * 256 / 100; + double a = get_option_value_int("King Safety Coefficient") / 100.0; + double b = get_option_value_int("King Safety X Intercept"); + bool quad = (get_option_value_string("King Safety Curve") == "Quadratic"); + bool linear = (get_option_value_string("King Safety Curve") == "Linear"); + + for (int i = 0; i < 100; i++) + { + if (i < b) + SafetyTable[i] = Value(0); + else if(quad) + SafetyTable[i] = Value((int)(a * (i - b) * (i - b))); + else if(linear) + SafetyTable[i] = Value((int)(100 * a * (i - b))); } - for(i = 0; i < 100; i++) - if(SafetyTable[i+1] - SafetyTable[i] > maxSlope) { - for(j = i + 1; j < 100; j++) - SafetyTable[j] = SafetyTable[j-1] + Value(maxSlope); - } - for(i = 0; i < 100; i++) - if(SafetyTable[i] > Value(peak)) - SafetyTable[i] = Value(peak); + for (int i = 0; i < 100; i++) + { + if (SafetyTable[i+1] - SafetyTable[i] > maxSlope) + for (int j = i + 1; j < 100; j++) + SafetyTable[j] = SafetyTable[j-1] + Value(maxSlope); + + if (SafetyTable[i] > Value(peak)) + SafetyTable[i] = Value(peak); + } } }