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 28... | Line 28... | ||
28 | #include "evaluate.h" |
28 | #include "evaluate.h" |
29 | #include "material.h" |
29 | #include "material.h" |
30 | #include "pawns.h" |
30 | #include "pawns.h" |
31 | 31 | ||
32 | namespace { |
32 | namespace { |
- | 33 | ||
- | 34 | const Bitboard Center = (FileDBB | FileEBB) & (Rank4BB | Rank5BB); |
|
- | 35 | const Bitboard QueenSide = FileABB | FileBBB | FileCBB | FileDBB; |
|
- | 36 | const Bitboard CenterFiles = FileCBB | FileDBB | FileEBB | FileFBB; |
|
- | 37 | const Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB; |
|
- | 38 | ||
- | 39 | const Bitboard KingFlank[FILE_NB] = { |
|
- | 40 | QueenSide, QueenSide, QueenSide, CenterFiles, CenterFiles, KingSide, KingSide, KingSide |
|
- | 41 | }; |
|
33 | 42 | ||
34 | namespace Trace { |
43 | namespace Trace { |
- | 44 | ||
- | 45 | enum Tracing {NO_TRACE, TRACE}; |
|
35 | 46 | ||
36 | enum Term { // The first 8 entries are for PieceType |
47 | enum Term { // The first 8 entries are for PieceType |
37 | MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, TOTAL, TERM_NB |
48 | MATERIAL = 8, IMBALANCE, MOBILITY, THREAT, PASSED, SPACE, INITIATIVE, TOTAL, TERM_NB |
38 | }; |
49 | }; |
39 | 50 | ||
40 | double scores[TERM_NB][COLOR_NB][PHASE_NB]; |
51 | double scores[TERM_NB][COLOR_NB][PHASE_NB]; |
41 | 52 | ||
42 | double to_cp(Value v) { return double(v) / PawnValueEg; } |
53 | double to_cp(Value v) { return double(v) / PawnValueEg; } |
Line 50... | Line 61... | ||
50 | add(idx, WHITE, w); add(idx, BLACK, b); |
61 | add(idx, WHITE, w); add(idx, BLACK, b); |
51 | } |
62 | } |
52 | 63 | ||
53 | std::ostream& operator<<(std::ostream& os, Term t) { |
64 | std::ostream& operator<<(std::ostream& os, Term t) { |
54 | 65 | ||
55 | if (t == MATERIAL || t == IMBALANCE || t == Term(PAWN) || t == TOTAL) |
66 | if (t == MATERIAL || t == IMBALANCE || t == Term(PAWN) || t == INITIATIVE || t == TOTAL) |
56 | os << " --- --- | --- --- | "; |
67 | os << " --- --- | --- --- | "; |
57 | else |
68 | else |
58 | os << std::setw(5) << scores[t][WHITE][MG] << " " |
69 | os << std::setw(5) << scores[t][WHITE][MG] << " " |
59 | << std::setw(5) << scores[t][WHITE][EG] << " | " |
70 | << std::setw(5) << scores[t][WHITE][EG] << " | " |
60 | << std::setw(5) << scores[t][BLACK][MG] << " " |
71 | << std::setw(5) << scores[t][BLACK][MG] << " " |
Line 67... | Line 78... | ||
67 | } |
78 | } |
68 | } |
79 | } |
69 | 80 | ||
70 | using namespace Trace; |
81 | using namespace Trace; |
71 | 82 | ||
72 | // |
83 | // Evaluation class contains various information computed and collected |
73 | // by the evaluation functions. |
84 | // by the evaluation functions. |
- | 85 | template<Tracing T = NO_TRACE> |
|
74 |
|
86 | class Evaluation { |
- | 87 | ||
- | 88 | public: |
|
- | 89 | Evaluation() = delete; |
|
- | 90 | Evaluation(const Position& p) : pos(p) {} |
|
- | 91 | Evaluation& operator=(const Evaluation&) = delete; |
|
- | 92 | ||
- | 93 | Value value(); |
|
- | 94 | ||
- | 95 | private: |
|
- | 96 | // Evaluation helpers (used when calling value()) |
|
- | 97 | template<Color Us> void initialize(); |
|
- | 98 | template<Color Us> Score evaluate_king(); |
|
- | 99 | template<Color Us> Score evaluate_threats(); |
|
- | 100 | int king_distance(Color c, Square s); |
|
- | 101 | template<Color Us> Score evaluate_passed_pawns(); |
|
- | 102 | template<Color Us> Score evaluate_space(); |
|
- | 103 | template<Color Us, PieceType Pt> Score evaluate_pieces(); |
|
- | 104 | ScaleFactor evaluate_scale_factor(Value eg); |
|
- | 105 | Score evaluate_initiative(Value eg); |
|
- | 106 | ||
- | 107 | // Data members |
|
- | 108 | const Position& pos; |
|
- | 109 | Material::Entry* me; |
|
- | 110 | Pawns::Entry* pe; |
|
- | 111 | Bitboard mobilityArea[COLOR_NB]; |
|
- | 112 | Score mobility[COLOR_NB] = { SCORE_ZERO, SCORE_ZERO }; |
|
75 | 113 | ||
76 | // attackedBy[color][piece type] is a bitboard representing all squares |
114 | // attackedBy[color][piece type] is a bitboard representing all squares |
77 | // attacked by a given color and piece type |
115 | // attacked by a given color and piece type. Special "piece types" which are |
- | 116 | // also calculated are QUEEN_DIAGONAL and ALL_PIECES. |
|
78 | Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB]; |
117 | Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB]; |
79 | 118 | ||
80 | // attackedBy2[color] are the squares attacked by 2 pieces of a given color, |
119 | // attackedBy2[color] are the squares attacked by 2 pieces of a given color, |
81 | // possibly via x-ray or by one pawn and one piece. Diagonal x-ray through |
120 | // possibly via x-ray or by one pawn and one piece. Diagonal x-ray through |
82 | // pawn or squares attacked by 2 pawns are not explicitly added. |
121 | // pawn or squares attacked by 2 pawns are not explicitly added. |
83 | Bitboard attackedBy2[COLOR_NB]; |
122 | Bitboard attackedBy2[COLOR_NB]; |
84 | 123 | ||
85 | // kingRing[color] is the zone around the king which is considered |
124 | // kingRing[color] is the zone around the king which is considered |
86 | // by the king safety evaluation. This consists of the squares directly |
125 | // by the king safety evaluation. This consists of the squares directly |
87 | // adjacent to the king, and |
126 | // adjacent to the king, and (only for a king on its first rank) the |
88 | // squares two ranks in front of the king. For instance, if black's king |
127 | // squares two ranks in front of the king. For instance, if black's king |
89 | // is on g8, kingRing[BLACK] is a bitboard containing the squares f8, h8, |
128 | // is on g8, kingRing[BLACK] is a bitboard containing the squares f8, h8, |
90 | // f7, g7, h7, f6, g6 and h6. |
129 | // f7, g7, h7, f6, g6 and h6. |
91 | Bitboard kingRing[COLOR_NB]; |
130 | Bitboard kingRing[COLOR_NB]; |
92 | 131 | ||
Line 104... | Line 143... | ||
104 | // color to squares directly adjacent to the enemy king. Pieces which attack |
143 | // color to squares directly adjacent to the enemy king. Pieces which attack |
105 | // more than one square are counted multiple times. For instance, if there is |
144 | // more than one square are counted multiple times. For instance, if there is |
106 | // a white knight on g5 and black's king is on g8, this white knight adds 2 |
145 | // a white knight on g5 and black's king is on g8, this white knight adds 2 |
107 | // to kingAdjacentZoneAttacksCount[WHITE]. |
146 | // to kingAdjacentZoneAttacksCount[WHITE]. |
108 | int kingAdjacentZoneAttacksCount[COLOR_NB]; |
147 | int kingAdjacentZoneAttacksCount[COLOR_NB]; |
109 | - | ||
110 | Bitboard pinnedPieces[COLOR_NB]; |
- | |
111 | Material::Entry* me; |
- | |
112 | Pawns::Entry* pi; |
- | |
113 | }; |
148 | }; |
114 | 149 | ||
115 | #define V(v) Value(v) |
150 | #define V(v) Value(v) |
116 | #define S(mg, eg) make_score(mg, eg) |
151 | #define S(mg, eg) make_score(mg, eg) |
117 | 152 | ||
118 | // MobilityBonus[PieceType][attacked] contains bonuses for middle and end |
153 | // MobilityBonus[PieceType-2][attacked] contains bonuses for middle and end game, |
119 | // |
154 | // indexed by piece type and number of attacked squares in the mobility area. |
120 | const Score MobilityBonus[][32] = { |
155 | const Score MobilityBonus[][32] = { |
121 | {}, {}, |
- | |
122 | { S(-75,-76), S(- |
156 | { S(-75,-76), S(-57,-54), S( -9,-28), S( -2,-10), S( 6, 5), S( 14, 12), // Knights |
123 | S( 22, 26), S( |
157 | S( 22, 26), S( 29, 29), S( 36, 29) }, |
124 | { S(-48,- |
158 | { S(-48,-59), S(-20,-23), S( 16, -3), S( 26, 13), S( 38, 24), S( 51, 42), // Bishops |
125 | S( |
159 | S( 55, 54), S( 63, 57), S( 63, 65), S( 68, 73), S( 81, 78), S( 81, 86), |
126 | S( |
160 | S( 91, 88), S( 98, 97) }, |
127 | { S(- |
161 | { S(-58,-76), S(-27,-18), S(-15, 28), S(-10, 55), S( -5, 69), S( -2, 82), // Rooks |
128 | S( |
162 | S( 9,112), S( 16,118), S( 30,132), S( 29,142), S( 32,155), S( 38,165), |
129 | S( |
163 | S( 46,166), S( 48,169), S( 58,171) }, |
130 | { S(- |
164 | { S(-39,-36), S(-21,-15), S( 3, 8), S( 3, 18), S( 14, 34), S( 22, 54), // Queens |
131 | S( |
165 | S( 28, 61), S( 41, 73), S( 43, 79), S( 48, 92), S( 56, 94), S( 60,104), |
132 | S( 60, |
166 | S( 60,113), S( 66,120), S( 67,123), S( 70,126), S( 71,133), S( 73,136), |
133 | S( |
167 | S( 79,140), S( 88,143), S( 88,148), S( 99,166), S(102,170), S(102,175), |
134 | S( |
168 | S(106,184), S(109,191), S(113,206), S(116,212) } |
135 | }; |
169 | }; |
136 | 170 | ||
137 | // Outpost[knight/bishop][supported by pawn] contains bonuses for |
171 | // Outpost[knight/bishop][supported by pawn] contains bonuses for minor |
138 | // |
172 | // pieces if they can reach an outpost square, bigger if that square is |
- | 173 | // supported by a pawn. If the minor piece occupies an outpost square |
|
- | 174 | // then score is doubled. |
|
139 | const Score Outpost[][2] = { |
175 | const Score Outpost[][2] = { |
140 | { S(43,11), S(65,20) }, // Knights |
- | |
141 | { S(20, 3), S(29, 8) } // Bishops |
- | |
142 | }; |
- | |
143 | - | ||
144 | // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for |
- | |
145 | // knights and bishops which can reach an outpost square in one move, bigger |
- | |
146 | // if outpost square is supported by a pawn. |
- | |
147 | const Score ReachableOutpost[][2] = { |
- | |
148 | { S( |
176 | { S(22, 6), S(36,12) }, // Knight |
149 | { S( |
177 | { S( 9, 2), S(15, 5) } // Bishop |
150 | }; |
178 | }; |
151 | 179 | ||
152 | // RookOnFile[semiopen/open] contains bonuses for each rook when there is no |
180 | // RookOnFile[semiopen/open] contains bonuses for each rook when there is no |
153 | // friendly pawn on the rook file. |
181 | // friendly pawn on the rook file. |
154 | const Score RookOnFile[ |
182 | const Score RookOnFile[] = { S(20, 7), S(45, 20) }; |
155 | 183 | ||
156 | // |
184 | // ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to |
157 | // |
185 | // which piece type attacks which one. Attacks on lesser pieces which are |
- | 186 | // pawn-defended are not considered. |
|
158 | const Score |
187 | const Score ThreatByMinor[PIECE_TYPE_NB] = { |
159 | S(0, 0), S(0, |
188 | S(0, 0), S(0, 33), S(45, 43), S(46, 47), S(72, 107), S(48, 118) |
160 | }; |
189 | }; |
161 | 190 | ||
162 | // Threat[by minor/by rook][attacked PieceType] contains |
- | |
163 | // bonuses according to which piece type attacks which one. |
- | |
164 | // Attacks on lesser pieces which are pawn-defended are not considered. |
- | |
165 | const Score |
191 | const Score ThreatByRook[PIECE_TYPE_NB] = { |
166 | { S(0, 0), S(0, 33), S(45, 43), S(46, 47), S(72,107), S(48,118) }, // by Minor |
- | |
167 |
|
192 | S(0, 0), S(0, 25), S(40, 62), S(40, 59), S(0, 34), S(35, 48) |
168 | }; |
193 | }; |
169 | 194 | ||
170 | // ThreatByKing[on one/on many] contains bonuses for |
195 | // ThreatByKing[on one/on many] contains bonuses for king attacks on |
171 | // pawns or pieces which are not pawn-defended. |
196 | // pawns or pieces which are not pawn-defended. |
172 | const Score ThreatByKing[ |
197 | const Score ThreatByKing[] = { S(3, 62), S(9, 138) }; |
173 | 198 | ||
174 | // Passed[mg/eg][Rank] contains midgame and endgame bonuses for passed pawns. |
199 | // Passed[mg/eg][Rank] contains midgame and endgame bonuses for passed pawns. |
175 | // We don't use a Score because we process the two components independently. |
200 | // We don't use a Score because we process the two components independently. |
176 | const Value Passed[][RANK_NB] = { |
201 | const Value Passed[][RANK_NB] = { |
177 | { V(5), V( 5), V(31), V(73), V(166), V(252) }, |
202 | { V(0), V(5), V( 5), V(31), V(73), V(166), V(252) }, |
178 | { V(7), V(14), V(38), V(73), V(166), V(252) } |
203 | { V(0), V(7), V(14), V(38), V(73), V(166), V(252) } |
179 | }; |
204 | }; |
180 | 205 | ||
181 | // PassedFile[File] contains a bonus according to the file of a passed pawn |
206 | // PassedFile[File] contains a bonus according to the file of a passed pawn |
182 | const Score PassedFile[FILE_NB] = { |
207 | const Score PassedFile[FILE_NB] = { |
183 | S( 9, 10), S( 2, 10), S( 1, -8), S(-20,-12), |
208 | S( 9, 10), S( 2, 10), S( 1, -8), S(-20,-12), |
184 | S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10) |
209 | S(-20,-12), S( 1, -8), S( 2, 10), S( 9, 10) |
185 | }; |
210 | }; |
186 | 211 | ||
187 | // |
212 | // Rank factor applied on some bonus for passed pawn on rank 4 or beyond |
188 | const Score MinorBehindPawn = S(16, 0); |
- | |
189 | const Score BishopPawns = S( 8, 12); |
- | |
190 | const |
213 | const int RankFactor[RANK_NB] = {0, 0, 0, 2, 6, 11, 16}; |
191 | const Score TrappedRook = S(92, 0); |
- | |
192 | const Score CloseEnemies = S( 7, 0); |
- | |
193 | const Score SafeCheck = S(20, 20); |
- | |
194 | const Score OtherCheck = S(10, 10); |
- | |
195 | const Score ThreatByHangingPawn = S(71, 61); |
- | |
196 | const Score LooseEnemies = S( 0, 25); |
- | |
197 | const Score WeakQueen = S(35, 0); |
- | |
198 | const Score Hanging = S(48, 27); |
- | |
199 | const Score ThreatByPawnPush = S(38, 22); |
- | |
200 | const Score Unstoppable = S( 0, 20); |
- | |
201 | const Score PawnlessFlank = S(20, 80); |
- | |
202 | const Score HinderPassedPawn = S( 7, 0); |
- | |
203 | 214 | ||
204 | // |
215 | // KingProtector[PieceType-2] contains a bonus according to distance from king |
- | 216 | const Score KingProtector[] = { S(-3, -5), S(-4, -3), S(-3, 0), S(-1, 1) }; |
|
- | 217 | ||
205 | // |
218 | // Assorted bonuses and penalties used by evaluation |
- | 219 | const Score MinorBehindPawn = S( 16, 0); |
|
- | 220 | const Score BishopPawns = S( 8, 12); |
|
- | 221 | const Score LongRangedBishop = S( 22, 0); |
|
- | 222 | const Score RookOnPawn = S( 8, 24); |
|
- | 223 | const Score TrappedRook = S( 92, 0); |
|
- | 224 | const Score WeakQueen = S( 50, 10); |
|
- | 225 | const Score CloseEnemies = S( 7, 0); |
|
- | 226 | const Score PawnlessFlank = S( 20, 80); |
|
- | 227 | const Score ThreatBySafePawn = S(192,175); |
|
- | 228 | const Score ThreatByRank = S( 16, 3); |
|
- | 229 | const Score Hanging = S( 48, 27); |
|
206 |
|
230 | const Score WeakUnopposedPawn = S( 5, 25); |
- | 231 | const Score ThreatByPawnPush = S( 38, 22); |
|
- | 232 | const Score ThreatByAttackOnQueen = S( 38, 22); |
|
- | 233 | const Score HinderPassedPawn = S( 7, 0); |
|
207 | const Score TrappedBishopA1H1 = S(50, 50); |
234 | const Score TrappedBishopA1H1 = S( 50, 50); |
208 | 235 | ||
209 | #undef S |
236 | #undef S |
210 | #undef V |
237 | #undef V |
211 | 238 | ||
212 | // KingAttackWeights[PieceType] contains king attack weights by piece type |
239 | // KingAttackWeights[PieceType] contains king attack weights by piece type |
213 | const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 }; |
240 | const int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 78, 56, 45, 11 }; |
214 | 241 | ||
215 | // Penalties for enemy's safe checks |
242 | // Penalties for enemy's safe checks |
216 | const int |
243 | const int QueenSafeCheck = 780; |
217 | const int QueenCheck = 695; |
- | |
218 | const int |
244 | const int RookSafeCheck = 880; |
219 | const int |
245 | const int BishopSafeCheck = 435; |
220 | const int |
246 | const int KnightSafeCheck = 790; |
221 | 247 | ||
- | 248 | // Threshold for lazy and space evaluation |
|
- | 249 | const Value LazyThreshold = Value(1500); |
|
- | 250 | const Value SpaceThreshold = Value(12222); |
|
222 | 251 | ||
223 | // eval_init() initializes king and attack bitboards for a given color |
- | |
224 | // adding pawn attacks. To be done at the beginning of the evaluation. |
- | |
225 | 252 | ||
226 |
|
253 | // initialize() computes king and pawn attacks, and the king ring bitboard |
227 |
|
254 | // for a given color. This is done at the beginning of the evaluation. |
228 | 255 | ||
229 |
|
256 | template<Tracing T> template<Color Us> |
230 |
|
257 | void Evaluation<T>::initialize() { |
231 | 258 | ||
232 |
|
259 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
233 |
|
260 | const Direction Up = (Us == WHITE ? NORTH : SOUTH); |
234 |
|
261 | const Direction Down = (Us == WHITE ? SOUTH : NORTH); |
235 | ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us); |
- | |
236 |
|
262 | const Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB); |
237 | 263 | ||
- | 264 | // Find our pawns on the first two ranks, and those which are blocked |
|
- | 265 | Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks); |
|
- | 266 | ||
- | 267 | // Squares occupied by those pawns, by our king, or controlled by enemy pawns |
|
- | 268 | // are excluded from the mobility area. |
|
- | 269 | mobilityArea[Us] = ~(b | pos.square<KING>(Us) | pe->pawn_attacks(Them)); |
|
- | 270 | ||
- | 271 | // Initialise the attack bitboards with the king and pawn information |
|
- | 272 | b = attackedBy[Us][KING] = pos.attacks_from<KING>(pos.square<KING>(Us)); |
|
- | 273 | attackedBy[Us][PAWN] = pe->pawn_attacks(Us); |
|
- | 274 | ||
- | 275 | attackedBy2[Us] = b & attackedBy[Us][PAWN]; |
|
- | 276 | attackedBy[Us][ALL_PIECES] = b | attackedBy[Us][PAWN]; |
|
- | 277 | ||
238 | // Init king safety tables only if we are going to use them |
278 | // Init our king safety tables only if we are going to use them |
239 | if (pos.non_pawn_material( |
279 | if (pos.non_pawn_material(Them) >= RookValueMg + KnightValueMg) |
240 | { |
280 | { |
241 |
|
281 | kingRing[Us] = b; |
- | 282 | if (relative_rank(Us, pos.square<KING>(Us)) == RANK_1) |
|
242 |
|
283 | kingRing[Us] |= shift<Up>(b); |
- | 284 | ||
243 |
|
285 | kingAttackersCount[Them] = popcount(b & pe->pawn_attacks(Them)); |
244 |
|
286 | kingAdjacentZoneAttacksCount[Them] = kingAttackersWeight[Them] = 0; |
245 | } |
287 | } |
246 | else |
288 | else |
247 |
|
289 | kingRing[Us] = kingAttackersCount[Them] = 0; |
248 | } |
290 | } |
249 | 291 | ||
250 | 292 | ||
251 | // evaluate_pieces() assigns bonuses and penalties to the pieces of a given |
293 | // evaluate_pieces() assigns bonuses and penalties to the pieces of a given |
252 | // color and type. |
294 | // color and type. |
253 | 295 | ||
254 | template< |
296 | template<Tracing T> template<Color Us, PieceType Pt> |
255 | Score |
297 | Score Evaluation<T>::evaluate_pieces() { |
256 | const Bitboard* mobilityArea) { |
- | |
257 | Bitboard b, bb; |
- | |
258 | Square s; |
- | |
259 | Score score = SCORE_ZERO; |
- | |
260 | 298 | ||
261 | const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1)); |
- | |
262 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
299 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
263 | const Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB |
300 | const Bitboard OutpostRanks = (Us == WHITE ? Rank4BB | Rank5BB | Rank6BB |
264 | : Rank5BB | Rank4BB | Rank3BB); |
301 | : Rank5BB | Rank4BB | Rank3BB); |
265 | const Square* pl = pos.squares<Pt>(Us); |
302 | const Square* pl = pos.squares<Pt>(Us); |
266 | 303 | ||
- | 304 | Bitboard b, bb; |
|
- | 305 | Square s; |
|
- | 306 | Score score = SCORE_ZERO; |
|
- | 307 | ||
267 |
|
308 | attackedBy[Us][Pt] = 0; |
- | 309 | ||
- | 310 | if (Pt == QUEEN) |
|
- | 311 | attackedBy[Us][QUEEN_DIAGONAL] = 0; |
|
268 | 312 | ||
269 | while ((s = *pl++) != SQ_NONE) |
313 | while ((s = *pl++) != SQ_NONE) |
270 | { |
314 | { |
271 | // Find attacked squares, including x-ray attacks for bishops and rooks |
315 | // Find attacked squares, including x-ray attacks for bishops and rooks |
272 | b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces( |
316 | b = Pt == BISHOP ? attacks_bb<BISHOP>(s, pos.pieces() ^ pos.pieces(QUEEN)) |
273 | : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces( |
317 | : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK)) |
274 | : pos.attacks_from<Pt>(s); |
318 | : pos.attacks_from<Pt>(s); |
275 | 319 | ||
276 | if ( |
320 | if (pos.pinned_pieces(Us) & s) |
277 | b &= LineBB[pos.square<KING>(Us)][s]; |
321 | b &= LineBB[pos.square<KING>(Us)][s]; |
278 | 322 | ||
279 |
|
323 | attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b; |
280 |
|
324 | attackedBy[Us][ALL_PIECES] |= attackedBy[Us][Pt] |= b; |
281 | 325 | ||
- | 326 | if (Pt == QUEEN) |
|
- | 327 | attackedBy[Us][QUEEN_DIAGONAL] |= b & PseudoAttacks[BISHOP][s]; |
|
- | 328 | ||
282 | if (b & |
329 | if (b & kingRing[Them]) |
283 | { |
330 | { |
284 |
|
331 | kingAttackersCount[Us]++; |
285 |
|
332 | kingAttackersWeight[Us] += KingAttackWeights[Pt]; |
286 |
|
333 | kingAdjacentZoneAttacksCount[Us] += popcount(b & attackedBy[Them][KING]); |
287 | } |
334 | } |
288 | 335 | ||
289 | if (Pt == QUEEN) |
- | |
290 | b &= ~( ei.attackedBy[Them][KNIGHT] |
- | |
291 | | ei.attackedBy[Them][BISHOP] |
- | |
292 |
|
336 | int mob = popcount(b & mobilityArea[Us]); |
293 | 337 | ||
294 |
|
338 | mobility[Us] += MobilityBonus[Pt - 2][mob]; |
295 | 339 | ||
296 |
|
340 | // Bonus for this piece as a king protector |
- | 341 | score += KingProtector[Pt - 2] * distance(s, pos.square<KING>(Us)); |
|
297 | 342 | ||
298 | if (Pt == BISHOP || Pt == KNIGHT) |
343 | if (Pt == BISHOP || Pt == KNIGHT) |
299 | { |
344 | { |
300 | // Bonus for outpost squares |
345 | // Bonus for outpost squares |
301 | bb = OutpostRanks & |
346 | bb = OutpostRanks & ~pe->pawn_attacks_span(Them); |
302 | if (bb & s) |
347 | if (bb & s) |
303 | score += Outpost[Pt == BISHOP][ |
348 | score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & s)] * 2; |
304 | else |
349 | else |
305 | { |
350 | { |
306 | bb &= b & ~pos.pieces(Us); |
351 | bb &= b & ~pos.pieces(Us); |
307 | if (bb) |
352 | if (bb) |
308 | score += |
353 | score += Outpost[Pt == BISHOP][bool(attackedBy[Us][PAWN] & bb)]; |
309 | } |
354 | } |
310 | 355 | ||
311 | // Bonus when behind a pawn |
356 | // Bonus when behind a pawn |
312 | if ( relative_rank(Us, s) < RANK_5 |
357 | if ( relative_rank(Us, s) < RANK_5 |
313 | && (pos.pieces(PAWN) & (s + pawn_push(Us)))) |
358 | && (pos.pieces(PAWN) & (s + pawn_push(Us)))) |
314 | score += MinorBehindPawn; |
359 | score += MinorBehindPawn; |
315 | 360 | ||
316 | // Penalty for pawns on the same color square as the bishop |
- | |
317 | if (Pt == BISHOP) |
361 | if (Pt == BISHOP) |
- | 362 | { |
|
- | 363 | // Penalty for pawns on the same color square as the bishop |
|
318 | score -= BishopPawns * |
364 | score -= BishopPawns * pe->pawns_on_same_color_squares(Us, s); |
- | 365 | ||
- | 366 | // Bonus for bishop on a long diagonal which can "see" both center squares |
|
- | 367 | if (more_than_one(Center & (attacks_bb<BISHOP>(s, pos.pieces(PAWN)) | s))) |
|
- | 368 | score += LongRangedBishop; |
|
- | 369 | } |
|
319 | 370 | ||
320 | // An important Chess960 pattern: A cornered bishop blocked by a friendly |
371 | // An important Chess960 pattern: A cornered bishop blocked by a friendly |
321 | // pawn diagonally in front of it is a very serious problem, especially |
372 | // pawn diagonally in front of it is a very serious problem, especially |
322 | // when that pawn is also blocked. |
373 | // when that pawn is also blocked. |
323 | if ( Pt == BISHOP |
374 | if ( Pt == BISHOP |
324 | && pos.is_chess960() |
375 | && pos.is_chess960() |
325 | && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1))) |
376 | && (s == relative_square(Us, SQ_A1) || s == relative_square(Us, SQ_H1))) |
326 | { |
377 | { |
327 |
|
378 | Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST); |
328 | if (pos.piece_on(s + d) == make_piece(Us, PAWN)) |
379 | if (pos.piece_on(s + d) == make_piece(Us, PAWN)) |
329 | score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4 |
380 | score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4 |
330 | : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2 |
381 | : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2 |
331 | : TrappedBishopA1H1; |
382 | : TrappedBishopA1H1; |
332 | } |
383 | } |
Line 337... | Line 388... | ||
337 | // Bonus for aligning with enemy pawns on the same rank/file |
388 | // Bonus for aligning with enemy pawns on the same rank/file |
338 | if (relative_rank(Us, s) >= RANK_5) |
389 | if (relative_rank(Us, s) >= RANK_5) |
339 | score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]); |
390 | score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]); |
340 | 391 | ||
341 | // Bonus when on an open or semi-open file |
392 | // Bonus when on an open or semi-open file |
342 | if ( |
393 | if (pe->semiopen_file(Us, file_of(s))) |
343 | score += RookOnFile[ |
394 | score += RookOnFile[bool(pe->semiopen_file(Them, file_of(s)))]; |
344 | 395 | ||
345 | // |
396 | // Penalty when trapped by the king, even more if the king cannot castle |
346 | else if (mob <= 3) |
397 | else if (mob <= 3) |
347 | { |
398 | { |
348 | Square ksq = pos.square<KING>(Us); |
399 | Square ksq = pos.square<KING>(Us); |
349 | 400 | ||
350 | if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq))) |
401 | if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq))) |
351 | && (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1) |
- | |
352 | && ! |
402 | && !pe->semiopen_side(Us, file_of(ksq), file_of(s) < file_of(ksq))) |
353 | score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us)); |
403 | score -= (TrappedRook - make_score(mob * 22, 0)) * (1 + !pos.can_castle(Us)); |
354 | } |
404 | } |
355 | } |
405 | } |
356 | 406 | ||
357 | if (Pt == QUEEN) |
407 | if (Pt == QUEEN) |
Line 361... | Line 411... | ||
361 | if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners)) |
411 | if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners)) |
362 | score -= WeakQueen; |
412 | score -= WeakQueen; |
363 | } |
413 | } |
364 | } |
414 | } |
365 | 415 | ||
366 | if ( |
416 | if (T) |
367 | Trace::add(Pt, Us, score); |
417 | Trace::add(Pt, Us, score); |
368 | 418 | ||
369 | // Recursively call evaluate_pieces() of next piece type until KING is excluded |
- | |
370 | return score |
419 | return score; |
371 | } |
420 | } |
372 | - | ||
373 | template<> |
- | |
374 | Score evaluate_pieces<false, WHITE, KING>(const Position&, EvalInfo&, Score*, const Bitboard*) { return SCORE_ZERO; } |
- | |
375 | template<> |
- | |
376 | Score evaluate_pieces< true, WHITE, KING>(const Position&, EvalInfo&, Score*, const Bitboard*) { return SCORE_ZERO; } |
- | |
377 | 421 | ||
378 | 422 | ||
379 | // evaluate_king() assigns bonuses and penalties to a king of a given color |
423 | // evaluate_king() assigns bonuses and penalties to a king of a given color |
380 | 424 | ||
381 | const Bitboard WhiteCamp = Rank1BB | Rank2BB | Rank3BB | Rank4BB | Rank5BB; |
- | |
382 | const Bitboard BlackCamp = Rank8BB | Rank7BB | Rank6BB | Rank5BB | Rank4BB; |
- | |
383 |
|
425 | template<Tracing T> template<Color Us> |
384 |
|
426 | Score Evaluation<T>::evaluate_king() { |
385 | const Bitboard KingSide = FileEBB | FileFBB | FileGBB | FileHBB; |
- | |
386 | 427 | ||
387 | const Bitboard KingFlank[COLOR_NB][FILE_NB] = { |
- | |
388 | { QueenSide & WhiteCamp, QueenSide & WhiteCamp, QueenSide & WhiteCamp, CenterFiles & WhiteCamp, |
- | |
389 | CenterFiles & WhiteCamp, KingSide & WhiteCamp, KingSide & WhiteCamp, KingSide & WhiteCamp }, |
- | |
390 | { QueenSide & BlackCamp, QueenSide & BlackCamp, QueenSide & BlackCamp, CenterFiles & BlackCamp, |
- | |
391 | CenterFiles & BlackCamp, KingSide & BlackCamp, KingSide & BlackCamp, KingSide & BlackCamp }, |
- | |
392 | }; |
- | |
393 | - | ||
394 | template<Color Us, bool DoTrace> |
- | |
395 | Score evaluate_king(const Position& pos, const EvalInfo& ei) { |
- | |
396 | - | ||
397 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
428 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
398 | const |
429 | const Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB |
- | 430 | : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); |
|
399 | 431 | ||
400 | Bitboard undefended, b, b1, b2, safe, other; |
- | |
401 | int kingDanger; |
- | |
402 | const Square ksq = pos.square<KING>(Us); |
432 | const Square ksq = pos.square<KING>(Us); |
- | 433 | Bitboard weak, b, b1, b2, safe, unsafeChecks; |
|
403 | 434 | ||
404 | // King shelter and enemy pawns storm |
435 | // King shelter and enemy pawns storm |
405 | Score score = |
436 | Score score = pe->king_safety<Us>(pos, ksq); |
406 | 437 | ||
407 | // Main king safety evaluation |
438 | // Main king safety evaluation |
408 | if ( |
439 | if (kingAttackersCount[Them] > (1 - pos.count<QUEEN>(Them))) |
409 | { |
440 | { |
410 | // |
441 | // Attacked squares defended at most once by our queen or king |
411 |
|
442 | weak = attackedBy[Them][ALL_PIECES] |
412 | & ei.attackedBy[Us][KING] |
- | |
413 |
|
443 | & ~attackedBy2[Us] |
414 | - | ||
415 | // ... and those which are not defended at all in the larger king ring |
- | |
416 |
|
444 | & (attackedBy[Us][KING] | attackedBy[Us][QUEEN] | ~attackedBy[Us][ALL_PIECES]); |
417 | & ei.kingRing[Us] & ~pos.pieces(Them); |
- | |
418 | 445 | ||
419 | // Initialize the 'kingDanger' variable, which will be transformed |
- | |
420 | // later into a king danger score. The initial value is based on the |
- | |
421 | // number and types of the enemy's attacking pieces, the number of |
- | |
422 |
|
446 | unsafeChecks = 0; // Pierre-Marie Baty -- fixed variable initialization |
423 | // the pawn shelter (current 'score' value). |
- | |
424 | kingDanger = std::min(807, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) |
- | |
425 | + 101 * ei.kingAdjacentZoneAttacksCount[Them] |
- | |
426 | + 235 * popcount(undefended) |
- | |
427 | + 134 * (popcount(b) + !!ei.pinnedPieces[Us]) |
- | |
428 | - 717 * !pos.count<QUEEN>(Them) |
- | |
429 |
|
447 | int kingDanger = 0; |
430 | - | ||
431 | // Analyse the enemy's safe queen contact checks. Firstly, find the |
- | |
432 | // undefended squares around the king reachable by the enemy queen... |
- | |
433 | b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces(Them); |
- | |
434 | - | ||
435 | // ...and keep squares supported by another enemy piece |
- | |
436 | kingDanger += QueenContactCheck * popcount(b & ei.attackedBy2[Them]); |
- | |
437 | - | ||
438 | // Analyse the safe enemy's checks which are possible on next move... |
- | |
439 | safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them)); |
- | |
440 | 448 | ||
441 | // |
449 | // Analyse the safe enemy's checks which are possible on next move |
442 | // safe from pawn-attacks, and not being occupied by a blocked pawn. |
- | |
443 |
|
450 | safe = ~pos.pieces(Them); |
444 |
|
451 | safe &= ~attackedBy[Us][ALL_PIECES] | (weak & attackedBy2[Them]); |
445 | 452 | ||
446 | b1 = |
453 | b1 = attacks_bb<ROOK >(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); |
447 | b2 = |
454 | b2 = attacks_bb<BISHOP>(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); |
448 | 455 | ||
449 | // Enemy queen safe checks |
456 | // Enemy queen safe checks |
450 | if ((b1 | b2) & |
457 | if ((b1 | b2) & attackedBy[Them][QUEEN] & safe & ~attackedBy[Us][QUEEN]) |
451 | kingDanger += |
458 | kingDanger += QueenSafeCheck; |
452 | 459 | ||
453 | // For other pieces, also consider the square safe if attacked twice, |
- | |
454 | // and only defended by a queen. |
- | |
455 |
|
460 | b1 &= attackedBy[Them][ROOK]; |
456 | & ~(ei.attackedBy2[Us] | pos.pieces(Them)) |
- | |
457 |
|
461 | b2 &= attackedBy[Them][BISHOP]; |
458 | 462 | ||
459 | // Enemy rooks |
463 | // Enemy rooks checks |
460 | if (b1 |
464 | if (b1 & safe) |
461 | kingDanger += |
465 | kingDanger += RookSafeCheck; |
- | 466 | else |
|
- | 467 | unsafeChecks |= b1; |
|
462 | 468 | ||
- | 469 | // Enemy bishops checks |
|
- | 470 | if (b2 & safe) |
|
463 |
|
471 | kingDanger += BishopSafeCheck; |
- | 472 | else |
|
464 |
|
473 | unsafeChecks |= b2; |
465 | 474 | ||
466 | // Enemy bishops safe and other checks |
- | |
467 | if (b2 & ei.attackedBy[Them][BISHOP] & safe) |
- | |
468 | kingDanger += BishopCheck, score -= SafeCheck; |
- | |
469 | - | ||
470 | else if (b2 & ei.attackedBy[Them][BISHOP] & other) |
- | |
471 | score -= OtherCheck; |
- | |
472 | - | ||
473 | // Enemy knights |
475 | // Enemy knights checks |
474 | b = pos.attacks_from<KNIGHT>(ksq) & |
476 | b = pos.attacks_from<KNIGHT>(ksq) & attackedBy[Them][KNIGHT]; |
475 | if (b & safe) |
477 | if (b & safe) |
476 | kingDanger += |
478 | kingDanger += KnightSafeCheck; |
- | 479 | else |
|
- | 480 | unsafeChecks |= b; |
|
477 | 481 | ||
- | 482 | // Unsafe or occupied checking squares will also be considered, as long as |
|
478 |
|
483 | // the square is in the attacker's mobility area. |
479 |
|
484 | unsafeChecks &= mobilityArea[Them]; |
480 | 485 | ||
- | 486 | kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them] |
|
- | 487 | + 102 * kingAdjacentZoneAttacksCount[Them] |
|
- | 488 | + 191 * popcount(kingRing[Us] & weak) |
|
- | 489 | + 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks) |
|
- | 490 | - 848 * !pos.count<QUEEN>(Them) |
|
- | 491 | - 9 * mg_value(score) / 8 |
|
- | 492 | + 40; |
|
- | 493 | ||
481 | // |
494 | // Transform the kingDanger units into a Score, and subtract it from the evaluation |
482 | if (kingDanger > 0) |
495 | if (kingDanger > 0) |
- | 496 | { |
|
- | 497 | int mobilityDanger = mg_value(mobility[Them] - mobility[Us]); |
|
- | 498 | kingDanger = std::max(0, kingDanger + mobilityDanger); |
|
483 | score -= make_score |
499 | score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16); |
- | 500 | } |
|
484 | } |
501 | } |
485 | 502 | ||
486 | // King tropism: firstly, find squares that opponent attacks in our king flank |
503 | // King tropism: firstly, find squares that opponent attacks in our king flank |
487 | File kf = file_of(ksq); |
504 | File kf = file_of(ksq); |
488 | b = |
505 | b = attackedBy[Them][ALL_PIECES] & KingFlank[kf] & Camp; |
489 | 506 | ||
490 | assert(((Us == WHITE ? b << 4 : b >> 4) & b) == 0); |
507 | assert(((Us == WHITE ? b << 4 : b >> 4) & b) == 0); |
491 | assert(popcount(Us == WHITE ? b << 4 : b >> 4) == popcount(b)); |
508 | assert(popcount(Us == WHITE ? b << 4 : b >> 4) == popcount(b)); |
492 | 509 | ||
493 | // Secondly, add the squares which are attacked twice in that flank and |
510 | // Secondly, add the squares which are attacked twice in that flank and |
494 | // which are not defended by our pawns. |
511 | // which are not defended by our pawns. |
495 | b = (Us == WHITE ? b << 4 : b >> 4) |
512 | b = (Us == WHITE ? b << 4 : b >> 4) |
496 | | (b & |
513 | | (b & attackedBy2[Them] & ~attackedBy[Us][PAWN]); |
497 | 514 | ||
498 | score -= CloseEnemies * popcount(b); |
515 | score -= CloseEnemies * popcount(b); |
499 | 516 | ||
500 | // Penalty when our king is on a pawnless flank |
517 | // Penalty when our king is on a pawnless flank |
501 | if (!(pos.pieces(PAWN) & |
518 | if (!(pos.pieces(PAWN) & KingFlank[kf])) |
502 | score -= PawnlessFlank; |
519 | score -= PawnlessFlank; |
503 | 520 | ||
504 | if ( |
521 | if (T) |
505 | Trace::add(KING, Us, score); |
522 | Trace::add(KING, Us, score); |
506 | 523 | ||
507 | return score; |
524 | return score; |
508 | } |
525 | } |
509 | 526 | ||
510 | 527 | ||
511 | // evaluate_threats() assigns bonuses according to the types of the attacking |
528 | // evaluate_threats() assigns bonuses according to the types of the attacking |
512 | // and the attacked pieces. |
529 | // and the attacked pieces. |
513 | 530 | ||
514 | template< |
531 | template<Tracing T> template<Color Us> |
515 | Score |
532 | Score Evaluation<T>::evaluate_threats() { |
516 | 533 | ||
517 | const Color |
534 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
518 | const |
535 | const Direction Up = (Us == WHITE ? NORTH : SOUTH); |
519 | const |
536 | const Direction Left = (Us == WHITE ? NORTH_WEST : SOUTH_EAST); |
520 | const |
537 | const Direction Right = (Us == WHITE ? NORTH_EAST : SOUTH_WEST); |
521 | const Bitboard TRank2BB = (Us == WHITE ? Rank2BB : Rank7BB); |
- | |
522 | const Bitboard |
538 | const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); |
523 | 539 | ||
524 | enum { Minor, Rook }; |
- | |
525 | - | ||
526 | Bitboard b, weak, defended, safeThreats; |
540 | Bitboard b, weak, defended, stronglyProtected, safeThreats; |
527 | Score score = SCORE_ZERO; |
541 | Score score = SCORE_ZERO; |
528 | - | ||
529 | // Small bonus if the opponent has loose pawns or pieces |
- | |
530 | if ( (pos.pieces(Them) ^ pos.pieces(Them, QUEEN, KING)) |
- | |
531 | & ~(ei.attackedBy[Us][ALL_PIECES] | ei.attackedBy[Them][ALL_PIECES])) |
- | |
532 | score += LooseEnemies; |
- | |
533 | 542 | ||
534 | // Non-pawn enemies attacked by a pawn |
543 | // Non-pawn enemies attacked by a pawn |
535 | weak = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & |
544 | weak = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & attackedBy[Us][PAWN]; |
536 | 545 | ||
537 | if (weak) |
546 | if (weak) |
538 | { |
547 | { |
539 | b = pos.pieces(Us, PAWN) & ( |
548 | b = pos.pieces(Us, PAWN) & ( ~attackedBy[Them][ALL_PIECES] |
540 | | |
549 | | attackedBy[Us][ALL_PIECES]); |
541 | 550 | ||
542 | safeThreats = (shift<Right>(b) | shift<Left>(b)) & weak; |
551 | safeThreats = (shift<Right>(b) | shift<Left>(b)) & weak; |
543 | 552 | ||
544 | if (weak ^ safeThreats) |
- | |
545 | score += ThreatByHangingPawn; |
- | |
546 | - | ||
547 | while (safeThreats) |
- | |
548 |
|
553 | score += ThreatBySafePawn * popcount(safeThreats); |
549 | } |
554 | } |
550 | 555 | ||
- | 556 | // Squares strongly protected by the opponent, either because they attack the |
|
- | 557 | // square with a pawn, or because they attack the square twice and we don't. |
|
- | 558 | stronglyProtected = attackedBy[Them][PAWN] |
|
- | 559 | | (attackedBy2[Them] & ~attackedBy2[Us]); |
|
- | 560 | ||
551 | // Non-pawn |
561 | // Non-pawn enemies, strongly protected |
552 | defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) |
562 | defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) |
- | 563 | & stronglyProtected; |
|
553 | 564 | ||
554 | // Enemies not |
565 | // Enemies not strongly protected and under our attack |
555 | weak = pos.pieces(Them) |
566 | weak = pos.pieces(Them) |
556 | & |
567 | & ~stronglyProtected |
557 | & |
568 | & attackedBy[Us][ALL_PIECES]; |
558 | 569 | ||
559 | // Add a bonus according to the kind of attacking pieces |
570 | // Add a bonus according to the kind of attacking pieces |
560 | if (defended | weak) |
571 | if (defended | weak) |
561 | { |
572 | { |
562 | b = (defended | weak) & ( |
573 | b = (defended | weak) & (attackedBy[Us][KNIGHT] | attackedBy[Us][BISHOP]); |
563 | while (b) |
574 | while (b) |
- | 575 | { |
|
- | 576 | Square s = pop_lsb(&b); |
|
564 | score += |
577 | score += ThreatByMinor[type_of(pos.piece_on(s))]; |
- | 578 | if (type_of(pos.piece_on(s)) != PAWN) |
|
- | 579 | score += ThreatByRank * (int)relative_rank(Them, s); |
|
- | 580 | } |
|
565 | 581 | ||
566 | b = (pos.pieces(Them, QUEEN) | weak) & |
582 | b = (pos.pieces(Them, QUEEN) | weak) & attackedBy[Us][ROOK]; |
567 | while (b) |
583 | while (b) |
- | 584 | { |
|
- | 585 | Square s = pop_lsb(&b); |
|
568 | score += |
586 | score += ThreatByRook[type_of(pos.piece_on(s))]; |
- | 587 | if (type_of(pos.piece_on(s)) != PAWN) |
|
- | 588 | score += ThreatByRank * (int)relative_rank(Them, s); |
|
- | 589 | } |
|
569 | 590 | ||
570 | score += Hanging * popcount(weak & |
591 | score += Hanging * popcount(weak & ~attackedBy[Them][ALL_PIECES]); |
571 | 592 | ||
572 | b = weak & |
593 | b = weak & attackedBy[Us][KING]; |
573 | if (b) |
594 | if (b) |
574 | score += ThreatByKing[more_than_one(b)]; |
595 | score += ThreatByKing[more_than_one(b)]; |
575 | } |
596 | } |
576 | 597 | ||
577 | // Bonus |
598 | // Bonus for opponent unopposed weak pawns |
578 |
|
599 | if (pos.pieces(Us, ROOK, QUEEN)) |
579 |
|
600 | score += WeakUnopposedPawn * pe->weak_unopposed(Them); |
580 | 601 | ||
581 |
|
602 | // Find squares where our pawns can push on the next move |
582 |
|
603 | b = shift<Up>(pos.pieces(Us, PAWN)) & ~pos.pieces(); |
583 |
|
604 | b |= shift<Up>(b & TRank3BB) & ~pos.pieces(); |
584 | 605 | ||
- | 606 | // Keep only the squares which are not completely unsafe |
|
- | 607 | b &= ~attackedBy[Them][PAWN] |
|
- | 608 | & (attackedBy[Us][ALL_PIECES] | ~attackedBy[Them][ALL_PIECES]); |
|
- | 609 | ||
- | 610 | // Add a bonus for each new pawn threats from those squares |
|
585 | b = (shift<Left>(b) | shift<Right>(b)) |
611 | b = (shift<Left>(b) | shift<Right>(b)) |
586 | & pos.pieces(Them) |
612 | & pos.pieces(Them) |
587 | & |
613 | & ~attackedBy[Us][PAWN]; |
588 | 614 | ||
589 | score += ThreatByPawnPush * popcount(b); |
615 | score += ThreatByPawnPush * popcount(b); |
590 | 616 | ||
- | 617 | // Add a bonus for safe slider attack threats on opponent queen |
|
- | 618 | safeThreats = ~pos.pieces(Us) & ~attackedBy2[Them] & attackedBy2[Us]; |
|
- | 619 | b = (attackedBy[Us][BISHOP] & attackedBy[Them][QUEEN_DIAGONAL]) |
|
- | 620 | | (attackedBy[Us][ROOK ] & attackedBy[Them][QUEEN] & ~attackedBy[Them][QUEEN_DIAGONAL]); |
|
- | 621 | ||
- | 622 | score += ThreatByAttackOnQueen * popcount(b & safeThreats); |
|
- | 623 | ||
591 | if ( |
624 | if (T) |
592 | Trace::add(THREAT, Us, score); |
625 | Trace::add(THREAT, Us, score); |
593 | 626 | ||
594 | return score; |
627 | return score; |
595 | } |
628 | } |
596 | 629 | ||
- | 630 | // helper used by evaluate_passed_pawns to cap the distance |
|
- | 631 | template<Tracing T> |
|
- | 632 | int Evaluation<T>::king_distance(Color c, Square s) { |
|
- | 633 | return std::min(distance(pos.square<KING>(c), s), 5); |
|
- | 634 | } |
|
597 | 635 | ||
598 | // evaluate_passed_pawns() evaluates the passed pawns |
636 | // evaluate_passed_pawns() evaluates the passed pawns and candidate passed |
- | 637 | // pawns of the given color. |
|
599 | 638 | ||
600 | template< |
639 | template<Tracing T> template<Color Us> |
601 | Score |
640 | Score Evaluation<T>::evaluate_passed_pawns() { |
602 | 641 | ||
603 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
642 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
- | 643 | const Direction Up = (Us == WHITE ? NORTH : SOUTH); |
|
604 | 644 | ||
605 | Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares; |
645 | Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares; |
606 | Score score = SCORE_ZERO; |
646 | Score score = SCORE_ZERO; |
607 | 647 | ||
608 | b = |
648 | b = pe->passed_pawns(Us); |
609 | 649 | ||
610 | while (b) |
650 | while (b) |
611 | { |
651 | { |
612 | Square s = pop_lsb(&b); |
652 | Square s = pop_lsb(&b); |
613 | 653 | ||
614 | assert(pos.pawn_passed(Us, s)); |
- | |
615 | assert(!(pos.pieces(PAWN) & |
654 | assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up))); |
616 | 655 | ||
617 | bb = |
656 | bb = forward_file_bb(Us, s) & (attackedBy[Them][ALL_PIECES] | pos.pieces(Them)); |
618 | score -= HinderPassedPawn * popcount(bb); |
657 | score -= HinderPassedPawn * popcount(bb); |
619 | 658 | ||
620 | int r = relative_rank(Us, s) |
659 | int r = relative_rank(Us, s); |
621 | int rr = |
660 | int rr = RankFactor[r]; |
622 | 661 | ||
623 | Value mbonus = Passed[MG][r], ebonus = Passed[EG][r]; |
662 | Value mbonus = Passed[MG][r], ebonus = Passed[EG][r]; |
624 | 663 | ||
625 | if (rr) |
664 | if (rr) |
626 | { |
665 | { |
627 | Square blockSq = s + |
666 | Square blockSq = s + Up; |
628 | 667 | ||
629 | // Adjust bonus based on the king's proximity |
668 | // Adjust bonus based on the king's proximity |
630 | ebonus += |
669 | ebonus += (king_distance(Them, blockSq) * 5 - king_distance(Us, blockSq) * 2) * rr; |
631 | - distance(pos.square<KING>(Us ), blockSq) * 2 * rr; |
- | |
632 | 670 | ||
633 | // If blockSq is not the queening square then consider also a second push |
671 | // If blockSq is not the queening square then consider also a second push |
634 | if ( |
672 | if (r != RANK_7) |
635 | ebonus -= |
673 | ebonus -= king_distance(Us, blockSq + Up) * rr; |
636 | 674 | ||
637 | // If the pawn is free to advance, then increase the bonus |
675 | // If the pawn is free to advance, then increase the bonus |
638 | if (pos.empty(blockSq)) |
676 | if (pos.empty(blockSq)) |
639 | { |
677 | { |
640 | // If there is a rook or queen attacking/defending the pawn from behind, |
678 | // If there is a rook or queen attacking/defending the pawn from behind, |
641 | // consider all the squaresToQueen. Otherwise consider only the squares |
679 | // consider all the squaresToQueen. Otherwise consider only the squares |
642 | // in the pawn's path attacked or occupied by the enemy. |
680 | // in the pawn's path attacked or occupied by the enemy. |
643 | defendedSquares = unsafeSquares = squaresToQueen = |
681 | defendedSquares = unsafeSquares = squaresToQueen = forward_file_bb(Us, s); |
644 | 682 | ||
645 | bb = |
683 | bb = forward_file_bb(Them, s) & pos.pieces(ROOK, QUEEN) & pos.attacks_from<ROOK>(s); |
646 | 684 | ||
647 | if (!(pos.pieces(Us) & bb)) |
685 | if (!(pos.pieces(Us) & bb)) |
648 | defendedSquares &= |
686 | defendedSquares &= attackedBy[Us][ALL_PIECES]; |
649 | 687 | ||
650 | if (!(pos.pieces(Them) & bb)) |
688 | if (!(pos.pieces(Them) & bb)) |
651 | unsafeSquares &= |
689 | unsafeSquares &= attackedBy[Them][ALL_PIECES] | pos.pieces(Them); |
652 | 690 | ||
653 | // If there aren't any enemy attacks, assign a big bonus. Otherwise |
691 | // If there aren't any enemy attacks, assign a big bonus. Otherwise |
654 | // assign a smaller bonus if the block square isn't attacked. |
692 | // assign a smaller bonus if the block square isn't attacked. |
655 | int k = !unsafeSquares ? 18 : !(unsafeSquares & blockSq) ? 8 : 0; |
693 | int k = !unsafeSquares ? 18 : !(unsafeSquares & blockSq) ? 8 : 0; |
656 | 694 | ||
Line 665... | Line 703... | ||
665 | mbonus += k * rr, ebonus += k * rr; |
703 | mbonus += k * rr, ebonus += k * rr; |
666 | } |
704 | } |
667 | else if (pos.pieces(Us) & blockSq) |
705 | else if (pos.pieces(Us) & blockSq) |
668 | mbonus += rr + r * 2, ebonus += rr + r * 2; |
706 | mbonus += rr + r * 2, ebonus += rr + r * 2; |
669 | } // rr != 0 |
707 | } // rr != 0 |
- | 708 | ||
- | 709 | // Scale down bonus for candidate passers which need more than one |
|
- | 710 | // pawn push to become passed or have a pawn in front of them. |
|
- | 711 | if (!pos.pawn_passed(Us, s + Up) || (pos.pieces(PAWN) & forward_file_bb(Us, s))) |
|
- | 712 | mbonus /= 2, ebonus /= 2; |
|
670 | 713 | ||
671 | score += make_score(mbonus, ebonus) + PassedFile[file_of(s)]; |
714 | score += make_score(mbonus, ebonus) + PassedFile[file_of(s)]; |
672 | } |
715 | } |
673 | 716 | ||
674 | if ( |
717 | if (T) |
675 | Trace::add(PASSED, Us, score); |
718 | Trace::add(PASSED, Us, score); |
676 | 719 | ||
677 | // Add the scores to the middlegame and endgame eval |
- | |
678 | return score; |
720 | return score; |
679 | } |
721 | } |
680 | 722 | ||
681 | 723 | ||
682 | // evaluate_space() computes the space evaluation for a given side. The |
724 | // evaluate_space() computes the space evaluation for a given side. The |
683 | // space evaluation is a simple bonus based on the number of safe squares |
725 | // space evaluation is a simple bonus based on the number of safe squares |
684 | // available for minor pieces on the central four files on ranks 2--4. Safe |
726 | // available for minor pieces on the central four files on ranks 2--4. Safe |
685 | // squares one, two or three squares behind a friendly pawn are counted |
727 | // squares one, two or three squares behind a friendly pawn are counted |
686 | // twice. Finally, the space bonus is multiplied by a weight. The aim is to |
728 | // twice. Finally, the space bonus is multiplied by a weight. The aim is to |
687 | // improve play on game opening. |
729 | // improve play on game opening. |
- | 730 | ||
688 | template<Color Us> |
731 | template<Tracing T> template<Color Us> |
689 | Score |
732 | Score Evaluation<T>::evaluate_space() { |
690 | 733 | ||
691 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
734 | const Color Them = (Us == WHITE ? BLACK : WHITE); |
692 | const Bitboard SpaceMask = |
735 | const Bitboard SpaceMask = |
693 | Us == WHITE ? |
736 | Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB) |
694 | : |
737 | : CenterFiles & (Rank7BB | Rank6BB | Rank5BB); |
695 | 738 | ||
696 | // Find the safe squares for our pieces inside the area defined by |
739 | // Find the safe squares for our pieces inside the area defined by |
697 | // SpaceMask. A square is unsafe if it is attacked by an enemy |
740 | // SpaceMask. A square is unsafe if it is attacked by an enemy |
698 | // pawn, or if it is undefended and attacked by an enemy piece. |
741 | // pawn, or if it is undefended and attacked by an enemy piece. |
699 | Bitboard safe = SpaceMask |
742 | Bitboard safe = SpaceMask |
700 | & ~pos.pieces(Us, PAWN) |
743 | & ~pos.pieces(Us, PAWN) |
701 | & |
744 | & ~attackedBy[Them][PAWN] |
702 | & ( |
745 | & (attackedBy[Us][ALL_PIECES] | ~attackedBy[Them][ALL_PIECES]); |
703 | 746 | ||
704 | // Find all squares which are at most three squares behind some friendly pawn |
747 | // Find all squares which are at most three squares behind some friendly pawn |
705 | Bitboard behind = pos.pieces(Us, PAWN); |
748 | Bitboard behind = pos.pieces(Us, PAWN); |
706 | behind |= (Us == WHITE ? behind >> 8 : behind << 8); |
749 | behind |= (Us == WHITE ? behind >> 8 : behind << 8); |
707 | behind |= (Us == WHITE ? behind >> 16 : behind << 16); |
750 | behind |= (Us == WHITE ? behind >> 16 : behind << 16); |
708 | 751 | ||
709 | // Since SpaceMask[Us] is fully on our half of the board... |
752 | // Since SpaceMask[Us] is fully on our half of the board... |
710 | assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0); |
753 | assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0); |
711 | 754 | ||
712 | // ...count safe + (behind & safe) with a single popcount |
755 | // ...count safe + (behind & safe) with a single popcount. |
713 | int bonus = popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe)); |
756 | int bonus = popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe)); |
714 | bonus = std::min(16, bonus); |
- | |
715 | int weight = pos.count<ALL_PIECES>(Us) - 2 * |
757 | int weight = pos.count<ALL_PIECES>(Us) - 2 * pe->open_files(); |
716 | 758 | ||
717 | return make_score(bonus * weight * weight / |
759 | return make_score(bonus * weight * weight / 16, 0); |
718 | } |
760 | } |
719 | 761 | ||
720 | 762 | ||
721 | // evaluate_initiative() computes the initiative correction value for the |
763 | // evaluate_initiative() computes the initiative correction value for the |
722 | // position, i.e., second order bonus/malus based on the known attacking/defending |
764 | // position, i.e., second order bonus/malus based on the known attacking/defending |
723 | // status of the players. |
765 | // status of the players. |
- | 766 | ||
- | 767 | template<Tracing T> |
|
724 | Score |
768 | Score Evaluation<T>::evaluate_initiative(Value eg) { |
725 | 769 | ||
726 | int kingDistance = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK)) |
770 | int kingDistance = distance<File>(pos.square<KING>(WHITE), pos.square<KING>(BLACK)) |
727 | - distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK)); |
771 | - distance<Rank>(pos.square<KING>(WHITE), pos.square<KING>(BLACK)); |
728 |
|
772 | bool bothFlanks = (pos.pieces(PAWN) & QueenSide) && (pos.pieces(PAWN) & KingSide); |
729 | 773 | ||
730 | // Compute the initiative bonus for the attacking side |
774 | // Compute the initiative bonus for the attacking side |
731 | int initiative = 8 * ( |
775 | int initiative = 8 * (pe->pawn_asymmetry() + kingDistance - 17) + 12 * pos.count<PAWN>() + 16 * bothFlanks; |
732 | 776 | ||
733 | // Now apply the bonus: note that we find the attacking side by extracting |
777 | // Now apply the bonus: note that we find the attacking side by extracting |
734 | // the sign of the endgame value, and that we carefully cap the bonus so |
778 | // the sign of the endgame value, and that we carefully cap the bonus so |
735 | // that the endgame score will never |
779 | // that the endgame score will never change sign after the bonus. |
736 | int |
780 | int v = ((eg > 0) - (eg < 0)) * std::max(initiative, -abs(eg)); |
- | 781 | ||
- | 782 | if (T) |
|
- | 783 | Trace::add(INITIATIVE, make_score(0, v)); |
|
737 | 784 | ||
738 | return make_score(0, |
785 | return make_score(0, v); |
739 | } |
786 | } |
740 | 787 | ||
741 | 788 | ||
742 | // evaluate_scale_factor() computes the scale factor for the winning side |
789 | // evaluate_scale_factor() computes the scale factor for the winning side |
- | 790 | ||
- | 791 | template<Tracing T> |
|
743 | ScaleFactor |
792 | ScaleFactor Evaluation<T>::evaluate_scale_factor(Value eg) { |
744 | 793 | ||
745 | Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK; |
794 | Color strongSide = eg > VALUE_DRAW ? WHITE : BLACK; |
746 | ScaleFactor sf = |
795 | ScaleFactor sf = me->scale_factor(pos, strongSide); |
747 | 796 | ||
748 | // If we don't already have an unusual scale factor, check for certain |
797 | // If we don't already have an unusual scale factor, check for certain |
749 | // types of endgames, and use a lower scale for those. |
798 | // types of endgames, and use a lower scale for those. |
750 | if ( ei.me->game_phase() < PHASE_MIDGAME |
- | |
751 |
|
799 | if (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN) |
752 | { |
800 | { |
753 | if (pos.opposite_bishops()) |
801 | if (pos.opposite_bishops()) |
754 | { |
802 | { |
755 | // Endgame with opposite-colored bishops and no other pieces (ignoring pawns) |
803 | // Endgame with opposite-colored bishops and no other pieces (ignoring pawns) |
756 | // is almost a draw, in case of KBP vs KB, it is even more a draw. |
804 | // is almost a draw, in case of KBP vs KB, it is even more a draw. |
757 | if ( pos.non_pawn_material(WHITE) == BishopValueMg |
805 | if ( pos.non_pawn_material(WHITE) == BishopValueMg |
758 | && pos.non_pawn_material(BLACK) == BishopValueMg) |
806 | && pos.non_pawn_material(BLACK) == BishopValueMg) |
759 |
|
807 | return more_than_one(pos.pieces(PAWN)) ? ScaleFactor(31) : ScaleFactor(9); |
760 | 808 | ||
761 | // Endgame with opposite-colored bishops, but also other pieces. Still |
809 | // Endgame with opposite-colored bishops, but also other pieces. Still |
762 | // a bit drawish, but not as drawish as with only the two bishops. |
810 | // a bit drawish, but not as drawish as with only the two bishops. |
763 | else |
- | |
764 |
|
811 | return ScaleFactor(46); |
765 | } |
812 | } |
766 | // Endings where weaker side can place his king in front of the opponent's |
813 | // Endings where weaker side can place his king in front of the opponent's |
767 | // pawns are drawish. |
814 | // pawns are drawish. |
768 | else if ( abs(eg) <= BishopValueEg |
815 | else if ( abs(eg) <= BishopValueEg |
769 | && pos.count<PAWN>(strongSide) <= 2 |
816 | && pos.count<PAWN>(strongSide) <= 2 |
770 | && !pos.pawn_passed(~strongSide, pos.square<KING>(~strongSide))) |
817 | && !pos.pawn_passed(~strongSide, pos.square<KING>(~strongSide))) |
771 |
|
818 | return ScaleFactor(37 + 7 * pos.count<PAWN>(strongSide)); |
772 | } |
819 | } |
773 | 820 | ||
774 | return sf; |
821 | return sf; |
775 | } |
822 | } |
776 | 823 | ||
777 | } // namespace |
- | |
778 | 824 | ||
- | 825 | // value() is the main function of the class. It computes the various parts of |
|
- | 826 | // the evaluation and returns the value of the position from the point of view |
|
- | 827 | // of the side to move. |
|
779 | 828 | ||
780 |
|
829 | template<Tracing T> |
781 |
|
830 | Value Evaluation<T>::value() { |
782 | 831 | ||
783 |
|
832 | assert(!pos.checkers()); |
784 | Value Eval::evaluate(const Position& pos) { |
- | |
785 | 833 | ||
- | 834 | // Probe the material hash table |
|
786 |
|
835 | me = Material::probe(pos); |
787 | 836 | ||
- | 837 | // If we have a specialized evaluation function for the current material |
|
788 |
|
838 | // configuration, call it and return. |
- | 839 | if (me->specialized_eval_exists()) |
|
789 |
|
840 | return me->evaluate(pos); |
790 | 841 | ||
- | 842 | // Initialize score by reading the incrementally updated scores included in |
|
791 | // |
843 | // the position object (material + piece square tables) and the material |
- | 844 | // imbalance. Score is computed internally from the white point of view. |
|
792 |
|
845 | Score score = pos.psq_score() + me->imbalance() + Eval::Contempt; |
793 | 846 | ||
794 | // If we have a specialized evaluation function for the current material |
- | |
795 | // |
847 | // Probe the pawn hash table |
796 |
|
848 | pe = Pawns::probe(pos); |
797 |
|
849 | score += pe->pawns_score(); |
798 | 850 | ||
799 |
|
851 | // Early exit if score is high |
800 |
|
852 | Value v = (mg_value(score) + eg_value(score)) / 2; |
801 |
|
853 | if (abs(v) > LazyThreshold) |
802 |
|
854 | return pos.side_to_move() == WHITE ? v : -v; |
803 | 855 | ||
804 | // |
856 | // Main evaluation begins here |
805 | ei.pi = Pawns::probe(pos); |
- | |
806 | score += ei.pi->pawns_score(); |
- | |
807 | 857 | ||
808 | // Initialize attack and king safety bitboards |
- | |
809 | ei.attackedBy[WHITE][ALL_PIECES] = ei.attackedBy[BLACK][ALL_PIECES] = 0; |
- | |
810 | ei.attackedBy[WHITE][KING] = pos.attacks_from<KING>(pos.square<KING>(WHITE)); |
- | |
811 | ei.attackedBy[BLACK][KING] = pos.attacks_from<KING>(pos.square<KING>(BLACK)); |
- | |
812 |
|
858 | initialize<WHITE>(); |
813 |
|
859 | initialize<BLACK>(); |
814 | 860 | ||
815 |
|
861 | score += evaluate_pieces<WHITE, KNIGHT>() - evaluate_pieces<BLACK, KNIGHT>(); |
816 |
|
862 | score += evaluate_pieces<WHITE, BISHOP>() - evaluate_pieces<BLACK, BISHOP>(); |
817 |
|
863 | score += evaluate_pieces<WHITE, ROOK >() - evaluate_pieces<BLACK, ROOK >(); |
818 |
|
864 | score += evaluate_pieces<WHITE, QUEEN >() - evaluate_pieces<BLACK, QUEEN >(); |
819 | }; |
- | |
820 | 865 | ||
821 | // Do not include in mobility area squares protected by enemy pawns, or occupied |
- | |
822 | // by our blocked pawns or king. |
- | |
823 |
|
866 | score += mobility[WHITE] - mobility[BLACK]; |
824 | ~(ei.attackedBy[BLACK][PAWN] | blockedPawns[WHITE] | pos.square<KING>(WHITE)), |
- | |
825 | ~(ei.attackedBy[WHITE][PAWN] | blockedPawns[BLACK] | pos.square<KING>(BLACK)) |
- | |
826 | }; |
- | |
827 | 867 | ||
828 |
|
868 | score += evaluate_king<WHITE>() |
829 | score += evaluate_pieces<DoTrace>(pos, ei, mobility, mobilityArea); |
- | |
830 |
|
869 | - evaluate_king<BLACK>(); |
831 | 870 | ||
832 | // Evaluate kings after all other pieces because we need full attack |
- | |
833 | // information when computing the king safety evaluation. |
- | |
834 | score += |
871 | score += evaluate_threats<WHITE>() |
835 |
|
872 | - evaluate_threats<BLACK>(); |
836 | 873 | ||
837 | // Evaluate tactical threats, we need full attack information including king |
- | |
838 | score += |
874 | score += evaluate_passed_pawns<WHITE>() |
839 |
|
875 | - evaluate_passed_pawns<BLACK>(); |
840 | 876 | ||
841 |
|
877 | if (pos.non_pawn_material() >= SpaceThreshold) |
842 | score += |
878 | score += evaluate_space<WHITE>() |
843 | - |
879 | - evaluate_space<BLACK>(); |
844 | 880 | ||
845 | // If both sides have only pawns, score for potential unstoppable pawns |
- | |
846 | if (!pos.non_pawn_material(WHITE) && !pos.non_pawn_material(BLACK)) |
- | |
847 | { |
- | |
848 | Bitboard b; |
- | |
849 |
|
881 | score += evaluate_initiative(eg_value(score)); |
850 | score += Unstoppable * int(relative_rank(WHITE, frontmost_sq(WHITE, b))); |
- | |
851 | 882 | ||
- | 883 | // Interpolate between a middlegame and a (scaled by 'sf') endgame score |
|
- | 884 | ScaleFactor sf = evaluate_scale_factor(eg_value(score)); |
|
852 |
|
885 | v = mg_value(score) * int(me->game_phase()) |
853 |
|
886 | + eg_value(score) * int(PHASE_MIDGAME - me->game_phase()) * sf / SCALE_FACTOR_NORMAL; |
854 | } |
- | |
855 | 887 | ||
856 | // Evaluate space for both sides, only during opening |
- | |
857 | if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >= 12222) |
- | |
858 |
|
888 | v /= int(PHASE_MIDGAME); |
859 | - evaluate_space<BLACK>(pos, ei); |
- | |
860 | 889 | ||
861 | // |
890 | // In case of tracing add all remaining individual evaluation terms |
- | 891 | if (T) |
|
- | 892 | { |
|
- | 893 | Trace::add(MATERIAL, pos.psq_score()); |
|
- | 894 | Trace::add(IMBALANCE, me->imbalance()); |
|
862 |
|
895 | Trace::add(PAWN, pe->pawns_score()); |
- | 896 | Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]); |
|
- | 897 | if (pos.non_pawn_material() >= SpaceThreshold) |
|
- | 898 | Trace::add(SPACE, evaluate_space<WHITE>() |
|
- | 899 | , evaluate_space<BLACK>()); |
|
- | 900 | Trace::add(TOTAL, score); |
|
- | 901 | } |
|
863 | 902 | ||
864 | // Evaluate scale factor for the winning side |
- | |
865 |
|
903 | return pos.side_to_move() == WHITE ? v : -v; // Side to move point of view |
- | 904 | } |
|
866 | 905 | ||
867 | // Interpolate between a middlegame and a (scaled by 'sf') endgame score |
- | |
868 |
|
906 | } // namespace |
869 | + eg_value(score) * int(PHASE_MIDGAME - ei.me->game_phase()) * sf / SCALE_FACTOR_NORMAL; |
- | |
870 | 907 | ||
871 |
|
908 | Score Eval::Contempt = SCORE_ZERO; |
872 | 909 | ||
873 |
|
910 | /// evaluate() is the evaluator for the outer world. It returns a static evaluation |
874 | if (DoTrace) |
- | |
875 | { |
- | |
876 | Trace::add(MATERIAL, pos.psq_score()); |
- | |
877 | Trace::add(IMBALANCE, ei.me->imbalance()); |
- | |
878 | Trace::add(PAWN, ei.pi->pawns_score()); |
- | |
879 | Trace::add(MOBILITY, mobility[WHITE], mobility[BLACK]); |
- | |
880 | Trace::add(SPACE, evaluate_space<WHITE>(pos, ei) |
- | |
881 |
|
911 | /// of the position from the point of view of the side to move. |
882 | Trace::add(TOTAL, score); |
- | |
883 | } |
- | |
884 | 912 | ||
- | 913 | Value Eval::evaluate(const Position& pos) |
|
- | 914 | { |
|
885 | return (pos. |
915 | return Evaluation<>(pos).value() + Eval::Tempo; |
886 | } |
916 | } |
887 | - | ||
888 | // Explicit template instantiations |
- | |
889 | template Value Eval::evaluate<true >(const Position&); |
- | |
890 | template Value Eval::evaluate<false>(const Position&); |
- | |
891 | - | ||
892 | 917 | ||
893 | /// trace() is like evaluate(), but instead of returning a value, it returns |
918 | /// trace() is like evaluate(), but instead of returning a value, it returns |
894 | /// a string (suitable for outputting to stdout) that contains the detailed |
919 | /// a string (suitable for outputting to stdout) that contains the detailed |
895 | /// descriptions and values of each evaluation term. Useful for debugging. |
920 | /// descriptions and values of each evaluation term. Useful for debugging. |
896 | 921 | ||
897 | std::string Eval::trace(const Position& pos) { |
922 | std::string Eval::trace(const Position& pos) { |
898 | 923 | ||
899 | std::memset(scores, 0, sizeof(scores)); |
924 | std::memset(scores, 0, sizeof(scores)); |
900 | 925 | ||
901 | Value v = |
926 | Value v = Evaluation<TRACE>(pos).value() + Eval::Tempo; |
902 | v = pos.side_to_move() == WHITE ? v : -v; // White's point of view |
927 | v = pos.side_to_move() == WHITE ? v : -v; // White's point of view |
903 | 928 | ||
904 | std::stringstream ss; |
929 | std::stringstream ss; |
905 | ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2) |
930 | ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2) |
906 | << " Eval term | White | Black | Total \n" |
931 | << " Eval term | White | Black | Total \n" |
Line 908... | Line 933... | ||
908 | << "----------------+-------------+-------------+-------------\n" |
933 | << "----------------+-------------+-------------+-------------\n" |
909 | << " Material | " << Term(MATERIAL) |
934 | << " Material | " << Term(MATERIAL) |
910 | << " Imbalance | " << Term(IMBALANCE) |
935 | << " Imbalance | " << Term(IMBALANCE) |
911 | << " Pawns | " << Term(PAWN) |
936 | << " Pawns | " << Term(PAWN) |
912 | << " Knights | " << Term(KNIGHT) |
937 | << " Knights | " << Term(KNIGHT) |
913 | << " |
938 | << " Bishops | " << Term(BISHOP) |
914 | << " Rooks | " << Term(ROOK) |
939 | << " Rooks | " << Term(ROOK) |
915 | << " Queens | " << Term(QUEEN) |
940 | << " Queens | " << Term(QUEEN) |
916 | << " Mobility | " << Term(MOBILITY) |
941 | << " Mobility | " << Term(MOBILITY) |
917 | << " King safety | " << Term(KING) |
942 | << " King safety | " << Term(KING) |
918 | << " Threats | " << Term(THREAT) |
943 | << " Threats | " << Term(THREAT) |
919 | << " Passed pawns | " << Term(PASSED) |
944 | << " Passed pawns | " << Term(PASSED) |
920 | << " Space | " << Term(SPACE) |
945 | << " Space | " << Term(SPACE) |
- | 946 | << " Initiative | " << Term(INITIATIVE) |
|
921 | << "----------------+-------------+-------------+-------------\n" |
947 | << "----------------+-------------+-------------+-------------\n" |
922 | << " Total | " << Term(TOTAL); |
948 | << " Total | " << Term(TOTAL); |
923 | 949 | ||
924 | ss << "\nTotal Evaluation: " << to_cp(v) << " (white side)\n"; |
950 | ss << "\nTotal Evaluation: " << to_cp(v) << " (white side)\n"; |
925 | 951 |