Rev 96 | Rev 169 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 96 | Rev 154 | ||
---|---|---|---|
Line 20... | Line 20... | ||
20 | 20 | ||
21 | #include <algorithm> |
21 | #include <algorithm> |
22 | #include <cassert> |
22 | #include <cassert> |
23 | 23 | ||
24 | #include "bitboard.h" |
24 | #include "bitboard.h" |
25 | #include "bitcount.h" |
- | |
26 | #include "pawns.h" |
25 | #include "pawns.h" |
27 | #include "position.h" |
26 | #include "position.h" |
28 | #include "thread.h" |
27 | #include "thread.h" |
29 | 28 | ||
30 | namespace { |
29 | namespace { |
31 | 30 | ||
32 | #define V Value |
31 | #define V Value |
33 | #define S(mg, eg) make_score(mg, eg) |
32 | #define S(mg, eg) make_score(mg, eg) |
34 | 33 | ||
35 | // Isolated pawn penalty by opposed flag |
34 | // Isolated pawn penalty by opposed flag |
36 | const Score Isolated[2][FILE_NB] = { |
- | |
37 | { S(31, 36), S(45, 41), S(50, 41), S(50, 41), |
- | |
38 |
|
35 | const Score Isolated[2] = { S(45, 40), S(30, 27) }; |
39 | { S(21, 24), S(30, 28), S(33, 28), S(33, 28), |
- | |
40 | S(33, 28), S(33, 28), S(30, 28), S(21, 24) } }; |
- | |
41 | 36 | ||
42 | // Backward pawn penalty by opposed flag |
37 | // Backward pawn penalty by opposed flag |
43 | const Score Backward[2] = { S(56, 33), S(41, 19) }; |
38 | const Score Backward[2] = { S(56, 33), S(41, 19) }; |
44 | 39 | ||
45 | // Unsupported pawn penalty for pawns which are neither isolated or |
40 | // Unsupported pawn penalty for pawns which are neither isolated or backward |
46 | // by number of pawns it supports [less than 2 / exactly 2]. |
- | |
47 | const Score Unsupported |
41 | const Score Unsupported = S(17, 8); |
48 | 42 | ||
49 | // Connected pawn bonus by opposed, phalanx, twice supported and rank |
43 | // Connected pawn bonus by opposed, phalanx, twice supported and rank |
50 | Score Connected[2][2][2][RANK_NB]; |
44 | Score Connected[2][2][2][RANK_NB]; |
51 | 45 | ||
52 | // Doubled pawn penalty |
46 | // Doubled pawn penalty |
53 | const Score Doubled |
47 | const Score Doubled = S(18,38); |
54 | S(11, 34), S(17, 38), S(19, 38), S(19, 38), |
- | |
55 | S(19, 38), S(19, 38), S(17, 38), S(11, 34) }; |
- | |
56 | 48 | ||
57 | // Lever bonus by rank |
49 | // Lever bonus by rank |
58 | const Score Lever[RANK_NB] = { |
50 | const Score Lever[RANK_NB] = { |
59 | S( 0, 0), S( 0, 0), S(0, 0), S(0, 0), |
51 | S( 0, 0), S( 0, 0), S(0, 0), S(0, 0), |
60 | S(17, 16), S(33, 32), S(0, 0), S(0, 0) |
52 | S(17, 16), S(33, 32), S(0, 0), S(0, 0) |
- | 53 | }; |
|
61 | 54 | ||
62 | // Weakness of our pawn shelter in front of the king by [distance from edge][rank] |
55 | // Weakness of our pawn shelter in front of the king by [distance from edge][rank] |
63 | const Value ShelterWeakness[][RANK_NB] = { |
56 | const Value ShelterWeakness[][RANK_NB] = { |
64 | { V( 97), V(21), V(26), V(51), V(87), V( 89), V( 99) }, |
57 | { V( 97), V(21), V(26), V(51), V(87), V( 89), V( 99) }, |
65 | { V(120), V( 0), V(28), V(76), V(88), V(103), V(104) }, |
58 | { V(120), V( 0), V(28), V(76), V(88), V(103), V(104) }, |
66 | { V(101), V( 7), V(54), V(78), V(77), V( 92), V(101) }, |
59 | { V(101), V( 7), V(54), V(78), V(77), V( 92), V(101) }, |
67 | { V( 80), V(11), V(44), V(68), V(87), V( 90), V(119) } |
60 | { V( 80), V(11), V(44), V(68), V(87), V( 90), V(119) } |
- | 61 | }; |
|
68 | 62 | ||
69 | // Danger of enemy pawns moving toward our king by [type][distance from edge][rank] |
63 | // Danger of enemy pawns moving toward our king by [type][distance from edge][rank] |
70 | const Value StormDanger[][4][RANK_NB] = { |
64 | const Value StormDanger[][4][RANK_NB] = { |
71 | { { V( 0), V( 67), V( 134), V(38), V(32) }, |
65 | { { V( 0), V( 67), V( 134), V(38), V(32) }, |
72 | { V( 0), V( 57), V( 139), V(37), V(22) }, |
66 | { V( 0), V( 57), V( 139), V(37), V(22) }, |
Line 81... | Line 75... | ||
81 | { V( 0), V( 0), V( 160), V(22), V( 5) }, |
75 | { V( 0), V( 0), V( 160), V(22), V( 5) }, |
82 | { V( 0), V( 0), V( 166), V(24), V(13) } }, |
76 | { V( 0), V( 0), V( 166), V(24), V(13) } }, |
83 | { { V( 0), V(-283), V(-281), V(57), V(31) }, |
77 | { { V( 0), V(-283), V(-281), V(57), V(31) }, |
84 | { V( 0), V( 58), V( 141), V(39), V(18) }, |
78 | { V( 0), V( 58), V( 141), V(39), V(18) }, |
85 | { V( 0), V( 65), V( 142), V(48), V(32) }, |
79 | { V( 0), V( 65), V( 142), V(48), V(32) }, |
86 | { V( 0), V( 60), V( 126), V(51), V(19) } } |
80 | { V( 0), V( 60), V( 126), V(51), V(19) } } |
- | 81 | }; |
|
87 | 82 | ||
88 | // Max bonus for king safety. Corresponds to start position with all the pawns |
83 | // Max bonus for king safety. Corresponds to start position with all the pawns |
89 | // in front of the king and no enemy pawn on the horizon. |
84 | // in front of the king and no enemy pawn on the horizon. |
90 | const Value MaxSafetyBonus = V(258); |
85 | const Value MaxSafetyBonus = V(258); |
91 | 86 | ||
Line 93... | Line 88... | ||
93 | #undef V |
88 | #undef V |
94 | 89 | ||
95 | template<Color Us> |
90 | template<Color Us> |
96 | Score evaluate(const Position& pos, Pawns::Entry* e) { |
91 | Score evaluate(const Position& pos, Pawns::Entry* e) { |
97 | 92 | ||
98 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
93 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
99 | const Square Up = (Us == WHITE ? |
94 | const Square Up = (Us == WHITE ? NORTH : SOUTH); |
100 | const Square Right = (Us == WHITE ? |
95 | const Square Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST); |
101 | const Square Left = (Us == WHITE ? |
96 | const Square Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); |
102 | 97 | ||
103 | Bitboard b, neighbours, doubled, supported, phalanx; |
98 | Bitboard b, neighbours, stoppers, doubled, supported, phalanx; |
104 | Square s; |
99 | Square s; |
105 | bool |
100 | bool opposed, lever, connected, backward; |
106 | Score score = SCORE_ZERO; |
101 | Score score = SCORE_ZERO; |
107 | const Square* pl = pos.squares<PAWN>(Us); |
102 | const Square* pl = pos.squares<PAWN>(Us); |
108 | const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)]; |
103 | const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)]; |
109 | 104 | ||
110 | Bitboard ourPawns = pos.pieces(Us , PAWN); |
105 | Bitboard ourPawns = pos.pieces(Us , PAWN); |
111 | Bitboard theirPawns = pos.pieces(Them, PAWN); |
106 | Bitboard theirPawns = pos.pieces(Them, PAWN); |
112 | 107 | ||
113 | e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0; |
108 | e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0; |
114 | e->kingSquares[Us] = SQ_NONE; |
- | |
115 | e->semiopenFiles[Us] = 0xFF; |
109 | e->semiopenFiles[Us] = 0xFF; |
- | 110 | e->kingSquares[Us] = SQ_NONE; |
|
116 | e->pawnAttacks[Us] = |
111 | e->pawnAttacks[Us] = shift<Right>(ourPawns) | shift<Left>(ourPawns); |
117 | e->pawnsOnSquares[Us][BLACK] = popcount |
112 | e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares); |
118 | e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK]; |
113 | e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK]; |
119 | 114 | ||
120 | // Loop through all pawns of the current color and score each pawn |
115 | // Loop through all pawns of the current color and score each pawn |
121 | while ((s = *pl++) != SQ_NONE) |
116 | while ((s = *pl++) != SQ_NONE) |
122 | { |
117 | { |
123 | assert(pos.piece_on(s) == make_piece(Us, PAWN)); |
118 | assert(pos.piece_on(s) == make_piece(Us, PAWN)); |
124 | 119 | ||
125 | File f = file_of(s); |
120 | File f = file_of(s); |
126 | 121 | ||
127 | e->semiopenFiles[Us] &= ~(1 << f); |
122 | e->semiopenFiles[Us] &= ~(1 << f); |
128 | e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); |
123 | e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); |
129 | 124 | ||
130 | // Flag the pawn |
125 | // Flag the pawn |
131 |
|
126 | opposed = theirPawns & forward_bb(Us, s); |
132 |
|
127 | stoppers = theirPawns & passed_pawn_mask(Us, s); |
133 |
|
128 | lever = theirPawns & pawnAttacksBB[s]; |
134 |
|
129 | doubled = ourPawns & (s + Up); |
135 |
|
130 | neighbours = ourPawns & adjacent_files_bb(f); |
136 | phalanx |
131 | phalanx = neighbours & rank_bb(s); |
137 | supported |
132 | supported = neighbours & rank_bb(s - Up); |
138 | connected |
133 | connected = supported | phalanx; |
139 | isolated = !neighbours; |
- | |
140 | 134 | ||
141 | // Test for backward pawn. |
- | |
142 | // If the pawn is passed, isolated, lever or connected it cannot be |
- | |
143 | // backward |
135 | // A pawn is backward when it is behind all pawns of the same color on the |
144 | // |
136 | // adjacent files and cannot be safely advanced. |
145 | if ( (passed | isolated | lever | connected) |
- | |
146 | || (ourPawns & pawn_attack_span(Them, s)) |
- | |
147 |
|
137 | if (!neighbours || lever || relative_rank(Us, s) >= RANK_5) |
148 | backward = false; |
138 | backward = false; |
149 | else |
139 | else |
150 | { |
140 | { |
151 | // We now know there are no friendly pawns beside or behind this |
- | |
152 | // pawn on adjacent files. We now check whether the pawn is |
- | |
153 | // backward by looking in the forward direction on the adjacent |
- | |
154 | // |
141 | // Find the backmost rank with neighbours or stoppers |
155 | b = |
142 | b = rank_bb(backmost_sq(Us, neighbours | stoppers)); |
156 | b = pawn_attack_span(Us, s) & rank_bb(backmost_sq(Us, b)); |
- | |
157 | 143 | ||
- | 144 | // The pawn is backward when it cannot safely progress to that rank: |
|
158 | // |
145 | // either there is a stopper in the way on this rank, or there is a |
159 | // |
146 | // stopper on adjacent file which controls the way to that rank. |
160 | backward = (b | |
147 | backward = (b | shift<Up>(b & adjacent_files_bb(f))) & stoppers; |
161 | } |
- | |
162 | 148 | ||
163 | assert( |
149 | assert(!backward || !(pawn_attack_span(Them, s + Up) & neighbours)); |
- | 150 | } |
|
164 | 151 | ||
165 | // Passed pawns will be properly scored in evaluation because we need |
152 | // Passed pawns will be properly scored in evaluation because we need |
166 | // full attack info to evaluate them. |
153 | // full attack info to evaluate them. |
167 |
|
154 | if (!stoppers && !(ourPawns & forward_bb(Us, s))) |
168 | if (passed && !doubled) |
- | |
169 | e->passedPawns[Us] |= s; |
155 | e->passedPawns[Us] |= s; |
170 | 156 | ||
171 | // Score this pawn |
157 | // Score this pawn |
172 | if ( |
158 | if (!neighbours) |
173 | score -= Isolated[opposed |
159 | score -= Isolated[opposed]; |
174 | 160 | ||
175 | else if (backward) |
161 | else if (backward) |
176 | score -= Backward[opposed]; |
162 | score -= Backward[opposed]; |
177 | 163 | ||
178 | else if (!supported) |
164 | else if (!supported) |
179 | score -= Unsupported |
165 | score -= Unsupported; |
180 | 166 | ||
181 | if (connected) |
167 | if (connected) |
182 | score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)]; |
168 | score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)]; |
183 | 169 | ||
184 | if (doubled) |
170 | if (doubled) |
185 | score -= Doubled |
171 | score -= Doubled; |
186 | 172 | ||
187 | if (lever) |
173 | if (lever) |
188 | score += Lever[relative_rank(Us, s)]; |
174 | score += Lever[relative_rank(Us, s)]; |
189 | } |
175 | } |
190 | - | ||
191 | b = e->semiopenFiles[Us] ^ 0xFF; |
- | |
192 | e->pawnSpan[Us] = b ? int(msb(b) - lsb(b)) : 0; |
- | |
193 | 176 | ||
194 | return score; |
177 | return score; |
195 | } |
178 | } |
196 | 179 | ||
197 | } // namespace |
180 | } // namespace |
Line 200... | Line 183... | ||
200 | 183 | ||
201 | /// Pawns::init() initializes some tables needed by evaluation. Instead of using |
184 | /// Pawns::init() initializes some tables needed by evaluation. Instead of using |
202 | /// hard-coded tables, when makes sense, we prefer to calculate them with a formula |
185 | /// hard-coded tables, when makes sense, we prefer to calculate them with a formula |
203 | /// to reduce independent parameters and to allow easier tuning and better insight. |
186 | /// to reduce independent parameters and to allow easier tuning and better insight. |
204 | 187 | ||
205 | void init() |
188 | void init() { |
206 | { |
189 | |
207 | static const int Seed[RANK_NB] = { 0, 8, 19, 13, 71, 94, 169, 324 }; |
190 | static const int Seed[RANK_NB] = { 0, 8, 19, 13, 71, 94, 169, 324 }; |
208 | 191 | ||
209 | for (int opposed = 0; opposed <= 1; ++opposed) |
192 | for (int opposed = 0; opposed <= 1; ++opposed) |
210 | for (int phalanx = 0; phalanx <= 1; ++phalanx) |
193 | for (int phalanx = 0; phalanx <= 1; ++phalanx) |
211 | for (int apex = 0; apex <= 1; ++apex) |
194 | for (int apex = 0; apex <= 1; ++apex) |
Line 231... | Line 214... | ||
231 | if (e->key == key) |
214 | if (e->key == key) |
232 | return e; |
215 | return e; |
233 | 216 | ||
234 | e->key = key; |
217 | e->key = key; |
235 | e->score = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e); |
218 | e->score = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e); |
236 | e->asymmetry = popcount |
219 | e->asymmetry = popcount(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]); |
- | 220 | e->openFiles = popcount(e->semiopenFiles[WHITE] & e->semiopenFiles[BLACK]); |
|
237 | return e; |
221 | return e; |
238 | } |
222 | } |
239 | 223 | ||
240 | 224 | ||
241 | /// Entry::shelter_storm() calculates shelter and storm penalties for the file |
225 | /// Entry::shelter_storm() calculates shelter and storm penalties for the file |
Line 285... | Line 269... | ||
285 | int minKingPawnDistance = 0; |
269 | int minKingPawnDistance = 0; |
286 | 270 | ||
287 | Bitboard pawns = pos.pieces(Us, PAWN); |
271 | Bitboard pawns = pos.pieces(Us, PAWN); |
288 | if (pawns) |
272 | if (pawns) |
289 | while (!(DistanceRingBB[ksq][minKingPawnDistance++] & pawns)) {} |
273 | while (!(DistanceRingBB[ksq][minKingPawnDistance++] & pawns)) {} |
290 | - | ||
291 | if (relative_rank(Us, ksq) > RANK_4) |
- | |
292 | return make_score(0, -16 * minKingPawnDistance); |
- | |
293 | 274 | ||
294 | Value bonus = shelter_storm<Us>(pos, ksq); |
275 | Value bonus = shelter_storm<Us>(pos, ksq); |
295 | 276 | ||
296 | // If we can castle use the bonus after the castling if it is bigger |
277 | // If we can castle use the bonus after the castling if it is bigger |
297 | if (pos.can_castle(MakeCastling<Us, KING_SIDE>::right)) |
278 | if (pos.can_castle(MakeCastling<Us, KING_SIDE>::right)) |