search: fixed a bug in NULL move pruning
[owl.git] / evaluate.c
blobe6581c78a5837919353c50e7d454a73c758faac9
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 #include "common.h"
17 #include "attacks.h"
18 #include "board.h"
19 #include "engine.h"
20 #include "evaluate.h"
21 #include "move.h"
22 #include "trans.h"
24 #define OPENING_SCORE (side_score[OPENING][brd.wtm] - \
25 side_score[OPENING][1 ^ brd.wtm])
26 #define ENDGAME_SCORE (side_score[ENDGAME][brd.wtm] - \
27 side_score[ENDGAME][1 ^ brd.wtm])
29 static int rank_flip[2][8] = {
30 { 0, 1, 2, 3, 4, 5, 6, 7 },
31 { 7, 6, 5, 4, 3, 2, 1, 0 }
34 /* cental pawns on their initial squares */
35 const uint64_t d2e2[2] = {
36 0x0000000000001800ULL, 0x0018000000000000ULL
38 /* bitmask for 7th rank */
39 const uint64_t rank7bb[2] = {
40 0x00FF000000000000ULL, 0x000000000000FF00ULL
43 static int king_attacks[2];
44 static int king_attackers[2];
45 static int king_score[2][2];
46 static int mobility_score[2][2];
47 static int pawn_score[2][2];
48 static int position_score[2][2];
49 static int side_score[2][2];
51 /* passed pawns bitboard */
52 static uint64_t passers[2];
54 /* bonus for side to move */
55 static int wtm_bonus[2] = {25, 10};
57 /* forward declarations of functions */
58 static void append_scores(void);
59 static void evaluate_pawns(int side);
60 static void evaluate_knights(int side);
61 static void evaluate_bishops(int side);
62 static void evaluate_rooks(int side);
63 static void evaluate_queens(int side);
64 static void evaluate_king(int side);
65 static int evaluate_draw_pattern(void);
66 static int evaluate_mate(int side);
67 static void evaluate_material_imbalances(int side);
68 static void evaluate_blocked_pieces(int side);
69 static void zero_scores(void);
71 static inline void
72 append_scores(void)
74 side_score[OPENING][WHITE] += king_score[OPENING][WHITE] + \
75 mobility_score[OPENING][WHITE] + pawn_score[OPENING][WHITE] + \
76 position_score[OPENING][WHITE];
77 side_score[OPENING][BLACK] += king_score[OPENING][BLACK] +
78 mobility_score[OPENING][BLACK] + pawn_score[OPENING][BLACK] + \
79 position_score[OPENING][BLACK];
80 side_score[ENDGAME][WHITE] += king_score[ENDGAME][WHITE] + \
81 mobility_score[ENDGAME][WHITE] + pawn_score[ENDGAME][WHITE] + \
82 position_score[ENDGAME][WHITE];
83 side_score[ENDGAME][BLACK] += king_score[ENDGAME][BLACK] + \
84 mobility_score[ENDGAME][BLACK] + pawn_score[ENDGAME][BLACK] + \
85 position_score[ENDGAME][BLACK];
88 /* bonus for rook behind passed pawn */
89 static int rook_behind_pp = 30;
91 /* bonus for having more pawns in endgame if there are no pieces
92 on the board */
93 static int more_pawns_bonus = 15;
94 static int lazy_margin = 250;
96 static uint64_t pawn_attacks[2];
98 /* return TRUE if current position is DRAW */
99 int
100 evaluate_draw(void)
102 if (brd.fifty_rule >= 100)
103 return TRUE; /* draw by fifty rule */
105 if (material_pawns[WHITE] || material_pawns[BLACK])
106 return FALSE; /* there are some pawns on the board */
108 /* check for draw by insufficient material */
109 if (((material_complete[WHITE] < piece_value[ROOK]) || \
110 piece_count[WHITE][KNIGHT] == 2) && \
111 ((material_complete[BLACK] < piece_value[ROOK]) || \
112 piece_count[BLACK][KNIGHT] == 2))
113 return TRUE;
115 return FALSE;
118 /* evaluate current position */
119 int
120 evaluate(int alpha, int beta)
122 int score;
123 int mate_score;
124 int side;
125 int xside;
127 assert(alpha >= -MATE_VALUE && beta <= MATE_VALUE);
128 assert(beta > alpha);
130 /* we should find mate position */
131 if ((!material_pawns[WHITE] && !material_complete[BLACK]) || \
132 (!material_pawns[BLACK] && !material_complete[WHITE])) {
133 mate_score = evaluate_mate(WHITE) - evaluate_mate(BLACK);
134 if (mate_score)
135 return brd.wtm ? -mate_score : mate_score;
138 /* check for drawish endgame */
139 if (evaluate_draw_pattern())
140 return 0;
142 #ifdef STATISTIC_COUNTERS
143 counters.evaluations++;
144 #endif
145 zero_scores();
147 side_score[OPENING][WHITE] = material_complete[WHITE] - wpc * 10;
148 side_score[OPENING][BLACK] = material_complete[BLACK] - bpc * 10;
149 side_score[ENDGAME][WHITE] = material_complete[WHITE];
150 side_score[ENDGAME][BLACK] = material_complete[BLACK];
152 /* wtm bonus */
153 side_score[OPENING][brd.wtm] += wtm_bonus[OPENING];
154 side_score[ENDGAME][brd.wtm] += wtm_bonus[ENDGAME];
156 pawn_attacks[WHITE] = ((PAWNS(WHITE) & ~file_bit[7]) << 9) | \
157 ((PAWNS(WHITE) & ~file_bit[0]) << 7);
158 pawn_attacks[BLACK] = ((PAWNS(BLACK) & ~file_bit[0]) >> 9) | \
159 ((PAWNS(BLACK) & ~file_bit[7]) >> 7);
161 score = (OPENING_SCORE * (256 - GAME_PHASE) + \
162 ENDGAME_SCORE * GAME_PHASE) / 256;
164 int lazy_eval = FALSE;
165 if (alpha == beta - 1 && ((score - lazy_margin >= beta) || (score + lazy_margin <= alpha))) {
166 lazy_eval = TRUE;
167 counters.lazy_evaluations++;
170 for (side = WHITE; side <= BLACK; side++) {
171 evaluate_pawns(side);
172 evaluate_material_imbalances(side);
173 evaluate_blocked_pieces(side);
174 if (!lazy_eval) {
175 evaluate_knights(side);
176 evaluate_bishops(side);
177 evaluate_rooks(side);
178 evaluate_queens(side);
179 evaluate_king(side);
183 /* look for rook behind passer */
184 for (side = WHITE; side <= BLACK; side++) {
185 int square;
186 uint64_t pp;
187 uint64_t bb = ROOKS(side);
189 while (bb) {
190 square = bit_scan_clear(&bb);
191 pp = file_bit[_FILE(square)] & passers[side];
192 if (pp) {
193 if (side == WHITE) {
194 if (_RANK(bit_scan(pp)) > _RANK(square))
195 position_score[ENDGAME][side] += rook_behind_pp;
196 } else {
197 if (_RANK(bit_scan(pp)) < _RANK(square))
198 position_score[ENDGAME][side] += rook_behind_pp;
204 /* bonus for having more pawns if there are now pieces on the board */
205 if (!material_pieces[WHITE] && !material_pieces[BLACK])
206 side_score[ENDGAME][WHITE] += (wpc - bpc) * more_pawns_bonus;
208 append_scores();
210 /* bishop of opposite colours */
211 if (wqc + wrc + wnc + bqc + brc + bnc == 0 && wbc == 1 && \
212 bbc == 1 && abs(wpc - bpc) <= 2) {
213 if (popcount((BISHOPS(WHITE) | BISHOPS(BLACK)) & WHITESQUARES) == 1) {
214 side_score[ENDGAME][WHITE] /= 2;
215 side_score[ENDGAME][BLACK] /= 2;
219 /* get final score according to game phase */
220 score = (OPENING_SCORE * (256 - GAME_PHASE) + \
221 ENDGAME_SCORE * GAME_PHASE) / 256;
222 assert(score >= -MATE_VALUE && score <= MATE_VALUE);
224 side = brd.wtm;
225 xside = 1 ^ side;
227 /* can't win if we have two knights or a bishop and no pawns
228 (but theoretically we can, for example so called 'cooperative mate') */
229 if (score > 0 && !material_pawns[side] && \
230 ((material_pieces[side] < piece_value[ROOK]) || \
231 ((KNIGHTS(side) | KING(side)) == side_boards[side]))) {
232 score = 0;
233 } else if (score < 0 && !material_pawns[xside] && \
234 ((material_pieces[xside] < piece_value[ROOK]) || \
235 ((KNIGHTS(xside) | KING(xside)) == side_boards[xside]))) {
236 score = 0;
239 if (wqc == bqc && wrc == brc && abs(wbc + wnc - bbc - bnc) < 2) {
240 if (!wpc && !bpc) {
241 /* no pawns and one side is ahead by minor piece */
242 score /= 2;
243 } else {
244 if (score > 0) {
245 if (side == WHITE && (wbc + wnc - bbc - bnc == 1) && !wpc && bpc) {
246 score /= bpc + 1;
247 } else if (side == BLACK && (bbc + bnc - wbc - wnc == 1) && !bpc && wpc) {
248 score /= wpc + 1;
254 /* ROOK vs [KNIGHT|BISHOP] + (PAWN)? */
255 if ((material_pieces[WHITE] == piece_value[ROOK] && !wpc) && \
256 ((material_pieces[BLACK] == piece_value[KNIGHT] && bpc <= 1) || \
257 (material_pieces[BLACK] == piece_value[BISHOP] && bpc <= 1)))
258 score /= 8;
259 else if ((material_pieces[BLACK] == piece_value[ROOK] && !bpc) && \
260 ((material_pieces[WHITE] == piece_value[KNIGHT] && wpc <= 1) || \
261 (material_pieces[WHITE] == piece_value[BISHOP] && wpc <= 1)))
262 score /= 8;
264 return score;
267 static int pawn_square_op[2][64] = {
269 -15, -5, 0, 5, 5, 0, -5, -15,
270 -15, -5, 0, 5, 5, 0, -5, -15,
271 -15, -5, 0, 15, 15, 0, -5, -15,
272 -15, -5, 0, 25, 25, 0, -5, -15,
273 -15, -5, 0, 15, 15, 0, -5, -15,
274 -15, -5, 0, 5, 5, 0, -5, -15,
275 -15, -5, 0, 5, 5, 0, -5, -15,
276 -15, -5, 0, 5, 5, 0, -5, -15
279 -15, -5, 0, 5, 5, 0, -5, -15,
280 -15, -5, 0, 5, 5, 0, -5, -15,
281 -15, -5, 0, 5, 5, 0, -5, -15,
282 -15, -5, 0, 15, 15, 0, -5, -15,
283 -15, -5, 0, 25, 25, 0, -5, -15,
284 -15, -5, 0, 15, 15, 0, -5, -15,
285 -15, -5, 0, 5, 5, 0, -5, -15,
286 -15, -5, 0, 5, 5, 0, -5, -15
290 static int pawn_square_eg[2][64] = {
292 0, 0, 0, 0, 0, 0, 0, 0,
293 -1, -0, -0, -0, -0, -0, -0, -1,
294 -1, 0, 0, 0, 0, 0, 0, -1,
295 0, 0, 0, 5, 5, 0, 0, 0,
296 0, 5, 5, 10, 10, 5, 5, 0,
297 0, 5, 5, 10, 10, 5, 5, 0,
298 5, 15, 15, 15, 15, 15, 15, 5,
299 0, 0, 0, 0, 0, 0, 0, 0
302 0, 0, 0, 0, 0, 0, 0, 0,
303 5, 15, 15, 15, 15, 15, 15, 5,
304 0, 5, 5, 10, 10, 5, 5, 0,
305 0, 5, 5, 10, 10, 5, 5, 0,
306 0, 0, 0, 5, 5, 0, 0, 0,
307 -1, 0, 0, 0, 0, 0, 0, -1,
308 -1, -0, -0, -0, -0, -0, -0, -1,
309 0, 0, 0, 0, 0, 0, 0, 0
312 /* bonus for passed pawns */
313 static int passer_score_op[8] = {0, 0, 10, 15, 30, 50, 90, 0};
314 static int passer_score_eg[8] = {0, 0, 20, 35, 90, 140, 180, 0};
315 /* bonus for candidate passers */
316 static int can_passed_score_op[8] = {0, 0, 5, 10, 20, 35, 50, 0};
317 static int can_passed_score_eg[8] = {0, 0, 10, 20, 40, 70, 100, 0};
318 /* penalty for isolated pawns */
319 static int isolated_penalty_op = -9;
320 static int isolated_penalty_eg = -18;
321 /* penalty for isolated pawns on open files */
322 static int weak_isolated_penalty_op = -18;
323 static int weak_isolated_penalty_eg = -18;
324 /* penalty for doubled pawns */
325 static int doubled_penalty_op[9] = {0, 0, -35, -28, -23, -16, -12, -12, -12};
326 static int doubled_penalty_eg[9] = {0, 0, -45, -39, -33, -28, -23, -16, -12};
327 /* penalty for backward pawns */
328 static int backward_penalty_op = -8;
329 static int backward_penalty_eg = -10;
330 /* bonus for unstoppable */
331 static int unstoppable_bonus = 777;
333 static void
334 evaluate_pawns(int side)
336 uint64_t b, bb;
337 int i;
338 int count;
339 int square;
340 int score_op, score_eg;
341 int xside;
343 int passed;
344 int next_square;
345 int candidate;
346 int side_defenders, xside_attackers;
347 struct pawn_hash_entry_t *phe;
349 score_op = 0;
350 score_eg = 0;
351 xside = 1 ^ side;
352 passers[side] = 0ULL;
353 bb = PAWNS(side);
355 phe = pawn_hash[side] + (brd.hash_pawn_key & pawn_hash_mask);
357 if (e.pawn_hash_enabled && phe->key == brd.hash_pawn_key) {
358 score_op = phe->score_op;
359 score_eg = phe->score_eg;
360 passers[side] = phe->passers;
361 #ifdef STATISTIC_COUNTERS
362 counters.pawn_hash_evaluations++;
363 #endif
364 } else {
365 while (bb) {
366 passed = FALSE;
367 square = bit_scan_clear(&bb);
369 /* search passers */
370 if (!(forward_ray[side][square] & PAWNS(side))) {
371 /* this is most advanced pawn */
372 if (!(PAWNS(xside) & passer_mask[side][square])) {
373 /* no opponents pawns on adjacent files */
374 score_op += passer_score_op[rank_flip[side][_RANK(square)]];
375 score_eg += passer_score_eg[rank_flip[side][_RANK(square)]];
377 next_square = side? square - 8 : square + 8;
378 if ((BIT(next_square) & complete) ||
379 (pawn_moves[side][next_square] & PAWNS(xside))) {
380 score_op -= passer_score_op[rank_flip[side][_RANK(square)]] / 2;
381 score_eg -= passer_score_eg[rank_flip[side][_RANK(square)]] / 2;
384 SET(passers[side], square);
386 passed = TRUE;
388 } else if (!(forward_ray[side][square] & PAWNS(xside))) {
389 /* no opponent's pawns on the same file */
390 candidate = TRUE;
391 uint64_t candidate_way = forward_ray[side][square] |
392 BIT(square);
394 while (candidate_way) {
395 next_square = bit_scan_clear(&candidate_way);
397 if (rank_flip[side][_RANK(next_square)] == 7)
398 break;
400 if (popcount(pawn_moves[xside][next_square] & PAWNS(xside)) >
401 popcount(pawn_moves[side][next_square] & PAWNS(side))) {
402 candidate = FALSE;
403 break;
407 if (candidate) {
408 score_op += can_passed_score_op[rank_flip[side][_RANK(square)]];
409 score_eg += can_passed_score_eg[rank_flip[side][_RANK(square)]];
414 if (isolated_mask[_FILE(square)] & PAWNS(side)) {
415 /* pawn is not isolated, but maybe backward? */
416 if (!((passer_mask[xside][square + (side == WHITE? 8 : -8)] & \
417 isolated_mask[_FILE(square)]) & PAWNS(side))) {
418 /* pawn is somewhat backward */
419 b = pawn_moves[side][square];
420 if (side == WHITE)
421 b <<= 8;
422 else
423 b >>= 8;
425 if (b & PAWNS(xside)) {
426 /* next square is attacked by opponents pawn */
427 score_op += backward_penalty_op;
428 score_eg += backward_penalty_eg;
430 /* backward on semiopen file */
431 if ((forward_ray[side][square] & PAWNS(xside)) == 0)
432 score_op += backward_penalty_op;
435 } else {
436 if (!passed) {
437 /* pawn is isolated */
438 if (!(forward_ray[side][square] & \
439 (PAWNS(side) | PAWNS(xside)))) {
440 /* isolated on semiopen file */
441 score_op += weak_isolated_penalty_op;
442 score_eg += weak_isolated_penalty_eg;
443 } else {
444 score_op += isolated_penalty_op;
445 score_eg += isolated_penalty_eg;
450 score_op += pawn_square_op[side][square];
451 score_eg += pawn_square_eg[side][square];
454 /* evaluate doubled pawns */
455 for (i = 0; i < 8; i++) {
456 count = popcount(file_bit[i] & PAWNS(side));
457 if (count > 1) {
458 score_op += doubled_penalty_op[piece_count[side][PAWN]] * (count - 1);
459 score_eg += doubled_penalty_eg[piece_count[side][PAWN]] * (count - 1);
463 /* store scores in hashtable */
464 if (e.pawn_hash_enabled) {
465 phe->key = brd.hash_pawn_key;
466 phe->score_op = score_op;
467 phe->score_eg = score_eg;
468 phe->passers = passers[side];
472 bb = passers[side];
473 while (bb) {
474 square = bit_scan_clear(&bb);
475 score_eg += 5 - distance[square][brd.kings[side]] * 5 +
476 distance[square][brd.kings[xside]] * 5;
478 /* check for unstoppable passers */
479 if (!material_pieces[xside] &&
480 !(forward_ray[side][square] & complete)) {
481 int promotion_square;
482 if (side == WHITE)
483 promotion_square = _FILE(square) + 56;
484 else
485 promotion_square = _FILE(square);
486 int distance_diff =
487 distance[promotion_square][brd.kings[xside]] -
488 distance[promotion_square][square];
489 if (distance_diff > 1) {
490 score_eg += unstoppable_bonus;
491 } else if (side && distance_diff == 1 && side == brd.wtm) {
492 score_eg += unstoppable_bonus;
497 pawn_score[OPENING][side] += score_op;
498 pawn_score[ENDGAME][side] += score_eg;
501 static int knight_square_op[2][64] = {
503 -35, -25, -20, -15, -15, -20, -25, -35,
504 -20, -15, -10, -5, -5, -10, -15, -20,
505 -10, -5, 0, 5, 5, 0, -5, -10,
506 -5, 0, 5, 10, 10, 5, 0, -5,
507 -5, 5, 10, 15, 15, 10, 5, -5,
508 -3, 5, 10, 10, 10, 10, 5, -3,
509 -10, -5, 0, 5, 5, 0, -5, -10,
510 -25, -15, -10, -10, -10, -10, -15, -25
513 -25, -15, -10, -10, -10, -10, -15, -25,
514 -10, -5, 0, 5, 5, 0, -5, -10,
515 -3, 5, 10, 10, 10, 10, 5, -3,
516 -5, 5, 10, 15, 15, 10, 5, -5,
517 -5, 0, 5, 10, 10, 5, 0, -5,
518 -10, -5, 0, 5, 5, 0, -5, -10,
519 -20, -15, -10, -5, -5, -10, -15, -20,
520 -35, -25, -20, -15, -15, -20, -25, -35
524 static int knight_square_eg[64] = {
525 -30, -20, -15, -10, -10, -15, -20, -30,
526 -20, -15, -10, -5, -5, -10, -15, -20,
527 -15, -10, 0, 5, 5, 0, -10, -15,
528 -10, -5, 5, 10, 10, 5, -5, -10,
529 -10, -5, 5, 10, 10, 5, -5, -10,
530 -15, -10, 0, 5, 5, 0, -10, -15,
531 -20, -15, -10, -5, -5, -10, -15, -20,
532 -30, -20, -15, -10, -10, -15, -20, -30
535 static int knight_outpost[2][64] = {
537 0, 0, 0, 0, 0, 0, 0, 0,
538 0, 0, 0, 0, 0, 0, 0, 0,
539 0, 0, 0, 0, 0, 0, 0, 0,
540 0, 5, 9, 15, 15, 9, 5, 0,
541 0, 5, 9, 18, 18, 9, 5, 0,
542 0, 0, 5, 9, 9, 5, 0, 0,
543 0, 0, 0, 0, 0, 0, 0, 0,
544 0, 0, 0, 0, 0, 0, 0, 0
547 0, 0, 0, 0, 0, 0, 0, 0,
548 0, 0, 0, 0, 0, 0, 0, 0,
549 0, 0, 5, 9, 9, 5, 0, 0,
550 0, 5, 9, 18, 18, 9, 5, 0,
551 0, 5, 9, 15, 15, 9, 5, 0,
552 0, 0, 0, 0, 0, 0, 0, 0,
553 0, 0, 0, 0, 0, 0, 0, 0,
554 0, 0, 0, 0, 0, 0, 0, 0
558 static int knight_mobility_op[9] = {-15, -10, -5, 0, 4, 8, 12, 16, 20};
559 static int knight_mobility_eg[9] = {-15, -10, -5, 0, 4, 8, 12, 16, 20};
560 static int knight_bonus[17] = {-12, -11, -11, -10, -10, -8, -8, -5, -5, 0, 0,
561 5, 5, 8, 8, 10, 10};
563 /* evaluate knights */
564 static void
565 evaluate_knights(int side)
567 int square;
568 int xside;
569 int xk;
570 int mobility;
571 uint64_t my_knights;
572 uint64_t mobility_xmask;
574 xside = 1 ^ side;
575 xk = brd.kings[xside];
576 my_knights = KNIGHTS(side);
578 if (my_knights)
579 mobility_xmask = ~(side_boards[side] | (pawn_attacks[xside] & ~complete));
581 while (my_knights) {
582 square = bit_scan_clear(&my_knights);
584 /* piece square tables */
585 position_score[OPENING][side] += knight_square_op[side][square];
586 position_score[ENDGAME][side] += knight_square_eg[square];
588 if (knight_outpost[side][square])
589 /* is there enemy pawn that can potentially attack
590 our knight? */
591 if (!(PAWNS(xside) & (passer_mask[side][square] & \
592 isolated_mask[_FILE(square)])))
593 if (pawn_moves[xside][square] & PAWNS(side)) {
594 /* knight is supported by our pawn */
595 position_score[OPENING][side] += knight_outpost[side][square];
598 /* calculate mobility */
599 mobility = popcount(piece_moves[KNIGHT][square] & mobility_xmask);
600 mobility_score[OPENING][side] += knight_mobility_op[mobility];
601 mobility_score[ENDGAME][side] += knight_mobility_eg[mobility];
603 /* value of the knight depending of the pawns count */
604 position_score[OPENING][side] += knight_bonus[wpc + bpc];
605 position_score[ENDGAME][side] += knight_bonus[wpc + bpc];
607 /* king attacks */
608 if ((piece_moves[KING][xk] | BIT(xk)) &
609 piece_moves[KNIGHT][square]) {
610 king_attacks[side]++;
611 king_attackers[side]++;
616 static int bishop_square_op[2][64] = {
618 -10, -10, -10, -5, -5, -10, -10, -10,
619 -5, -5, -5, 0, 0, -5, -5, -5,
620 -3, -1, 2, 3, 3, 2, -1, -3,
621 -2, 0, 3, 5, 5, 3, 0, -2,
622 -2, 0, 3, 5, 5, 3, 0, -2,
623 -3, -1, 2, 5, 5, 2, -1, -2,
624 -5, -2, 0, 0, 0, 0, -2, -5,
625 -10, -10, -10, -10, -10, -10, -10, -10
628 -10, -10, -10, -10, -10, -10, -10, -10,
629 -5, -2, 0, 0, 0, 0, -2, -5,
630 -3, -1, 2, 5, 5, 2, -1, -2,
631 -2, 0, 3, 5, 5, 3, 0, -2,
632 -2, 0, 3, 5, 5, 3, 0, -2,
633 -3, -1, 2, 3, 3, 2, -1, -3,
634 -5, -5, -5, 0, 0, -5, -5, -5,
635 -10, -10, -10, -5, -5, -10, -10, -10
639 static int bishop_square_eg[64] = {
640 -10, -10, -10, -5, -5, -10, -10, -10,
641 -5, -5, -5, 0, 0, -5, -5, -5,
642 -3, -1, 2, 3, 3, 2, -1, -3,
643 -2, 0, 3, 5, 5, 3, 0, -2,
644 -2, 0, 3, 5, 5, 3, 0, -2,
645 -3, -1, 2, 5, 5, 2, -1, -2,
646 -5, -5, -5, 0, 0, -5, -5, -5,
647 -10, -10, -10, -5, -5, -10, -10, -10
650 static int bishop_mobility[16] = {-15, -10, -5, -1, 2, 6, 10, 14, 18, 21, 24,
651 27, 30, 32, 33, 34};
653 /* evaluate bishops */
654 static void
655 evaluate_bishops(int side)
657 int square;
658 int mobility;
659 int xk;
660 int xside;
661 uint64_t attacks;
662 uint64_t mobility_xmask;
663 uint64_t my_bishops;
665 xside = 1 ^ side;
666 xk = brd.kings[xside];
667 my_bishops = BISHOPS(side);
669 if (my_bishops)
670 /* exclude these squares from mobility */
671 mobility_xmask = ~(side_boards[side] | (pawn_attacks[xside] & ~complete));
673 while (my_bishops) {
674 square = bit_scan_clear(&my_bishops);
676 attacks = BISHOP_ATTACKS(square, complete);
678 /* calculate mobility */
679 mobility = popcount(attacks & mobility_xmask);
680 mobility_score[OPENING][side] += bishop_mobility[mobility];
681 mobility_score[ENDGAME][side] += bishop_mobility[mobility];
683 position_score[OPENING][side] += bishop_square_op[side][square];
684 position_score[ENDGAME][side] += bishop_square_eg[square];
686 /* king attacks */
687 if (attacks & (piece_moves[KING][xk] | BIT(xk))) {
688 king_attacks[side]++;
689 king_attackers[side]++;
694 static int rook_on_semiopen_file_op = 10;
695 static int rook_on_semiopen_file_eg = 10;
697 static int rook_on_semiopen_file_near_king_op = 15;
698 static int rook_on_semiopen_file_before_king_op = 20;
700 static int rook_on_open_file_op = 15;
701 static int rook_on_open_file_eg = 15;
703 static int rook_on_seven_rank_op = 20;
704 static int rook_on_seven_rank_eg = 20;
706 static int rook_mobility_op[] = {
707 -8, -3, 0, 1, 2, 3, 5, 7, 10, 12, 14, 15, 16, 17, 18, 18
709 static int rook_mobility_eg[] = {
710 -16, -8, -2, 0, 2, 5, 9, 13, 17, 21, 25, 29, 32, 34, 35, 36
713 static void
714 evaluate_rooks(int side)
716 int xk;
717 int file;
718 int square;
719 int xside;
720 int mobility;
721 uint64_t my_rooks;
722 uint64_t attacks;
723 uint64_t mobility_xmask;
725 my_rooks = ROOKS(side);
726 xside = 1 ^ side; /* opponent's color */
727 xk = brd.kings[xside]; /* location of opponent's king */
729 if (my_rooks)
730 /* exclude these squares from mobility */
731 mobility_xmask = ~(side_boards[side] | (pawn_attacks[xside] & ~complete));
733 while (my_rooks) {
734 square = bit_scan_clear(&my_rooks);
735 file = _FILE(square);
737 if (!(PAWNS(side) & file_bit[file])) {
738 /* there are no our pawns on the rook's file */
739 if (PAWNS(xside) & file_bit[file]) {
740 /* ... but there are opponent's pawns */
741 if (file == (_FILE(xk) - 1) || file == (_FILE(xk) + 1))
742 /* opponent's king is on the adjacent file */
743 position_score[OPENING][side] += rook_on_semiopen_file_near_king_op;
744 else if (file == _FILE(xk))
745 /* opponent's king is on the same file */
746 position_score[OPENING][side] += rook_on_semiopen_file_before_king_op;
747 else {
748 /* rook on semiopen file */
749 position_score[OPENING][side] += rook_on_semiopen_file_op;
750 position_score[ENDGAME][side] += rook_on_semiopen_file_eg;
752 } else {
753 /* rook on open file */
754 position_score[OPENING][side] += rook_on_open_file_op;
755 position_score[ENDGAME][side] += rook_on_open_file_eg;
758 if (rank_flip[side][_RANK(square)] == 6) {
759 /* rook on 7th rank */
760 position_score[OPENING][side] += rook_on_seven_rank_op;
761 position_score[ENDGAME][side] += rook_on_seven_rank_eg;
764 attacks = ROOK_ATTACKS(square, complete);
765 /* calculate mobility */
766 mobility = popcount(attacks & mobility_xmask);
767 mobility_score[OPENING][side] += rook_mobility_op[mobility];
768 mobility_score[ENDGAME][side] += rook_mobility_eg[mobility];
770 /* king attacks */
771 if (attacks & (piece_moves[KING][xk] | BIT(xk))) {
772 king_attacks[side] += 2;
773 king_attackers[side]++;
778 /* queen evaluation */
779 static void
780 evaluate_queens(int side)
782 int xk;
783 int square;
784 uint64_t attacks;
785 uint64_t my_queens;
787 my_queens = QUEENS(side);
788 xk = brd.kings[1 ^ side];
790 while (my_queens) {
791 square = bit_scan_clear(&my_queens);
792 /* king attacks */
793 attacks = QUEEN_ATTACKS(square, complete);
794 if (attacks & (piece_moves[KING][xk] | BIT(xk))) {
795 king_attacks[side] += 4;
796 king_attackers[side]++;
801 static int king_square_op[2][64] = {
803 40, 50, 30, 10, 10, 30, 50, 40,
804 30, 40, 20, 0, 0, 20, 40, 30,
805 10, 20, 0, -20, -20, 0, 20, 10,
806 0, 10, -10, -30, -30, -10, 10, 0,
807 -10, 0, -20, -40, -40, -20, 0, -10,
808 -20, -10, -30, -50, -50, -30, -10, -20,
809 -30, -20, -40, -60, -60, -40, -20, -30,
810 -40, -30, -50, -70, -70, -50, -30, -40
813 -40, -30, -50, -70, -70, -50, -30, -40,
814 -30, -20, -40, -60, -60, -40, -20, -30,
815 -20, -10, -30, -50, -50, -30, -10, -20,
816 -10, 0, -20, -40, -40, -20, 0, -10,
817 0, 10, -10, -30, -30, -10, 10, 0,
818 10, 20, 0, -20, -20, 0, 20, 10,
819 30, 40, 20, 0, 0, 20, 40, 30,
820 40, 50, 30, 10, 10, 30, 50, 40
824 static int king_square_eg[64] = {
825 -72, -48, -36, -24, -24, -36, -48, -72,
826 -48, -24, -12, 0, 0, -12, -24, -48,
827 -36, -12, 0, 12, 12, 0, -12, -36,
828 -24, 0, 12, 24, 24, 12, 0, -24,
829 -24, 0, 12, 24, 24, 12, 0, -24,
830 -36, -12, 0, 12, 12, 0, -12, -36,
831 -48, -24, -12, 0, 0, -12, -24, -48,
832 -72, -48, -36, -24, -24, -36, -48, -72
835 static int attack_penalty_op = -20;
836 static int attack_scale[16] = {
837 0, 0, 8, 10, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
840 static const int side_offset[2] = {-8, 8};
842 /* evaluate king */
843 static void
844 evaluate_king(int side)
846 int i;
847 int file;
848 int rank;
849 int square;
850 int xside;
851 uint64_t bb, xbb;
853 xside = 1 ^ side; /* opponent's side */
854 square = brd.kings[side];
856 file = _FILE(square);
857 rank = _RANK(square);
859 /* include adjacent pawns into mask */
860 if ((side == WHITE && rank != 0) || (side == BLACK && rank != 7))
861 i = square + side_offset[side];
862 else
863 i = square;
865 /* pawn shield and pawn attacks */
866 bb = passer_mask[side][i] & PAWNS(side);
867 xbb = passer_mask[side][i] & PAWNS(xside);
869 if (file != 0) {
870 /* in case if there is no our pawn */
871 king_score[OPENING][side] += -36;
873 if (bb & file_bit[file - 1]) {
874 /* find nearest pawn */
875 if (side == BLACK)
876 i = bit_scan_rev(bb & file_bit[file - 1]);
877 else
878 i = bit_scan(bb & file_bit[file - 1]);
879 king_score[OPENING][side] += (7 - rank_flip[side][_RANK(i)]) * \
880 (7 - rank_flip[side][_RANK(i)]);
884 /* in case if there is no our pawn in front of our king */
885 king_score[OPENING][side] += -36;
887 if (bb & file_bit[file]) {
888 if (side == BLACK)
889 i = bit_scan_rev(bb & file_bit[file]);
890 else
891 i = bit_scan(bb & file_bit[file]);
892 king_score[OPENING][side] += (7 - rank_flip[side][_RANK(i)]) * \
893 (7 - rank_flip[side][_RANK(i)]);
896 if (file != 7) {
897 /* in case if there is no our pawn */
898 king_score[OPENING][side] += -36;
899 if (bb & file_bit[file + 1]) {
900 /* find nearest pawn */
901 if (side)
902 i = bit_scan_rev(bb & file_bit[file + 1]);
903 else
904 i = bit_scan(bb & file_bit[file + 1]);
905 king_score[OPENING][side] += (7 - rank_flip[side][_RANK(i)]) * \
906 (7 - rank_flip[side][_RANK(i)]);
910 king_score[OPENING][xside] += (attack_penalty_op * king_attacks[side] *
911 attack_scale[king_attackers[side]]) / 16;
913 position_score[OPENING][side] += king_square_op[side][square];
914 position_score[ENDGAME][side] += king_square_eg[square];
917 static int blocked_rook = -50;
918 static int trapped_bishop = -100;
920 static void
921 evaluate_blocked_pieces(int side)
923 int xside = 1 ^ side;
924 int side_inc = side * (A8 - A1);
926 /* rook */
927 if (square64[F1 + side_inc] == KING || square64[G1 + side_inc] == KING) {
928 if (square64[G1 + side_inc] == ROOK || square64[H1 + side_inc] == ROOK)
929 position_score[OPENING][side] += blocked_rook;
930 } else if (square64[C1 + side_inc] == KING || square64[B1 + side_inc] == KING) {
931 if (square64[A1 + side_inc] == ROOK || square64[B1 + side_inc] == ROOK)
932 position_score[OPENING][side] += blocked_rook;
935 int b_sq_a7 = side == WHITE? A7 : A2;
936 int b_sq_h7 = side == WHITE? H7 : H2;
937 int p_sq_b6 = side == WHITE? B6 : B3;
938 int p_sq_g6 = side == WHITE? G6 : G3;
940 if ((BISHOPS(side) & BIT(b_sq_a7)) && (PAWNS(xside) & BIT(p_sq_b6)) && \
941 SEE(SET_FROM(b_sq_a7) | SET_TO(p_sq_b6) | SET_TYPE(TYPE_CAPTURE)) < 0) {
942 position_score[OPENING][side] += trapped_bishop;
943 position_score[ENDGAME][side] += trapped_bishop;
945 if ((BISHOPS(side) & BIT(b_sq_h7)) && (PAWNS(xside) & BIT(p_sq_g6)) && \
946 SEE(SET_FROM(b_sq_h7) | SET_TO(p_sq_g6) | SET_TYPE(TYPE_CAPTURE)) < 0) {
947 position_score[OPENING][side] += trapped_bishop;
948 position_score[ENDGAME][side] += trapped_bishop;
952 /* clear scores */
953 static void
954 zero_scores(void)
956 king_attacks[WHITE] = 0;
957 king_attacks[BLACK] = 0;
958 king_attackers[WHITE] = 0;
959 king_attackers[BLACK] = 0;
961 king_score[OPENING][WHITE] = 0;
962 king_score[OPENING][BLACK] = 0;
963 king_score[ENDGAME][WHITE] = 0;
964 king_score[ENDGAME][BLACK] = 0;
966 mobility_score[OPENING][WHITE] = 0;
967 mobility_score[OPENING][BLACK] = 0;
968 mobility_score[ENDGAME][WHITE] = 0;
969 mobility_score[ENDGAME][BLACK] = 0;
971 pawn_score[OPENING][WHITE] = 0;
972 pawn_score[OPENING][BLACK] = 0;
973 pawn_score[ENDGAME][WHITE] = 0;
974 pawn_score[ENDGAME][BLACK] = 0;
976 position_score[OPENING][WHITE] = 0;
977 position_score[OPENING][BLACK] = 0;
978 position_score[ENDGAME][WHITE] = 0;
979 position_score[ENDGAME][BLACK] = 0;
982 static int simple_mate_squares[2][64] = {
984 160, 140, 120, 100, 100, 120, 140, 160,
985 140, 120, 100, 80, 80, 100, 120, 140,
986 120, 100, 80, 60, 60, 80, 100, 120,
987 100, 80, 60, 40, 40, 60, 80, 100,
988 100, 80, 60, 40, 40, 60, 80, 100,
989 120, 100, 80, 60, 60, 80, 100, 120,
990 140, 120, 100, 80, 80, 100, 120, 140,
991 160, 140, 120, 100, 100, 120, 140, 160
994 160, 140, 120, 100, 100, 120, 140, 160,
995 140, 120, 100, 80, 80, 100, 120, 140,
996 120, 100, 80, 60, 60, 80, 100, 120,
997 100, 80, 60, 40, 40, 60, 80, 100,
998 100, 80, 60, 40, 40, 60, 80, 100,
999 120, 100, 80, 60, 60, 80, 100, 120,
1000 140, 120, 100, 80, 80, 100, 120, 140,
1001 160, 140, 120, 100, 100, 120, 140, 160
1005 /* for KING vs KING, KNIGHT, BISHOP */
1006 static int b_n_mate_dark_squares[64] = {
1007 99, 90, 80, 70, 60, 50, 40, 30,
1008 90, 80, 70, 60, 50, 40, 30, 40,
1009 80, 70, 60, 50, 40, 30, 40, 50,
1010 70, 60, 50, 40, 30, 40, 50, 60,
1011 60, 50, 40, 30, 40, 50, 60, 70,
1012 50, 40, 30, 40, 50, 60, 70, 80,
1013 40, 30, 40, 50, 60, 70, 80, 90,
1014 30, 40, 50, 60, 70, 80, 90, 99
1017 static int b_n_mate_light_squares[64] = {
1018 30, 40, 50, 60, 70, 80, 90, 99,
1019 40, 30, 40, 50, 60, 70, 80, 90,
1020 50, 40, 30, 40, 50, 60, 70, 80,
1021 60, 50, 40, 30, 40, 50, 60, 70,
1022 70, 60, 50, 40, 30, 40, 50, 60,
1023 80, 70, 60, 50, 40, 30, 40, 50,
1024 90, 80, 70, 60, 50, 40, 30, 40,
1025 99, 90, 80, 70, 60, 50, 40, 30
1028 static int
1029 evaluate_mate(int side)
1031 int score = 0;
1032 int xside = 1 ^ side;
1034 if (material_complete[side]) {
1035 score = material_complete[side] + 200;
1037 if (piece_count[side][KNIGHT] == 1 && piece_count[side][BISHOP] == 1) {
1038 if (BISHOPS(side) & BLACKSQUARES)
1039 score += b_n_mate_dark_squares[brd.kings[xside]];
1040 else
1041 score += b_n_mate_light_squares[brd.kings[xside]];
1042 } else {
1043 score += simple_mate_squares[side][brd.kings[xside]];
1044 score -= distance[brd.kings[side]][brd.kings[xside]] * 10;
1047 return score;
1050 static int evaluate_draw_pattern()
1052 /* TODO: add real draw code */
1053 return FALSE;
1056 static int bishop_pair = 50;
1057 static int bishop_pair_correction_more = 5;
1058 static int bishop_pair_correction_less = 2;
1060 /* based on Larry Kaufman's paper */
1061 static void
1062 evaluate_material_imbalances(int side)
1064 /* TODO: more imbalances */
1066 int pc;
1068 /* bishop pair */
1069 if (piece_count[side][BISHOP] > 1) {
1070 side_score[OPENING][side] += bishop_pair;
1071 side_score[ENDGAME][side] += bishop_pair;
1073 /* how many pawns on the board? */
1074 pc = wpc + bpc;
1076 if (pc > 12) {
1077 side_score[OPENING][side] -= (4 - (16 - pc)) * bishop_pair_correction_more;
1078 side_score[ENDGAME][side] -= (4 - (16 - pc)) * bishop_pair_correction_more;
1079 } else if (pc < 8) {
1080 side_score[OPENING][side] += (8 - pc) * bishop_pair_correction_less;
1081 side_score[ENDGAME][side] += (8 - pc) * bishop_pair_correction_less;