Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const vector<string> Defaults = {
"8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw

// 7-man positions
"8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw
"8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124" // Draw
};

} // namespace
Expand Down
2 changes: 1 addition & 1 deletion src/endgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace {
70, 50, 30, 20, 20, 30, 50, 70,
80, 60, 40, 30, 30, 40, 60, 80,
90, 70, 60, 50, 50, 60, 70, 90,
100, 90, 80, 70, 70, 80, 90, 100,
100, 90, 80, 70, 70, 80, 90, 100
};

// Table used to drive the king towards a corner square of the
Expand Down
79 changes: 40 additions & 39 deletions src/evaluate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ namespace {
enum { PawnStructure, PassedPawns, Space, KingSafety };

const struct Weight { int mg, eg; } Weights[] = {
{214, 203}, {193, 262}, {47, 0}, {330, 0}
};
{214, 203}, {193, 262}, {47, 0}, {330, 0} };

Score operator*(Score s, const Weight& w) {
return make_score(mg_value(s) * w.mg / 256, eg_value(s) * w.eg / 256);
Expand Down Expand Up @@ -156,19 +155,26 @@ namespace {
{ S( 8, 2), S(13, 4) } // Bishops
};

// Threat[minor/rook][attacked PieceType] contains
// RookOnFile[semiopen/open] contains bonuses for each rook when there is no
// friendly pawn on the rook file.
const Score RookOnFile[2] = { S(19, 10), S(43, 21) };

// ThreatBySafePawn[PieceType] contains bonuses according to which piece
// type is attacked by a pawn which is protected or not attacked.
const Score ThreatBySafePawn[PIECE_TYPE_NB] = {
S(0, 0), S(0, 0), S(176, 139), S(131, 127), S(217, 218), S(203, 215) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alignment on 2 spaces, not 3 (see other similar code)


// Threat[by minor/by rook][attacked PieceType] contains
// bonuses according to which piece type attacks which one.
// Attacks on lesser pieces which are pawn defended are not considered.
const Score Threat[2][PIECE_TYPE_NB] = {
{ S(0, 0), S(0, 33), S(45, 43), S(46, 47), S(72, 107), S(48,118) }, // Minor attacks
{ S(0, 0), S(0, 25), S(40, 62), S(40, 59), S( 0, 34), S(35, 48) } // Rook attacks
const Score Threat[][PIECE_TYPE_NB] = {
{ S(0, 0), S(0, 33), S(45, 43), S(46, 47), S(72,107), S(48,118) }, // by Minor
{ S(0, 0), S(0, 25), S(40, 62), S(40, 59), S( 0, 34), S(35, 48) } // by Rook
};

// ThreatenedByPawn[PieceType] contains a penalty according to which piece
// type is attacked by a pawn.
const Score ThreatenedByPawn[PIECE_TYPE_NB] = {
S(0, 0), S(0, 0), S(176, 139), S(131, 127), S(217, 218), S(203, 215)
};
// ThreatByKing[on one/on many] contains bonuses for King attacks on
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverse descrition , should be ThreatByKing[on many / on one]

// pawns or pieces which are not pawn defended.
const Score ThreatByKing[2] = { S(3, 62), S(9, 138) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need [2], just [] for consistency


// Passed[mg/eg][Rank] contains midgame and endgame bonuses for passed pawns.
// We don't use a Score because we process the two components independently.
Expand All @@ -177,27 +183,22 @@ namespace {
{ V(7), V(14), V(37), V(63), V(134), V(189) }
};

// PassedFile[File] contains a bonus according to the file of a passed pawn.
const Score PassedFile[] = {
S( 12, 10), S( 3, 10), S( 1, -8), S(-27, -12),
S(-27, -12), S( 1, -8), S( 3, 10), S( 12, 10)
// PassedFile[File] contains a bonus according to the file of a passed pawn
const Score PassedFile[FILE_NB] = {
S( 12, 10), S( 3, 10), S( 1, -8), S(-27,-12),
S(-27,-12), S( 1, -8), S( 3, 10), S( 12, 10)
};

const Score ThreatenedByHangingPawn = S(70, 63);

// Assorted bonuses and penalties used by evaluation
const Score KingOnOne = S( 3, 62);
const Score KingOnMany = S( 9,138);
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(48, 28);
const Score PawnAttackThreat = S(31, 19);
const Score Checked = S(20, 20);
const Score MinorBehindPawn = S(16, 0);
const Score BishopPawns = S( 8, 12);
const Score RookOnPawn = S( 7, 27);
const Score TrappedRook = S(92, 0);
const Score Checked = S(20, 20);
const Score ThreatByHangingPawn = S(70, 63);
const Score Hanging = S(48, 28);
const Score ThreatByPawnPush = S(31, 19);
const Score Unstoppable = S( 0, 20);

// 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
Expand Down Expand Up @@ -343,15 +344,15 @@ namespace {
{
Bitboard alignedPawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s];
if (alignedPawns)
score += popcount<Max15>(alignedPawns) * RookOnPawn;
score += RookOnPawn * popcount<Max15>(alignedPawns);
}

// 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)) ? RookOnOpenFile : RookOnSemiOpenFile;
score += RookOnFile[!!ei.pi->semiopen_file(Them, file_of(s))];

// Penalize when trapped by the king, even more if king cannot castle
if (mob <= 3 && !ei.pi->semiopen_file(Us, file_of(s)))
else if (mob <= 3)
{
Square ksq = pos.square<KING>(Us);

Expand Down Expand Up @@ -506,10 +507,10 @@ namespace {
safeThreats = (shift_bb<Right>(b) | shift_bb<Left>(b)) & weak;

if (weak ^ safeThreats)
score += ThreatenedByHangingPawn;
score += ThreatByHangingPawn;

while (safeThreats)
score += ThreatenedByPawn[type_of(pos.piece_on(pop_lsb(&safeThreats)))];
score += ThreatBySafePawn[type_of(pos.piece_on(pop_lsb(&safeThreats)))];
}

// Non-pawn enemies defended by a pawn
Expand Down Expand Up @@ -537,7 +538,7 @@ namespace {

b = weak & ei.attackedBy[Us][KING];
if (b)
score += more_than_one(b) ? KingOnMany : KingOnOne;
score += ThreatByKing[more_than_one(b)];
}

// Bonus if some pawns can safely push and attack an enemy piece
Expand All @@ -553,7 +554,7 @@ namespace {
& ~ei.attackedBy[Us][PAWN];

if (b)
score += popcount<Max15>(b) * PawnAttackThreat;
score += ThreatByPawnPush * popcount<Max15>(b);

if (DoTrace)
Trace::add(THREAT, Us, score);
Expand Down Expand Up @@ -811,10 +812,10 @@ Value Eval::evaluate(const Position& pos) {
{
Bitboard b;
if ((b = ei.pi->passed_pawns(WHITE)) != 0)
score += int(relative_rank(WHITE, frontmost_sq(WHITE, b))) * Unstoppable;
score += Unstoppable * int(relative_rank(WHITE, frontmost_sq(WHITE, b)));

if ((b = ei.pi->passed_pawns(BLACK)) != 0)
score -= int(relative_rank(BLACK, frontmost_sq(BLACK, b))) * Unstoppable;
score -= Unstoppable * int(relative_rank(BLACK, frontmost_sq(BLACK, b)));
}

// Evaluate space for both sides, only during opening
Expand All @@ -839,7 +840,7 @@ Value Eval::evaluate(const Position& pos) {
{
Trace::add(MATERIAL, pos.psq_score());
Trace::add(IMBALANCE, ei.me->imbalance());
Trace::add(PAWN, ei.pi->pawns_score());
Trace::add(PAWN, ei.pi->pawns_score() * Weights[PawnStructure]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one!

Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]);
Trace::add(SPACE, evaluate_space<WHITE>(pos, ei) * Weights[Space]
, evaluate_space<BLACK>(pos, ei) * Weights[Space]);
Expand Down
78 changes: 39 additions & 39 deletions src/pawns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,59 +31,60 @@ namespace {
#define V Value
#define S(mg, eg) make_score(mg, eg)

// Doubled pawn penalty by file
const Score Doubled[FILE_NB] = {
S(13, 43), S(20, 48), S(23, 48), S(23, 48),
S(23, 48), S(23, 48), S(20, 48), S(13, 43) };

// Isolated pawn penalty by opposed flag and file
const Score Isolated[2][FILE_NB] = {
{ S(37, 45), S(54, 52), S(60, 52), S(60, 52),
S(60, 52), S(60, 52), S(54, 52), S(37, 45) },
{ S(25, 30), S(36, 35), S(40, 35), S(40, 35),
S(40, 35), S(40, 35), S(36, 35), S(25, 30) } };
{ S(37, 45), S(54, 52), S(60, 52), S(60, 52),
S(60, 52), S(60, 52), S(54, 52), S(37, 45) },
{ S(25, 30), S(36, 35), S(40, 35), S(40, 35),
S(40, 35), S(40, 35), S(36, 35), S(25, 30) } };

// Backward pawn penalty by opposed flag
const Score Backward[2] = { S(67, 42), S(49, 24) };

// Unsupported pawn penalty, for pawns which are neither isolated or backward
const Score Unsupported = S(20, 10);

// Connected pawn bonus by opposed, phalanx, twice supported and rank
Score Connected[2][2][2][RANK_NB];

// Doubled pawn penalty by file
const Score Doubled[FILE_NB] = {
S(13, 43), S(20, 48), S(23, 48), S(23, 48),
S(23, 48), S(23, 48), S(20, 48), S(13, 43) };

// Levers bonus by rank
// Lever bonus by rank
const Score Lever[RANK_NB] = {
S( 0, 0), S( 0, 0), S(0, 0), S(0, 0),
S(20,20), S(40,40), S(0, 0), S(0, 0) };

// Unsupported pawn penalty
const Score UnsupportedPawnPenalty = S(20, 10);
S( 0, 0), S( 0, 0), S(0, 0), S(0, 0),
S(20, 20), S(40, 40), S(0, 0), S(0, 0) };

// Center bind bonus, when two pawns controls the same central square
const Score CenterBind = S(16, 0);

// Weakness of our pawn shelter in front of the king by [distance from edge][rank]
const Value ShelterWeakness[][RANK_NB] = {
{ V( 97), V(21), V(26), V(51), V(87), V( 89), V( 99) },
{ V(120), V( 0), V(28), V(76), V(88), V(103), V(104) },
{ V(101), V( 7), V(54), V(78), V(77), V( 92), V(101) },
{ V( 80), V(11), V(44), V(68), V(87), V( 90), V(119) } };
{ V( 97), V(21), V(26), V(51), V(87), V( 89), V( 99) },
{ V(120), V( 0), V(28), V(76), V(88), V(103), V(104) },
{ V(101), V( 7), V(54), V(78), V(77), V( 92), V(101) },
{ V( 80), V(11), V(44), V(68), V(87), V( 90), V(119) } };

// Danger of enemy pawns moving toward our king by [type][distance from edge][rank]
const Value StormDanger[][4][RANK_NB] = {
{ { V( 0), V( 67), V( 134), V(38), V(32) },
{ V( 0), V( 57), V( 139), V(37), V(22) },
{ V( 0), V( 43), V( 115), V(43), V(27) },
{ V( 0), V( 68), V( 124), V(57), V(32) } },
{ { V(20), V( 43), V( 100), V(56), V(20) },
{ V(23), V( 20), V( 98), V(40), V(15) },
{ V(23), V( 39), V( 103), V(36), V(18) },
{ V(28), V( 19), V( 108), V(42), V(26) } },
{ { V( 0), V( 0), V( 75), V(14), V( 2) },
{ V( 0), V( 0), V( 150), V(30), V( 4) },
{ V( 0), V( 0), V( 160), V(22), V( 5) },
{ V( 0), V( 0), V( 166), V(24), V(13) } },
{ { V( 0), V(-283), V(-281), V(57), V(31) },
{ V( 0), V( 58), V( 141), V(39), V(18) },
{ V( 0), V( 65), V( 142), V(48), V(32) },
{ V( 0), V( 60), V( 126), V(51), V(19) } } };
{ { V( 0), V( 67), V( 134), V(38), V(32) },
{ V( 0), V( 57), V( 139), V(37), V(22) },
{ V( 0), V( 43), V( 115), V(43), V(27) },
{ V( 0), V( 68), V( 124), V(57), V(32) } },
{ { V(20), V( 43), V( 100), V(56), V(20) },
{ V(23), V( 20), V( 98), V(40), V(15) },
{ V(23), V( 39), V( 103), V(36), V(18) },
{ V(28), V( 19), V( 108), V(42), V(26) } },
{ { V( 0), V( 0), V( 75), V(14), V( 2) },
{ V( 0), V( 0), V( 150), V(30), V( 4) },
{ V( 0), V( 0), V( 160), V(22), V( 5) },
{ V( 0), V( 0), V( 166), V(24), V(13) } },
{ { V( 0), V(-283), V(-281), V(57), V(31) },
{ V( 0), V( 58), V( 141), V(39), V(18) },
{ V( 0), V( 65), V( 142), V(48), V(32) },
{ V( 0), V( 60), V( 126), V(51), V(19) } } };

// Max bonus for king safety. Corresponds to start position with all the pawns
// in front of the king and no enemy pawn on the horizon.
Expand Down Expand Up @@ -167,7 +168,7 @@ namespace {
assert(opposed | passed | (pawn_attack_span(Us, s) & theirPawns));

// Passed pawns will be properly scored in evaluation because we need
// full attack info to evaluate passed pawns. Only the frontmost passed
// full attack info to evaluate them. Only the frontmost passed
// pawn on each file is considered a true passed pawn.
if (passed && !doubled)
e->passedPawns[Us] |= s;
Expand All @@ -180,7 +181,7 @@ namespace {
score -= Backward[opposed];

else if (!supported)
score -= UnsupportedPawnPenalty;
score -= Unsupported;

if (connected)
score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)];
Expand All @@ -195,9 +196,8 @@ namespace {
b = e->semiopenFiles[Us] ^ 0xFF;
e->pawnSpan[Us] = b ? int(msb(b) - lsb(b)) : 0;

// Center binds: Two pawns controlling the same central square
b = shift_bb<Right>(ourPawns) & shift_bb<Left>(ourPawns) & CenterBindMask;
score += popcount<Max15>(b) * CenterBind;
score += CenterBind * popcount<Max15>(b);

return score;
}
Expand Down