username ********* password ****** begin namespace { struct EvalInfo { Material::Entry* mi; Pawns::Entry* pi; Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB]; Bitboard kingRing[COLOR_NB]; int kingAttackersCount[COLOR_NB]; int kingAttackersWeight[COLOR_NB]; int kingAdjacentZoneAttacksCount[COLOR_NB]; Bitboard pinnedPieces[COLOR_NB]; }; namespace Tracing { enum Terms { // First 8 entries are for PieceType MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, TOTAL, TERMS_NB }; Score scores[COLOR_NB][TERMS_NB]; EvalInfo ei; ScaleFactor sf; double to_cp(Value v); void write(int idx, Color c, Score s); void write(int idx, Score w, Score b = SCORE_ZERO); void print(std::stringstream& ss, const char* name, int idx); std::string do_trace(const Position& pos); } enum { Mobility, PawnStructure, PassedPawns, Space, KingSafety }; const struct Weight { int mg, eg; } Weights[] = { {289, 344}, {233, 201}, {221, 273}, {46, 0}, {318, 0} }; typedef Value V; #define S(mg, eg) make_score(mg, eg) const Score MobilityBonus[][32] = { {}, {}, { S(-65,-50), S(-42,-30), S(-9,-10), S( 3, 0), S(15, 10), S(27, 20), // Knights S( 37, 28), S( 42, 31), S(44, 33) }, { S(-52,-47), S(-28,-23), S( 6, 1), S(20, 15), S(34, 29), S(48, 43), // Bishops S( 60, 55), S( 68, 63), S(74, 68), S(77, 72), S(80, 75), S(82, 77), S( 84, 79), S( 86, 81) }, { S(-47,-53), S(-31,-26), S(-5, 0), S( 1, 16), S( 7, 32), S(13, 48), // Rooks S( 18, 64), S( 22, 80), S(26, 96), S(29,109), S(31,115), S(33,119), S( 35,122), S( 36,123), S(37,124) }, { S(-42,-40), S(-28,-23), S(-5, -7), S( 0, 0), S( 6, 10), S(11, 19), // Queens S( 13, 29), S( 18, 38), S(20, 40), S(21, 41), S(22, 41), S(22, 41), S( 22, 41), S( 23, 41), S(24, 41), S(25, 41), S(25, 41), S(25, 41), S( 25, 41), S( 25, 41), S(25, 41), S(25, 41), S(25, 41), S(25, 41), S( 25, 41), S( 25, 41), S(25, 41), S(25, 41) } }; const Value Outpost[][SQUARE_NB] = { {// A B C D E F G H V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // Knights V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(4), V(8), V(8), V(4), V(0), V(0), V(0), V(4),V(17),V(26),V(26),V(17), V(4), V(0), V(0), V(8),V(26),V(35),V(35),V(26), V(8), V(0), V(0), V(4),V(17),V(17),V(17),V(17), V(4), V(0) }, { V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // Bishops V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(5), V(5), V(5), V(5), V(0), V(0), V(0), V(5),V(10),V(10),V(10),V(10), V(5), V(0), V(0),V(10),V(21),V(21),V(21),V(21),V(10), V(0), V(0), V(5), V(8), V(8), V(8), V(8), V(5), V(0) } }; const Score Threat[][2][PIECE_TYPE_NB] = { { { S(0, 0), S( 0, 0), S(19, 37), S(24, 37), S(44, 97), S(35,106) }, // Defended Minor { S(0, 0), S( 0, 0), S( 9, 14), S( 9, 14), S( 7, 14), S(24, 48) } }, // Defended Major { { S(0, 0), S( 0,32), S(33, 41), S(31, 50), S(41,100), S(35,104) }, // Weak Minor { S(0, 0), S( 0,27), S(26, 57), S(26, 57), S(0 , 43), S(23, 51) } } // Weak Major }; const Score ThreatenedByPawn[] = { S(0, 0), S(0, 0), S(87, 118), S(84, 122), S(114, 203), S(121, 217) }; const Score KingOnOne = S( 2, 58); const Score KingOnMany = S( 6,125); const Score RookOnPawn = S( 7, 27); const Score RookOpenFile = S(43, 21); const Score RookSemiOpenFile = S(19, 10); const Score BishopPawns = S( 8, 12); const Score MinorBehindPawn = S(16, 0); const Score TrappedRook = S(92, 0); const Score Unstoppable = S( 0, 20); const Score Hanging = S(31, 26); const Score TrappedBishopA1H1 = S(50, 50); #undef S const Bitboard SpaceMask[] = { (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank2BB | Rank3BB | Rank4BB), (FileCBB | FileDBB | FileEBB | FileFBB) & (Rank7BB | Rank6BB | Rank5BB) }; const int KingAttackWeights[] = { 0, 0, 2, 2, 3, 5 }; const int QueenContactCheck = 24; const int RookContactCheck = 16; const int QueenCheck = 12; const int RookCheck = 8; const int BishopCheck = 2; const int KnightCheck = 3; Score KingDanger[128]; Score apply_weight(Score v, const Weight& w) { return make_score(mg_value(v) * w.mg / 256, eg_value(v) * w.eg / 256); } template void init_eval_info(const Position& pos, EvalInfo& ei) { const Color Them = (Us == WHITE ? BLACK : WHITE); const Square Down = (Us == WHITE ? DELTA_S : DELTA_N); ei.pinnedPieces[Us] = pos.pinned_pieces(Us); Bitboard b = ei.attackedBy[Them][KING] = pos.attacks_from(pos.king_square(Them)); ei.attackedBy[Us][ALL_PIECES] = ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us); if (pos.non_pawn_material(Us) >= QueenValueMg) { ei.kingRing[Them] = b | shift_bb(b); b &= ei.attackedBy[Us][PAWN]; ei.kingAttackersCount[Us] = b ? popcount(b) : 0; ei.kingAdjacentZoneAttacksCount[Us] = ei.kingAttackersWeight[Us] = 0; } else ei.kingRing[Them] = ei.kingAttackersCount[Us] = 0; } template Score evaluate_outpost(const Position& pos, const EvalInfo& ei, Square s) { const Color Them = (Us == WHITE ? BLACK : WHITE); assert (Pt == BISHOP || Pt == KNIGHT); Value bonus = Outpost[Pt == BISHOP][relative_square(Us, s)]; if (bonus && (ei.attackedBy[Us][PAWN] & s)) { if ( !pos.pieces(Them, KNIGHT) && !(squares_of_color(s) & pos.pieces(Them, BISHOP))) bonus += bonus + bonus / 2; else bonus += bonus / 2; } return make_score(bonus * 2, bonus / 2); } template Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility, Bitboard* mobilityArea) { Bitboard b; Square s; Score score = SCORE_ZERO; const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1)); const Color Them = (Us == WHITE ? BLACK : WHITE); const Square* pl = pos.list(Us); ei.attackedBy[Us][Pt] = 0; while ((s = *pl++) != SQ_NONE) { b = Pt == BISHOP ? attacks_bb(s, pos.pieces() ^ pos.pieces(Us, QUEEN)) : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(Us, ROOK, QUEEN)) : pos.attacks_from(s); if (ei.pinnedPieces[Us] & s) b &= LineBB[pos.king_square(Us)][s]; ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][Pt] |= b; if (b & ei.kingRing[Them]) { ei.kingAttackersCount[Us]++; ei.kingAttackersWeight[Us] += KingAttackWeights[Pt]; Bitboard bb = b & ei.attackedBy[Them][KING]; if (bb) ei.kingAdjacentZoneAttacksCount[Us] += popcount(bb); } if (Pt == QUEEN) b &= ~( ei.attackedBy[Them][KNIGHT] | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]); int mob = Pt != QUEEN ? popcount(b & mobilityArea[Us]) : popcount(b & mobilityArea[Us]); mobility[Us] += MobilityBonus[Pt][mob]; if (ei.attackedBy[Them][PAWN] & s) score -= ThreatenedByPawn[Pt]; if (Pt == BISHOP || Pt == KNIGHT) { if (Pt == BISHOP) score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s); if (!(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s))) score += evaluate_outpost(pos, ei, s); if ( relative_rank(Us, s) < RANK_5 && (pos.pieces(PAWN) & (s + pawn_push(Us)))) score += MinorBehindPawn; } if (Pt == ROOK) { if (relative_rank(Us, s) >= RANK_5) { Bitboard pawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]; if (pawns) score += popcount(pawns) * RookOnPawn; } if (ei.pi->semiopen_file(Us, file_of(s))) score += ei.pi->semiopen_file(Them, file_of(s)) ? RookOpenFile : RookSemiOpenFile; if (mob > 3 || ei.pi->semiopen_file(Us, file_of(s))) continue; Square ksq = pos.king_square(Us); if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq))) && (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1) && !ei.pi->semiopen_side(Us, file_of(ksq), file_of(s) < file_of(ksq))) score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us)); } if ( Pt == BISHOP && pos.is_chess960() && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1))) { Square d = pawn_push(Us) + (file_of(s) == FILE_A ? DELTA_E : DELTA_W); if (pos.piece_on(s + d) == make_piece(Us, PAWN)) score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4 : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2 : TrappedBishopA1H1; } } if (Trace) Tracing::write(Pt, Us, score); return score - evaluate_pieces(pos, ei, mobility, mobilityArea); } template<> Score evaluate_pieces(const Position&, EvalInfo&, Score*, Bitboard*) { return SCORE_ZERO; } template<> Score evaluate_pieces(const Position&, EvalInfo&, Score*, Bitboard*) { return SCORE_ZERO; } template Score evaluate_king(const Position& pos, const EvalInfo& ei) { const Color Them = (Us == WHITE ? BLACK : WHITE); Bitboard undefended, b, b1, b2, safe; int attackUnits; const Square ksq = pos.king_square(Us); Score score = ei.pi->king_safety(pos, ksq); if (ei.kingAttackersCount[Them]) { undefended = ei.attackedBy[Them][ALL_PIECES] & ei.attackedBy[Us][KING] & ~( ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK] | ei.attackedBy[Us][QUEEN]); attackUnits = std::min(20, (ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) / 2) + 3 * (ei.kingAdjacentZoneAttacksCount[Them] + popcount(undefended)) + 2 * (ei.pinnedPieces[Us] != 0) - mg_value(score) / 32 - !pos.count(Them) * 15; b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them); if (b) { b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT] | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]); if (b) attackUnits += QueenContactCheck * popcount(b); } b = undefended & ei.attackedBy[Them][ROOK] & ~pos.pieces(Them); b &= PseudoAttacks[ROOK][ksq]; if (b) { b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT] | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]); if (b) attackUnits += RookContactCheck * popcount(b); } safe = ~(pos.pieces(Them) | ei.attackedBy[Us][ALL_PIECES]); b1 = pos.attacks_from(ksq) & safe; b2 = pos.attacks_from(ksq) & safe; b = (b1 | b2) & ei.attackedBy[Them][QUEEN]; if (b) attackUnits += QueenCheck * popcount(b); b = b1 & ei.attackedBy[Them][ROOK]; if (b) attackUnits += RookCheck * popcount(b); b = b2 & ei.attackedBy[Them][BISHOP]; if (b) attackUnits += BishopCheck * popcount(b); b = pos.attacks_from(ksq) & ei.attackedBy[Them][KNIGHT] & safe; if (b) attackUnits += KnightCheck * popcount(b); attackUnits = std::min(99, std::max(0, attackUnits)); score -= KingDanger[attackUnits]; } if (Trace) Tracing::write(KING, Us, score); return score; } template Score evaluate_threats(const Position& pos, const EvalInfo& ei) { const Color Them = (Us == WHITE ? BLACK : WHITE); enum { Defended, Weak }; enum { Minor, Major }; Bitboard b, weak, defended; Score score = SCORE_ZERO; defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Them][PAWN]; if (defended) { b = defended & (ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]); while (b) score += Threat[Defended][Minor][type_of(pos.piece_on(pop_lsb(&b)))]; b = defended & (ei.attackedBy[Us][ROOK]); while (b) score += Threat[Defended][Major][type_of(pos.piece_on(pop_lsb(&b)))]; } weak = pos.pieces(Them) & ~ei.attackedBy[Them][PAWN] & ei.attackedBy[Us][ALL_PIECES]; if (weak) { b = weak & (ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP]); while (b) score += Threat[Weak][Minor][type_of(pos.piece_on(pop_lsb(&b)))]; b = weak & (ei.attackedBy[Us][ROOK] | ei.attackedBy[Us][QUEEN]); while (b) score += Threat[Weak][Major][type_of(pos.piece_on(pop_lsb(&b)))]; b = weak & ~ei.attackedBy[Them][ALL_PIECES]; if (b) score += more_than_one(b) ? Hanging * popcount(b) : Hanging; b = weak & ei.attackedBy[Us][KING]; if (b) score += more_than_one(b) ? KingOnMany : KingOnOne; } if (Trace) Tracing::write(Tracing::THREAT, Us, score); return score; } template Score evaluate_passed_pawns(const Position& pos, const EvalInfo& ei) { const Color Them = (Us == WHITE ? BLACK : WHITE); Bitboard b, squaresToQueen, defendedSquares, unsafeSquares; Score score = SCORE_ZERO; b = ei.pi->passed_pawns(Us); while (b) { Square s = pop_lsb(&b); assert(pos.pawn_passed(Us, s)); int r = relative_rank(Us, s) - RANK_2; int rr = r * (r - 1); Value mbonus = Value(17 * rr), ebonus = Value(7 * (rr + r + 1)); if (rr) { Square blockSq = s + pawn_push(Us); ebonus += distance(pos.king_square(Them), blockSq) * 5 * rr - distance(pos.king_square(Us ), blockSq) * 2 * rr; if (relative_rank(Us, blockSq) != RANK_8) ebonus -= distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr; if (pos.empty(blockSq)) { defendedSquares = unsafeSquares = squaresToQueen = forward_bb(Us, s); Bitboard bb = forward_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from(s); if (!(pos.pieces(Us) & bb)) defendedSquares &= ei.attackedBy[Us][ALL_PIECES]; if (!(pos.pieces(Them) & bb)) unsafeSquares &= ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them); int k = !unsafeSquares ? 15 : !(unsafeSquares & blockSq) ? 9 : 0; if (defendedSquares == squaresToQueen) k += 6; else if (defendedSquares & blockSq) k += 4; mbonus += k * rr, ebonus += k * rr; } else if (pos.pieces(Us) & blockSq) mbonus += rr * 3 + r * 2 + 3, ebonus += rr + r * 2; } // rr != 0 if (pos.count(Us) < pos.count(Them)) ebonus += ebonus / 4; score += make_score(mbonus, ebonus); } if (Trace) Tracing::write(Tracing::PASSED, Us, apply_weight(score, Weights[PassedPawns])); return apply_weight(score, Weights[PassedPawns]); } Score evaluate_unstoppable_pawns(Color us, const EvalInfo& ei) { Bitboard b = ei.pi->passed_pawns(us); return b ? Unstoppable * int(relative_rank(us, frontmost_sq(us, b))) : SCORE_ZERO; } template int evaluate_space(const Position& pos, const EvalInfo& ei) { const Color Them = (Us == WHITE ? BLACK : WHITE); Bitboard safe = SpaceMask[Us] & ~pos.pieces(Us, PAWN) & ~ei.attackedBy[Them][PAWN] & (ei.attackedBy[Us][ALL_PIECES] | ~ei.attackedBy[Them][ALL_PIECES]); Bitboard behind = pos.pieces(Us, PAWN); behind |= (Us == WHITE ? behind >> 8 : behind << 8); behind |= (Us == WHITE ? behind >> 16 : behind << 16); assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0); return popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe)); } template Value do_evaluate(const Position& pos) { assert(!pos.checkers()); EvalInfo ei; Score score, mobility[2] = { SCORE_ZERO, SCORE_ZERO }; Thread* thisThread = pos.this_thread(); score = pos.psq_score(); ei.mi = Material::probe(pos, thisThread->materialTable, thisThread->endgames); score += ei.mi->material_value(); if (ei.mi->specialized_eval_exists()) return ei.mi->evaluate(pos) + Eval::Tempo; ei.pi = Pawns::probe(pos, thisThread->pawnsTable); score += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]); init_eval_info(pos, ei); init_eval_info(pos, ei); ei.attackedBy[WHITE][ALL_PIECES] |= ei.attackedBy[WHITE][KING]; ei.attackedBy[BLACK][ALL_PIECES] |= ei.attackedBy[BLACK][KING]; Bitboard mobilityArea[] = { ~(ei.attackedBy[BLACK][PAWN] | pos.pieces(WHITE, PAWN, KING)), ~(ei.attackedBy[WHITE][PAWN] | pos.pieces(BLACK, PAWN, KING)) }; score += evaluate_pieces(pos, ei, mobility, mobilityArea); score += apply_weight(mobility[WHITE] - mobility[BLACK], Weights[Mobility]); score += evaluate_king(pos, ei) - evaluate_king(pos, ei); score += evaluate_threats(pos, ei) - evaluate_threats(pos, ei); score += evaluate_passed_pawns(pos, ei) - evaluate_passed_pawns(pos, ei); if (!pos.non_pawn_material(WHITE) && !pos.non_pawn_material(BLACK)) score += evaluate_unstoppable_pawns(WHITE, ei) - evaluate_unstoppable_pawns(BLACK, ei); if (ei.mi->space_weight()) { int s = evaluate_space(pos, ei) - evaluate_space(pos, ei); score += apply_weight(s * ei.mi->space_weight(), Weights[Space]); } Color strongSide = eg_value(score) > VALUE_DRAW ? WHITE : BLACK; ScaleFactor sf = ei.mi->scale_factor(pos, strongSide); if ( ei.mi->game_phase() < PHASE_MIDGAME && (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN)) { if (pos.opposite_bishops()) { if ( pos.non_pawn_material(WHITE) == BishopValueMg && pos.non_pawn_material(BLACK) == BishopValueMg) sf = more_than_one(pos.pieces(PAWN)) ? ScaleFactor(32) : ScaleFactor(8); else sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL); } else if ( abs(eg_value(score)) <= BishopValueEg && ei.pi->pawn_span(strongSide) <= 1 && !pos.pawn_passed(~strongSide, pos.king_square(~strongSide))) sf = ei.pi->pawn_span(strongSide) ? ScaleFactor(56) : ScaleFactor(38); } Value v = mg_value(score) * int(ei.mi->game_phase()) + eg_value(score) * int(PHASE_MIDGAME - ei.mi->game_phase()) * sf / SCALE_FACTOR_NORMAL; v /= int(PHASE_MIDGAME); if (Trace) { Tracing::write(Tracing::MATERIAL, pos.psq_score()); Tracing::write(Tracing::IMBALANCE, ei.mi->material_value()); Tracing::write(PAWN, ei.pi->pawns_value()); Tracing::write(Tracing::MOBILITY, apply_weight(mobility[WHITE], Weights[Mobility]) , apply_weight(mobility[BLACK], Weights[Mobility])); Score w = ei.mi->space_weight() * evaluate_space(pos, ei); Score b = ei.mi->space_weight() * evaluate_space(pos, ei); Tracing::write(Tracing::SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space])); Tracing::write(Tracing::TOTAL, score); Tracing::ei = ei; Tracing::sf = sf; } return (pos.side_to_move() == WHITE ? v : -v) + Eval::Tempo; } double Tracing::to_cp(Value v) { return double(v) / PawnValueEg; } void Tracing::write(int idx, Color c, Score s) { scores[c][idx] = s; } void Tracing::write(int idx, Score w, Score b) { write(idx, WHITE, w); write(idx, BLACK, b); } void Tracing::print(std::stringstream& ss, const char* name, int idx) { Score wScore = scores[WHITE][idx]; Score bScore = scores[BLACK][idx]; switch (idx) { case MATERIAL: case IMBALANCE: case PAWN: case TOTAL: ss << std::setw(15) << name << " | --- --- | --- --- | " << std::setw(5) << to_cp(mg_value(wScore - bScore)) << " " << std::setw(5) << to_cp(eg_value(wScore - bScore)) << " \n"; break; default: ss << std::setw(15) << name << " | " << std::noshowpos << std::setw(5) << to_cp(mg_value(wScore)) << " " << std::setw(5) << to_cp(eg_value(wScore)) << " | " << std::setw(5) << to_cp(mg_value(bScore)) << " " << std::setw(5) << to_cp(eg_value(bScore)) << " | " << std::setw(5) << to_cp(mg_value(wScore - bScore)) << " " << std::setw(5) << to_cp(eg_value(wScore - bScore)) << " \n"; } } std::string Tracing::do_trace(const Position& pos) { std::memset(scores, 0, sizeof(scores)); Value v = do_evaluate(pos); v = pos.side_to_move() == WHITE ? v : -v; // White's point of view std::stringstream ss; ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2) << " Eval term | White | Black | Total \n" << " | MG EG | MG EG | MG EG \n" << "----------------+-------------+-------------+-------------\n"; print(ss, "Material", MATERIAL); print(ss, "Imbalance", IMBALANCE); print(ss, "Pawns", PAWN); print(ss, "Knights", KNIGHT); print(ss, "Bishops", BISHOP); print(ss, "Rooks", ROOK); print(ss, "Queens", QUEEN); print(ss, "Mobility", MOBILITY); print(ss, "King safety", KING); print(ss, "Threats", THREAT); print(ss, "Passed pawns", PASSED); print(ss, "Space", SPACE); ss << "----------------+-------------+-------------+-------------\n"; print(ss, "Total", TOTAL); ss << "\nTotal Evaluation: " << to_cp(v) << " (white side)\n"; return ss.str(); } } // namespace namespace Eval { Value evaluate(const Position& pos) { return do_evaluate(pos); } std::string trace(const Position& pos) { return Tracing::do_trace(pos); } void init() { const double MaxSlope = 30; const double Peak = 1280; for (int t = 0, i = 1; i < 100; ++i) { t = int(std::min(Peak, std::min(0.4 * i * i, t + MaxSlope))); KingDanger[i] = apply_weight(make_score(t, 0), Weights[KingSafety]); } } }