mirror of
https://github.com/sockspls/badfish
synced 2025-04-29 16:23:09 +00:00
Use score and value consistently
And other assorted small fixing, code style tweaks and reshuffles in evaluate.cpp No functional change.
This commit is contained in:
parent
f9571e8d57
commit
6933f05f4b
5 changed files with 98 additions and 106 deletions
176
src/evaluate.cpp
176
src/evaluate.cpp
|
@ -94,7 +94,7 @@ namespace {
|
|||
{289, 344}, {233, 201}, {221, 273}, {46, 0}, {318, 0}
|
||||
};
|
||||
|
||||
typedef Value V;
|
||||
#define V(v) Value(v)
|
||||
#define S(mg, eg) make_score(mg, eg)
|
||||
|
||||
// MobilityBonus[PieceType][attacked] contains bonuses for middle and end
|
||||
|
@ -152,16 +152,16 @@ namespace {
|
|||
};
|
||||
|
||||
// Assorted bonuses and penalties used by evaluation
|
||||
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 KingOnOne = S( 2, 58);
|
||||
const Score KingOnMany = S( 6,125);
|
||||
const Score RookOnPawn = S( 7, 27);
|
||||
const Score RookOnOpenFile = S(43, 21);
|
||||
const Score RookOnSemiOpenFile = 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);
|
||||
|
||||
// Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by
|
||||
// a friendly pawn on b2/g2 (b7/g7 for black). This can obviously only
|
||||
|
@ -169,6 +169,7 @@ namespace {
|
|||
const Score TrappedBishopA1H1 = S(50, 50);
|
||||
|
||||
#undef S
|
||||
#undef V
|
||||
|
||||
// SpaceMask[Color] contains the area of the board which is considered
|
||||
// by the space evaluation. In the middlegame, each side is given a bonus
|
||||
|
@ -179,8 +180,8 @@ namespace {
|
|||
(FileCBB | FileDBB | FileEBB | FileFBB) & (Rank7BB | Rank6BB | Rank5BB)
|
||||
};
|
||||
|
||||
// King danger constants and variables. The king danger scores are taken
|
||||
// from KingDanger[]. Various little "meta-bonuses" measuring the strength
|
||||
// King danger constants and variables. The king danger scores are looked-up
|
||||
// in KingDanger[]. Various little "meta-bonuses" measuring the strength
|
||||
// of the enemy attack are added up into an integer, which is used as an
|
||||
// index to KingDanger[].
|
||||
//
|
||||
|
@ -199,9 +200,9 @@ namespace {
|
|||
// scores, indexed by a calculated integer number.
|
||||
Score KingDanger[128];
|
||||
|
||||
// apply_weight() weighs score 'v' by weight 'w' trying to prevent overflow
|
||||
Score apply_weight(Score v, const Weight& w) {
|
||||
return make_score(mg_value(v) * w.mg / 256, eg_value(v) * w.eg / 256);
|
||||
// apply_weight() weighs score 's' by weight 'w' trying to prevent overflow
|
||||
Score apply_weight(Score s, const Weight& w) {
|
||||
return make_score(mg_value(s) * w.mg / 256, eg_value(s) * w.eg / 256);
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,65 +313,65 @@ namespace {
|
|||
|
||||
if (Pt == BISHOP || Pt == KNIGHT)
|
||||
{
|
||||
// Penalty for bishop with same colored pawns
|
||||
if (Pt == BISHOP)
|
||||
score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s);
|
||||
|
||||
// Bishop and knight outpost square
|
||||
// Bonus for outpost square
|
||||
if (!(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s)))
|
||||
score += evaluate_outpost<Pt, Us>(pos, ei, s);
|
||||
|
||||
// Bishop or knight behind a pawn
|
||||
// Bonus when behind a pawn
|
||||
if ( relative_rank(Us, s) < RANK_5
|
||||
&& (pos.pieces(PAWN) & (s + pawn_push(Us))))
|
||||
score += MinorBehindPawn;
|
||||
|
||||
// Penalty for pawns on same color square of bishop
|
||||
if (Pt == BISHOP)
|
||||
score -= BishopPawns * ei.pi->pawns_on_same_color_squares(Us, s);
|
||||
|
||||
// An important Chess960 pattern: A cornered bishop blocked by a friendly
|
||||
// pawn diagonally in front of it is a very serious problem, especially
|
||||
// when that pawn is also blocked.
|
||||
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 (Pt == ROOK)
|
||||
{
|
||||
// Rook piece attacking enemy pawns on the same rank/file
|
||||
// Bonus for aligning with enemy pawns on the same rank/file
|
||||
if (relative_rank(Us, s) >= RANK_5)
|
||||
{
|
||||
Bitboard pawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s];
|
||||
if (pawns)
|
||||
score += popcount<Max15>(pawns) * RookOnPawn;
|
||||
Bitboard alignedPawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s];
|
||||
if (alignedPawns)
|
||||
score += popcount<Max15>(alignedPawns) * RookOnPawn;
|
||||
}
|
||||
|
||||
// Give a bonus for a rook on a open or semi-open file
|
||||
// Bonus when on an open or semi-open file
|
||||
if (ei.pi->semiopen_file(Us, file_of(s)))
|
||||
score += ei.pi->semiopen_file(Them, file_of(s)) ? RookOpenFile : RookSemiOpenFile;
|
||||
score += ei.pi->semiopen_file(Them, file_of(s)) ? RookOnOpenFile : RookOnSemiOpenFile;
|
||||
|
||||
if (mob > 3 || ei.pi->semiopen_file(Us, file_of(s)))
|
||||
continue;
|
||||
// Penalize when trapped by the king, even more if king cannot castle
|
||||
if (mob <= 3 && !ei.pi->semiopen_file(Us, file_of(s)))
|
||||
{
|
||||
Square ksq = pos.king_square(Us);
|
||||
|
||||
Square ksq = pos.king_square(Us);
|
||||
|
||||
// Penalize rooks which are trapped by a king. Penalize more if the
|
||||
// king has lost its castling capability.
|
||||
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));
|
||||
}
|
||||
|
||||
// An important Chess960 pattern: A cornered bishop blocked by a friendly
|
||||
// pawn diagonally in front of it is a very serious problem, especially
|
||||
// when that pawn is also blocked.
|
||||
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 ( ((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 (Trace)
|
||||
Tracing::write(Pt, Us, score);
|
||||
|
||||
// Recursively call evaluate_pieces() of next piece type until KING excluded
|
||||
return score - evaluate_pieces<NextPt, Them, Trace>(pos, ei, mobility, mobilityArea);
|
||||
}
|
||||
|
||||
|
@ -406,7 +407,7 @@ namespace {
|
|||
| ei.attackedBy[Us][QUEEN]);
|
||||
|
||||
// Initialize the 'attackUnits' variable, which is used later on as an
|
||||
// index to the KingDanger[] array. The initial value is based on the
|
||||
// index into the KingDanger[] array. The initial value is based on the
|
||||
// number and types of the enemy's attacking pieces, the number of
|
||||
// attacked and undefended squares around our king and the quality of
|
||||
// the pawn shelter (current 'score' value).
|
||||
|
@ -417,22 +418,20 @@ namespace {
|
|||
- !pos.count<QUEEN>(Them) * 15;
|
||||
|
||||
// Analyse the enemy's safe queen contact checks. Firstly, find the
|
||||
// undefended squares around the king that are attacked by the enemy's
|
||||
// queen...
|
||||
// undefended squares around the king reachable by the enemy queen...
|
||||
b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them);
|
||||
if (b)
|
||||
{
|
||||
// ...and then remove squares not supported by another enemy piece
|
||||
b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT]
|
||||
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]);
|
||||
b &= ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT]
|
||||
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK];
|
||||
|
||||
if (b)
|
||||
attackUnits += QueenContactCheck * popcount<Max15>(b);
|
||||
attackUnits += QueenContactCheck * popcount<Max15>(b);
|
||||
}
|
||||
|
||||
// Analyse the enemy's safe rook contact checks. Firstly, find the
|
||||
// undefended squares around the king that are attacked by the enemy's
|
||||
// rooks...
|
||||
// undefended squares around the king reachable by the enemy rooks...
|
||||
b = undefended & ei.attackedBy[Them][ROOK] & ~pos.pieces(Them);
|
||||
|
||||
// Consider only squares where the enemy's rook gives check
|
||||
|
@ -445,13 +444,13 @@ namespace {
|
|||
| ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]);
|
||||
|
||||
if (b)
|
||||
attackUnits += RookContactCheck * popcount<Max15>(b);
|
||||
attackUnits += RookContactCheck * popcount<Max15>(b);
|
||||
}
|
||||
|
||||
// Analyse the enemy's safe distance checks for sliders and knights
|
||||
safe = ~(pos.pieces(Them) | ei.attackedBy[Us][ALL_PIECES]);
|
||||
safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them));
|
||||
|
||||
b1 = pos.attacks_from<ROOK>(ksq) & safe;
|
||||
b1 = pos.attacks_from<ROOK >(ksq) & safe;
|
||||
b2 = pos.attacks_from<BISHOP>(ksq) & safe;
|
||||
|
||||
// Enemy queen safe checks
|
||||
|
@ -474,12 +473,9 @@ namespace {
|
|||
if (b)
|
||||
attackUnits += KnightCheck * popcount<Max15>(b);
|
||||
|
||||
// To index KingDanger[] attackUnits must be in [0, 99] range
|
||||
attackUnits = std::min(99, std::max(0, attackUnits));
|
||||
|
||||
// Finally, extract the king danger score from the KingDanger[]
|
||||
// array and subtract the score from evaluation.
|
||||
score -= KingDanger[attackUnits];
|
||||
score -= KingDanger[std::max(std::min(attackUnits, 99), 0)];
|
||||
}
|
||||
|
||||
if (Trace)
|
||||
|
@ -635,18 +631,6 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
// evaluate_unstoppable_pawns() scores the most advanced passed pawn. In case
|
||||
// both players have no pieces but pawns, this is somewhat related to the
|
||||
// possibility that pawns are unstoppable.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// evaluate_space() computes the space evaluation for a given side. The
|
||||
// space evaluation is a simple bonus based on the number of safe squares
|
||||
// available for minor pieces on the central four files on ranks 2--4. Safe
|
||||
|
@ -654,7 +638,7 @@ namespace {
|
|||
// twice. Finally, the space bonus is scaled by a weight taken from the
|
||||
// material hash table. The aim is to improve play on game opening.
|
||||
template<Color Us>
|
||||
int evaluate_space(const Position& pos, const EvalInfo& ei) {
|
||||
Score evaluate_space(const Position& pos, const EvalInfo& ei, Score weight) {
|
||||
|
||||
const Color Them = (Us == WHITE ? BLACK : WHITE);
|
||||
|
||||
|
@ -675,7 +659,7 @@ namespace {
|
|||
assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0);
|
||||
|
||||
// Count safe + (behind & safe) with a single popcount
|
||||
return popcount<Full>((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe));
|
||||
return popcount<Full>((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe)) * weight;
|
||||
}
|
||||
|
||||
|
||||
|
@ -697,7 +681,7 @@ namespace {
|
|||
|
||||
// Probe the material hash table
|
||||
ei.mi = Material::probe(pos, thisThread->materialTable, thisThread->endgames);
|
||||
score += ei.mi->material_value();
|
||||
score += ei.mi->imbalance();
|
||||
|
||||
// If we have a specialized evaluation function for the current material
|
||||
// configuration, call it and return.
|
||||
|
@ -706,7 +690,7 @@ namespace {
|
|||
|
||||
// Probe the pawn hash table
|
||||
ei.pi = Pawns::probe(pos, thisThread->pawnsTable);
|
||||
score += apply_weight(ei.pi->pawns_value(), Weights[PawnStructure]);
|
||||
score += apply_weight(ei.pi->pawns_score(), Weights[PawnStructure]);
|
||||
|
||||
// Initialize attack and king safety bitboards
|
||||
init_eval_info<WHITE>(pos, ei);
|
||||
|
@ -738,14 +722,22 @@ namespace {
|
|||
|
||||
// If both sides have only pawns, score for potential unstoppable pawns
|
||||
if (!pos.non_pawn_material(WHITE) && !pos.non_pawn_material(BLACK))
|
||||
score += evaluate_unstoppable_pawns(WHITE, ei)
|
||||
- evaluate_unstoppable_pawns(BLACK, ei);
|
||||
{
|
||||
Bitboard b;
|
||||
if ((b = ei.pi->passed_pawns(WHITE)) != 0)
|
||||
score += int(relative_rank(WHITE, frontmost_sq(WHITE, b))) * Unstoppable;
|
||||
|
||||
if ((b = ei.pi->passed_pawns(BLACK)) != 0)
|
||||
score -= int(relative_rank(BLACK, frontmost_sq(BLACK, b))) * Unstoppable;
|
||||
}
|
||||
|
||||
// Evaluate space for both sides, only in middlegame
|
||||
if (ei.mi->space_weight())
|
||||
{
|
||||
int s = evaluate_space<WHITE>(pos, ei) - evaluate_space<BLACK>(pos, ei);
|
||||
score += apply_weight(s * ei.mi->space_weight(), Weights[Space]);
|
||||
Score s = evaluate_space<WHITE>(pos, ei, ei.mi->space_weight())
|
||||
- evaluate_space<BLACK>(pos, ei, ei.mi->space_weight());
|
||||
|
||||
score += apply_weight(s, Weights[Space]);
|
||||
}
|
||||
|
||||
// Scale winning side if position is more drawish than it appears
|
||||
|
@ -788,12 +780,12 @@ namespace {
|
|||
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::IMBALANCE, ei.mi->imbalance());
|
||||
Tracing::write(PAWN, ei.pi->pawns_score());
|
||||
Tracing::write(Tracing::MOBILITY, apply_weight(mobility[WHITE], Weights[Mobility])
|
||||
, apply_weight(mobility[BLACK], Weights[Mobility]));
|
||||
Score w = ei.mi->space_weight() * evaluate_space<WHITE>(pos, ei);
|
||||
Score b = ei.mi->space_weight() * evaluate_space<BLACK>(pos, ei);
|
||||
Score w = evaluate_space<WHITE>(pos, ei, ei.mi->space_weight());
|
||||
Score b = evaluate_space<BLACK>(pos, ei, ei.mi->space_weight());
|
||||
Tracing::write(Tracing::SPACE, apply_weight(w, Weights[Space]), apply_weight(b, Weights[Space]));
|
||||
Tracing::write(Tracing::TOTAL, score);
|
||||
Tracing::ei = ei;
|
||||
|
@ -894,7 +886,7 @@ namespace Eval {
|
|||
}
|
||||
|
||||
|
||||
/// init() computes evaluation weights.
|
||||
/// init() computes evaluation weights, usually at startup
|
||||
|
||||
void init() {
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ using namespace std;
|
|||
|
||||
namespace {
|
||||
|
||||
// Polynomial material balance parameters
|
||||
// Polynomial material imbalance parameters
|
||||
|
||||
// pair pawn knight bishop rook queen
|
||||
const int Linear[6] = { 1852, -162, -1122, -183, 249, -154 };
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
namespace Material {
|
||||
|
||||
/// Material::Entry contains various information about a material configuration.
|
||||
/// It contains a material balance evaluation, a function pointer to a special
|
||||
/// It contains a material imbalance evaluation, a function pointer to a special
|
||||
/// endgame evaluation function (which in most cases is NULL, meaning that the
|
||||
/// standard evaluation function will be used), and "scale factors".
|
||||
///
|
||||
|
@ -38,7 +38,7 @@ namespace Material {
|
|||
|
||||
struct Entry {
|
||||
|
||||
Score material_value() const { return make_score(value, value); }
|
||||
Score imbalance() const { return make_score(value, value); }
|
||||
Score space_weight() const { return spaceWeight; }
|
||||
Phase game_phase() const { return gamePhase; }
|
||||
bool specialized_eval_exists() const { return evaluationFunction != NULL; }
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace {
|
|||
Bitboard b, p, doubled, connected;
|
||||
Square s;
|
||||
bool passed, isolated, opposed, phalanx, backward, unsupported, lever;
|
||||
Score value = SCORE_ZERO;
|
||||
Score score = SCORE_ZERO;
|
||||
const Square* pl = pos.list<PAWN>(Us);
|
||||
const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)];
|
||||
|
||||
|
@ -174,28 +174,28 @@ namespace {
|
|||
|
||||
// Score this pawn
|
||||
if (isolated)
|
||||
value -= Isolated[opposed][f];
|
||||
score -= Isolated[opposed][f];
|
||||
|
||||
if (unsupported && !isolated)
|
||||
value -= UnsupportedPawnPenalty;
|
||||
score -= UnsupportedPawnPenalty;
|
||||
|
||||
if (doubled)
|
||||
value -= Doubled[f] / distance<Rank>(s, frontmost_sq(Us, doubled));
|
||||
score -= Doubled[f] / distance<Rank>(s, frontmost_sq(Us, doubled));
|
||||
|
||||
if (backward)
|
||||
value -= Backward[opposed][f];
|
||||
score -= Backward[opposed][f];
|
||||
|
||||
if (connected)
|
||||
value += Connected[opposed][phalanx][relative_rank(Us, s)];
|
||||
score += Connected[opposed][phalanx][relative_rank(Us, s)];
|
||||
|
||||
if (lever)
|
||||
value += Lever[relative_rank(Us, s)];
|
||||
score += Lever[relative_rank(Us, s)];
|
||||
}
|
||||
|
||||
b = e->semiopenFiles[Us] ^ 0xFF;
|
||||
e->pawnSpan[Us] = b ? int(msb(b) - lsb(b)) : 0;
|
||||
|
||||
return value;
|
||||
return score;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -233,7 +233,7 @@ Entry* probe(const Position& pos, Table& entries) {
|
|||
return e;
|
||||
|
||||
e->key = key;
|
||||
e->value = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e);
|
||||
e->score = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Pawns {
|
|||
|
||||
struct Entry {
|
||||
|
||||
Score pawns_value() const { return value; }
|
||||
Score pawns_score() const { return score; }
|
||||
Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
|
||||
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
|
||||
|
||||
|
@ -65,7 +65,7 @@ struct Entry {
|
|||
Value shelter_storm(const Position& pos, Square ksq);
|
||||
|
||||
Key key;
|
||||
Score value;
|
||||
Score score;
|
||||
Bitboard passedPawns[COLOR_NB];
|
||||
Bitboard pawnAttacks[COLOR_NB];
|
||||
Square kingSquares[COLOR_NB];
|
||||
|
|
Loading…
Add table
Reference in a new issue