1 /***************************************************************************
2 evaluate.cpp - description
4 begin : Wed Mar 13 2002
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
19 #include "evaluations.h"
22 #define DEFENDED_PAWN 4
23 #define PASSED_PAWN 30
24 #define BLOCKED_PASSER 12
25 #define PASSED_PIECE 15
26 #define ATTACKING_PIECE 7
27 #define ATTACKING_PAWN 4
28 #define DEFEND_PASSED_PAWN 13
29 #define CONNECTED_ROOKS 24
30 #define UNDEVELOPED 12
31 #define TWO_BISHOPS 23
33 #define VERY_UNSAFE_KING_LATERAL -16
34 #define UNSAFE_KING_LATERAL -10
35 #define VERY_UNSAFE_KING -23
36 #define UNSAFE_KING -14
38 //------------------------------------------------------
40 const int king_still_to_castle = -115;
42 const int pawn_isulated = -10;
43 const int pawn_isulated_blocked = -17;
44 const int pawn_backward_open_file = -10;
45 const int pawn_backward_blocked = -13;
47 const int queen_value = 960;
48 const int queen_seventh = 9;
49 const int queen_open_file = 7;
50 const int queen_semiopen_file = 5;
52 const int rook_value = 490;
53 const int rook_seventh = 19;
54 const int rook_open_file = 14;
55 const int rook_semiopen_file = 10;
57 const int coupled_pawns[7] = { 2, 4, 8, 10, 8, 4, 2 };
59 const int controlled_bonus[128] = {
67 2,2,2,2,2,2,2,2,ENDL };
69 const int kn_val[128] = {
70 285,289,295,300,300,295,289,285,ENDL,
71 295,303,303,303,303,303,303,295,ENDL,
72 297,303,307,307,307,307,303,297,ENDL,
73 299,303,307,309,309,307,303,299,ENDL,
74 299,303,307,309,309,307,303,299,ENDL,
75 297,303,307,307,307,307,303,297,ENDL,
76 295,303,303,303,303,303,303,295,ENDL,
77 285,289,295,300,300,295,289,285,ENDL
80 const int bsh_val[128] = {
81 312,298,300,307,307,300,298,312,ENDL,
82 311,314,311,311,311,311,314,311,ENDL,
83 312,313,315,314,314,315,313,312,ENDL,
84 312,313,314,315,315,314,313,312,ENDL,
85 312,313,314,315,315,314,313,312,ENDL,
86 312,313,315,314,314,315,313,312,ENDL,
87 311,314,311,311,311,311,314,311,ENDL,
88 312,298,300,307,307,300,298,312,ENDL
91 const int paw_val[128] = {
93 -3,0,1,-15,-15,1,0,-3,ENDL,
94 -2,1,3, 7, 7,3,1,-2,ENDL,
95 -1,2,9,16,16,9,2,-1,ENDL,
96 0,4,11,22,22,11,4,0,ENDL,
97 1,6,13,24,24,13,6,1,ENDL,
98 2,8,15,26,26,15,8,2,ENDL,
102 const int king_safety[128] = {
103 0,0,-20,-120,-120,-25,0,0,ENDL,
104 -1,-4,-50,-150,-150,-50,-4,-1,ENDL,
105 -300,-300,-300,-300,-300,-300,-300,-300,ENDL,
106 -300,-300,-300,-300,-300,-300,-300,-300,ENDL,
107 -300,-300,-300,-300,-300,-300,-300,-300,ENDL,
108 -300,-300,-300,-300,-300,-300,-300,-300,ENDL,
109 -1,-4,-50,-150,-150,-50,-4,-1,ENDL,
110 0,0,-20,-120,-120,-25,0,0,ENDL
113 const int endgame_king_val[128] = {
114 -5,-5,1,2,2,1,-5,-5,ENDL,
115 -5,1,4,6,6,4,1,-5,ENDL,
116 0,4,10,12,12,10,4,0,ENDL,
117 1,6,12,14,14,12,6,1,ENDL,
118 1,6,12,14,14,12,6,1,ENDL,
119 0,4,10,12,12,10,4,0,ENDL,
120 -5,1,4,6,6,4,1,-5,ENDL,
121 -5,-5,1,2,2,1,-5,-5,ENDL
124 const int backward_pawn[8] = { -2, -3, -5, -7, -7, -5, -3, -2 };
125 const int doubled_pawn[8] = { -10, -8, -6, -4, -4, -6, -8, -10 };
127 const int queen_tropism[8] = { 0, 51, 70, 40, 10, 0, 0, 0};
128 const int rook_tropism[8] = { 0, 3, 2, 1, 0, 0, 0, 0};
129 const int knight_tropism[8] = { 0, 10, 7, 5, 2, 0, 0, 0};
130 const int bishop_tropism[8] = { 0, 3, 3, 2, 1, 0, 0, 0};
131 const int rook_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
132 const int knight_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
133 const int bishop_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
135 const int piece_val[] = { 500, 325, 1000, 325, 100, 0 };
139 inline int distance(uint8_t a, uint8_t b)
141 return MAX(ABS(X(a)-X(b)), ABS(Y(a)-Y(b)));
144 int16_t Board::dummy_evaluate()
146 int material[2] = { 0, 0 };
149 for(int col=0;col<2;col++)
151 material[col] += mat_tracking[p++].count * piece_val[i];
153 return material[IS_WHITE(color_to_move)] -
154 material[IS_WHITE(other_color)];
158 int16_t Board::evaluate(uint8_t eng_color, int16_t alpha, int16_t beta)
160 int material[2] = { 0, 0 };
161 int evaluation[2] = { 0, 0 };
162 int king_danger[2] = { 0, 0 };
163 int tropism[2] = { 0, 0 };
166 for(int col=0;col<2;col++)
168 material[col] += mat_tracking[p++].count * piece_val[i];
170 for(int is_white=0;is_white<2;is_white++)
172 uint8_t color = is_white ? WHITE : BLACK;
173 uint8_t othcol = OTHER_COLOR(color);
174 uint8_t up = up_dir[is_white];
175 uint8_t up_left = up+LEFT;
176 uint8_t up_right = up+RIGHT;
177 uint8_t othpawn = PAWN|othcol;
178 uint8_t mypawn = PAWN|color;
179 int mt = (is_white ? +5 : -1);
181 /* Evaluate bishops */
182 for(int i=mat_tracking[BISHOP+mt].count-1;i>=0;i--)
185 uint8_t pos = mat_tracking[BISHOP+mt].pos[i];
187 for(int i=3;i>=0;i--)
189 register uint8_t currpos = pos;
190 register uint8_t currinc = bishmoves[i];
196 if(OUT_OF_BOARD(currpos))
202 uint8_t p1 = currpos + up_left;
203 uint8_t p2 = currpos + up_right;
204 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
205 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
206 v += controlled_bonus[currpos];
211 if(OUT_OF_BOARD(currpos))
214 if(COLOR_OF(data[currpos]) == othcol)
216 uint8_t p1 = currpos + up_left;
217 uint8_t p2 = currpos + up_right;
219 /* give a bonus activity value if attacking a pawn/piece
220 that is not defended by an enemy pawn */
221 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
222 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
223 v += PIECE_OF(data[currpos])==PAWN
224 ? ATTACKING_PAWN : ATTACKING_PIECE;
226 bishop_attack_tropism[distance(currpos, king_pos[1-is_white])];
228 else if(data[currpos] == mypawn)
230 uint8_t x = X(currpos);
231 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
233 /* give a bonus for defending passed pawns */
234 if( (x==0||!line_pawns[1-is_white][x-1].count ||
235 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
236 (x==7||!line_pawns[1-is_white][x+1].count ||
237 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
238 !line_pawns[1-is_white][x].count)
240 v += DEFEND_PASSED_PAWN/2;
245 v = v*3 - UNDEVELOPED*2;
248 tropism[is_white] += bishop_tropism[distance(pos, king_pos[1-is_white])];
250 /* penalize the bishop if there are a lot of pawns around */
251 //v -= 2*(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count);
254 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
255 if( (x==0||!line_pawns[!is_white][x-1].count ||
256 line_pawns[!is_white][x-1].pos[0]>=7-y) &&
257 (x==7||!line_pawns[!is_white][x+1].count ||
258 line_pawns[!is_white][x+1].pos[0]>=7-y) )
261 evaluation[is_white] += v;
263 /* bonus for having both bishops */
264 if(mat_tracking[BISHOP+mt].count == 2)
265 evaluation[is_white] += TWO_BISHOPS;
268 for(int i=mat_tracking[ROOK+mt].count-1;i>=0;i--)
271 uint8_t pos = mat_tracking[ROOK+mt].pos[i];
273 for(int i=3;i>=0;i--)
275 register uint8_t currpos = pos;
276 register uint8_t currinc = rookmoves[i];
282 if(OUT_OF_BOARD(currpos))
288 uint8_t p1 = currpos + up_left;
289 uint8_t p2 = currpos + up_right;
290 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
291 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
292 v += controlled_bonus[currpos];
297 if(OUT_OF_BOARD(currpos))
300 if(COLOR_OF(data[currpos]) == othcol)
302 uint8_t p1 = currpos + up_left;
303 uint8_t p2 = currpos + up_right;
305 /* give a bonus activity value if attacking a pawn/piece
306 that is not defended by an enemy pawn */
307 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
308 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
309 v += PIECE_OF(data[currpos])==PAWN
310 ? ATTACKING_PAWN : ATTACKING_PIECE;
313 rook_attack_tropism[distance(currpos, king_pos[1-is_white])];
315 else if(data[currpos] == mypawn)
317 uint8_t x = X(currpos);
318 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
320 /* give a bonus for defending passed pawns */
321 if( (x==0||!line_pawns[1-is_white][x-1].count ||
322 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
323 (x==7||!line_pawns[1-is_white][x+1].count ||
324 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
325 !line_pawns[1-is_white][x].count)
327 v += DEFEND_PASSED_PAWN;
330 else if((~BISHOP&data[currpos])==(ROOK|color))
331 v += CONNECTED_ROOKS;
334 v = v*3 - UNDEVELOPED*2;
336 /* evaluate less rook activity (more important is
337 if it is on a open/close file)*/
342 if(line_pawns[is_white][X(pos)].count == 0)
344 if(line_pawns[1-is_white][X(pos)].count == 0)
347 v += rook_semiopen_file;
349 if( ROW_OF(pos) == seventh_rank[is_white] )
352 tropism[is_white] += rook_tropism[distance(pos, king_pos[!is_white])];
354 evaluation[is_white] += v;
357 /* Evaluate queen(s) */
358 for(int i=mat_tracking[QUEEN+mt].count-1;i>=0;i--)
361 uint8_t pos = mat_tracking[QUEEN+mt].pos[i];
363 for(int i=7;i>=0;i--)
365 register uint8_t currpos = pos;
366 register uint8_t currinc = kingmoves[i];
372 if(OUT_OF_BOARD(currpos))
377 v += controlled_bonus[currpos];
379 while(!IS_OF_COLOR(data[currpos],othcol));
382 /* evaluate less queen activity, so ratta won't go
383 around with the queen all the time */
386 /* bonus for 7th or open file */
387 if(line_pawns[is_white][X(pos)].count == 0)
389 if(line_pawns[1-is_white][X(pos)].count == 0)
390 v += queen_open_file;
392 v += queen_semiopen_file;
394 if(Y(pos) == (color==WHITE?6:1))
395 v += queen_seventh/2;
398 tropism[is_white] += queen_tropism[distance(pos, king_pos[1-is_white])];
400 if(color == eng_color) v += 17;
402 evaluation[is_white] += v;
405 /* Evaluate knights */
406 for(int i=mat_tracking[KNIGHT+mt].count-1;i>=0;i--)
409 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
410 KnightMove* hm = &knightmoves[pos];
412 for(int i=hm->numm;i>=0;i--)
414 register uint8_t currpos = hm->jump[i];
415 if(IS_OF_COLOR(data[currpos], color))
418 uint8_t p1 = currpos + up_left;
419 uint8_t p2 = currpos + up_right;
421 if((OUT_OF_BOARD(p1) || data[p1]!=othpawn) &&
422 (OUT_OF_BOARD(p2) || data[p2]!=othpawn))
424 v += controlled_bonus[currpos];
426 /* give a bonus activity value if attacking a pawn/piece
427 that is not defended by an enemy pawn */
428 if(IS_OF_COLOR(data[currpos], othcol))
429 v += PIECE_OF(data[currpos])==PAWN
430 ? ATTACKING_PAWN : ATTACKING_PIECE;
435 if(IS_OF_COLOR(data[currpos], othcol))
438 knight_attack_tropism[distance(currpos, king_pos[!is_white])];
440 else if(data[currpos] == mypawn)
442 uint8_t x = X(currpos);
443 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
445 /* give a bonus for defending passed pawns */
446 if( (x==0||!line_pawns[1-is_white][x-1].count ||
447 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
448 (x==7||!line_pawns[1-is_white][x+1].count ||
449 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
450 !line_pawns[1-is_white][x].count)
452 v += DEFEND_PASSED_PAWN/2;
457 v = v*3 - UNDEVELOPED*2;
460 tropism[is_white] += knight_tropism[distance(pos, king_pos[!is_white])];
463 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
464 if( (x==0||!line_pawns[!is_white][x-1].count ||
465 line_pawns[!is_white][x-1].pos[0]>=7-y) &&
466 (x==7||!line_pawns[!is_white][x+1].count ||
467 line_pawns[!is_white][x+1].pos[0]<=7-y) )
470 evaluation[is_white] += v;
474 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
477 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
479 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
481 v += (100 + paw_val[POS_XY(x,y)]);
482 if( (x == 0 || line_pawns[is_white][x-1].count == 0) &&
483 (x == 7 || line_pawns[is_white][x+1].count == 0) )
486 if(COLOR_OF(data[uint8_t(up+pos)]) == othcol)
487 v += pawn_isulated_blocked;
490 if( (x == 0 || line_pawns[is_white][x-1].count == 0
491 || line_pawns[is_white][x-1].pos[0] > y) &&
492 (x == 7 || line_pawns[is_white][x+1].count == 0
493 || line_pawns[is_white][x+1].pos[0] > y) )
495 v += backward_pawn[x];
496 if(!line_pawns[1-is_white][x].count)
497 v += pawn_backward_open_file;
498 if(COLOR_OF(data[uint8_t(up+pos)]) == othcol
499 && PIECE_OF(data[uint8_t(up+pos)]) != PAWN)
500 v += pawn_backward_blocked;
503 if(x!=0 && data[LEFT_OF(pos)]==data[pos])
504 v += MAX(y-1,0)*coupled_pawns[x];
505 if(x!=0 && (data[LEFTUP_OF(pos)]==data[pos] ||
506 data[LEFTDOWN_OF(pos)]==data[pos]))
510 if( (x==0||!line_pawns[1-is_white][x-1].count ||
511 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
512 (x==7||!line_pawns[1-is_white][x+1].count ||
513 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
514 !line_pawns[1-is_white][x].count)
516 if(COLOR_OF(up_dir[is_white]+pos) == othcol)
517 v += MAX(y-2,1)*BLOCKED_PASSER;
519 v += MAX(y-2,1)*PASSED_PAWN;
523 if(line_pawns[is_white][x].count > 1)
524 v += doubled_pawn[x];
526 evaluation[is_white] += v;
530 for(int i=mat_tracking[KING+mt].count-1;i>=0;i--)
533 uint8_t pos = mat_tracking[KING+mt].pos[i];
535 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
537 if( is_white ? !(castle_passing_mask & 0x30) :
538 !(castle_passing_mask & 0xc0) )
540 if(material[!is_white]>=1500)
542 v += king_safety[pos];
543 if((x>=5 || x<=2) && y<=1)
545 uint8_t f = x<=2 ? 2 : 5;
546 uint8_t g = x<=2 ? 1 : 6;
547 uint8_t h = x<=2 ? 0 : 7;
548 uint8_t fpawn = line_pawns[is_white][f].count ? line_pawns[is_white][f].pos[0] : 255;
549 uint8_t gpawn = line_pawns[is_white][g].count ? line_pawns[is_white][g].pos[0] : 255;
550 uint8_t hpawn = line_pawns[is_white][h].count ? line_pawns[is_white][h].pos[0] : 255;
564 if(fpawn==1 && gpawn>=2 && hpawn==1)
566 uint8_t start = POS_XY(x<=2 ? 1 : 6, is_white?1:6);
567 uint8_t defbish = color | BISHOP;
568 if(data[start] == defbish || data[RIGHTUP_OF(start)] == defbish ||
569 data[LEFTUP_OF(start)] == defbish || data[RIGHTDOWN_OF(start)] == defbish ||
570 data[LEFTDOWN_OF(start)] == defbish)
575 if(!line_pawns[is_white][f].count)
577 if(!line_pawns[is_white][g].count)
579 if(!line_pawns[is_white][h].count)
581 if(data[POS_XY(h, is_white?0:7)] == (color | ROOK) ||
582 data[POS_XY(h, is_white?1:6)] == (color | ROOK) )
587 // if((!line_pawns[1-is_white][x-1].count) ||
588 // line_pawns[1-is_white][x-1].pos[0]>=3)
589 // v += VERY_UNSAFE_KING_LATERAL;
590 // if(!line_pawns[is_white][x-1].count ||
591 // line_pawns[is_white][x-1].pos[0]>=2)
592 // v += UNSAFE_KING_LATERAL;
596 // if((!line_pawns[1-is_white][x+1].count) ||
597 // line_pawns[1-is_white][x+1].pos[0]>=3)
598 // v += VERY_UNSAFE_KING_LATERAL;
599 // if(!line_pawns[is_white][x+1].count ||
600 // line_pawns[is_white][x+1].pos[0]>=2)
601 // v += UNSAFE_KING_LATERAL;
603 // if((!line_pawns[1-is_white][x].count) ||
604 // line_pawns[1-is_white][x].pos[0]>=3)
605 // v += VERY_UNSAFE_KING;
606 // if(!line_pawns[is_white][x].count ||
607 // line_pawns[is_white][x].pos[0]>=2)
610 v = v * (material[!is_white]-1500)/1500;
611 // if(color == eng_color)
613 king_danger[is_white] = v;
615 if(material[!is_white]<2400)
616 v += endgame_king_val[pos];
619 v += king_still_to_castle;
621 evaluation[is_white] += v;
626 evaluation[0] += (1500*(evaluation[0]-evaluation[1]))/
627 (2000+material[0]+material[1]);
628 evaluation[0] += tropism[0] * 200 / MAX(200 + king_danger[1], 70);
629 evaluation[1] += tropism[1] * 200 / MAX(200 + king_danger[0], 70);
631 int16_t retv = 5 + evaluation[IS_WHITE(color_to_move)] -
632 evaluation[IS_WHITE(other_color)];
634 // if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
635 // retv += color_to_move == eng_color ? -15 : 15;
636 // else if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
637 // retv += color_to_move == eng_color ? -8 : 8;