From: Alain SAVARD Date: Wed, 30 Dec 2015 11:29:25 +0000 (+0000) Subject: Correct Pawn Trace Score + Code Clean up X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=6a79d5d10eb4313fd71abe249a64aaed6bba1e67;hp=3e4fed3a91752da394f7c912f4e5e29dc39391f6 Correct Pawn Trace Score + Code Clean up No functional change Resolves #542 --- diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 33e26689..8eaa8824 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -75,7 +75,7 @@ const vector 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 diff --git a/src/endgame.cpp b/src/endgame.cpp index 681b290c..8eb76788 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -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 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 925d70ac..3379725c 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -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); @@ -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) }; + + // 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 + // pawns or pieces which are not pawn defended. + const Score ThreatByKing[2] = { S(3, 62), S(9, 138) }; // 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. @@ -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 @@ -343,15 +344,15 @@ namespace { { Bitboard alignedPawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]; if (alignedPawns) - score += popcount(alignedPawns) * RookOnPawn; + score += RookOnPawn * popcount(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(Us); @@ -506,10 +507,10 @@ namespace { safeThreats = (shift_bb(b) | shift_bb(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 @@ -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 @@ -553,7 +554,7 @@ namespace { & ~ei.attackedBy[Us][PAWN]; if (b) - score += popcount(b) * PawnAttackThreat; + score += ThreatByPawnPush * popcount(b); if (DoTrace) Trace::add(THREAT, Us, score); @@ -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 @@ -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]); Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]); Trace::add(SPACE, evaluate_space(pos, ei) * Weights[Space] , evaluate_space(pos, ei) * Weights[Space]); diff --git a/src/pawns.cpp b/src/pawns.cpp index 1653e23a..626f2b57 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -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. @@ -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; @@ -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)]; @@ -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(ourPawns) & shift_bb(ourPawns) & CenterBindMask; - score += popcount(b) * CenterBind; + score += CenterBind * popcount(b); return score; }