X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=4d47b7e6df64a681bdc1b979626a04d942643d32;hp=9bd403e1bf8ab1100284eec6d27f791f5b3b6bcc;hb=0439a79566d03065317b2025b9b479b9ae9f2d65;hpb=d1e18fc7dd78a3f5223162dfc79c26baaefcf69e diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 9bd403e1..4d47b7e6 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -36,8 +36,8 @@ namespace { struct EvalInfo { // Pointers to material and pawn hash table entries - MaterialInfo* mi; - PawnInfo* pi; + MaterialEntry* mi; + PawnEntry* pi; // attackedBy[color][piece type] is a bitboard representing all squares // attacked by a given color and piece type, attackedBy[color][0] contains @@ -167,8 +167,8 @@ namespace { // happen in Chess960 games. const Score TrappedBishopA1H1Penalty = make_score(100, 100); - // Penalty for a minor piece that is not defended by anything - const Score UndefendedMinorPenalty = make_score(25, 10); + // Penalty for BNR that is not defended by anything + const Score UndefendedPiecePenalty = make_score(25, 10); // The SpaceMask[Color] contains the area of the board which is considered // by the space evaluation. In the middle game, each side is given a bonus @@ -250,8 +250,7 @@ namespace { Score evaluate_unstoppable_pawns(const Position& pos, EvalInfo& ei); - inline Score apply_weight(Score v, Score weight); - Value scale_by_game_phase(const Score& v, Phase ph, ScaleFactor sf); + Value interpolate(const Score& v, Phase ph, ScaleFactor sf); Score weight_option(const std::string& mgOpt, const std::string& egOpt, Score internalWeight); double to_cp(Value v); void trace_add(int idx, Score term_w, Score term_b = SCORE_ZERO); @@ -357,23 +356,22 @@ namespace { template Value do_evaluate(const Position& pos, Value& margin) { + assert(!pos.in_check()); + EvalInfo ei; Value margins[2]; Score score, mobilityWhite, mobilityBlack; - assert(pos.thread() >= 0 && pos.thread() < MAX_THREADS); - assert(!pos.in_check()); - // Initialize score by reading the incrementally updated scores included // in the position object (material + piece square tables). - score = pos.value(); + score = pos.psq_score(); // margins[] store the uncertainty estimation of position's evaluation // that typically is used by the search for pruning decisions. margins[WHITE] = margins[BLACK] = VALUE_ZERO; // Probe the material hash table - ei.mi = Threads[pos.thread()].materialTable.material_info(pos); + ei.mi = Threads[pos.this_thread()].materialTable.probe(pos); score += ei.mi->material_value(); // If we have a specialized evaluation function for the current material @@ -385,7 +383,7 @@ Value do_evaluate(const Position& pos, Value& margin) { } // Probe the pawn hash table - ei.pi = Threads[pos.thread()].pawnTable.pawn_info(pos); + ei.pi = Threads[pos.this_thread()].pawnTable.probe(pos); score += ei.pi->pawns_value(); // Initialize attack and king safety bitboards @@ -429,7 +427,7 @@ Value do_evaluate(const Position& pos, Value& margin) { // If we don't already have an unusual scale factor, check for opposite // colored bishop endgames, and use a lower scale for those. if ( ei.mi->game_phase() < PHASE_MIDGAME - && pos.opposite_colored_bishops() + && pos.opposite_bishops() && sf == SCALE_FACTOR_NORMAL) { // Only the two bishops ? @@ -447,14 +445,13 @@ Value do_evaluate(const Position& pos, Value& margin) { sf = ScaleFactor(50); } - // Interpolate between the middle game and the endgame score margin = margins[pos.side_to_move()]; - Value v = scale_by_game_phase(score, ei.mi->game_phase(), sf); + Value v = interpolate(score, ei.mi->game_phase(), sf); // In case of tracing add all single evaluation contributions for both white and black if (Trace) { - trace_add(PST, pos.value()); + trace_add(PST, pos.psq_score()); trace_add(IMBALANCE, ei.mi->material_value()); trace_add(PAWN, ei.pi->pawns_value()); trace_add(MOBILITY, apply_weight(mobilityWhite, Weights[Mobility]), apply_weight(mobilityBlack, Weights[Mobility])); @@ -613,7 +610,7 @@ Value do_evaluate(const Position& pos, Value& margin) { Square d = pawn_push(Us) + (file_of(s) == FILE_A ? DELTA_E : DELTA_W); if (pos.piece_on(s + d) == make_piece(Us, PAWN)) { - if (!pos.square_is_empty(s + d + pawn_push(Us))) + if (!pos.square_empty(s + d + pawn_push(Us))) score -= 2*TrappedBishopA1H1Penalty; else if (pos.piece_on(s + 2*d) == make_piece(Us, PAWN)) score -= TrappedBishopA1H1Penalty; @@ -679,23 +676,24 @@ Value do_evaluate(const Position& pos, Value& margin) { const Color Them = (Us == WHITE ? BLACK : WHITE); - Bitboard b; + Bitboard b, undefended, undefendedMinors, weakEnemies; Score score = SCORE_ZERO; - // Undefended minors get penalized even if not under attack - const Bitboard undefended = pos.pieces(Them) - & (pos.pieces(BISHOP) | pos.pieces(KNIGHT)) - & ~ei.attackedBy[Them][0]; - if (undefended) { - score += UndefendedMinorPenalty; - if (!single_bit(undefended)) - score += UndefendedMinorPenalty; - } + // Undefended pieces get penalized even if not under attack + undefended = pos.pieces(Them) & ~ei.attackedBy[Them][0]; + undefendedMinors = undefended & (pos.pieces(BISHOP) | pos.pieces(KNIGHT)); + + if (undefendedMinors) + score += single_bit(undefendedMinors) ? UndefendedPiecePenalty + : UndefendedPiecePenalty * 2; + if (undefended & pos.pieces(ROOK)) + score += UndefendedPiecePenalty; // Enemy pieces not defended by a pawn and under our attack - const Bitboard weakEnemies = pos.pieces(Them) - & ~ei.attackedBy[Them][PAWN] - & ei.attackedBy[Us][0]; + weakEnemies = pos.pieces(Them) + & ~ei.attackedBy[Them][PAWN] + & ei.attackedBy[Us][0]; + if (!weakEnemies) return score; @@ -751,8 +749,8 @@ Value do_evaluate(const Position& pos, Value& margin) { int attackUnits; const Square ksq = pos.king_square(Us); - // King shelter - Score score = ei.pi->king_shelter(pos, ksq); + // King shelter and enemy pawns storm + Score score = ei.pi->king_safety(pos, ksq); // King safety. This is quite complicated, and is almost certainly far // from optimally tuned. @@ -774,7 +772,7 @@ Value do_evaluate(const Position& pos, Value& margin) { attackUnits = std::min(25, (ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) / 2) + 3 * (ei.kingAdjacentZoneAttacksCount[Them] + popcount(undefended)) + InitKingDanger[relative_square(Us, ksq)] - - mg_value(ei.pi->king_shelter(pos, ksq)) / 32; + - mg_value(ei.pi->king_safety(pos, ksq)) / 32; // Analyse enemy's safe queen contact checks. First find undefended // squares around the king attacked by enemy queen... @@ -893,7 +891,7 @@ Value do_evaluate(const Position& pos, Value& margin) { ebonus -= Value(square_distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr); // If the pawn is free to advance, increase bonus - if (pos.square_is_empty(blockSq)) + if (pos.square_empty(blockSq)) { squaresToQueen = squares_in_front_of(Us, s); defendedSquares = squaresToQueen & ei.attackedBy[Us][0]; @@ -1140,18 +1138,10 @@ Value do_evaluate(const Position& pos, Value& margin) { } - // apply_weight() applies an evaluation weight to a value trying to prevent overflow - - inline Score apply_weight(Score v, Score w) { - return make_score((int(mg_value(v)) * mg_value(w)) / 0x100, - (int(eg_value(v)) * eg_value(w)) / 0x100); - } - - - // scale_by_game_phase() interpolates between a middle game and an endgame score, + // interpolate() 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(const Score& v, Phase ph, ScaleFactor sf) { + Value interpolate(const Score& v, Phase ph, ScaleFactor sf) { assert(mg_value(v) > -VALUE_INFINITE && mg_value(v) < VALUE_INFINITE); assert(eg_value(v) > -VALUE_INFINITE && eg_value(v) < VALUE_INFINITE);