Rev 154 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 154 | Rev 169 | ||
|---|---|---|---|
| Line 4... | Line 4... | ||
| 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
| 5 | Copyright (C) 2015- |
5 | Copyright (C) 2015-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad |
| 6 | 6 | ||
| 7 | Stockfish is free software: you can redistribute it and/or modify |
7 | Stockfish is free software: you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation, either version 3 of the License, or |
9 | the Free Software Foundation, either version 3 of the License, or |
| 10 | (at your option) any later version. |
10 | (at your option) any later version. |
| Line 29... | Line 29... | ||
| 29 | namespace { |
29 | namespace { |
| 30 | 30 | ||
| 31 | #define V Value |
31 | #define V Value |
| 32 | #define S(mg, eg) make_score(mg, eg) |
32 | #define S(mg, eg) make_score(mg, eg) |
| 33 | 33 | ||
| 34 | // Isolated pawn penalty |
34 | // Isolated pawn penalty |
| 35 | const Score Isolated |
35 | const Score Isolated = S(13, 18); |
| 36 | 36 | ||
| 37 | // Backward pawn penalty |
37 | // Backward pawn penalty |
| 38 | const Score Backward |
38 | const Score Backward = S(24, 12); |
| 39 | 39 | ||
| 40 | // Unsupported pawn penalty for pawns which are neither isolated or backward |
- | |
| 41 | const Score Unsupported = S(17, 8); |
- | |
| 42 | - | ||
| 43 | // Connected pawn bonus by opposed, phalanx, |
40 | // Connected pawn bonus by opposed, phalanx, #support and rank |
| 44 | Score Connected[2][2][ |
41 | Score Connected[2][2][3][RANK_NB]; |
| 45 | 42 | ||
| 46 | // Doubled pawn penalty |
43 | // Doubled pawn penalty |
| 47 | const Score Doubled = S(18,38); |
44 | const Score Doubled = S(18, 38); |
| 48 | - | ||
| 49 | // Lever bonus by rank |
- | |
| 50 | const Score Lever[RANK_NB] = { |
- | |
| 51 | S( 0, 0), S( 0, 0), S(0, 0), S(0, 0), |
- | |
| 52 | S(17, 16), S(33, 32), S(0, 0), S(0, 0) |
- | |
| 53 | }; |
- | |
| 54 | 45 | ||
| 55 | // Weakness of our pawn shelter in front of the king by [distance from edge][rank] |
46 | // Weakness of our pawn shelter in front of the king by [isKingFile][distance from edge][rank]. |
| - | 47 | // RANK_1 = 0 is used for files where we have no pawns or our pawn is behind our king. |
|
| 56 | const Value ShelterWeakness[][RANK_NB] = { |
48 | const Value ShelterWeakness[][int(FILE_NB) / 2][RANK_NB] = { |
| - | 49 | { { V( 97), V(17), V( 9), V(44), V( 84), V( 87), V( 99) }, // Not On King file |
|
| 57 | { V( |
50 | { V(106), V( 6), V(33), V(86), V( 87), V(104), V(112) }, |
| 58 | { V( |
51 | { V(101), V( 2), V(65), V(98), V( 58), V( 89), V(115) }, |
| 59 | { V( |
52 | { V( 73), V( 7), V(54), V(73), V( 84), V( 83), V(111) } }, |
| - | 53 | { { V(104), V(20), V( 6), V(27), V( 86), V( 93), V( 82) }, // On King file |
|
| - | 54 | { V(123), V( 9), V(34), V(96), V(112), V( 88), V( 75) }, |
|
| - | 55 | { V(120), V(25), V(65), V(91), V( 66), V( 78), V(117) }, |
|
| 60 | { V( |
56 | { V( 81), V( 2), V(47), V(63), V( 94), V( 93), V(104) } } |
| 61 | }; |
57 | }; |
| 62 | 58 | ||
| 63 | // Danger of enemy pawns moving toward our king by [type][distance from edge][rank] |
59 | // Danger of enemy pawns moving toward our king by [type][distance from edge][rank]. |
| - | 60 | // For the unopposed and unblocked cases, RANK_1 = 0 is used when opponent has |
|
| - | 61 | // no pawn on the given file, or their pawn is behind our king. |
|
| 64 | const Value StormDanger[][4][RANK_NB] = { |
62 | const Value StormDanger[][4][RANK_NB] = { |
| 65 | { { V( 0), V( |
63 | { { V( 0), V(-290), V(-274), V(57), V(41) }, // BlockedByKing |
| 66 | { V( 0), V( |
64 | { V( 0), V( 60), V( 144), V(39), V(13) }, |
| 67 | { V( 0), V( |
65 | { V( 0), V( 65), V( 141), V(41), V(34) }, |
| 68 | { V( 0), V( |
66 | { V( 0), V( 53), V( 127), V(56), V(14) } }, |
| 69 | { { V( |
67 | { { V( 4), V( 73), V( 132), V(46), V(31) }, // Unopposed |
| 70 | { V( |
68 | { V( 1), V( 64), V( 143), V(26), V(13) }, |
| 71 | { V( |
69 | { V( 1), V( 47), V( 110), V(44), V(24) }, |
| 72 | { V( |
70 | { V( 0), V( 72), V( 127), V(50), V(31) } }, |
| 73 | { { V( 0), V( 0), V( |
71 | { { V( 0), V( 0), V( 79), V(23), V( 1) }, // BlockedByPawn |
| 74 | { V( 0), V( 0), V( |
72 | { V( 0), V( 0), V( 148), V(27), V( 2) }, |
| 75 | { V( 0), V( 0), V( |
73 | { V( 0), V( 0), V( 161), V(16), V( 1) }, |
| 76 | { V( 0), V( 0), V( |
74 | { V( 0), V( 0), V( 171), V(22), V(15) } }, |
| 77 | { { V( |
75 | { { V(22), V( 45), V( 104), V(62), V( 6) }, // Unblocked |
| 78 | { V( |
76 | { V(31), V( 30), V( 99), V(39), V(19) }, |
| 79 | { V( |
77 | { V(23), V( 29), V( 96), V(41), V(15) }, |
| 80 | { V( |
78 | { V(21), V( 23), V( 116), V(41), V(15) } } |
| 81 | }; |
79 | }; |
| 82 | 80 | ||
| 83 | // Max bonus for king safety. Corresponds to start position with all the pawns |
81 | // Max bonus for king safety. Corresponds to start position with all the pawns |
| 84 | // in front of the king and no enemy pawn on the horizon. |
82 | // in front of the king and no enemy pawn on the horizon. |
| 85 | const Value MaxSafetyBonus = V(258); |
83 | const Value MaxSafetyBonus = V(258); |
| Line 88... | Line 86... | ||
| 88 | #undef V |
86 | #undef V |
| 89 | 87 | ||
| 90 | template<Color Us> |
88 | template<Color Us> |
| 91 | Score evaluate(const Position& pos, Pawns::Entry* e) { |
89 | Score evaluate(const Position& pos, Pawns::Entry* e) { |
| 92 | 90 | ||
| 93 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
91 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
| 94 | const |
92 | const Direction Up = (Us == WHITE ? NORTH : SOUTH); |
| 95 | const |
93 | const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST); |
| 96 | const |
94 | const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); |
| 97 | 95 | ||
| 98 | Bitboard b, neighbours, stoppers, doubled, supported, phalanx; |
96 | Bitboard b, neighbours, stoppers, doubled, supported, phalanx; |
| - | 97 | Bitboard lever, leverPush; |
|
| 99 | Square s; |
98 | Square s; |
| 100 | bool opposed, |
99 | bool opposed, backward; |
| 101 | Score score = SCORE_ZERO; |
100 | Score score = SCORE_ZERO; |
| 102 | const Square* pl = pos.squares<PAWN>(Us); |
101 | const Square* pl = pos.squares<PAWN>(Us); |
| 103 | const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)]; |
- | |
| 104 | 102 | ||
| 105 | Bitboard ourPawns = pos.pieces( |
103 | Bitboard ourPawns = pos.pieces( Us, PAWN); |
| 106 | Bitboard theirPawns = pos.pieces(Them, PAWN); |
104 | Bitboard theirPawns = pos.pieces(Them, PAWN); |
| 107 | 105 | ||
| 108 | e->passedPawns[Us] |
106 | e->passedPawns[Us] = e->pawnAttacksSpan[Us] = e->weakUnopposed[Us] = 0; |
| 109 | e->semiopenFiles[Us] = 0xFF; |
107 | e->semiopenFiles[Us] = 0xFF; |
| 110 | e->kingSquares[Us] = SQ_NONE; |
108 | e->kingSquares[Us] = SQ_NONE; |
| 111 | e->pawnAttacks[Us] = shift<Right>(ourPawns) | shift<Left>(ourPawns); |
109 | e->pawnAttacks[Us] = shift<Right>(ourPawns) | shift<Left>(ourPawns); |
| 112 | e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares); |
110 | e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares); |
| 113 | e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK]; |
111 | e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK]; |
| Line 121... | Line 119... | ||
| 121 | 119 | ||
| 122 | e->semiopenFiles[Us] &= ~(1 << f); |
120 | e->semiopenFiles[Us] &= ~(1 << f); |
| 123 | e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); |
121 | e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); |
| 124 | 122 | ||
| 125 | // Flag the pawn |
123 | // Flag the pawn |
| 126 | opposed = theirPawns & |
124 | opposed = theirPawns & forward_file_bb(Us, s); |
| 127 | stoppers = theirPawns & passed_pawn_mask(Us, s); |
125 | stoppers = theirPawns & passed_pawn_mask(Us, s); |
| 128 | lever = theirPawns & |
126 | lever = theirPawns & PawnAttacks[Us][s]; |
| - | 127 | leverPush = theirPawns & PawnAttacks[Us][s + Up]; |
|
| 129 | doubled = ourPawns & (s |
128 | doubled = ourPawns & (s - Up); |
| 130 | neighbours = ourPawns & adjacent_files_bb(f); |
129 | neighbours = ourPawns & adjacent_files_bb(f); |
| 131 | phalanx = neighbours & rank_bb(s); |
130 | phalanx = neighbours & rank_bb(s); |
| 132 | supported = neighbours & rank_bb(s - Up); |
131 | supported = neighbours & rank_bb(s - Up); |
| 133 | connected = supported | phalanx; |
- | |
| 134 | 132 | ||
| 135 | // A pawn is backward when it is behind all pawns of the same color on the |
133 | // A pawn is backward when it is behind all pawns of the same color on the |
| 136 | // adjacent files and cannot be safely advanced. |
134 | // adjacent files and cannot be safely advanced. |
| 137 | if (!neighbours || lever || relative_rank(Us, s) >= RANK_5) |
135 | if (!neighbours || lever || relative_rank(Us, s) >= RANK_5) |
| 138 | backward = false; |
136 | backward = false; |
| Line 144... | Line 142... | ||
| 144 | // The pawn is backward when it cannot safely progress to that rank: |
142 | // The pawn is backward when it cannot safely progress to that rank: |
| 145 | // either there is a stopper in the way on this rank, or there is a |
143 | // either there is a stopper in the way on this rank, or there is a |
| 146 | // stopper on adjacent file which controls the way to that rank. |
144 | // stopper on adjacent file which controls the way to that rank. |
| 147 | backward = (b | shift<Up>(b & adjacent_files_bb(f))) & stoppers; |
145 | backward = (b | shift<Up>(b & adjacent_files_bb(f))) & stoppers; |
| 148 | 146 | ||
| 149 | assert(!backward |
147 | assert(!(backward && (forward_ranks_bb(Them, s + Up) & neighbours))); |
| 150 | } |
148 | } |
| 151 | 149 | ||
| 152 | // Passed pawns will be properly scored in evaluation because we need |
150 | // Passed pawns will be properly scored in evaluation because we need |
| 153 | // full attack info to evaluate them. |
151 | // full attack info to evaluate them. Include also not passed pawns |
| - | 152 | // which could become passed after one or two pawn pushes when are |
|
| - | 153 | // not attacked more times than defended. |
|
| - | 154 | if ( !(stoppers ^ lever ^ leverPush) |
|
| 154 |
|
155 | && !(ourPawns & forward_file_bb(Us, s)) |
| - | 156 | && popcount(supported) >= popcount(lever) |
|
| - | 157 | && popcount(phalanx) >= popcount(leverPush)) |
|
| 155 | e->passedPawns[Us] |= s; |
158 | e->passedPawns[Us] |= s; |
| - | 159 | ||
| - | 160 | else if ( stoppers == SquareBB[s + Up] |
|
| - | 161 | && relative_rank(Us, s) >= RANK_5) |
|
| - | 162 | { |
|
| - | 163 | b = shift<Up>(supported) & ~theirPawns; |
|
| - | 164 | while (b) |
|
| - | 165 | if (!more_than_one(theirPawns & PawnAttacks[Us][pop_lsb(&b)])) |
|
| - | 166 | e->passedPawns[Us] |= s; |
|
| - | 167 | } |
|
| 156 | 168 | ||
| 157 | // Score this pawn |
169 | // Score this pawn |
| - | 170 | if (supported | phalanx) |
|
| - | 171 | score += Connected[opposed][bool(phalanx)][popcount(supported)][relative_rank(Us, s)]; |
|
| - | 172 | ||
| 158 | if (!neighbours) |
173 | else if (!neighbours) |
| 159 | score -= |
174 | score -= Isolated, e->weakUnopposed[Us] += !opposed; |
| 160 | 175 | ||
| 161 | else if (backward) |
176 | else if (backward) |
| 162 | score -= |
177 | score -= Backward, e->weakUnopposed[Us] += !opposed; |
| 163 | 178 | ||
| 164 |
|
179 | if (doubled && !supported) |
| 165 | score -= Unsupported; |
- | |
| 166 | - | ||
| 167 | if (connected) |
- | |
| 168 | score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)]; |
- | |
| 169 | - | ||
| 170 | if (doubled) |
- | |
| 171 | score -= Doubled; |
180 | score -= Doubled; |
| 172 | - | ||
| 173 | if (lever) |
- | |
| 174 | score += Lever[relative_rank(Us, s)]; |
- | |
| 175 | } |
181 | } |
| 176 | 182 | ||
| 177 | return score; |
183 | return score; |
| 178 | } |
184 | } |
| 179 | 185 | ||
| Line 185... | Line 191... | ||
| 185 | /// hard-coded tables, when makes sense, we prefer to calculate them with a formula |
191 | /// hard-coded tables, when makes sense, we prefer to calculate them with a formula |
| 186 | /// to reduce independent parameters and to allow easier tuning and better insight. |
192 | /// to reduce independent parameters and to allow easier tuning and better insight. |
| 187 | 193 | ||
| 188 | void init() { |
194 | void init() { |
| 189 | 195 | ||
| 190 | static const int Seed[RANK_NB] = { 0, |
196 | static const int Seed[RANK_NB] = { 0, 13, 24, 18, 76, 100, 175, 330 }; |
| 191 | 197 | ||
| 192 | for (int opposed = 0; opposed <= 1; ++opposed) |
198 | for (int opposed = 0; opposed <= 1; ++opposed) |
| 193 | for (int phalanx = 0; phalanx <= 1; ++phalanx) |
199 | for (int phalanx = 0; phalanx <= 1; ++phalanx) |
| 194 | for (int |
200 | for (int support = 0; support <= 2; ++support) |
| 195 | for (Rank r = RANK_2; r < RANK_8; ++r) |
201 | for (Rank r = RANK_2; r < RANK_8; ++r) |
| 196 | { |
202 | { |
| - | 203 | int v = 17 * support; |
|
| 197 |
|
204 | v += (Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0)) >> opposed; |
| 198 | v += (apex ? v / 2 : 0); |
- | |
| - | 205 | ||
| 199 | Connected[opposed][phalanx][ |
206 | Connected[opposed][phalanx][support][r] = make_score(v, v * (r - 2) / 4); |
| 200 | } |
207 | } |
| 201 | } |
208 | } |
| 202 | 209 | ||
| 203 | 210 | ||
| 204 | /// Pawns::probe() looks up the current position's pawns configuration in |
211 | /// Pawns::probe() looks up the current position's pawns configuration in |
| Line 221... | Line 228... | ||
| 221 | return e; |
228 | return e; |
| 222 | } |
229 | } |
| 223 | 230 | ||
| 224 | 231 | ||
| 225 | /// Entry::shelter_storm() calculates shelter and storm penalties for the file |
232 | /// Entry::shelter_storm() calculates shelter and storm penalties for the file |
| 226 | /// the king is on, as well as the two |
233 | /// the king is on, as well as the two closest files. |
| 227 | 234 | ||
| 228 | template<Color Us> |
235 | template<Color Us> |
| 229 | Value Entry::shelter_storm(const Position& pos, Square ksq) { |
236 | Value Entry::shelter_storm(const Position& pos, Square ksq) { |
| 230 | 237 | ||
| 231 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
238 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
| 232 | 239 | ||
| 233 | enum { |
240 | enum { BlockedByKing, Unopposed, BlockedByPawn, Unblocked }; |
| 234 | 241 | ||
| 235 | Bitboard b = pos.pieces(PAWN) & ( |
242 | Bitboard b = pos.pieces(PAWN) & (forward_ranks_bb(Us, ksq) | rank_bb(ksq)); |
| 236 | Bitboard ourPawns = b & pos.pieces(Us); |
243 | Bitboard ourPawns = b & pos.pieces(Us); |
| 237 | Bitboard theirPawns = b & pos.pieces(Them); |
244 | Bitboard theirPawns = b & pos.pieces(Them); |
| 238 | Value safety = MaxSafetyBonus; |
245 | Value safety = MaxSafetyBonus; |
| 239 | File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); |
246 | File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); |
| 240 | 247 | ||
| 241 | for (File f = center - |
248 | for (File f = File(center - 1); f <= File(center + 1); ++f) |
| 242 | { |
249 | { |
| 243 | b = ourPawns & file_bb(f); |
250 | b = ourPawns & file_bb(f); |
| 244 | Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1; |
251 | Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1; |
| 245 | 252 | ||
| 246 | b |
253 | b = theirPawns & file_bb(f); |
| 247 | Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; |
254 | Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; |
| 248 | 255 | ||
| - | 256 | int d = std::min(f, ~f); |
|
| 249 | safety -= ShelterWeakness[ |
257 | safety -= ShelterWeakness[f == file_of(ksq)][d][rkUs] |
| 250 | + StormDanger |
258 | + StormDanger |
| 251 | [f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing : |
259 | [f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing : |
| 252 | rkUs == RANK_1 ? |
260 | rkUs == RANK_1 ? Unopposed : |
| 253 | rkThem == rkUs + 1 ? BlockedByPawn : Unblocked] |
261 | rkThem == rkUs + 1 ? BlockedByPawn : Unblocked] |
| 254 | [ |
262 | [d][rkThem]; |
| 255 | } |
263 | } |
| 256 | 264 | ||
| 257 | return safety; |
265 | return safety; |
| 258 | } |
266 | } |
| 259 | 267 | ||