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