Rev 33 | Rev 154 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
33 | pmbaty | 1 | #include "chess.h" |
108 | pmbaty | 2 | #include "evaluate.h" |
33 | pmbaty | 3 | #include "data.h" |
108 | pmbaty | 4 | /* last modified 12/31/15 */ |
33 | pmbaty | 5 | /* |
6 | ******************************************************************************* |
||
7 | * * |
||
8 | * Evaluate() is used to evaluate the chess board. Broadly, it addresses * |
||
9 | * four (4) distinct areas: (1) material score which is simply a summing of * |
||
10 | * piece types multiplied by piece values; (2) pawn scoring which considers * |
||
11 | * placement of pawns and also evaluates passed pawns, particularly in end- * |
||
12 | * game situations; (3) piece scoring which evaluates the placement of each * |
||
13 | * piece as well as things like piece mobility; (4) king safety which * |
||
108 | pmbaty | 14 | * considers the pawn shelter around the king and enemy pieces and how close * |
15 | * they are to assist in a king-side attack. * |
||
33 | pmbaty | 16 | * * |
17 | ******************************************************************************* |
||
18 | */ |
||
19 | int Evaluate(TREE * RESTRICT tree, int ply, int wtm, int alpha, int beta) { |
||
20 | PAWN_HASH_ENTRY *ptable; |
||
21 | PXOR *pxtable; |
||
108 | pmbaty | 22 | int score, side, can_win = 3, phase, lscore, cutoff; |
23 | int full = 0; |
||
24 | uint64_t *etable; |
||
25 | uint64_t temp_hashkey; |
||
33 | pmbaty | 26 | |
27 | /* |
||
108 | pmbaty | 28 | ************************************************************* |
29 | * * |
||
30 | * First thing we do is if -DSKILL was passed in to the * |
||
31 | * compiler, we burn some time to slow the search down, * |
||
32 | * then we fall into the normal evaluation code. * |
||
33 | * * |
||
34 | ************************************************************* |
||
33 | pmbaty | 35 | */ |
36 | #if defined(SKILL) |
||
37 | if (skill < 100) { |
||
38 | int i, j; |
||
108 | pmbaty | 39 | for (i = 0; i < burnc[skill / 10] && !abort_search; i++) |
40 | for (j = 1; j < 10 && !abort_search; j++) |
||
33 | pmbaty | 41 | burner[j - 1] = burner[j - 1] * burner[j]; |
108 | pmbaty | 42 | if (TimeCheck(tree, 1)) |
43 | abort_search = 1; |
||
33 | pmbaty | 44 | } |
45 | #endif |
||
46 | /* |
||
47 | ************************************************************ |
||
48 | * * |
||
108 | pmbaty | 49 | * Next we check to see if this position has been handled * |
50 | * before. If so, we can skip the work saved in the eval * |
||
51 | * hash table and just return the score found there. Note * |
||
52 | * that we only store FULL evaluations in the evaluation * |
||
53 | * hash, if an early (lazy) exit is taken, nothing is * |
||
54 | * stored. * |
||
33 | pmbaty | 55 | * * |
56 | ************************************************************ |
||
108 | pmbaty | 57 | */ |
58 | temp_hashkey = (wtm) ? HashKey : ~HashKey; |
||
59 | etable = eval_hash_table + (temp_hashkey & eval_hash_mask); |
||
60 | if (*etable >> 16 == temp_hashkey >> 16) { |
||
61 | score = (*etable & 0xffff) - 32768; |
||
62 | return (wtm) ? score : -score; |
||
63 | } |
||
33 | pmbaty | 64 | /* |
108 | pmbaty | 65 | ************************************************************* |
66 | * * |
||
67 | * First lazy cutoff attempt. If the material score is way * |
||
68 | * below alpha or way above beta (way above means so far * |
||
69 | * above it is very unlikely the positional score can bring * |
||
70 | * the total score back into the alpha / beta window) then * |
||
71 | * we take what is known as a "lazy evaluation exit" and * |
||
72 | * avoid the computational cost of a full evaluation in a * |
||
73 | * position where one side is way ahead or behind. * |
||
74 | * * |
||
75 | ************************************************************* |
||
33 | pmbaty | 76 | */ |
108 | pmbaty | 77 | cutoff = (TotalPieces(white, occupied) && TotalPieces(black, occupied)) |
78 | ? KNIGHT_VALUE : ROOK_VALUE; |
||
79 | lscore = MaterialSTM(wtm); |
||
80 | if (lscore + cutoff < alpha) |
||
81 | return alpha; |
||
82 | if (lscore - cutoff > beta) |
||
83 | return beta; |
||
33 | pmbaty | 84 | /* |
108 | pmbaty | 85 | ************************************************************* |
86 | * * |
||
87 | * Check for draws where one side seems to be ahead, but * |
||
88 | * has no actual winning chances. One simple example is a * |
||
89 | * king, bishop and rook pawn, with the wrong colored * |
||
90 | * bishop and the enemy king too close to the promotion * |
||
91 | * square. * |
||
92 | * * |
||
93 | * The variable "can_win" uses 2 bits. If White can * |
||
94 | * actually win in this position, bit 1 is set. If Black * |
||
95 | * can actually win in this position, bit 0 is set. If * |
||
96 | * both sides can win, both bits are set. This is used * |
||
97 | * later to drag the score closer to a draw score if the * |
||
98 | * side with the better score can't actually win. * |
||
99 | * * |
||
100 | * Note that we only set these bits in minimal material * |
||
101 | * positions (both sides have < 13 points of material * |
||
102 | * total). Otherwise we assume normal scoring should * |
||
103 | * apply. * |
||
104 | * * |
||
105 | ************************************************************* |
||
33 | pmbaty | 106 | */ |
108 | pmbaty | 107 | tree->evaluations++; |
108 | tree->score_mg = 0; |
||
109 | tree->score_eg = 0; |
||
110 | EvaluateMaterial(tree, wtm); |
||
111 | if (TotalPieces(white, occupied) < 13 && TotalPieces(black, occupied) < 13) |
||
112 | for (side = black; side <= white; side++) |
||
113 | if (!EvaluateWinningChances(tree, side, wtm)) |
||
114 | can_win ^= (1 << side); |
||
33 | pmbaty | 115 | /* |
108 | pmbaty | 116 | ************************************************************* |
117 | * * |
||
118 | * Determine if this position should be evaluated to force * |
||
119 | * mate (neither side has pawns) or if it should be * |
||
120 | * evaluated normally. * |
||
121 | * * |
||
122 | * Note the special case of no pawns, one side is ahead in * |
||
123 | * total material, but the game is a hopeless draw. KRN vs * |
||
124 | * KR is one example. If EvaluateWinningChances() * |
||
125 | * determines that the side with extra material can not * |
||
126 | * win, the score is pulled closer to a draw although it * |
||
127 | * can not collapse completely to the drawscore as it is * |
||
128 | * possible to lose KRB vs KR if the KR side lets the king * |
||
129 | * get trapped on the edge of the board. * |
||
130 | * * |
||
131 | ************************************************************* |
||
33 | pmbaty | 132 | */ |
133 | tree->all_pawns = Pawns(black) | Pawns(white); |
||
134 | if (!tree->all_pawns) { |
||
135 | if (TotalPieces(white, occupied) > 3 || TotalPieces(black, occupied) > 3) { |
||
136 | if (Material > 0) |
||
137 | EvaluateMate(tree, white); |
||
138 | else if (Material < 0) |
||
139 | EvaluateMate(tree, black); |
||
108 | pmbaty | 140 | if (tree->score_eg > DrawScore(1) && !(can_win & 2)) |
141 | tree->score_eg = tree->score_eg / 16; |
||
142 | if (tree->score_eg < DrawScore(1) && !(can_win & 1)) |
||
143 | tree->score_eg = tree->score_eg / 16; |
||
33 | pmbaty | 144 | #if defined(SKILL) |
145 | if (skill < 100) |
||
108 | pmbaty | 146 | tree->score_eg = (int) // Pierre-Marie Baty -- added type cast |
147 | (skill * tree->score_eg / 100 + ((100 - |
||
33 | pmbaty | 148 | skill) * PAWN_VALUE * (uint64_t) Random32() / |
108 | pmbaty | 149 | 0x100000000ull) / 100); |
33 | pmbaty | 150 | #endif |
151 | return (wtm) ? tree->score_eg : -tree->score_eg; |
||
152 | } |
||
153 | } |
||
154 | /* |
||
108 | pmbaty | 155 | ************************************************************* |
156 | * * |
||
157 | * Now evaluate pawns. If the pawn hash signature has not * |
||
158 | * changed from the last entry to Evaluate() then we * |
||
159 | * already have everything we need in the pawn hash entry. * |
||
160 | * In this case, we do not need to call EvaluatePawns() at * |
||
161 | * all. EvaluatePawns() does all of the analysis for * |
||
162 | * information specifically regarding only pawns. In many * |
||
163 | * cases, it merely records the presence/absence of * |
||
164 | * positional pawn features because those features also * |
||
165 | * depends on pieces. * |
||
166 | * * |
||
167 | * Note that anything put into EvaluatePawns() can only * |
||
168 | * consider the placement of pawns. Kings or other pieces * |
||
169 | * can not influence the score because those pieces are not * |
||
170 | * hashed into the pawn hash signature. Violating this * |
||
171 | * principle leads to lots of very difficult and * |
||
172 | * challenging debugging problems. * |
||
173 | * * |
||
174 | ************************************************************* |
||
33 | pmbaty | 175 | */ |
176 | else { |
||
177 | if (PawnHashKey == tree->pawn_score.key) { |
||
178 | tree->score_mg += tree->pawn_score.score_mg; |
||
179 | tree->score_eg += tree->pawn_score.score_eg; |
||
180 | } |
||
181 | /* |
||
108 | pmbaty | 182 | ************************************************************* |
183 | * * |
||
184 | * First check to see if this position has been handled * |
||
185 | * before. If so, we can skip the work saved in the pawn * |
||
186 | * hash table. * |
||
187 | * * |
||
188 | ************************************************************* |
||
33 | pmbaty | 189 | */ |
190 | else { |
||
191 | ptable = pawn_hash_table + (PawnHashKey & pawn_hash_mask); |
||
192 | pxtable = (PXOR *) & (tree->pawn_score); |
||
193 | tree->pawn_score = *ptable; |
||
108 | pmbaty | 194 | tree->pawn_score.key ^= pxtable->entry[1] ^ pxtable->entry[2]; |
33 | pmbaty | 195 | if (tree->pawn_score.key != PawnHashKey) { |
196 | tree->pawn_score.key = PawnHashKey; |
||
197 | tree->pawn_score.score_mg = 0; |
||
198 | tree->pawn_score.score_eg = 0; |
||
199 | for (side = black; side <= white; side++) |
||
200 | EvaluatePawns(tree, side); |
||
201 | ptable->key = |
||
108 | pmbaty | 202 | pxtable->entry[0] ^ pxtable->entry[1] ^ pxtable->entry[2]; |
203 | memcpy((char *) ptable + 8, (char *) &(tree->pawn_score) + 8, |
||
204 | sizeof(PAWN_HASH_ENTRY) - 8); |
||
33 | pmbaty | 205 | } |
206 | tree->score_mg += tree->pawn_score.score_mg; |
||
207 | tree->score_eg += tree->pawn_score.score_eg; |
||
208 | } |
||
209 | /* |
||
108 | pmbaty | 210 | ************************************************************* |
211 | * * |
||
212 | * If there are any passed pawns, first call * |
||
213 | * EvaluatePassedPawns() to evaluate them. Then, if one * |
||
214 | * side has a passed pawn and the other side has no pieces, * |
||
215 | * call EvaluatePassedPawnRaces() to see if the passed pawn * |
||
216 | * can be stopped from promoting. * |
||
217 | * * |
||
218 | ************************************************************* |
||
33 | pmbaty | 219 | */ |
220 | if (tree->pawn_score.passed[black] || tree->pawn_score.passed[white]) { |
||
221 | for (side = black; side <= white; side++) |
||
222 | if (tree->pawn_score.passed[side]) |
||
223 | EvaluatePassedPawns(tree, side, wtm); |
||
224 | if ((TotalPieces(white, occupied) == 0 && |
||
225 | tree->pawn_score.passed[black]) |
||
226 | || (TotalPieces(black, occupied) == 0 && |
||
227 | tree->pawn_score.passed[white])) |
||
228 | EvaluatePassedPawnRaces(tree, wtm); |
||
229 | } |
||
230 | } |
||
231 | /* |
||
108 | pmbaty | 232 | ************************************************************* |
233 | * * |
||
234 | * Call EvaluateCastling() to evaluate castling potential. * |
||
235 | * Note we only do this when that side has not castled at * |
||
236 | * the root. * |
||
237 | * * |
||
238 | ************************************************************* |
||
33 | pmbaty | 239 | */ |
240 | for (side = black; side <= white; side++) |
||
108 | pmbaty | 241 | if (Castle(1, side) > 0) |
242 | EvaluateCastling(tree, ply, side); |
||
33 | pmbaty | 243 | /* |
108 | pmbaty | 244 | ************************************************************* |
245 | * * |
||
246 | * The "dangerous" flag simply indicates whether that side * |
||
247 | * has enough material to whip up a mating attack if the * |
||
248 | * other side is careless (Q + minor or better, or RR + two * |
||
249 | * minors or better). * |
||
250 | * * |
||
251 | ************************************************************* |
||
33 | pmbaty | 252 | */ |
108 | pmbaty | 253 | tree->dangerous[white] = (Queens(white) && TotalPieces(white, occupied) > 9) |
254 | || (TotalPieces(white, rook) > 1 && TotalPieces(white, occupied) > 15); |
||
255 | tree->dangerous[black] = (Queens(black) && TotalPieces(black, occupied) > 9) |
||
256 | || (TotalPieces(black, rook) > 1 && TotalPieces(black, occupied) > 15); |
||
257 | /* |
||
258 | ************************************************************* |
||
259 | * * |
||
260 | * Second lazy evaluation test. We have computed the large * |
||
261 | * positional scores (except for king safety). If the * |
||
262 | * score is too far outside the alpha/beta window, we skip * |
||
263 | * the piece scoring which is the most expensive of all the * |
||
264 | * evaluation terms, and simply use what we have at this * |
||
265 | * point. * |
||
266 | * * |
||
267 | ************************************************************* |
||
268 | */ |
||
33 | pmbaty | 269 | phase = |
270 | Min(62, TotalPieces(white, occupied) + TotalPieces(black, occupied)); |
||
271 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
||
272 | lscore = (wtm) ? score : -score; |
||
108 | pmbaty | 273 | int w_mat = (2 * TotalPieces(white, rook)) + TotalPieces(white, |
274 | knight) + TotalPieces(white, bishop); |
||
275 | int b_mat = (2 * TotalPieces(black, rook)) + TotalPieces(black, |
||
276 | knight) + TotalPieces(black, bishop); |
||
277 | cutoff = 72 + (w_mat + b_mat) * 8 + abs(w_mat - b_mat) * 16; |
||
278 | if (tree->dangerous[white] || tree->dangerous[black]) |
||
279 | cutoff += 35; |
||
280 | /* |
||
281 | ************************************************************* |
||
282 | * * |
||
283 | * Then evaluate pieces if the lazy eval test fails. * |
||
284 | * * |
||
285 | * Note: We MUST evaluate kings last, since their scoring * |
||
286 | * depends on the tropism scores computed by the other * |
||
287 | * piece evaluators. Do NOT try to collapse the following * |
||
288 | * loops into one loop. That will break things since it * |
||
289 | * would violate the kings last rule. More importantly * |
||
290 | * there is no benefit as the loops below are unrolled by * |
||
291 | * the compiler anyway. * |
||
292 | * * |
||
293 | ************************************************************* |
||
294 | */ |
||
33 | pmbaty | 295 | if (lscore + cutoff > alpha && lscore - cutoff < beta) { |
296 | tree->tropism[white] = 0; |
||
297 | tree->tropism[black] = 0; |
||
298 | for (side = black; side <= white; side++) |
||
299 | EvaluateKnights(tree, side); |
||
300 | for (side = black; side <= white; side++) |
||
301 | EvaluateBishops(tree, side); |
||
302 | for (side = black; side <= white; side++) |
||
303 | EvaluateRooks(tree, side); |
||
304 | for (side = black; side <= white; side++) |
||
305 | EvaluateQueens(tree, side); |
||
306 | for (side = black; side <= white; side++) |
||
108 | pmbaty | 307 | EvaluateKing(tree, ply, side); |
308 | full = 1; |
||
33 | pmbaty | 309 | } |
310 | /* |
||
108 | pmbaty | 311 | ************************************************************* |
312 | * * |
||
313 | * Caclulate the final score, which is interpolated between * |
||
314 | * the middlegame score and endgame score based on the * |
||
315 | * material left on the board. * |
||
316 | * * |
||
317 | * Adjust the score if one side can't win, but the score * |
||
318 | * actually favors that side significantly. * |
||
319 | * * |
||
320 | ************************************************************* |
||
33 | pmbaty | 321 | */ |
322 | score = ((tree->score_mg * phase) + (tree->score_eg * (62 - phase))) / 62; |
||
323 | score = EvaluateDraws(tree, ply, can_win, score); |
||
324 | #if defined(SKILL) |
||
325 | if (skill < 100) |
||
108 | pmbaty | 326 | score = (int) // Pierre-Marie Baty -- added type cast |
327 | (skill * score / 100 + ((100 - |
||
33 | pmbaty | 328 | skill) * PAWN_VALUE * (uint64_t) Random32() / 0x100000000ull) / |
108 | pmbaty | 329 | 100); |
33 | pmbaty | 330 | #endif |
108 | pmbaty | 331 | if (full) |
332 | *etable = (temp_hashkey & 0xffffffffffff0000) + score + 32768; |
||
33 | pmbaty | 333 | return (wtm) ? score : -score; |
334 | } |
||
335 | |||
108 | pmbaty | 336 | /* last modified 10/19/15 */ |
33 | pmbaty | 337 | /* |
338 | ******************************************************************************* |
||
339 | * * |
||
340 | * EvaluateBishops() is used to evaluate bishops. * |
||
341 | * * |
||
342 | ******************************************************************************* |
||
343 | */ |
||
344 | void EvaluateBishops(TREE * RESTRICT tree, int side) { |
||
345 | uint64_t temp, moves; |
||
108 | pmbaty | 346 | int square, special, i, mobility; |
347 | int score_eg = 0, score_mg = 0, enemy = Flip(side), tpawns; |
||
33 | pmbaty | 348 | /* |
349 | ************************************************************ |
||
350 | * * |
||
351 | * First, locate each bishop and add in its piece/square * |
||
108 | pmbaty | 352 | * table score. * |
33 | pmbaty | 353 | * * |
354 | ************************************************************ |
||
355 | */ |
||
356 | for (temp = Bishops(side); temp; temp &= temp - 1) { |
||
357 | square = LSB(temp); |
||
358 | score_mg += bval[mg][side][square]; |
||
359 | score_eg += bval[eg][side][square]; |
||
360 | /* |
||
361 | ************************************************************ |
||
362 | * * |
||
363 | * Evaluate for "outposts" which is a bishop that can't be * |
||
364 | * driven off by an enemy pawn, and which is supported by * |
||
365 | * a friendly pawn. * |
||
366 | * * |
||
367 | * If the enemy has NO minor to take this bishop, then * |
||
368 | * increase the bonus. * |
||
369 | * * |
||
370 | ************************************************************ |
||
371 | */ |
||
108 | pmbaty | 372 | special = bishop_outpost[side][square]; |
373 | if (special) { |
||
374 | if (!(mask_pattacks[enemy][square] & Pawns(enemy))) { |
||
375 | if (pawn_attacks[enemy][square] & Pawns(side)) { |
||
376 | special += special / 2; |
||
377 | if (!Knights(enemy) && !(Color(square) & Bishops(enemy))) |
||
378 | special += bishop_outpost[side][square]; |
||
33 | pmbaty | 379 | } |
108 | pmbaty | 380 | score_eg += special; |
381 | score_mg += special; |
||
33 | pmbaty | 382 | } |
108 | pmbaty | 383 | } |
33 | pmbaty | 384 | /* |
385 | ************************************************************ |
||
386 | * * |
||
108 | pmbaty | 387 | * Next we count the number of friendly pawns on the same * |
388 | * color squares as the bishop. This is a bad thing since * |
||
389 | * it restricts the bishop's ability to move. We only do * |
||
390 | * this if there is only one bishop for this side. * |
||
33 | pmbaty | 391 | * * |
392 | ************************************************************ |
||
393 | */ |
||
108 | pmbaty | 394 | if (TotalPieces(side, bishop) == 1) { |
395 | if (dark_squares & SetMask(square)) |
||
396 | tpawns = PopCnt(dark_squares & Pawns(side)); |
||
397 | else |
||
398 | tpawns = PopCnt(~dark_squares & Pawns(side)); |
||
399 | score_mg -= tpawns * bishop_pawns_on_color[mg]; |
||
400 | score_eg -= tpawns * bishop_pawns_on_color[eg]; |
||
33 | pmbaty | 401 | } |
402 | /* |
||
403 | ************************************************************ |
||
404 | * * |
||
108 | pmbaty | 405 | * Mobility counts the number of squares the bishop * |
406 | * attacks, excluding squares with friendly pieces, and * |
||
407 | * weighs each square according to centralization. * |
||
33 | pmbaty | 408 | * * |
409 | ************************************************************ |
||
410 | */ |
||
411 | mobility = BishopMobility(square, OccupiedSquares); |
||
412 | if (mobility < 0 && (pawn_attacks[enemy][square] & Pawns(side)) |
||
413 | && (File(square) == FILEA || File(square) == FILEH)) |
||
414 | mobility -= 8; |
||
415 | score_mg += mobility; |
||
416 | score_eg += mobility; |
||
417 | /* |
||
418 | ************************************************************ |
||
419 | * * |
||
420 | * Check for pawns on both wings, which makes a bishop * |
||
421 | * even more valuable against an enemy knight * |
||
422 | * * |
||
423 | ************************************************************ |
||
424 | */ |
||
425 | if (tree->all_pawns & mask_fgh && tree->all_pawns & mask_abc) { |
||
108 | pmbaty | 426 | score_mg += bishop_wing_pawns[mg]; |
427 | score_eg += bishop_wing_pawns[eg]; |
||
33 | pmbaty | 428 | } |
429 | /* |
||
430 | ************************************************************ |
||
431 | * * |
||
432 | * Adjust the tropism count for this piece. * |
||
433 | * * |
||
434 | ************************************************************ |
||
435 | */ |
||
436 | if (tree->dangerous[side]) { |
||
437 | moves = king_attacks[KingSQ(enemy)]; |
||
108 | pmbaty | 438 | i = ((bishop_attacks[square] & moves) && |
439 | ((BishopAttacks(square, OccupiedSquares & ~Queens(side))) & moves)) |
||
440 | ? 1 : Distance(square, KingSQ(enemy)); |
||
441 | tree->tropism[side] += king_tropism_b[i]; |
||
33 | pmbaty | 442 | } |
443 | } |
||
108 | pmbaty | 444 | /* |
445 | ************************************************************ |
||
446 | * * |
||
447 | * Add a bonus if this side has a pair of bishops, which * |
||
448 | * can become very strong in open positions. * |
||
449 | * * |
||
450 | ************************************************************ |
||
451 | */ |
||
452 | if (TotalPieces(side, bishop) > 1) { |
||
453 | score_mg += bishop_pair[mg]; |
||
454 | score_eg += bishop_pair[eg]; |
||
455 | } |
||
33 | pmbaty | 456 | tree->score_mg += sign[side] * score_mg; |
457 | tree->score_eg += sign[side] * score_eg; |
||
458 | } |
||
459 | |||
108 | pmbaty | 460 | /* last modified 01/03/15 */ |
33 | pmbaty | 461 | /* |
462 | ******************************************************************************* |
||
463 | * * |
||
108 | pmbaty | 464 | * EvaluateCastling() is called when "side" has not castled at the root. * |
465 | * Its main purpose is to determine if it has either castled somewhere in * |
||
466 | * the tree, or else has lost all (or some) castling rights, which reduces * |
||
467 | * options significantly. * |
||
33 | pmbaty | 468 | * * |
469 | ******************************************************************************* |
||
470 | */ |
||
108 | pmbaty | 471 | void EvaluateCastling(TREE * RESTRICT tree, int ply, int side) { |
472 | int enemy = Flip(side), oq, score_mg = 0;; |
||
33 | pmbaty | 473 | |
474 | /* |
||
475 | ************************************************************ |
||
476 | * * |
||
108 | pmbaty | 477 | * If the king castled during the search, we are done and * |
478 | * we leave it to EvaluateKing() to figure out how safe it * |
||
479 | * is. If it has not castled, we give a significant * |
||
480 | * penalty if the king moves since that loses all castling * |
||
481 | * rights, otherwise we give a smaller penalty for moving * |
||
482 | * a rook and giving up castling rights to that side of * |
||
483 | * the board. The penalty is always increased if the * |
||
484 | * opponent has a queen since the position is much more * |
||
485 | * dangerous. * |
||
33 | pmbaty | 486 | * * |
487 | ************************************************************ |
||
488 | */ |
||
108 | pmbaty | 489 | oq = (Queens(enemy)) ? 3 : 1; |
490 | if (Castle(ply, side) != Castle(1, side)) { |
||
491 | if (Castle(ply, side) == 0) |
||
492 | score_mg -= oq * development_losing_castle; |
||
493 | else if (Castle(ply, side) > 0) |
||
494 | score_mg -= (oq * development_losing_castle) / 2; |
||
495 | } else |
||
496 | score_mg -= oq * development_not_castled; |
||
33 | pmbaty | 497 | tree->score_mg += sign[side] * score_mg; |
498 | } |
||
499 | |||
108 | pmbaty | 500 | /* last modified 01/03/15 */ |
33 | pmbaty | 501 | /* |
502 | ******************************************************************************* |
||
503 | * * |
||
504 | * EvaluateDraws() is used to adjust the score based on whether the side * |
||
505 | * that appears to be better according the computed score can actually win * |
||
506 | * the game or not. If the answer is "no" then the score is reduced * |
||
507 | * significantly to reflect the lack of winning chances. * |
||
508 | * * |
||
509 | ******************************************************************************* |
||
510 | */ |
||
511 | int EvaluateDraws(TREE * RESTRICT tree, int ply, int can_win, int score) { |
||
512 | /* |
||
513 | ************************************************************ |
||
514 | * * |
||
515 | * If the ending has only bishops of opposite colors, the * |
||
108 | pmbaty | 516 | * score is pulled closer to a draw. * |
33 | pmbaty | 517 | * * |
518 | * If this is a pure BOC ending, it is very drawish unless * |
||
519 | * one side has at least 4 pawns. More pawns makes it * |
||
520 | * harder for a bishop and king to stop them all from * |
||
521 | * advancing. * |
||
522 | * * |
||
108 | pmbaty | 523 | * If the following are both true: * |
524 | * * |
||
525 | * black and white have less than a queen left (pieces * |
||
526 | * only). * |
||
527 | * * |
||
528 | * both have one bishop and they are opposite colored. * |
||
529 | * * |
||
530 | * then either * |
||
531 | * * |
||
532 | * (a) both have just one bishop, both have less than 4 * |
||
533 | * pawns or one side has only one more pawn than the * |
||
534 | * other side then score is divided by 2 with draw score * |
||
535 | * added in; or * |
||
536 | * * |
||
537 | * (b) pieces are equal, then score is reduced by 25% * |
||
538 | * with draw score added in. * |
||
539 | * * |
||
33 | pmbaty | 540 | ************************************************************ |
541 | */ |
||
542 | if (TotalPieces(white, occupied) <= 8 && TotalPieces(black, occupied) <= 8) { |
||
543 | if (TotalPieces(white, bishop) == 1 && TotalPieces(black, bishop) == 1) |
||
544 | if (square_color[LSB(Bishops(black))] != |
||
545 | square_color[LSB(Bishops(white))]) { |
||
546 | if (TotalPieces(white, occupied) == 3 && |
||
547 | TotalPieces(black, occupied) == 3 && |
||
548 | ((TotalPieces(white, pawn) < 4 && TotalPieces(black, pawn) < 4) |
||
549 | || Abs(TotalPieces(white, pawn) - TotalPieces(black, |
||
550 | pawn)) < 2)) |
||
551 | score = score / 2 + DrawScore(1); |
||
552 | else if (TotalPieces(white, occupied) == TotalPieces(black, occupied)) |
||
553 | score = 3 * score / 4 + DrawScore(1); |
||
554 | } |
||
555 | } |
||
108 | pmbaty | 556 | /* |
557 | ************************************************************ |
||
558 | * * |
||
559 | * Final score adjustment. If the score says white is * |
||
560 | * better, but can_win says white can not win, or if the * |
||
561 | * score says black is better, but can_win says black can * |
||
562 | * not win, then we divide the score by 16, and then add * |
||
563 | * in the draw score. If the can_win says neither side * |
||
564 | * can win, we just set the score to draw score and exit. * |
||
565 | * * |
||
566 | ************************************************************ |
||
567 | */ |
||
33 | pmbaty | 568 | if (can_win != 3) { |
108 | pmbaty | 569 | if (can_win & 1) { |
570 | if (score > DrawScore(1)) |
||
571 | score = score / 16 + DrawScore(1); |
||
572 | } else if (can_win & 2) { |
||
573 | if (score < DrawScore(1)) |
||
574 | score = score / 16 + DrawScore(1); |
||
575 | } else |
||
576 | score = DrawScore(1); |
||
33 | pmbaty | 577 | } |
578 | /* |
||
579 | ************************************************************ |
||
580 | * * |
||
581 | * If we are running into the 50-move rule, then start * |
||
582 | * dragging the score toward draw. This is the idea of a * |
||
583 | * "weariness factor" as mentioned by Dave Slate many * |
||
584 | * times. This avoids slamming into a draw at move 50 and * |
||
585 | * having to move something quickly, rather than slowly * |
||
586 | * discovering that the score is dropping and that pushing * |
||
587 | * a pawn or capturing something will cause it to go back * |
||
588 | * to its correct value a bit more smoothly. * |
||
589 | * * |
||
590 | ************************************************************ |
||
591 | */ |
||
592 | if (Reversible(ply) > 80) { |
||
108 | pmbaty | 593 | int closeness = 101 - Reversible(ply); |
33 | pmbaty | 594 | |
108 | pmbaty | 595 | score = DrawScore(1) + score * closeness / 20; |
33 | pmbaty | 596 | } |
597 | return score; |
||
598 | } |
||
599 | |||
108 | pmbaty | 600 | /* last modified 01/03/15 */ |
33 | pmbaty | 601 | /* |
602 | ******************************************************************************* |
||
603 | * * |
||
604 | * EvaluateHasOpposition() is used to determine if one king stands in * |
||
605 | * "opposition" to the other. If the kings are opposed on the same file or * |
||
606 | * else are opposed on the same diagonal, then the side not-to-move has the * |
||
607 | * opposition and the side-to-move must give way. * |
||
608 | * * |
||
609 | ******************************************************************************* |
||
610 | */ |
||
611 | int EvaluateHasOpposition(int on_move, int king, int enemy_king) { |
||
612 | int file_distance, rank_distance; |
||
613 | |||
614 | file_distance = FileDistance(king, enemy_king); |
||
615 | rank_distance = RankDistance(king, enemy_king); |
||
616 | if (rank_distance < 2) |
||
617 | return 1; |
||
618 | if (on_move) { |
||
619 | if (rank_distance & 1) |
||
620 | rank_distance--; |
||
621 | if (file_distance & 1) |
||
622 | file_distance--; |
||
623 | } |
||
624 | if (!(file_distance & 1) && !(rank_distance & 1)) |
||
625 | return 1; |
||
626 | return 0; |
||
627 | } |
||
628 | |||
108 | pmbaty | 629 | /* last modified 01/03/15 */ |
33 | pmbaty | 630 | /* |
631 | ******************************************************************************* |
||
632 | * * |
||
108 | pmbaty | 633 | * EvaluateKing() is used to evaluate a king. * |
33 | pmbaty | 634 | * * |
635 | ******************************************************************************* |
||
636 | */ |
||
108 | pmbaty | 637 | void EvaluateKing(TREE * RESTRICT tree, int ply, int side) { |
33 | pmbaty | 638 | int score_eg = 0, score_mg = 0, defects; |
639 | int ksq = KingSQ(side), enemy = Flip(side); |
||
640 | |||
641 | /* |
||
642 | ************************************************************ |
||
643 | * * |
||
644 | * First, check for where the king should be if this is an * |
||
108 | pmbaty | 645 | * endgame. The basic idea is to centralize unless the * |
646 | * king is needed to deal with a passed enemy pawn. * |
||
33 | pmbaty | 647 | * * |
648 | ************************************************************ |
||
649 | */ |
||
108 | pmbaty | 650 | score_eg += kval[side][ksq]; |
33 | pmbaty | 651 | /* |
652 | ************************************************************ |
||
653 | * * |
||
654 | * Do castle scoring, if the king has castled, the pawns * |
||
655 | * in front are important. If not castled yet, the pawns * |
||
656 | * on the kingside should be preserved for this. * |
||
657 | * * |
||
658 | ************************************************************ |
||
659 | */ |
||
660 | if (tree->dangerous[enemy]) { |
||
661 | defects = 0; |
||
662 | if (Castle(ply, side) <= 0) { |
||
108 | pmbaty | 663 | if (File(ksq) > FILEE) |
664 | defects = tree->pawn_score.defects_k[side]; |
||
665 | else if (File(ksq) < FILED) |
||
666 | defects = tree->pawn_score.defects_q[side]; |
||
667 | else |
||
668 | defects = tree->pawn_score.defects_m[side]; |
||
33 | pmbaty | 669 | } else { |
670 | if (Castle(ply, side) == 3) |
||
671 | defects = |
||
672 | Min(Min(tree->pawn_score.defects_k[side], |
||
108 | pmbaty | 673 | tree->pawn_score.defects_m[side]), |
33 | pmbaty | 674 | tree->pawn_score.defects_q[side]); |
675 | else if (Castle(ply, side) == 1) |
||
676 | defects = |
||
677 | Min(tree->pawn_score.defects_k[side], |
||
108 | pmbaty | 678 | tree->pawn_score.defects_m[side]); |
33 | pmbaty | 679 | else |
680 | defects = |
||
681 | Min(tree->pawn_score.defects_q[side], |
||
108 | pmbaty | 682 | tree->pawn_score.defects_m[side]); |
33 | pmbaty | 683 | if (defects < 3) |
684 | defects = 3; |
||
685 | } |
||
686 | /* |
||
687 | ************************************************************ |
||
688 | * * |
||
689 | * Fold in the king tropism and king pawn shelter scores * |
||
690 | * together. * |
||
691 | * * |
||
692 | ************************************************************ |
||
693 | */ |
||
694 | if (tree->tropism[enemy] < 0) |
||
695 | tree->tropism[enemy] = 0; |
||
696 | else if (tree->tropism[enemy] > 15) |
||
697 | tree->tropism[enemy] = 15; |
||
698 | if (defects > 15) |
||
699 | defects = 15; |
||
700 | score_mg -= king_safety[defects][tree->tropism[enemy]]; |
||
701 | } |
||
702 | tree->score_mg += sign[side] * score_mg; |
||
703 | tree->score_eg += sign[side] * score_eg; |
||
704 | } |
||
705 | |||
108 | pmbaty | 706 | /* last modified 01/03/15 */ |
33 | pmbaty | 707 | /* |
708 | ******************************************************************************* |
||
709 | * * |
||
710 | * EvaluateKingsFile computes defects for a file, based on whether the file * |
||
711 | * is open or half-open. If there are friendly pawns still on the file, * |
||
712 | * they are penalized for advancing in front of the king. * |
||
713 | * * |
||
714 | ******************************************************************************* |
||
715 | */ |
||
108 | pmbaty | 716 | int EvaluateKingsFile(TREE * RESTRICT tree, int side, int first, int last) { |
717 | int defects = 0, file, enemy = Flip(side); |
||
33 | pmbaty | 718 | |
108 | pmbaty | 719 | for (file = first; file <= last; file++) |
33 | pmbaty | 720 | if (!(file_mask[file] & tree->all_pawns)) |
721 | defects += open_file[file]; |
||
722 | else { |
||
723 | if (!(file_mask[file] & Pawns(enemy))) |
||
724 | defects += half_open_file[file] / 2; |
||
725 | else |
||
726 | defects += |
||
108 | pmbaty | 727 | pawn_defects[side][Rank(MostAdvanced(enemy, |
33 | pmbaty | 728 | file_mask[file] & Pawns(enemy)))]; |
729 | if (!(file_mask[file] & Pawns(side))) |
||
730 | defects += half_open_file[file]; |
||
731 | else if (!(Pawns(side) & SetMask(sqflip[side][A2] + file))) { |
||
732 | defects++; |
||
733 | if (!(Pawns(side) & SetMask(sqflip[side][A3] + file))) |
||
734 | defects++; |
||
735 | } |
||
736 | } |
||
737 | return defects; |
||
738 | } |
||
739 | |||
108 | pmbaty | 740 | /* last modified 10/19/15 */ |
33 | pmbaty | 741 | /* |
742 | ******************************************************************************* |
||
743 | * * |
||
744 | * EvaluateKnights() is used to evaluate knights. * |
||
745 | * * |
||
746 | ******************************************************************************* |
||
747 | */ |
||
748 | void EvaluateKnights(TREE * RESTRICT tree, int side) { |
||
749 | uint64_t temp; |
||
108 | pmbaty | 750 | int square, special, i, score_eg = 0, score_mg = 0, enemy = Flip(side); |
33 | pmbaty | 751 | |
752 | /* |
||
753 | ************************************************************ |
||
754 | * * |
||
755 | * First fold in centralization score from the piece/ * |
||
756 | * square table "nval". * |
||
757 | * * |
||
758 | ************************************************************ |
||
759 | */ |
||
760 | for (temp = Knights(side); temp; temp &= temp - 1) { |
||
761 | square = LSB(temp); |
||
762 | score_mg += nval[mg][side][square]; |
||
763 | score_eg += nval[eg][side][square]; |
||
764 | /* |
||
765 | ************************************************************ |
||
766 | * * |
||
767 | * Evaluate for "outposts" which is a knight that can't * |
||
768 | * be driven off by an enemy pawn, and which is supported * |
||
769 | * by a friendly pawn. * |
||
770 | * * |
||
771 | * If the enemy has NO minor to take this knight, then * |
||
772 | * increase the bonus. * |
||
773 | * * |
||
774 | ************************************************************ |
||
775 | */ |
||
108 | pmbaty | 776 | special = knight_outpost[side][square]; |
777 | if (special && !(mask_pattacks[enemy][square] & Pawns(enemy))) { |
||
33 | pmbaty | 778 | if (pawn_attacks[enemy][square] & Pawns(side)) { |
108 | pmbaty | 779 | special += special / 2; |
33 | pmbaty | 780 | if (!Knights(enemy) && !(Color(square) & Bishops(enemy))) |
108 | pmbaty | 781 | special += knight_outpost[side][square]; |
33 | pmbaty | 782 | } |
108 | pmbaty | 783 | score_eg += special; |
784 | score_mg += special; |
||
33 | pmbaty | 785 | } |
786 | /* |
||
787 | ************************************************************ |
||
788 | * * |
||
789 | * Adjust the tropism count for this piece. * |
||
790 | * * |
||
791 | ************************************************************ |
||
792 | */ |
||
793 | if (tree->dangerous[side]) { |
||
108 | pmbaty | 794 | i = Distance(square, KingSQ(enemy)); |
795 | tree->tropism[side] += king_tropism_n[i]; |
||
33 | pmbaty | 796 | } |
797 | } |
||
798 | tree->score_mg += sign[side] * score_mg; |
||
799 | tree->score_eg += sign[side] * score_eg; |
||
800 | } |
||
801 | |||
108 | pmbaty | 802 | /* last modified 03/30/15 */ |
33 | pmbaty | 803 | /* |
804 | ******************************************************************************* |
||
805 | * * |
||
806 | * EvaluateMate() is used to evaluate positions where neither side has pawns * |
||
807 | * and one side has enough material to force checkmate. It simply trys to * |
||
808 | * force the losing king to the edge of the board, and then to the corner * |
||
809 | * where mates are easier to find. * |
||
810 | * * |
||
811 | ******************************************************************************* |
||
812 | */ |
||
813 | void EvaluateMate(TREE * RESTRICT tree, int side) { |
||
108 | pmbaty | 814 | int mate_score = 0, enemy = Flip(side); |
33 | pmbaty | 815 | |
816 | /* |
||
817 | ************************************************************ |
||
818 | * * |
||
108 | pmbaty | 819 | * If the winning side has a bishop + knight and the other * |
820 | * side has no pieces or pawns, then use the special * |
||
821 | * bishop_knight scoring board for the losing king to * |
||
822 | * force it to the right corner for mate. * |
||
33 | pmbaty | 823 | * * |
824 | ************************************************************ |
||
825 | */ |
||
108 | pmbaty | 826 | if (!TotalPieces(enemy, occupied) && TotalPieces(side, bishop) == 1 && |
827 | TotalPieces(side, knight) == 1) { |
||
33 | pmbaty | 828 | if (dark_squares & Bishops(side)) |
829 | mate_score = b_n_mate_dark_squares[KingSQ(enemy)]; |
||
830 | else |
||
831 | mate_score = b_n_mate_light_squares[KingSQ(enemy)]; |
||
832 | } |
||
833 | /* |
||
834 | ************************************************************ |
||
835 | * * |
||
108 | pmbaty | 836 | * The winning side has to force the losing king to the * |
33 | pmbaty | 837 | * edge of the board. * |
838 | * * |
||
839 | ************************************************************ |
||
840 | */ |
||
108 | pmbaty | 841 | else |
33 | pmbaty | 842 | mate_score = mate[KingSQ(enemy)]; |
108 | pmbaty | 843 | /* |
844 | ************************************************************ |
||
845 | * * |
||
846 | * And for either, it is important to bring the winning * |
||
847 | * king to help force mate. * |
||
848 | * * |
||
849 | ************************************************************ |
||
850 | */ |
||
851 | mate_score -= Distance(KingSQ(side), KingSQ(enemy)) * king_king_tropism; |
||
33 | pmbaty | 852 | tree->score_eg += sign[side] * mate_score; |
853 | } |
||
854 | |||
108 | pmbaty | 855 | /* last modified 10/19/15 */ |
33 | pmbaty | 856 | /* |
857 | ******************************************************************************* |
||
858 | * * |
||
859 | * EvaluateMaterial() is used to evaluate material on the board. It really * |
||
860 | * accomplishes detecting cases where one side has made a 'bad trade' as the * |
||
861 | * comments below show. * |
||
862 | * * |
||
863 | ******************************************************************************* |
||
864 | */ |
||
865 | void EvaluateMaterial(TREE * RESTRICT tree, int wtm) { |
||
108 | pmbaty | 866 | int score_mg, score_eg, majors, minors; |
33 | pmbaty | 867 | |
868 | /* |
||
108 | pmbaty | 869 | ************************************************************* |
870 | * * |
||
871 | * We start with the raw Material balance for the current * |
||
872 | * position, then adjust this with a small bonus for the * |
||
873 | * side on move. * |
||
874 | * * |
||
875 | ************************************************************* |
||
33 | pmbaty | 876 | */ |
877 | score_mg = Material + ((wtm) ? wtm_bonus[mg] : -wtm_bonus[mg]); |
||
878 | score_eg = Material + ((wtm) ? wtm_bonus[eg] : -wtm_bonus[eg]); |
||
879 | /* |
||
108 | pmbaty | 880 | ************************************************************* |
881 | * * |
||
882 | * test 1. if Majors or Minors are not balanced, then if * |
||
883 | * one side is only an exchange up or down, we give a * |
||
884 | * penalty to the side that is an exchange down, but not as * |
||
885 | * big a penalty as the bad trade case below. * |
||
886 | * * |
||
887 | * test 2. if Majors or Minors are not balanced, then if * |
||
888 | * one side has more piece material points than the other * |
||
889 | * (using normal piece values of 3, 3, 5, 9 for N, B, R * |
||
890 | * and Q) then the side that is behind in piece material * |
||
891 | * gets a penalty. * |
||
892 | * * |
||
893 | ************************************************************* |
||
33 | pmbaty | 894 | */ |
108 | pmbaty | 895 | majors = |
896 | TotalPieces(white, rook) + 2 * TotalPieces(white, |
||
897 | queen) - TotalPieces(black, rook) - 2 * TotalPieces(black, queen); |
||
898 | minors = |
||
899 | TotalPieces(white, knight) + TotalPieces(white, |
||
900 | bishop) - TotalPieces(black, knight) - TotalPieces(black, bishop); |
||
901 | if (majors || minors) { |
||
902 | if (Abs(TotalPieces(white, occupied) - TotalPieces(black, occupied)) != 2 |
||
903 | && TotalPieces(white, occupied) - TotalPieces(black, occupied) != 0) { |
||
904 | score_mg += |
||
905 | Sign(TotalPieces(white, occupied) - TotalPieces(black, |
||
906 | occupied)) * bad_trade; |
||
907 | score_eg += |
||
908 | Sign(TotalPieces(white, occupied) - TotalPieces(black, |
||
909 | occupied)) * bad_trade; |
||
33 | pmbaty | 910 | } |
911 | } |
||
912 | tree->score_mg += score_mg; |
||
913 | tree->score_eg += score_eg; |
||
914 | } |
||
915 | |||
108 | pmbaty | 916 | /* last modified 11/27/15 */ |
33 | pmbaty | 917 | /* |
918 | ******************************************************************************* |
||
919 | * * |
||
920 | * EvaluatePassedPawns() is used to evaluate passed pawns and the danger * |
||
108 | pmbaty | 921 | * they produce. This code considers pieces as well, so it MUST NOT be done * |
922 | * in the normal EvaluatePawns() code since that hashes information based * |
||
923 | * only on the position of pawns. * |
||
33 | pmbaty | 924 | * * |
108 | pmbaty | 925 | * This is a significant rewrite of passed pawn evaluation, with the primary * |
926 | * change being to collect the passed pawn scoring into one place, rather * |
||
927 | * than have it scattered around all over the place. One example is the old * |
||
928 | * rook_behind_passed_pawn scoring term that was done in rook scoring. It * |
||
929 | * is now done here along with other passed pawn terms such as blockaded and * |
||
930 | * the ability to advance or not. * |
||
931 | * * |
||
33 | pmbaty | 932 | ******************************************************************************* |
933 | */ |
||
934 | void EvaluatePassedPawns(TREE * RESTRICT tree, int side, int wtm) { |
||
108 | pmbaty | 935 | uint64_t behind, forward, backward, attacked, defended, thispawn; |
936 | int file, square, score, score_mg = 0, score_eg = 0, next_sq; |
||
937 | int pawns, rank, mg_base, eg_base, bonus, enemy = Flip(side); |
||
938 | uint64_t fsliders = Queens(side) | Rooks(side); |
||
939 | uint64_t esliders = Queens(enemy) | Rooks(enemy); |
||
33 | pmbaty | 940 | |
941 | /* |
||
942 | ************************************************************ |
||
943 | * * |
||
108 | pmbaty | 944 | * Initialize. The base value "passed_pawn[rank]" is * |
945 | * almost the "square" of the rank. That got a bit too * |
||
946 | * big, so a hand-tuned set of values, one per rank, * |
||
947 | * proved to be a better value. * |
||
33 | pmbaty | 948 | * * |
949 | ************************************************************ |
||
950 | */ |
||
951 | for (pawns = tree->pawn_score.passed[side]; pawns; pawns &= pawns - 1) { |
||
952 | file = LSB8Bit(pawns); |
||
108 | pmbaty | 953 | thispawn = Pawns(side) & file_mask[file]; |
954 | if (thispawn) { |
||
955 | square = MostAdvanced(side, thispawn); |
||
956 | rank = rankflip[side][Rank(square)]; |
||
957 | score = passed_pawn[rank]; |
||
33 | pmbaty | 958 | /* |
959 | ************************************************************ |
||
960 | * * |
||
108 | pmbaty | 961 | * For endgame only, we add in a bonus based on how close * |
962 | * our king is to this pawn and a penalty based on how * |
||
963 | * close the enemy king is. We also try to keep our king * |
||
964 | * ahead of the pawn so it can escort it to promotion. We * |
||
965 | * only do this for passed pawns whose base score value is * |
||
966 | * greater than zero (ie pawns on ranks 4-7 since those * |
||
967 | * are the ones threatening to become a major problem.) * |
||
968 | * Also, if you happen to think that a small bonus for a * |
||
969 | * passed pawn on the 3rd rank might be useful, consider * |
||
970 | * speed. If the 3rd rank score is non-zero, that will * |
||
971 | * trigger a significant amount of work below. In testing * |
||
972 | * the additional cost more than offset the gain and so it * |
||
973 | * is basically ignored unless rank > 3. * |
||
974 | * * |
||
33 | pmbaty | 975 | ************************************************************ |
976 | */ |
||
108 | pmbaty | 977 | if (score) { |
978 | mg_base = score * passed_pawn_base[mg]; |
||
979 | eg_base = score * passed_pawn_base[eg]; |
||
980 | next_sq = square + direction[side]; |
||
981 | eg_base += |
||
982 | Distance(KingSQ(enemy), |
||
983 | next_sq) * 2 * score - Distance(KingSQ(side), next_sq) * score; |
||
984 | if (rank < RANK7) |
||
985 | eg_base -= |
||
986 | Distance(KingSQ(side), next_sq + direction[side]) * score / 2; |
||
33 | pmbaty | 987 | /* |
988 | ************************************************************ |
||
989 | * * |
||
108 | pmbaty | 990 | * If the pawn is not blockaded, we need to see whether it * |
991 | * can actually advance or not. Note that this directly * |
||
992 | * gives a bonus for blockading a passed pawn since the * |
||
993 | * mobility evaluation below will not be applied when the * |
||
994 | * pawn is blockaded by any piece. * |
||
33 | pmbaty | 995 | * * |
108 | pmbaty | 996 | * Step one is to determine if the squares in front of the * |
997 | * pawn are attacked by the enemy. If not, we add in a * |
||
998 | * significant score bonus. If some are attacked, we look * |
||
999 | * to see if at least the square directly in front of the * |
||
1000 | * pawn is not attacked so that we can advance one square, * |
||
1001 | * anyway. This gets a smaller score bonus. * |
||
33 | pmbaty | 1002 | * * |
1003 | ************************************************************ |
||
1004 | */ |
||
108 | pmbaty | 1005 | if (!(OccupiedSquares & SetMask(next_sq))) { |
1006 | bonus = 0; |
||
1007 | if (Pawns(side) & pawn_attacks[enemy][next_sq]) |
||
1008 | bonus = passed_pawn_free_advance; |
||
1009 | else { |
||
1010 | attacked = 0; |
||
1011 | forward = (side) ? plus8dir[square] : minus8dir[square]; |
||
1012 | backward = (side) ? minus8dir[square] : plus8dir[square]; |
||
1013 | if ((behind = backward & esliders) && |
||
1014 | (FileAttacks(square) & behind)) |
||
1015 | attacked = forward; |
||
1016 | else |
||
1017 | attacked = Attacked(tree, enemy, forward); |
||
1018 | if (!attacked) |
||
1019 | bonus = passed_pawn_free_advance; |
||
1020 | else if (!(attacked & SetMask(next_sq))) |
||
1021 | bonus = passed_pawn_free_advance_1; |
||
33 | pmbaty | 1022 | /* |
1023 | ************************************************************ |
||
1024 | * * |
||
108 | pmbaty | 1025 | * Step two is to determine if the squares in front of the * |
1026 | * pawn are are defended by the friendly side. If all are * |
||
1027 | * defended (such as with a rook or queen behind the pawn * |
||
1028 | * or the king in front and to one side of the pawn, then * |
||
1029 | * we give a bonus (but smaller than the previous cases). * |
||
1030 | * As a last resort, if we at least defend the square in * |
||
1031 | * front of the pawn, we give a small bonus. * |
||
33 | pmbaty | 1032 | * * |
1033 | ************************************************************ |
||
1034 | */ |
||
108 | pmbaty | 1035 | if ((behind = backward & fsliders) && |
1036 | (FileAttacks(square) & behind)) |
||
1037 | defended = forward; |
||
1038 | else |
||
1039 | defended = Attacked(tree, side, forward); |
||
1040 | if (defended == forward) |
||
1041 | bonus += passed_pawn_defended; |
||
1042 | else if (defended & SetMask(next_sq)) |
||
1043 | bonus += passed_pawn_defended_1; |
||
1044 | } |
||
33 | pmbaty | 1045 | /* |
1046 | ************************************************************ |
||
1047 | * * |
||
108 | pmbaty | 1048 | * Fold in the bonus for this pawn and move on to the next * |
1049 | * (if there is one). Note that the bonus computed above * |
||
1050 | * is multiplied by the base passed pawn score for this * |
||
1051 | * particular rank. * |
||
33 | pmbaty | 1052 | * * |
1053 | ************************************************************ |
||
1054 | */ |
||
108 | pmbaty | 1055 | mg_base += bonus * score; |
1056 | eg_base += bonus * score; |
||
1057 | } |
||
1058 | score_mg += mg_base; |
||
1059 | score_eg += eg_base; |
||
1060 | } else |
||
1061 | score_eg += 4; |
||
33 | pmbaty | 1062 | } |
1063 | } |
||
1064 | /* |
||
1065 | ************************************************************ |
||
1066 | * * |
||
108 | pmbaty | 1067 | * All pawns done, add score to the two evaluation values * |
1068 | * and return. * |
||
33 | pmbaty | 1069 | * * |
1070 | ************************************************************ |
||
1071 | */ |
||
1072 | tree->score_mg += sign[side] * score_mg; |
||
1073 | tree->score_eg += sign[side] * score_eg; |
||
1074 | } |
||
1075 | |||
108 | pmbaty | 1076 | /* last modified 11/27/15 */ |
33 | pmbaty | 1077 | /* |
1078 | ******************************************************************************* |
||
1079 | * * |
||
1080 | * EvaluatePassedPawnRaces() is used to evaluate passed pawns when one * |
||
1081 | * side has passed pawns and the other side (or neither) has pieces. In * |
||
108 | pmbaty | 1082 | * such a case, the critical question is can the defending king stop the * |
1083 | * pawn from queening or is it too far away? If only one side has pawns * |
||
1084 | * that can "run" then the situation is simple. When both sides have pawns * |
||
1085 | * that can "run" it becomes more complex as it then becomes necessary to * |
||
1086 | * see if one side can use a forced king move to stop the other side, while * |
||
1087 | * the other side doesn't have the same ability to stop ours. * |
||
33 | pmbaty | 1088 | * * |
1089 | * In the case of king and pawn endings with exactly one pawn, the simple * |
||
1090 | * evaluation rules are used: if the king is two squares in front of the * |
||
1091 | * pawn then it is a win, if the king is one one square in front with the * |
||
1092 | * opposition, then it is a win, if the king is on the 6th rank with the * |
||
1093 | * pawn close by, it is a win. Rook pawns are handled separately and are * |
||
1094 | * more difficult to queen because the king can get trapped in front of the * |
||
1095 | * pawn blocking promotion. * |
||
1096 | * * |
||
1097 | ******************************************************************************* |
||
1098 | */ |
||
1099 | void EvaluatePassedPawnRaces(TREE * RESTRICT tree, int wtm) { |
||
108 | pmbaty | 1100 | uint64_t pawns, thispawn; |
1101 | int file, square, queen_distance, pawnsq, passed, side, enemy; |
||
33 | pmbaty | 1102 | int queener[2] = { 8, 8 }; |
1103 | /* |
||
1104 | ************************************************************ |
||
1105 | * * |
||
1106 | * Check to see if side has one pawn and neither side has * |
||
1107 | * any pieces. If so, use the simple pawn evaluation * |
||
1108 | * logic. * |
||
1109 | * * |
||
1110 | ************************************************************ |
||
1111 | */ |
||
1112 | for (side = black; side <= white; side++) { |
||
1113 | enemy = Flip(side); |
||
1114 | if (Pawns(side) && !Pawns(enemy) && TotalPieces(white, occupied) == 0 && |
||
1115 | TotalPieces(black, occupied) == 0) { |
||
1116 | for (pawns = Pawns(side); pawns; pawns &= pawns - 1) { |
||
1117 | pawnsq = LSB(pawns); |
||
1118 | /* |
||
1119 | ************************************************************ |
||
1120 | * * |
||
1121 | * King must be in front of the pawn or we go no further. * |
||
1122 | * * |
||
1123 | ************************************************************ |
||
1124 | */ |
||
1125 | if (sign[side] * Rank(KingSQ(side)) <= sign[side] * Rank(pawnsq)) |
||
1126 | continue; |
||
1127 | /* |
||
1128 | ************************************************************ |
||
1129 | * * |
||
1130 | * First a special case. If this is a rook pawn, then the * |
||
1131 | * king must be on the adjacent file, and be closer to the * |
||
1132 | * queening square than the opposing king. * |
||
1133 | * * |
||
1134 | ************************************************************ |
||
1135 | */ |
||
1136 | if (File(pawnsq) == FILEA) { |
||
1137 | if (File(KingSQ(side)) == FILEB && |
||
1138 | Distance(KingSQ(side), |
||
1139 | sqflip[side][A8]) < Distance(KingSQ(enemy), |
||
1140 | sqflip[side][A8])) { |
||
1141 | tree->score_eg += sign[side] * pawn_can_promote; |
||
1142 | return; |
||
1143 | } |
||
1144 | continue; |
||
1145 | } else if (File(pawnsq) == FILEH) { |
||
1146 | if (File(KingSQ(side)) == FILEG && |
||
1147 | Distance(KingSQ(side), |
||
1148 | sqflip[side][H8]) < Distance(KingSQ(enemy), |
||
1149 | sqflip[side][H8])) { |
||
1150 | tree->score_eg += sign[side] * pawn_can_promote; |
||
1151 | return; |
||
1152 | } |
||
1153 | continue; |
||
1154 | } |
||
1155 | /* |
||
1156 | ************************************************************ |
||
1157 | * * |
||
1158 | * If king is two squares in front of the pawn then it's a * |
||
1159 | * win immediately. If the king is on the 6th rank and * |
||
1160 | * closer to the pawn than the opposing king, it's also a * |
||
1161 | * win. * |
||
1162 | * * |
||
1163 | ************************************************************ |
||
1164 | */ |
||
1165 | if (Distance(KingSQ(side), pawnsq) < Distance(KingSQ(enemy), pawnsq)) { |
||
1166 | if (sign[side] * Rank(KingSQ(side)) > |
||
1167 | sign[side] * (Rank(pawnsq) - 1 + 2 * side)) { |
||
1168 | tree->score_eg += sign[side] * pawn_can_promote; |
||
1169 | return; |
||
1170 | } |
||
108 | pmbaty | 1171 | if (Rank(KingSQ(side)) == rank6[side]) { |
33 | pmbaty | 1172 | tree->score_eg += sign[side] * pawn_can_promote; |
1173 | return; |
||
1174 | } |
||
1175 | /* |
||
1176 | ************************************************************ |
||
1177 | * * |
||
1178 | * Last chance: if the king is one square in front of the * |
||
1179 | * pawn and has the opposition, then it's still a win. * |
||
1180 | * * |
||
1181 | ************************************************************ |
||
1182 | */ |
||
1183 | if (Rank(KingSQ(side)) == Rank(pawnsq) - 1 + 2 * side && |
||
1184 | EvaluateHasOpposition(wtm == side, KingSQ(side), |
||
1185 | KingSQ(enemy))) { |
||
1186 | tree->score_eg += sign[side] * pawn_can_promote; |
||
1187 | return; |
||
1188 | } |
||
1189 | } |
||
1190 | } |
||
1191 | } |
||
1192 | /* |
||
1193 | ************************************************************ |
||
1194 | * * |
||
1195 | * Check to see if enemy is out of pieces and stm has * |
||
1196 | * passed pawns. If so, see if any of these passed pawns * |
||
1197 | * can outrun the defending king and promote. * |
||
1198 | * * |
||
1199 | ************************************************************ |
||
1200 | */ |
||
1201 | if (TotalPieces(enemy, occupied) == 0 && tree->pawn_score.passed[side]) { |
||
1202 | passed = tree->pawn_score.passed[side]; |
||
1203 | for (; passed; passed &= passed - 1) { |
||
1204 | file = LSB8Bit(passed); |
||
108 | pmbaty | 1205 | thispawn = Pawns(side) & file_mask[file]; |
1206 | if (thispawn) { |
||
1207 | square = MostAdvanced(side, thispawn); |
||
1208 | if (!(pawn_race[side][wtm][square] & Kings(enemy))) { |
||
1209 | queen_distance = Abs(rank8[side] - Rank(square)); |
||
1210 | if (Kings(side) & ((side) ? plus8dir[square] : minus8dir[square])) { |
||
1211 | if (file == FILEA || file == FILEH) |
||
1212 | queen_distance = 99; |
||
1213 | queen_distance++; |
||
1214 | } |
||
1215 | if (Rank(square) == rank2[side]) |
||
1216 | queen_distance--; |
||
1217 | if (queen_distance < queener[side]) |
||
1218 | queener[side] = queen_distance; |
||
33 | pmbaty | 1219 | } |
1220 | } |
||
1221 | } |
||
1222 | } |
||
1223 | } |
||
1224 | /* |
||
1225 | ************************************************************ |
||
1226 | * * |
||
1227 | * Now that we know which pawns can outrun the kings for * |
||
108 | pmbaty | 1228 | * each side, we need to do determine if one side queens * |
1229 | * before the other. If so, that side wins. If they * |
||
1230 | * queen at the same time, then we will have to rely on * |
||
1231 | * the search to handle queening with check or queening * |
||
1232 | * and attacking the opponent's queening square. * |
||
33 | pmbaty | 1233 | * * |
1234 | ************************************************************ |
||
1235 | */ |
||
108 | pmbaty | 1236 | if (queener[white] < queener[black]) |
33 | pmbaty | 1237 | tree->score_eg += pawn_can_promote + (5 - queener[white]) * 10; |
108 | pmbaty | 1238 | else if (queener[black] < queener[white]) |
1239 | tree->score_eg -= pawn_can_promote + (5 - queener[black]) * 10; |
||
33 | pmbaty | 1240 | } |
1241 | |||
108 | pmbaty | 1242 | /* last modified 11/27/15 */ |
33 | pmbaty | 1243 | /* |
1244 | ******************************************************************************* |
||
1245 | * * |
||
1246 | * EvaluatePawns() is used to evaluate pawns. It evaluates pawns for only * |
||
1247 | * one side, and fills in the pawn hash entry information. It requires two * |
||
1248 | * calls to evaluate all pawns on the board. Comments below indicate the * |
||
1249 | * particular pawn structure features that are evaluated. * |
||
1250 | * * |
||
108 | pmbaty | 1251 | * This procedure also flags which pawns are passed, since this is scored in * |
1252 | * another part of the evaluation because that includes piece information * |
||
1253 | * which can not be used here since the pawn hash signature does not include * |
||
1254 | * piece information of any kind. * |
||
33 | pmbaty | 1255 | * * |
108 | pmbaty | 1256 | * Note that a pawn is not penalized for two different reasons. If it is * |
1257 | * isolated, it is not backward. Etc. This simplifies evaluation tuning * |
||
1258 | * not to mention eliminating the overlap and interaction that was happening * |
||
1259 | * previously when multiple penalties could be applied. * |
||
1260 | * * |
||
33 | pmbaty | 1261 | ******************************************************************************* |
1262 | */ |
||
1263 | void EvaluatePawns(TREE * RESTRICT tree, int side) { |
||
108 | pmbaty | 1264 | uint64_t pawns, attackers, defenders; |
1265 | uint64_t doubled, supported, connected, passed, backward; |
||
1266 | int square, file, rank, score_eg = 0, score_mg = 0, enemy = Flip(side); |
||
1267 | unsigned int isolated, pawn_files = 0; |
||
33 | pmbaty | 1268 | |
1269 | /* |
||
1270 | ************************************************************ |
||
1271 | * * |
||
108 | pmbaty | 1272 | * Loop through all pawns for this side. * |
33 | pmbaty | 1273 | * * |
1274 | ************************************************************ |
||
1275 | */ |
||
1276 | tree->pawn_score.passed[side] = 0; |
||
1277 | for (pawns = Pawns(side); pawns; pawns &= pawns - 1) { |
||
1278 | square = LSB(pawns); |
||
1279 | file = File(square); |
||
1280 | rank = rankflip[side][Rank(square)]; |
||
108 | pmbaty | 1281 | pawn_files |= 1 << file; |
33 | pmbaty | 1282 | /* |
1283 | ************************************************************ |
||
1284 | * * |
||
1285 | * Evaluate pawn advances. Center pawns are encouraged to * |
||
108 | pmbaty | 1286 | * occupy central squares, edge pawns are penalized on all * |
1287 | * edge squares to encourage capture toward the center, * |
||
1288 | * the rest are neutral. * |
||
33 | pmbaty | 1289 | * * |
1290 | ************************************************************ |
||
1291 | */ |
||
1292 | score_mg += pval[mg][side][square]; |
||
1293 | score_eg += pval[eg][side][square]; |
||
1294 | /* |
||
1295 | ************************************************************ |
||
1296 | * * |
||
108 | pmbaty | 1297 | * Evaluate isolated pawns, which are penalized based on * |
1298 | * which file they occupy. * |
||
33 | pmbaty | 1299 | * * |
1300 | ************************************************************ |
||
1301 | */ |
||
108 | pmbaty | 1302 | isolated = !(Pawns(side) & mask_pawn_isolated[square]); |
1303 | if (isolated) { |
||
1304 | score_mg -= pawn_isolated[mg][file]; |
||
1305 | score_eg -= pawn_isolated[eg][file]; |
||
33 | pmbaty | 1306 | } |
1307 | /* |
||
1308 | ************************************************************ |
||
1309 | * * |
||
108 | pmbaty | 1310 | * Evaluate unsupported pawns, which provide a target * |
1311 | * since they are undefended by a pawn. We exclude pawns * |
||
1312 | * that are isolated since they have already been given a * |
||
1313 | * penalty. * |
||
33 | pmbaty | 1314 | * * |
1315 | ************************************************************ |
||
1316 | */ |
||
108 | pmbaty | 1317 | supported = Pawns(side) & pawn_attacks[enemy][square]; |
1318 | if (!isolated && !supported) { |
||
1319 | score_mg += pawn_unsupported[mg]; |
||
1320 | score_eg += pawn_unsupported[eg]; |
||
1321 | } |
||
33 | pmbaty | 1322 | /* |
1323 | ************************************************************ |
||
1324 | * * |
||
108 | pmbaty | 1325 | * Evaluate doubled pawns. If there are other pawns on * |
1326 | * this file in front of this pawn, penalize this pawn. * |
||
1327 | * Note that this will NOT penalize both pawns, just the * |
||
1328 | * most rearward one that is really almost worthless. * |
||
33 | pmbaty | 1329 | * * |
108 | pmbaty | 1330 | * The farther apart two doubled pawns (same file) are, * |
1331 | * the less weak they are, so the penalty is reduced as * |
||
1332 | * this distance increases. * |
||
1333 | * * |
||
33 | pmbaty | 1334 | ************************************************************ |
1335 | */ |
||
108 | pmbaty | 1336 | doubled = Pawns(side) & ((side) ? plus8dir[square] : minus8dir[square]); |
1337 | if (doubled) { |
||
1338 | score_mg -= |
||
1339 | pawn_doubled[mg][file] / RankDistance(square, MostAdvanced(side, |
||
1340 | doubled)); |
||
1341 | score_eg -= |
||
1342 | pawn_doubled[eg][file] / RankDistance(square, MostAdvanced(side, |
||
1343 | doubled)); |
||
1344 | } |
||
33 | pmbaty | 1345 | /* |
1346 | ************************************************************ |
||
1347 | * * |
||
108 | pmbaty | 1348 | * Test the pawn to see if it is connected to a neighbor * |
1349 | * which makes it easier to defend. * |
||
33 | pmbaty | 1350 | * * |
1351 | ************************************************************ |
||
1352 | */ |
||
108 | pmbaty | 1353 | connected = Pawns(side) & mask_pawn_connected[side][square]; |
1354 | if (connected) { |
||
1355 | score_mg += pawn_connected[rank][file]; |
||
1356 | score_eg += pawn_connected[rank][file]; |
||
1357 | } |
||
33 | pmbaty | 1358 | /* |
1359 | ************************************************************ |
||
1360 | * * |
||
108 | pmbaty | 1361 | * Flag passed pawns for use later when we finally call * |
1362 | * EvaluatePassedPawns. * |
||
33 | pmbaty | 1363 | * * |
1364 | ************************************************************ |
||
1365 | */ |
||
108 | pmbaty | 1366 | passed = !(Pawns(enemy) & mask_passed[side][square]); |
1367 | if (passed) |
||
1368 | tree->pawn_score.passed[side] |= 1 << file; |
||
33 | pmbaty | 1369 | /* |
1370 | ************************************************************ |
||
1371 | * * |
||
108 | pmbaty | 1372 | * Test the pawn to see if it is backward which makes it a * |
1373 | * target that ties down pieces to defend it. * |
||
33 | pmbaty | 1374 | * * |
1375 | ************************************************************ |
||
1376 | */ |
||
108 | pmbaty | 1377 | backward = 0; |
1378 | if (!(passed | isolated | connected | (Pawns(side) & |
||
1379 | mask_pattacks[side][square]) | (Pawns(enemy) & |
||
1380 | PawnAttacks(side, square)))) |
||
1381 | backward = Pawns(enemy) & PawnAttacks(side, square + direction[side]); |
||
1382 | if (backward) { |
||
1383 | score_mg -= pawn_backward[mg][file]; |
||
1384 | score_eg -= pawn_backward[eg][file]; |
||
1385 | } |
||
33 | pmbaty | 1386 | /* |
1387 | ************************************************************ |
||
1388 | * * |
||
108 | pmbaty | 1389 | * Determine if this pawn is a candidate passed pawn, * |
1390 | * which is a pawn on a file with no enemy pawns in front * |
||
1391 | * of it, and if it advances until it contacts an enemy * |
||
1392 | * pawn, and it is defended at least as many times as it * |
||
1393 | * is attacked when it reaches that pawn, then it will end * |
||
1394 | * up passed. * |
||
33 | pmbaty | 1395 | * * |
1396 | ************************************************************ |
||
1397 | */ |
||
108 | pmbaty | 1398 | if (!(passed | backward | isolated) && |
1399 | !(Pawns(enemy) & ((side) ? plus8dir[square] : minus8dir[square]))) { |
||
1400 | defenders = mask_pattacks[side][square + direction[side]] & Pawns(side); |
||
1401 | attackers = mask_pattacks[enemy][square] & Pawns(enemy); |
||
1402 | if (PopCnt(defenders) >= PopCnt(attackers)) { |
||
1403 | score_mg += passed_pawn_candidate[mg][rank]; |
||
1404 | score_eg += passed_pawn_candidate[eg][rank]; |
||
33 | pmbaty | 1405 | } |
1406 | } |
||
108 | pmbaty | 1407 | } |
33 | pmbaty | 1408 | /* |
1409 | ************************************************************ |
||
1410 | * * |
||
108 | pmbaty | 1411 | * Give a bonus for distance between left-most pawn and * |
1412 | * right-most pawn. The idea is that the wider the gap * |
||
1413 | * between the pawns, the harder they are for a lone king * |
||
1414 | * to control in the endgame. Botvinnik referred to this * |
||
1415 | * concept as "trousers" (pants with two legs, the farther * |
||
1416 | * the legs are apart, the better for the side with those * |
||
1417 | * pawns). * |
||
33 | pmbaty | 1418 | * * |
1419 | ************************************************************ |
||
1420 | */ |
||
108 | pmbaty | 1421 | score_eg += pawn_file_width * (MSB8Bit(pawn_files) - LSB8Bit(pawn_files)); |
33 | pmbaty | 1422 | /* |
1423 | ************************************************************ |
||
1424 | * * |
||
1425 | * Evaluate king safety. * |
||
1426 | * * |
||
108 | pmbaty | 1427 | * This uses the function EvaluateKingsFile() and looks at * |
1428 | * three possible positions for the king, either castled * |
||
33 | pmbaty | 1429 | * kingside, queenside or else standing on the d or e file * |
1430 | * stuck in the middle. This essentially is about the * |
||
1431 | * pawns in front of the king and what kind of "shelter" * |
||
1432 | * they provide for the king during the middlegame. * |
||
1433 | * * |
||
1434 | ************************************************************ |
||
1435 | */ |
||
108 | pmbaty | 1436 | tree->pawn_score.defects_q[side] = |
1437 | EvaluateKingsFile(tree, side, FILEA, FILEC); |
||
1438 | tree->pawn_score.defects_m[side] = |
||
1439 | EvaluateKingsFile(tree, side, FILEC, FILEF); |
||
1440 | tree->pawn_score.defects_k[side] = |
||
1441 | EvaluateKingsFile(tree, side, FILEF, FILEH); |
||
1442 | /* |
||
1443 | ************************************************************ |
||
1444 | * * |
||
1445 | * Done. Add mg/eg scores to final result (sign-corrected * |
||
1446 | * so that black = -, white = +) and return. * |
||
1447 | * * |
||
1448 | ************************************************************ |
||
1449 | */ |
||
33 | pmbaty | 1450 | tree->pawn_score.score_mg += sign[side] * score_mg; |
1451 | tree->pawn_score.score_eg += sign[side] * score_eg; |
||
1452 | } |
||
1453 | |||
108 | pmbaty | 1454 | /* last modified 10/19/15 */ |
33 | pmbaty | 1455 | /* |
1456 | ******************************************************************************* |
||
1457 | * * |
||
1458 | * EvaluateQueens() is used to evaluate queens. * |
||
1459 | * * |
||
1460 | ******************************************************************************* |
||
1461 | */ |
||
1462 | void EvaluateQueens(TREE * RESTRICT tree, int side) { |
||
1463 | uint64_t temp; |
||
108 | pmbaty | 1464 | int square, i, score_mg = 0, score_eg = 0, enemy = Flip(side); |
33 | pmbaty | 1465 | |
1466 | /* |
||
1467 | ************************************************************ |
||
1468 | * * |
||
1469 | * First locate each queen and obtain it's centralization * |
||
1470 | * score from the static piece/square table for queens. * |
||
1471 | * * |
||
1472 | ************************************************************ |
||
1473 | */ |
||
1474 | for (temp = Queens(side); temp; temp &= temp - 1) { |
||
1475 | square = LSB(temp); |
||
1476 | /* |
||
1477 | ************************************************************ |
||
1478 | * * |
||
1479 | * Then, add in the piece/square table value for the * |
||
1480 | * queen. * |
||
1481 | * * |
||
1482 | ************************************************************ |
||
1483 | */ |
||
1484 | score_mg += qval[mg][side][square]; |
||
1485 | score_eg += qval[eg][side][square]; |
||
1486 | /* |
||
1487 | ************************************************************ |
||
1488 | * * |
||
1489 | * Adjust the tropism count for this piece. * |
||
1490 | * * |
||
1491 | ************************************************************ |
||
1492 | */ |
||
1493 | if (tree->dangerous[side]) { |
||
108 | pmbaty | 1494 | i = KingSQ(enemy); |
1495 | tree->tropism[side] += king_tropism_q[Distance(square, i)]; |
||
1496 | i = 8 - (RankDistance(square, i) + FileDistance(square, i)); |
||
1497 | score_mg += i; |
||
1498 | score_eg += i; |
||
33 | pmbaty | 1499 | } |
1500 | } |
||
1501 | tree->score_mg += sign[side] * score_mg; |
||
1502 | tree->score_eg += sign[side] * score_eg; |
||
1503 | } |
||
1504 | |||
108 | pmbaty | 1505 | /* last modified 10/19/15 */ |
33 | pmbaty | 1506 | /* |
1507 | ******************************************************************************* |
||
1508 | * * |
||
1509 | * EvaluateRooks() is used to evaluate rooks. * |
||
1510 | * * |
||
1511 | ******************************************************************************* |
||
1512 | */ |
||
1513 | void EvaluateRooks(TREE * RESTRICT tree, int side) { |
||
1514 | uint64_t temp, moves; |
||
108 | pmbaty | 1515 | int square, rank, file, i, mobility, score_mg = 0, score_eg = 0; |
33 | pmbaty | 1516 | int enemy = Flip(side); |
1517 | |||
1518 | /* |
||
1519 | ************************************************************ |
||
1520 | * * |
||
1521 | * Initialize. * |
||
1522 | * * |
||
1523 | ************************************************************ |
||
1524 | */ |
||
1525 | for (temp = Rooks(side); temp; temp &= temp - 1) { |
||
1526 | square = LSB(temp); |
||
1527 | file = File(square); |
||
1528 | rank = Rank(square); |
||
1529 | /* |
||
1530 | ************************************************************ |
||
1531 | * * |
||
1532 | * Determine if the rook is on an open file or on a half- * |
||
1533 | * open file, either of which increases its ability to * |
||
1534 | * attack important squares. * |
||
1535 | * * |
||
1536 | ************************************************************ |
||
1537 | */ |
||
1538 | if (!(file_mask[file] & Pawns(side))) { |
||
1539 | if (!(file_mask[file] & Pawns(enemy))) { |
||
1540 | score_mg += rook_open_file[mg]; |
||
1541 | score_eg += rook_open_file[eg]; |
||
1542 | } else { |
||
1543 | score_mg += rook_half_open_file[mg]; |
||
1544 | score_eg += rook_half_open_file[eg]; |
||
1545 | } |
||
1546 | } |
||
1547 | /* |
||
1548 | ************************************************************ |
||
1549 | * * |
||
108 | pmbaty | 1550 | * Mobility counts the number of squares the rook attacks, * |
1551 | * excluding squares with friendly pieces, and weighs each * |
||
1552 | * square according to a complex formula that includes * |
||
1553 | * files as well as total number of squares attacked. * |
||
1554 | * * |
||
1555 | ************************************************************ |
||
1556 | */ |
||
1557 | mobility = RookMobility(square, OccupiedSquares); |
||
1558 | score_mg += mobility; |
||
1559 | score_eg += mobility; |
||
1560 | /* |
||
1561 | ************************************************************ |
||
1562 | * * |
||
33 | pmbaty | 1563 | * Check to see if the king has been forced to move and * |
1564 | * has trapped a rook at a1/b1/g1/h1, if so, then penalize * |
||
108 | pmbaty | 1565 | * the trapped rook to help extricate it. We only need to * |
1566 | * check this if the rooks mobility is very low. * |
||
33 | pmbaty | 1567 | * * |
1568 | ************************************************************ |
||
1569 | */ |
||
108 | pmbaty | 1570 | if (mobility < 0 && rank == rank1[side] && rank == Rank(KingSQ(side))) { |
1571 | i = File(KingSQ(side)); |
||
1572 | if (i > FILEE) { |
||
1573 | if (file > i) { |
||
1574 | score_mg += mobility * 3; |
||
1575 | score_eg += mobility * 3; |
||
33 | pmbaty | 1576 | } |
108 | pmbaty | 1577 | } else if (i < FILED && file < i) { |
1578 | score_mg += mobility * 3; |
||
1579 | score_eg += mobility * 3; |
||
33 | pmbaty | 1580 | } |
1581 | } |
||
1582 | /* |
||
1583 | ************************************************************ |
||
1584 | * * |
||
108 | pmbaty | 1585 | * finally check to see if any rooks are on the 7th rank, * |
1586 | * with the opponent having pawns on that rank or the * |
||
1587 | * opponent's king being hemmed in on the 7th/8th rank. * |
||
1588 | * If so, we give a bonus for the strong rook. If there * |
||
1589 | * is another rook or queen on the 7th that is connected * |
||
1590 | * with this one, then the positional advantage is even * |
||
1591 | * stronger. * |
||
33 | pmbaty | 1592 | * * |
1593 | ************************************************************ |
||
1594 | */ |
||
108 | pmbaty | 1595 | else if (rank == rank7[side] && (Rank(KingSQ(enemy)) == rank8[side] |
1596 | || Pawns(enemy) & rank_mask[rank])) { |
||
33 | pmbaty | 1597 | score_mg += rook_on_7th[mg]; |
1598 | score_eg += rook_on_7th[eg]; |
||
108 | pmbaty | 1599 | if (RankAttacks(square) & (Queens(side) | Rooks(side))) { |
1600 | score_mg += rook_connected_7th[mg]; |
||
1601 | score_eg += rook_connected_7th[eg]; |
||
1602 | } |
||
33 | pmbaty | 1603 | } |
1604 | /* |
||
1605 | ************************************************************ |
||
1606 | * * |
||
1607 | * Adjust the tropism count for this piece. * |
||
1608 | * * |
||
1609 | ************************************************************ |
||
1610 | */ |
||
1611 | if (tree->dangerous[side]) { |
||
1612 | moves = king_attacks[KingSQ(enemy)]; |
||
108 | pmbaty | 1613 | i = (rook_attacks[square] & moves && |
33 | pmbaty | 1614 | RookAttacks(square, |
108 | pmbaty | 1615 | OccupiedSquares & ~(Queens(side) | Rooks(side))) & moves) ? 1 : |
1616 | Distance(square, KingSQ(enemy)); |
||
1617 | tree->tropism[side] += king_tropism_r[i]; |
||
33 | pmbaty | 1618 | } |
1619 | } |
||
1620 | tree->score_mg += sign[side] * score_mg; |
||
1621 | tree->score_eg += sign[side] * score_eg; |
||
1622 | } |
||
1623 | |||
108 | pmbaty | 1624 | /* last modified 01/03/15 */ |
33 | pmbaty | 1625 | /* |
1626 | ******************************************************************************* |
||
1627 | * * |
||
1628 | * EvaluateWinningChances() is used to determine if one side has reached a * |
||
1629 | * position which can not be won, period, even though side may be ahead in * |
||
1630 | * material in some way. * |
||
1631 | * * |
||
1632 | * Return values: * |
||
108 | pmbaty | 1633 | * 0 -> side on move can not win. * |
1634 | * 1 -> side on move can win. * |
||
33 | pmbaty | 1635 | * * |
1636 | ******************************************************************************* |
||
1637 | */ |
||
1638 | int EvaluateWinningChances(TREE * RESTRICT tree, int side, int wtm) { |
||
108 | pmbaty | 1639 | int square, ekd, promote, majors, minors, enemy = Flip(side); |
33 | pmbaty | 1640 | |
108 | pmbaty | 1641 | if (!Pawns(side)) { |
33 | pmbaty | 1642 | /* |
1643 | ************************************************************ |
||
1644 | * * |
||
1645 | * If side has a piece and no pawn, it can not possibly * |
||
1646 | * win. If side is a piece ahead, the only way it can win * |
||
1647 | * is if the enemy is already trapped on the edge of the * |
||
1648 | * board (special case to handle KRB vs KR which can be * |
||
1649 | * won if the king gets trapped). * |
||
1650 | * * |
||
1651 | ************************************************************ |
||
1652 | */ |
||
1653 | if (TotalPieces(side, occupied) <= 3) |
||
1654 | return 0; |
||
1655 | if (TotalPieces(side, occupied) - TotalPieces(enemy, occupied) <= 3 && |
||
1656 | mask_not_edge & Kings(enemy)) |
||
1657 | return 0; |
||
108 | pmbaty | 1658 | /* |
1659 | ************************************************************ |
||
1660 | * * |
||
1661 | * If one side is an exchange up, but has no pawns, then * |
||
1662 | * that side can not possibly win. * |
||
1663 | * * |
||
1664 | ************************************************************ |
||
1665 | */ |
||
1666 | majors = |
||
1667 | TotalPieces(white, rook) + 2 * TotalPieces(white, |
||
1668 | queen) - TotalPieces(black, rook) - 2 * TotalPieces(black, queen); |
||
1669 | if (Abs(majors) == 1) { |
||
1670 | minors = |
||
1671 | TotalPieces(black, knight) + TotalPieces(black, |
||
1672 | bishop) - TotalPieces(white, knight) - TotalPieces(white, bishop); |
||
1673 | if (majors == minors) |
||
1674 | return 0; |
||
1675 | } |
||
1676 | } else { |
||
1677 | /* |
||
1678 | ************************************************************ |
||
1679 | * * |
||
1680 | * If neither side has any pieces, and both sides have * |
||
1681 | * non-rookpawns, then either side can win. * |
||
1682 | * * |
||
1683 | ************************************************************ |
||
1684 | */ |
||
1685 | if (TotalPieces(white, occupied) == 0 && TotalPieces(black, occupied) == 0 |
||
1686 | && Pawns(white) & not_rook_pawns && Pawns(black) & not_rook_pawns) |
||
1687 | return 1; |
||
33 | pmbaty | 1688 | } |
1689 | /* |
||
1690 | ************************************************************ |
||
1691 | * * |
||
1692 | * If "side" has a pawn, then either the pawn had better * |
||
108 | pmbaty | 1693 | * not be a rook pawn, or else side had better have the * |
33 | pmbaty | 1694 | * right color bishop or any other piece, otherwise it is * |
1695 | * not winnable if the enemy king can get to the queening * |
||
1696 | * square first. * |
||
1697 | * * |
||
1698 | ************************************************************ |
||
1699 | */ |
||
108 | pmbaty | 1700 | if (!(Pawns(side) & not_rook_pawns)) |
33 | pmbaty | 1701 | do { |
1702 | if (TotalPieces(side, occupied) > 3 || (TotalPieces(side, occupied) == 3 |
||
1703 | && Knights(side))) |
||
1704 | continue; |
||
1705 | if (file_mask[FILEA] & Pawns(side) && file_mask[FILEH] & Pawns(side)) |
||
1706 | continue; |
||
1707 | if (Bishops(side)) { |
||
1708 | if (Bishops(side) & dark_squares) { |
||
1709 | if (file_mask[dark_corner[side]] & Pawns(side)) |
||
1710 | continue; |
||
1711 | } else if (file_mask[light_corner[side]] & Pawns(side)) |
||
1712 | continue; |
||
1713 | } |
||
1714 | if (Pawns(side) & file_mask[FILEA]) |
||
1715 | promote = A8; |
||
1716 | else |
||
1717 | promote = H8; |
||
1718 | ekd = Distance(KingSQ(enemy), sqflip[side][promote]) - (wtm != side); |
||
1719 | if (ekd <= 1) |
||
1720 | return 0; |
||
1721 | } while (0); |
||
1722 | /* |
||
1723 | ************************************************************ |
||
1724 | * * |
||
108 | pmbaty | 1725 | * Check to see if this is a KRP vs KR ending. If so, and * |
1726 | * the losing king is in front of the passer, then this is * |
||
1727 | * a drawish ending. * |
||
33 | pmbaty | 1728 | * * |
1729 | ************************************************************ |
||
1730 | */ |
||
1731 | if (TotalPieces(side, pawn) == 1 && TotalPieces(enemy, pawn) == 0 && |
||
108 | pmbaty | 1732 | TotalPieces(side, occupied) == 5 && TotalPieces(enemy, occupied) == 5) { |
33 | pmbaty | 1733 | square = LSB(Pawns(side)); |
1734 | if (FileDistance(KingSQ(enemy), square) <= 1 && |
||
1735 | InFront(side, Rank(KingSQ(enemy)), Rank(square))) |
||
1736 | return 0; |
||
1737 | } |
||
1738 | /* |
||
1739 | ************************************************************ |
||
1740 | * * |
||
1741 | * If this side has pawns, and we have made it through the * |
||
1742 | * previous tests, then this side has winning chances. * |
||
1743 | * * |
||
1744 | ************************************************************ |
||
1745 | */ |
||
1746 | if (TotalPieces(side, pawn)) |
||
1747 | return 1; |
||
1748 | /* |
||
1749 | ************************************************************ |
||
1750 | * * |
||
1751 | * If this side has two bishops, and the enemy has only a * |
||
1752 | * single kinght, the two bishops win. * |
||
1753 | * * |
||
1754 | ************************************************************ |
||
1755 | */ |
||
1756 | if (TotalPieces(side, occupied) == 6) |
||
1757 | if (TotalPieces(enemy, occupied) == 3 && (Knights(side) |
||
1758 | || !Knights(enemy))) |
||
1759 | return 0; |
||
1760 | /* |
||
1761 | ************************************************************ |
||
1762 | * * |
||
1763 | * If one side is two knights ahead and the opponent has * |
||
1764 | * no remaining material, it is a draw. * |
||
1765 | * * |
||
1766 | ************************************************************ |
||
1767 | */ |
||
1768 | if (TotalPieces(side, occupied) == 6 && !Bishops(side) |
||
1769 | && TotalPieces(enemy, occupied) + TotalPieces(enemy, pawn) == 0) |
||
1770 | return 0; |
||
108 | pmbaty | 1771 | /* |
1772 | ************************************************************ |
||
1773 | * * |
||
1774 | * If we make it through all the above tests, then "side" * |
||
1775 | * can win so we return 1. * |
||
1776 | * * |
||
1777 | ************************************************************ |
||
1778 | */ |
||
33 | pmbaty | 1779 | return 1; |
1780 | } |
||
108 | pmbaty | 1781 | |
1782 | /* |
||
1783 | ******************************************************************************* |
||
1784 | * * |
||
1785 | * InitializeKingSafety() is used to initialize the king safety matrix. * |
||
1786 | * This is set so that the matrix, indexed by king safety pawn structure * |
||
1787 | * index and by king safety piece tropism, combines the two indices to * |
||
1788 | * produce a single score. As either index rises, the king safety score * |
||
1789 | * tracks along, but as both rise, the king safety score rises much more * |
||
1790 | * quickly. * |
||
1791 | * * |
||
1792 | ******************************************************************************* |
||
1793 | */ |
||
1794 | void InitializeKingSafety() { |
||
1795 | int safety, tropism; |
||
1796 | |||
1797 | for (safety = 0; safety < 16; safety++) { |
||
1798 | for (tropism = 0; tropism < 16; tropism++) { |
||
1799 | king_safety[safety][tropism] = |
||
1800 | 180 * ((safety_vector[safety] + 100) * (tropism_vector[tropism] + |
||
1801 | 100) / 100 - 100) / 100; |
||
1802 | } |
||
1803 | } |
||
1804 | } |