mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 00:33:09 +00:00
Asymmetry bonus for the attacking side
Use asymmetry in the position (king separation, pawn structure) to compute an "initiative bonus" for the attacking side. Passed STC: LLR: 2.95 (-2.94,2.94) [0.00,5.00] Total: 14563 W: 2826 L: 2636 D: 9101 And LTC: LLR: 2.96 (-2.94,2.94) [0.00,5.00] Total: 14363 W: 2317 L: 2141 D: 9905 Bench: 8116244 Resolves #462
This commit is contained in:
parent
8fd34d7763
commit
7ea5659c5f
3 changed files with 27 additions and 5 deletions
|
@ -686,6 +686,27 @@ namespace {
|
|||
return make_score(bonus * weight * weight, 0);
|
||||
}
|
||||
|
||||
|
||||
// evaluate_initiative() computes the initiative correction value for the position, i.e.
|
||||
// second order bonus/malus based on the known attacking/defending status of the players.
|
||||
Score evaluate_initiative(const Position& pos, const EvalInfo& ei, const Score positional_score) {
|
||||
|
||||
int pawns = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK);
|
||||
int king_separation = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK));
|
||||
int asymmetry = ei.pi->pawn_asymmetry();
|
||||
|
||||
// Compute the initiative bonus for the attacking side
|
||||
int attacker_bonus = 8 * (pawns + asymmetry + king_separation) - 120;
|
||||
|
||||
// Now apply the bonus: note that we find the attacking side by extracting the sign
|
||||
// of the endgame value of "positional_score", and that we carefully cap the bonus so
|
||||
// that the endgame score with the correction will never be divided by more than two.
|
||||
int eg = eg_value(positional_score);
|
||||
int value = ((eg > 0) - (eg < 0)) * std::max( attacker_bonus , -abs( eg / 2 ) );
|
||||
|
||||
return make_score( 0 , value ) ;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
@ -767,6 +788,9 @@ Value Eval::evaluate(const Position& pos) {
|
|||
// Evaluate space for both sides, only during opening
|
||||
if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 12222)
|
||||
score += (evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei)) * Weights[Space];
|
||||
|
||||
// Evaluate initiative
|
||||
score += evaluate_initiative(pos, ei, score);
|
||||
|
||||
// Scale winning side if position is more drawish than it appears
|
||||
Color strongSide = eg_value(score) > VALUE_DRAW ? WHITE : BLACK;
|
||||
|
@ -798,11 +822,6 @@ Value Eval::evaluate(const Position& pos) {
|
|||
sf = ei.pi->pawn_span(strongSide) ? ScaleFactor(51) : ScaleFactor(37);
|
||||
}
|
||||
|
||||
// Scale endgame by number of pawns
|
||||
int p = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK);
|
||||
int v_eg = 1 + abs(int(eg_value(score)));
|
||||
sf = ScaleFactor(std::max(sf / 2, sf - 8 * SCALE_FACTOR_NORMAL * (12 - p) / v_eg));
|
||||
|
||||
// Interpolate between a middlegame and a (scaled by 'sf') endgame score
|
||||
Value v = mg_value(score) * int(me->game_phase())
|
||||
+ eg_value(score) * int(PHASE_MIDGAME - me->game_phase()) * sf / SCALE_FACTOR_NORMAL;
|
||||
|
|
|
@ -243,6 +243,7 @@ Entry* probe(const Position& pos) {
|
|||
|
||||
e->key = key;
|
||||
e->score = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e);
|
||||
e->asymmetry = popcount<Max15>( e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK] );
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ struct Entry {
|
|||
Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
|
||||
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
|
||||
int pawn_span(Color c) const { return pawnSpan[c]; }
|
||||
int pawn_asymmetry() const { return asymmetry; }
|
||||
|
||||
int semiopen_file(Color c, File f) const {
|
||||
return semiopenFiles[c] & (1 << f);
|
||||
|
@ -71,6 +72,7 @@ struct Entry {
|
|||
int semiopenFiles[COLOR_NB];
|
||||
int pawnSpan[COLOR_NB];
|
||||
int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
|
||||
int asymmetry;
|
||||
};
|
||||
|
||||
typedef HashTable<Entry, 16384> Table;
|
||||
|
|
Loading…
Add table
Reference in a new issue