Replace constant '-1' to NOBODY for side to move
[owl.git] / evaluate.c
blob3200511dfabecddd0e7ec95234fa74f3f139349a
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_score[2][2];
44 static int mobility_score[2][2];
45 static int pawn_score[2][2];
46 static int position_score[2][2];
47 static int side_score[2][2];
49 /* passed pawns bitboard */
50 static uint64_t passers[2];
52 /* bonus for side to move */
53 static int wtm_bonus[2] = {10, 10};
55 /* forward declarations of functions */
56 static void append_scores(void);
57 static void evaluate_pawns(int side);
58 static void evaluate_knights(int side);
59 static void evaluate_bishops(int side);
60 static void evaluate_rooks(int side);
61 static void evaluate_queens(int side);
62 static void evaluate_king(int side);
63 static int evaluate_draw_pattern(void);
64 static int evaluate_mate(int side);
65 static void evaluate_material_imbalances(int side);
66 static void evaluate_blocked_pieces(int side);
67 static void zero_scores(void);
69 static inline void
70 append_scores(void)
72 side_score[OPENING][WHITE] += king_score[OPENING][WHITE] + \
73 mobility_score[OPENING][WHITE] + pawn_score[OPENING][WHITE] + \
74 position_score[OPENING][WHITE];
75 side_score[OPENING][BLACK] += king_score[OPENING][BLACK] +
76 mobility_score[OPENING][BLACK] + pawn_score[OPENING][BLACK] + \
77 position_score[OPENING][BLACK];
78 side_score[ENDGAME][WHITE] += king_score[ENDGAME][WHITE] + \
79 mobility_score[ENDGAME][WHITE] + pawn_score[ENDGAME][WHITE] + \
80 position_score[ENDGAME][WHITE];
81 side_score[ENDGAME][BLACK] += king_score[ENDGAME][BLACK] + \
82 mobility_score[ENDGAME][BLACK] + pawn_score[ENDGAME][BLACK] + \
83 position_score[ENDGAME][BLACK];
86 /* bonus for rook behind passed pawn */
87 static int rook_behind_pp = 30;
89 /* bonus for having more pawns in endgame if there are no pieces
90 on the board */
91 static int more_pawns_bonus = 15;
93 static uint64_t pawn_attacks[2];
95 /* return TRUE if current position is DRAW */
96 int
97 evaluate_draw(void)
99 if (brd.fifty_rule >= 100)
100 return TRUE; /* draw by fifty rule */
102 if (material_pawns[WHITE] || material_pawns[BLACK])
103 return FALSE; /* there are some pawns on the board */
105 /* check for draw by insufficient material */
106 if (((material_complete[WHITE] < piece_value[ROOK]) || \
107 piece_count[WHITE][KNIGHT] == 2) && \
108 ((material_complete[BLACK] < piece_value[ROOK]) || \
109 piece_count[BLACK][KNIGHT] == 2))
110 return TRUE;
112 return FALSE;
115 /* evaluate current position */
116 int
117 evaluate(int alpha, int beta)
119 int score;
120 int mate_score;
121 int side;
122 int xside;
124 assert(alpha >= -MATE_VALUE && beta <= MATE_VALUE);
125 assert(beta > alpha);
127 /* we should find mate position */
128 if ((!material_pawns[WHITE] && !material_complete[BLACK]) || \
129 (!material_pawns[BLACK] && !material_complete[WHITE])) {
130 mate_score = evaluate_mate(WHITE) - evaluate_mate(BLACK);
131 if (mate_score)
132 return brd.wtm ? -mate_score : mate_score;
135 /* check for drawish endgame */
136 if (evaluate_draw_pattern())
137 return 0;
139 #ifdef STATISTIC_COUNTERS
140 counters.evaluations++;
141 #endif
142 zero_scores();
144 side_score[OPENING][WHITE] = material_complete[WHITE];
145 side_score[OPENING][BLACK] = material_complete[BLACK];
146 side_score[ENDGAME][WHITE] = material_complete[WHITE];
147 side_score[ENDGAME][BLACK] = material_complete[BLACK];
149 /* wtm bonus */
150 side_score[OPENING][brd.wtm] += wtm_bonus[OPENING];
151 side_score[ENDGAME][brd.wtm] += wtm_bonus[ENDGAME];
153 pawn_attacks[WHITE] = ((PAWNS(WHITE) & ~file_bit[7]) << 9) | \
154 ((PAWNS(WHITE) & ~file_bit[0]) << 7);
155 pawn_attacks[BLACK] = ((PAWNS(BLACK) & ~file_bit[0]) >> 9) | \
156 ((PAWNS(BLACK) & ~file_bit[7]) >> 7);
158 for (side = WHITE; side <= BLACK; side++) {
159 evaluate_pawns(side);
160 evaluate_knights(side);
161 evaluate_bishops(side);
162 evaluate_rooks(side);
163 evaluate_queens(side);
164 evaluate_king(side);
165 evaluate_material_imbalances(side);
166 evaluate_blocked_pieces(side);
169 /* look for rook behind passer */
170 for (side = WHITE; side <= BLACK; side++) {
171 int square;
172 uint64_t pp;
173 uint64_t bb = ROOKS(side);
175 while (bb) {
176 square = bit_scan_clear(&bb);
177 pp = file_bit[_FILE(square)] & (passers[WHITE] | passers[BLACK]);
178 if (pp) {
179 if (side == WHITE) {
180 if (_RANK(bit_scan(pp)) > _RANK(square))
181 position_score[ENDGAME][side] += rook_behind_pp;
182 } else {
183 if (_RANK(bit_scan(pp)) < _RANK(square))
184 position_score[ENDGAME][side] += rook_behind_pp;
190 /* bonus for having more pawns if there are now pieces on the board */
191 if (!material_pieces[WHITE] && !material_pieces[BLACK])
192 side_score[ENDGAME][WHITE] += (wpc - bpc) * more_pawns_bonus;
194 append_scores();
196 /* bishop of opposite colours */
197 if (wqc + wrc + wnc + bqc + brc + bnc == 0 && wbc == 1 && \
198 bbc == 1 && abs(wpc - bpc) <= 2) {
199 if (popcount((BISHOPS(WHITE) | BISHOPS(BLACK)) & WHITESQUARES) == 1) {
200 side_score[ENDGAME][WHITE] /= 2;
201 side_score[ENDGAME][BLACK] /= 2;
205 /* get final score according to game phase */
206 score = (OPENING_SCORE * (256 - GAME_PHASE) + \
207 ENDGAME_SCORE * GAME_PHASE) / 256;
208 assert(score >= -MATE_VALUE && score <= MATE_VALUE);
210 side = brd.wtm;
211 xside = 1 ^ side;
213 /* can't win if we have two knights or a bishop and no pawns
214 (but theoretically we can, for example so called 'cooperative mate') */
215 if (score > 0 && !material_pawns[side] && \
216 ((material_pieces[side] < piece_value[ROOK]) || \
217 (KNIGHTS(side) == r_pieces[side]))) {
218 score = 0;
219 } else if (score < 0 && !material_pawns[xside] && \
220 ((material_pieces[xside] < piece_value[ROOK]) || \
221 (KNIGHTS(xside) == r_pieces[xside]))) {
222 score = 0;
225 if (wqc == bqc && wrc == brc && abs(wbc + wnc - bbc - bnc) < 2) {
226 if (!wpc && !bpc) {
227 /* no pawns and one side is ahead by minor piece */
228 score /= 2;
229 } else {
230 if (score > 0) {
231 if (side == WHITE && (wbc + wnc - bbc - bnc == 1) && !wpc && bpc) {
232 score /= bpc + 1;
233 } else if (side == BLACK && (bbc + bnc - wbc - wnc == 1) && !bpc && wpc) {
234 score /= wpc + 1;
240 /* ROOK vs [KNIGHT|BISHOP] + (PAWN)? */
241 if ((material_pieces[WHITE] == piece_value[ROOK] && !wpc) && \
242 ((material_pieces[BLACK] == piece_value[KNIGHT] && bpc <= 1) || \
243 (material_pieces[BLACK] == piece_value[BISHOP] && bpc <= 1)))
244 score /= 8;
245 else if ((material_pieces[BLACK] == piece_value[ROOK] && !bpc) && \
246 ((material_pieces[WHITE] == piece_value[KNIGHT] && wpc <= 1) || \
247 (material_pieces[WHITE] == piece_value[BISHOP] && wpc <= 1)))
248 score /= 8;
250 return score;
253 static int pawn_square_op[2][64] = {
255 -15, -5, 0, 5, 5, 0, -5, -15,
256 -15, -5, 0, 5, 5, 0, -5, -15,
257 -15, -5, 0, 15, 15, 0, -5, -15,
258 -15, -5, 0, 25, 25, 0, -5, -15,
259 -15, -5, 0, 15, 15, 0, -5, -15,
260 -15, -5, 0, 5, 5, 0, -5, -15,
261 -15, -5, 0, 5, 5, 0, -5, -15,
262 -15, -5, 0, 5, 5, 0, -5, -15
265 -15, -5, 0, 5, 5, 0, -5, -15,
266 -15, -5, 0, 5, 5, 0, -5, -15,
267 -15, -5, 0, 5, 5, 0, -5, -15,
268 -15, -5, 0, 15, 15, 0, -5, -15,
269 -15, -5, 0, 25, 25, 0, -5, -15,
270 -15, -5, 0, 15, 15, 0, -5, -15,
271 -15, -5, 0, 5, 5, 0, -5, -15,
272 -15, -5, 0, 5, 5, 0, -5, -15
276 static int pawn_square_eg[2][64] = {
278 0, 0, 0, 0, 0, 0, 0, 0,
279 -1, -0, -0, -0, -0, -0, -0, -1,
280 -1, 0, 0, 0, 0, 0, 0, -1,
281 0, 0, 0, 5, 5, 0, 0, 0,
282 0, 5, 5, 10, 10, 5, 5, 0,
283 0, 5, 5, 10, 10, 5, 5, 0,
284 5, 15, 15, 15, 15, 15, 15, 5,
285 0, 0, 0, 0, 0, 0, 0, 0
288 0, 0, 0, 0, 0, 0, 0, 0,
289 5, 15, 15, 15, 15, 15, 15, 5,
290 0, 5, 5, 10, 10, 5, 5, 0,
291 0, 5, 5, 10, 10, 5, 5, 0,
292 0, 0, 0, 5, 5, 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, 0, 0, 0, 0, 0
298 /* bonus for passed pawns */
299 static int passer_score_op[8] = {0, 0, 10, 15, 30, 45, 80, 0};
300 static int passer_score_eg[8] = {0, 0, 20, 35, 60, 10, 160, 0};
301 /* bonus for candidate passers */
302 static int can_passed_score_op[8] = {0, 0, 5, 10, 20, 35, 50, 0};
303 static int can_passed_score_eg[8] = {0, 0, 10, 20, 40, 70, 100, 0};
304 /* penalty for isolated pawns */
305 static int isolated_penalty_op[8] = {-6, -8, -10, -12, -12, -10, -8, -6};
306 static int isolated_penalty_eg[8] = {-7, -10, -14, -20, -20, -14, -10, -7};
307 /* penalty for isolated pawns on open files */
308 static int weak_isolated_penalty_op[8] = {-9, -10, -12, -18, -18, -12, -10, -9};
309 static int weak_isolated_penalty_eg[8] = {-10, -12, -14, -20, -20, -14, -12, -10};
310 /* penalty for doubled pawns */
311 static int doubled_penalty_op[8] = {-6, -8, -10, -12, -12, -10, -8, -6};
312 static int doubled_penalty_eg[8] = {-7, -10, -14, -20, -20, -14, -10, -7};
313 /* penalty for backward pawns */
314 static int backward_penalty_op = -8;
315 static int backward_penalty_eg = -10;
317 static void
318 evaluate_pawns(int side)
320 uint64_t b, bb;
321 int i;
322 int count;
323 int square;
324 int score_op, score_eg;
325 int xside;
327 int passed;
328 int side_defenders, xside_attackers;
329 struct pawn_hash_entry_t *phe;
331 score_op = 0;
332 score_eg = 0;
333 xside = 1 ^ side;
334 passers[side] = 0ULL;
335 bb = PAWNS(side);
337 phe = pawn_hash[side] + (brd.hash_pawn_key & pawn_hash_mask);
339 if (e.pawn_hash_enabled && phe->key == brd.hash_pawn_key) {
340 score_op = phe->score_op;
341 score_eg = phe->score_eg;
342 passers[side] = phe->passers;
344 counters.pawn_hash_evaluations++;
345 } else {
346 while (bb) {
347 passed = FALSE;
348 square = bit_scan_clear(&bb);
350 /* search passers */
351 if (!(forward_ray[side][square] & PAWNS(side))) {
352 /* this is most advanced pawn */
353 if (!(PAWNS(xside) & passer_mask[side][square])) {
354 /* no opponents pawns on adjacent files */
355 score_op += passer_score_op[rank_flip[side][_RANK(square)]];
356 score_eg += passer_score_eg[rank_flip[side][_RANK(square)]];
358 SET(passers[side], square);
360 passed = TRUE;
362 } else if (!(forward_ray[side][square] & PAWNS(xside))) {
363 /* no opponent's pawns on the same file */
365 /* how many pawns defend our candidate */
366 side_defenders = popcount(pawn_moves[side][square] &
367 PAWNS(xside));
368 /* how many pawns attack our candidate */
369 xside_attackers = popcount(pawn_moves[side][square] & \
370 PAWNS(xside));
372 if (xside_attackers <= side_defenders) {
373 /* pawn is well protected */
375 /* how many pawns can support our candidate */
376 side_defenders = popcount((passer_mask[xside][square + \
377 (side == WHITE? 8 : -8)] & \
378 isolated_mask[_FILE(square)]) & PAWNS(side));
379 /* how many pawns can stop our candidate */
380 xside_attackers = popcount(passer_mask[side][square] & \
381 PAWNS(xside));
383 if (xside_attackers <= side_defenders)
384 /* true passed pawn candidate */
385 score_op += can_passed_score_op[rank_flip[side][_RANK(square)]];
386 score_eg += can_passed_score_eg[rank_flip[side][_RANK(square)]];
390 if (isolated_mask[_FILE(square)] & PAWNS(side)) {
391 /* pawn is not isolated, but maybe backward? */
392 if (!((passer_mask[xside][square + (side == WHITE? 8 : -8)] & \
393 isolated_mask[_FILE(square)]) & PAWNS(side)) && \
394 (rank_flip[side][square] != 1)) {
395 /* pawn is somewhat backward */
396 b = pawn_moves[side][square];
397 if (side == WHITE)
398 b <<= 8;
399 else
400 b >>= 8;
402 if (b & PAWNS(xside)) {
403 /* next square is attacked by opponents pawn */
404 score_op += backward_penalty_op;
405 score_eg += backward_penalty_eg;
407 /* backward on semiopen file */
408 if ((forward_ray[side][square] & PAWNS(xside)) == 0)
409 score_op += backward_penalty_op;
412 } else {
413 if (!passed) {
414 /* pawn is isolated */
415 if (!(forward_ray[side][square] & \
416 (PAWNS(side) | PAWNS(xside)))) {
417 /* isolated on semiopen file */
418 score_op += weak_isolated_penalty_op[_FILE(square)];
419 score_eg += weak_isolated_penalty_eg[_FILE(square)];
420 } else {
421 score_op += isolated_penalty_op[_FILE(square)];
422 score_eg += isolated_penalty_eg[_FILE(square)];
427 score_op += pawn_square_op[side][square];
428 score_eg += pawn_square_eg[side][square];
430 /* store scores in hashtable */
431 if (e.pawn_hash_enabled) {
432 phe->key = brd.hash_pawn_key;
433 phe->score_op = score_op;
434 phe->score_eg = score_eg;
435 phe->passers = passers[side];
439 /* evaluate doubled pawns */
440 for (i = 0; i < 8; i++) {
441 count = popcount(file_bit[i] & PAWNS(side));
442 if (count > 1) {
443 score_op += doubled_penalty_op[i] * (count - 1);
444 score_eg += doubled_penalty_eg[i] * (count - 1);
448 pawn_score[OPENING][side] += score_op;
449 pawn_score[ENDGAME][side] += score_eg;
452 static int knight_square_op[2][64] = {
454 -35, -25, -20, -15, -15, -20, -25, -35,
455 -20, -15, -10, -5, -5, -10, -15, -20,
456 -10, -5, 0, 5, 5, 0, -5, -10,
457 -5, 0, 5, 10, 10, 5, 0, -5,
458 -5, 5, 10, 15, 15, 10, 5, -5,
459 -3, 5, 10, 10, 10, 10, 5, -3,
460 -10, -5, 0, 5, 5, 0, -5, -10,
461 -25, -15, -10, -10, -10, -10, -15, -25
464 -25, -15, -10, -10, -10, -10, -15, -25,
465 -10, -5, 0, 5, 5, 0, -5, -10,
466 -3, 5, 10, 10, 10, 10, 5, -3,
467 -5, 5, 10, 15, 15, 10, 5, -5,
468 -5, 0, 5, 10, 10, 5, 0, -5,
469 -10, -5, 0, 5, 5, 0, -5, -10,
470 -20, -15, -10, -5, -5, -10, -15, -20,
471 -35, -25, -20, -15, -15, -20, -25, -35
475 static int knight_square_eg[64] = {
476 -30, -20, -15, -10, -10, -15, -20, -30,
477 -20, -15, -10, -5, -5, -10, -15, -20,
478 -15, -10, 0, 5, 5, 0, -10, -15,
479 -10, -5, 5, 10, 10, 5, -5, -10,
480 -10, -5, 5, 10, 10, 5, -5, -10,
481 -15, -10, 0, 5, 5, 0, -10, -15,
482 -20, -15, -10, -5, -5, -10, -15, -20,
483 -30, -20, -15, -10, -10, -15, -20, -30
486 static int knight_outpost[2][64] = {
488 0, 0, 0, 0, 0, 0, 0, 0,
489 0, 0, 0, 0, 0, 0, 0, 0,
490 0, 0, 0, 0, 0, 0, 0, 0,
491 0, 5, 9, 15, 15, 9, 5, 0,
492 0, 5, 9, 18, 18, 9, 5, 0,
493 0, 0, 5, 9, 9, 5, 0, 0,
494 0, 0, 0, 0, 0, 0, 0, 0,
495 0, 0, 0, 0, 0, 0, 0, 0
498 0, 0, 0, 0, 0, 0, 0, 0,
499 0, 0, 0, 0, 0, 0, 0, 0,
500 0, 0, 5, 9, 9, 5, 0, 0,
501 0, 5, 9, 18, 18, 9, 5, 0,
502 0, 5, 9, 15, 15, 9, 5, 0,
503 0, 0, 0, 0, 0, 0, 0, 0,
504 0, 0, 0, 0, 0, 0, 0, 0,
505 0, 0, 0, 0, 0, 0, 0, 0
509 static int knight_mobility_op[9] = {-10, -4, 2, 8, 14, 18, 22, 24, 25};
510 static int knight_mobility_eg[9] = {-10, -4, 2, 8, 14, 18, 22, 24, 25};
512 /* evaluate knights */
513 static void
514 evaluate_knights(int side)
516 int square;
517 int xside;
518 int mobility;
519 uint64_t my_knights;
520 uint64_t mobility_xmask;
522 xside = 1 ^ side;
523 my_knights = KNIGHTS(side);
525 if (my_knights)
526 mobility_xmask = ~(side_boards[side] | pawn_attacks[xside]);
528 while (my_knights) {
529 square = bit_scan_clear(&my_knights);
531 /* piece square tables */
532 position_score[OPENING][side] += knight_square_op[side][square];
533 position_score[ENDGAME][side] += knight_square_eg[square];
535 if (knight_outpost[side][square])
536 /* is there enemy pawn that can potentially attack
537 our knight? */
538 if (!(PAWNS(xside) & (passer_mask[side][square] & \
539 isolated_mask[_FILE(square)])))
540 if (pawn_moves[xside][square] & PAWNS(side)) {
541 /* knight is supported by our pawn */
542 position_score[OPENING][side] += knight_outpost[side][square];
543 position_score[ENDGAME][side] += knight_outpost[side][square];
546 /* calculate mobility */
547 mobility = popcount(piece_moves[KNIGHT][square] & mobility_xmask);
548 mobility_score[OPENING][side] += knight_mobility_op[mobility];
549 mobility_score[ENDGAME][side] += knight_mobility_eg[mobility];
553 static int bishop_square_op[2][64] = {
555 -10, -10, -10, -5, -5, -10, -10, -10,
556 -5, -5, -5, 0, 0, -5, -5, -5,
557 -3, -1, 2, 3, 3, 2, -1, -3,
558 -2, 0, 3, 5, 5, 3, 0, -2,
559 -2, 0, 3, 5, 5, 3, 0, -2,
560 -3, -1, 2, 5, 5, 2, -1, -2,
561 -5, -2, 0, 0, 0, 0, -2, -5,
562 -10, -10, -10, -10, -10, -10, -10, -10
565 -10, -10, -10, -10, -10, -10, -10, -10,
566 -5, -2, 0, 0, 0, 0, -2, -5,
567 -3, -1, 2, 5, 5, 2, -1, -2,
568 -2, 0, 3, 5, 5, 3, 0, -2,
569 -2, 0, 3, 5, 5, 3, 0, -2,
570 -3, -1, 2, 3, 3, 2, -1, -3,
571 -5, -5, -5, 0, 0, -5, -5, -5,
572 -10, -10, -10, -5, -5, -10, -10, -10
576 static int bishop_square_eg[64] = {
577 -10, -10, -10, -5, -5, -10, -10, -10,
578 -5, -5, -5, 0, 0, -5, -5, -5,
579 -3, -1, 2, 3, 3, 2, -1, -3,
580 -2, 0, 3, 5, 5, 3, 0, -2,
581 -2, 0, 3, 5, 5, 3, 0, -2,
582 -3, -1, 2, 5, 5, 2, -1, -2,
583 -5, -5, -5, 0, 0, -5, -5, -5,
584 -10, -10, -10, -5, -5, -10, -10, -10
587 static int bishop_mobility_op[16] = {-20, -10, 0, 5, 10, 20, 30, 44, 48, 52, 54, 57, 58, 49, 60, 60};
588 static int bishop_mobility_eg[16] = {-20, -10, 0, 5, 10, 20, 30, 44, 48, 52, 54, 57, 58, 59, 60, 60};
590 /* evaluate bishops */
591 static void
592 evaluate_bishops(int side)
594 int square;
595 int mobility;
596 int xk;
597 int xside;
598 uint64_t attacks;
599 uint64_t mobility_xmask;
600 uint64_t my_bishops;
602 xside = 1 ^ side;
603 xk = brd.kings[xside];
604 my_bishops = BISHOPS(side);
606 if (my_bishops)
607 /* exclude these squares from mobility */
608 mobility_xmask = ~(side_boards[side] | pawn_attacks[xside]);
610 while (my_bishops) {
611 square = bit_scan_clear(&my_bishops);
613 attacks = BISHOP_ATTACKS(square, complete);
615 /* calculate mobility */
616 mobility = popcount(attacks & mobility_xmask);
617 mobility_score[OPENING][side] += bishop_mobility_op[mobility];
618 mobility_score[ENDGAME][side] += bishop_mobility_eg[mobility];
620 position_score[OPENING][side] += bishop_square_op[side][square];
621 position_score[ENDGAME][side] += bishop_square_eg[square];
625 static int rook_on_semiopen_file_op = 10;
626 static int rook_on_semiopen_file_eg = 10;
628 static int rook_on_semiopen_file_near_king_op = 15;
629 static int rook_on_semiopen_file_before_king_op = 20;
631 static int rook_on_open_file_op = 15;
632 static int rook_on_open_file_eg = 15;
634 static int rook_on_seven_rank_op = 20;
635 static int rook_on_seven_rank_eg = 20;
637 static int rook_mobility_op[] = {
638 -12, -8, -4, 0, 4, 8, 11, 14, 16, 18, 19, 20, 21, 22, 23, 24
640 static int rook_mobility_eg[] = {
641 -20, -12, -4, 4, 12, 20, 28, 36, 44, 50, 54, 56, 57, 58, 59, 60
644 static void
645 evaluate_rooks(int side)
647 int xk;
648 int file;
649 int square;
650 int xside;
651 int mobility;
652 uint64_t my_rooks;
653 uint64_t attacks;
654 uint64_t mobility_xmask;
656 my_rooks = ROOKS(side);
657 xside = 1 ^ side; /* opponent's color */
658 xk = brd.kings[xside]; /* location of opponent's king */
660 if (my_rooks)
661 /* exclude these squares from mobility */
662 mobility_xmask = ~(side_boards[side] | pawn_attacks[xside]);
664 while (my_rooks) {
665 square = bit_scan_clear(&my_rooks);
666 file = _FILE(square);
668 if (!(PAWNS(side) & file_bit[file])) {
669 /* there are no our pawns on the rook's file */
670 if (PAWNS(xside) & file_bit[file]) {
671 /* ... but there are opponent's pawns */
672 if (file == (_FILE(xk) - 1) || file == (_FILE(xk) + 1))
673 /* opponent's king is on the adjacent file */
674 position_score[OPENING][side] += rook_on_semiopen_file_near_king_op;
675 else if (file == _FILE(xk))
676 /* opponent's king is on the same file */
677 position_score[OPENING][side] += rook_on_semiopen_file_before_king_op;
678 else {
679 /* rook on semiopen file */
680 position_score[OPENING][side] += rook_on_semiopen_file_op;
681 position_score[ENDGAME][side] += rook_on_semiopen_file_eg;
683 } else {
684 /* rook on open file */
685 position_score[OPENING][side] += rook_on_open_file_op;
686 position_score[ENDGAME][side] += rook_on_open_file_eg;
689 if (rank_flip[side][_RANK(square)] == 6) {
690 /* rook on 7th rank */
691 position_score[OPENING][side] += rook_on_seven_rank_op;
692 position_score[ENDGAME][side] += rook_on_seven_rank_eg;
695 attacks = ROOK_ATTACKS(square, complete);
696 /* calculate mobility */
697 mobility = popcount(attacks & mobility_xmask);
698 mobility_score[OPENING][side] += rook_mobility_op[mobility];
699 mobility_score[ENDGAME][side] += rook_mobility_eg[mobility];
703 /* queen evaluation */
704 static void
705 evaluate_queens(int side)
707 /* TODO: mobility, attacks */
710 static int king_square_op[2][64] = {
712 40, 50, 30, 10, 10, 30, 50, 40,
713 30, 40, 20, 0, 0, 20, 40, 30,
714 10, 20, 0, -20, -20, 0, 20, 10,
715 0, 10, -10, -30, -30, -10, 10, 0,
716 -10, 0, -20, -40, -40, -20, 0, -10,
717 -20, -10, -30, -50, -50, -30, -10, -20,
718 -30, -20, -40, -60, -60, -40, -20, -30,
719 -40, -30, -50, -70, -70, -50, -30, -40
722 -40, -30, -50, -70, -70, -50, -30, -40,
723 -30, -20, -40, -60, -60, -40, -20, -30,
724 -20, -10, -30, -50, -50, -30, -10, -20,
725 -10, 0, -20, -40, -40, -20, 0, -10,
726 0, 10, -10, -30, -30, -10, 10, 0,
727 10, 20, 0, -20, -20, 0, 20, 10,
728 30, 40, 20, 0, 0, 20, 40, 30,
729 40, 50, 30, 10, 10, 30, 50, 40
733 static int king_square_eg[64] = {
734 -72, -48, -36, -24, -24, -36, -48, -72,
735 -48, -24, -12, 0, 0, -12, -24, -48,
736 -36, -12, 0, 12, 12, 0, -12, -36,
737 -24, 0, 12, 24, 24, 12, 0, -24,
738 -24, 0, 12, 24, 24, 12, 0, -24,
739 -36, -12, 0, 12, 12, 0, -12, -36,
740 -48, -24, -12, 0, 0, -12, -24, -48,
741 -72, -48, -36, -24, -24, -36, -48, -72
744 /* evaluate king */
745 static void
746 evaluate_king(int side)
748 int i;
749 int file;
750 int square;
751 int xside;
752 uint64_t bb, xbb;
754 xside = 1 ^ side; /* opponent's side */
755 square = brd.kings[side];
756 file = _FILE(square);
758 /* pawn shield and pawn attacks */
759 bb = passer_mask[side][square] & PAWNS(side);
760 xbb = passer_mask[side][square] & PAWNS(xside);
762 if (file != 0) {
763 /* in case if there is no our pawn */
764 king_score[OPENING][side] += -36;
766 if (bb & file_bit[file - 1]) {
767 /* find nearest pawn */
768 if (side == BLACK)
769 i = bit_scan_rev(bb & file_bit[file - 1]);
770 else
771 i = bit_scan(bb & file_bit[file - 1]);
772 king_score[OPENING][side] += (7 - rank_flip[side][_RANK(i)]) * \
773 (7 - rank_flip[side][_RANK(i)]);
776 /* pawn attack */
777 if (xbb & file_bit[file - 1]) {
778 if (side)
779 i = bit_scan_rev(xbb & file_bit[file - 1]);
780 else
781 i = bit_scan(xbb & file_bit[file - 1]);
782 king_score[OPENING][side] -= MAX(0, (5 - rank_flip[side][_RANK(i)])) * 15;
786 /* in case if there is no our pawn in front of our king */
787 king_score[OPENING][side] += -36;
789 if (bb & file_bit[file]) {
790 if (side == BLACK)
791 i = bit_scan_rev(bb & file_bit[file]);
792 else
793 i = bit_scan(bb & file_bit[file]);
794 king_score[OPENING][side] += (7 - rank_flip[side][_RANK(i)]) * \
795 (7 - rank_flip[side][_RANK(i)]);
798 if (xbb & file_bit[file]) {
799 if (side)
800 i = bit_scan_rev(xbb & file_bit[file]);
801 else
802 i = bit_scan(xbb & file_bit[file]);
803 king_score[OPENING][side] -= MAX(0, (5 - rank_flip[side][_RANK(i)])) * 15;
806 if (file != 7) {
807 /* in case if there is no our pawn */
808 king_score[OPENING][side] += -36;
809 if (bb & file_bit[file + 1]) {
810 /* find nearest pawn */
811 if (side)
812 i = bit_scan_rev(bb & file_bit[file + 1]);
813 else
814 i = bit_scan(bb & file_bit[file + 1]);
815 king_score[OPENING][side] += (7 - rank_flip[side][_RANK(i)]) * \
816 (7 - rank_flip[side][_RANK(i)]);
819 /* pawn attack */
820 if (xbb & file_bit[file + 1]) {
821 if (side)
822 i = bit_scan_rev(xbb & file_bit[file + 1]);
823 else
824 i = bit_scan(xbb & file_bit[file + 1]);
825 king_score[OPENING][side] -= MAX(0, (5 - rank_flip[side][_RANK(i)])) * 15;
829 position_score[OPENING][side] += king_square_op[side][square];
830 position_score[ENDGAME][side] += king_square_eg[square];
833 static int blocked_rook = -50;
834 static int trapped_bishop = -100;
836 static void
837 evaluate_blocked_pieces(int side)
839 int xside = 1 ^ side;
840 int side_inc = side * (A8 - A1);
842 /* rook */
843 if (square64[F1 + side_inc] == KING || square64[G1 + side_inc] == KING) {
844 if (square64[G1 + side_inc] == ROOK || square64[H1 + side_inc] == ROOK)
845 position_score[OPENING][side] += blocked_rook;
846 } else if (square64[C1 + side_inc] == KING || square64[B1 + side_inc] == KING) {
847 if (square64[A1 + side_inc] == ROOK || square64[B1 + side_inc] == ROOK)
848 position_score[OPENING][side] += blocked_rook;
851 int b_sq_a7 = side == WHITE? A7 : A2;
852 int b_sq_h7 = side == WHITE? H7 : H2;
853 int p_sq_b6 = side == WHITE? B6 : B3;
854 int p_sq_g6 = side == WHITE? G6 : G3;
856 if ((BISHOPS(side) & BIT(b_sq_a7)) && (PAWNS(xside) & BIT(p_sq_b6)) && \
857 SEE(SET_FROM(b_sq_a7) | SET_TO(p_sq_b6) | SET_TYPE(TYPE_CAPTURE)) < 0) {
858 position_score[OPENING][side] += trapped_bishop;
859 position_score[ENDGAME][side] += trapped_bishop;
861 if ((BISHOPS(side) & BIT(b_sq_h7)) && (PAWNS(xside) & BIT(p_sq_g6)) && \
862 SEE(SET_FROM(b_sq_h7) | SET_TO(p_sq_g6) | SET_TYPE(TYPE_CAPTURE)) < 0) {
863 position_score[OPENING][side] += trapped_bishop;
864 position_score[ENDGAME][side] += trapped_bishop;
868 /* clear scores */
869 static void
870 zero_scores(void)
872 king_score[OPENING][WHITE] = 0;
873 king_score[OPENING][BLACK] = 0;
874 king_score[ENDGAME][WHITE] = 0;
875 king_score[ENDGAME][BLACK] = 0;
877 mobility_score[OPENING][WHITE] = 0;
878 mobility_score[OPENING][BLACK] = 0;
879 mobility_score[ENDGAME][WHITE] = 0;
880 mobility_score[ENDGAME][BLACK] = 0;
882 pawn_score[OPENING][WHITE] = 0;
883 pawn_score[OPENING][BLACK] = 0;
884 pawn_score[ENDGAME][WHITE] = 0;
885 pawn_score[ENDGAME][BLACK] = 0;
887 position_score[OPENING][WHITE] = 0;
888 position_score[OPENING][BLACK] = 0;
889 position_score[ENDGAME][WHITE] = 0;
890 position_score[ENDGAME][BLACK] = 0;
893 static int simple_mate_squares[2][64] = {
895 160, 140, 120, 100, 100, 120, 140, 160,
896 140, 120, 100, 80, 80, 100, 120, 140,
897 120, 100, 80, 60, 60, 80, 100, 120,
898 100, 80, 60, 40, 40, 60, 80, 100,
899 100, 80, 60, 40, 40, 60, 80, 100,
900 120, 100, 80, 60, 60, 80, 100, 120,
901 140, 120, 100, 80, 80, 100, 120, 140,
902 160, 140, 120, 100, 100, 120, 140, 160
905 160, 140, 120, 100, 100, 120, 140, 160,
906 140, 120, 100, 80, 80, 100, 120, 140,
907 120, 100, 80, 60, 60, 80, 100, 120,
908 100, 80, 60, 40, 40, 60, 80, 100,
909 100, 80, 60, 40, 40, 60, 80, 100,
910 120, 100, 80, 60, 60, 80, 100, 120,
911 140, 120, 100, 80, 80, 100, 120, 140,
912 160, 140, 120, 100, 100, 120, 140, 160
916 /* for KING vs KING, KNIGHT, BISHOP */
917 static int b_n_mate_dark_squares[64] = {
918 99, 90, 80, 70, 60, 50, 40, 30,
919 90, 80, 70, 60, 50, 40, 30, 40,
920 80, 70, 60, 50, 40, 30, 40, 50,
921 70, 60, 50, 40, 30, 40, 50, 60,
922 60, 50, 40, 30, 40, 50, 60, 70,
923 50, 40, 30, 40, 50, 60, 70, 80,
924 40, 30, 40, 50, 60, 70, 80, 90,
925 30, 40, 50, 60, 70, 80, 90, 99
928 static int b_n_mate_light_squares[64] = {
929 30, 40, 50, 60, 70, 80, 90, 99,
930 40, 30, 40, 50, 60, 70, 80, 90,
931 50, 40, 30, 40, 50, 60, 70, 80,
932 60, 50, 40, 30, 40, 50, 60, 70,
933 70, 60, 50, 40, 30, 40, 50, 60,
934 80, 70, 60, 50, 40, 30, 40, 50,
935 90, 80, 70, 60, 50, 40, 30, 40,
936 99, 90, 80, 70, 60, 50, 40, 30
939 static int
940 evaluate_mate(int side)
942 int score = 0;
943 int xside = 1 ^ side;
945 if (material_complete[side]) {
946 score = material_complete[side] + 200;
948 if (piece_count[side][KNIGHT] == 1 && piece_count[side][BISHOP] == 1) {
949 if (BISHOPS(side) & BLACKSQUARES)
950 score += b_n_mate_dark_squares[brd.kings[xside]];
951 else
952 score += b_n_mate_light_squares[brd.kings[xside]];
953 } else {
954 score += simple_mate_squares[side][brd.kings[xside]];
955 score -= distance[brd.kings[side]][brd.kings[xside]] * 10;
958 return score;
961 static int evaluate_draw_pattern()
963 int file, square;
965 /* KBPK routine */
966 if (!material_pieces[BLACK] && bpc <= 1 && material_pawns[WHITE] && \
967 material_pieces[WHITE] == piece_value[BISHOP] && wbc == 1 && \
968 ((PAWNS(WHITE) & file_bit[0]) == PAWNS(WHITE) || (PAWNS(WHITE) & \
969 file_bit[7]) == PAWNS(WHITE))) {
971 square = bit_scan(PAWNS(WHITE));
972 file = _FILE(square);
974 if (file == 0 || file == 7) {
975 /* rook pawn */
976 if (file == 0 && (WHITESQUARES & BISHOPS(WHITE)))
977 return FALSE;
978 if (file == 7 && (BLACKSQUARES & BISHOPS(WHITE)))
979 return FALSE;
980 if (distance[brd.kings[BLACK]][file == 0? A8 : H8] <= 1)
981 return TRUE;
983 } else if (!material_pieces[WHITE] && wpc <= 1 && \
984 material_pieces[BLACK] == piece_value[BISHOP] && bbc == 1 && \
985 ((PAWNS(BLACK) & file_bit[0]) == PAWNS(BLACK) || (PAWNS(BLACK) & \
986 file_bit[7]) == PAWNS(BLACK))) {
987 square = bit_scan(PAWNS(BLACK));
988 file = _FILE(square);
990 if (file == 0 || file == 7) {
991 /* rook pawn */
992 if (file == 0 && (BLACKSQUARES & BISHOPS(BLACK)))
993 return FALSE;
994 if (file == 7 && (WHITESQUARES & BISHOPS(BLACK)))
995 return FALSE;
996 if (distance[brd.kings[WHITE]][file == 0? A1 : H1] <= 1)
997 return TRUE;
1001 return FALSE;
1004 static int bishop_pair = 50;
1005 static int bishop_pair_correction = 15;
1007 /* based on Larry Kaufman's paper */
1008 static void
1009 evaluate_material_imbalances(int side)
1011 /* TODO: more imbalances */
1013 int pc;
1015 /* bishop pair */
1016 if (piece_count[side][BISHOP] > 1) {
1017 side_score[OPENING][side] += bishop_pair;
1018 side_score[ENDGAME][side] += bishop_pair;
1020 /* how many pawns on the board? */
1021 pc = wpc + bpc;
1023 if (pc > 12) {
1024 side_score[OPENING][side] -= bishop_pair_correction;
1025 side_score[ENDGAME][side] -= bishop_pair_correction;
1026 } else if (pc < 8) {
1027 side_score[OPENING][side] += bishop_pair_correction;
1028 side_score[ENDGAME][side] += bishop_pair_correction;