Cleaned book/lines.
[rattatechess.git] / evaluate.cpp
blob9baaa133dad28146b2c28abdcc5668791236010c
1 /***************************************************************************
2 evaluate.cpp - description
3 -------------------
4 begin : Wed Mar 13 2002
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
10 * *
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. *
15 * *
16 ***************************************************************************/
18 #include "board.h"
19 #include "evaluations.h"
22 #define PASSED_PAWN 30
23 #define BLOCKED_PASSER 12
24 #define PASSED_PIECE 11
25 #define ATTACKING_PIECE 7
26 #define ATTACKING_PAWN 5
27 #define DEFEND_PASSED_PAWN 13
28 #define CONNECTED_ROOKS 21
29 #define UNDEVELOPED 10
30 #define TWO_BISHOPS 45
32 #define VERY_UNSAFE_KING_LATERAL -16
33 #define UNSAFE_KING_LATERAL -10
34 #define VERY_UNSAFE_KING -23
35 #define UNSAFE_KING -14
37 //------------------------------------------------------
39 const int king_still_to_castle = -120;
41 const int pawn_chain = 5;
42 const int pawn_insula = -18;
43 const int pawn_isulated = -10;
44 const int pawn_isulated_blocked = -17;
45 const int pawn_backward_open_file = -6;
46 const int pawn_backward_blocked = -9;
47 const int pawn_backward[8] = { -2, -3, -5, -7, -7, -5, -3, -2 };
48 const int pawn_doubled[8] = { -7, -5, -3, -2, -2, -3, -5, -7 }; //counted twice
49 const int pawn_duo[7] = { 2, 3, 4, 5, 4, 3, 2 }; //counted x the row, x2, x3, etc
51 const int queen_value = 975;
52 const int queen_seventh = 9;
53 const int queen_open_file = 7;
54 const int queen_semiopen_file = 5;
56 const int rook_value = 500;
57 const int rook_seventh = 19;
58 const int rook_open_file = 14;
59 const int rook_semiopen_file = 10;
62 const int controlled_bonus[128] = {
63 1, 1, 1, 1, 1, 1, 1, 1, ENDL,
64 1, 2, 2, 2, 2, 2, 2, 1, ENDL,
65 1, 2, 3, 3, 3, 3, 2, 1, ENDL,
66 1, 2, 3, 4, 4, 3, 2, 1, ENDL,
67 1, 2, 3, 4, 4, 3, 2, 1, ENDL,
68 1, 2, 3, 3, 3, 3, 2, 1, ENDL,
69 1, 2, 2, 2, 2, 2, 2, 1, ENDL,
70 1, 1, 1, 1, 1, 1, 1, 1, ENDL
73 const int knight_value[128] = {
74 285, 289, 295, 300, 300, 295, 289, 285, ENDL,
75 295, 303, 303, 303, 303, 303, 303, 295, ENDL,
76 297, 303, 307, 307, 307, 307, 303, 297, ENDL,
77 299, 303, 307, 309, 309, 307, 303, 299, ENDL,
78 299, 303, 307, 309, 309, 307, 303, 299, ENDL,
79 297, 303, 307, 307, 307, 307, 303, 297, ENDL,
80 295, 303, 303, 303, 303, 303, 303, 295, ENDL,
81 285, 289, 295, 300, 300, 295, 289, 285, ENDL
84 const int bishop_value[128] = {
85 312, 298, 300, 307, 307, 300, 298, 312, ENDL,
86 311, 314, 311, 311, 311, 311, 314, 311, ENDL,
87 312, 313, 315, 314, 314, 315, 313, 312, ENDL,
88 312, 313, 314, 315, 315, 314, 313, 312, ENDL,
89 312, 313, 314, 315, 315, 314, 313, 312, ENDL,
90 312, 313, 315, 314, 314, 315, 313, 312, ENDL,
91 311, 314, 311, 311, 311, 311, 314, 311, ENDL,
92 312, 298, 300, 307, 307, 300, 298, 312, ENDL
95 const int pawn_value[128] = {
96 0,0,0,0,0,0,0,0,ENDL,
97 -3,0,1,-15,-15,1,0,-3,ENDL,
98 -2,1,3, 7, 7,3,1,-2,ENDL,
99 -1,2,9,16,16,9,2,-1,ENDL,
100 0,4,11,22,22,11,4,0,ENDL,
101 1,6,13,24,24,13,6,1,ENDL,
102 2,8,15,26,26,15,8,2,ENDL,
103 0,0,0,0,0,0,0,0,ENDL
106 const int king_safety[128] = {
107 0, 0, -20,-120,-120, -25, 0, 0, ENDL,
108 -1, -4, -50,-150,-150, -50, -4, -1, ENDL,
109 -300,-300,-300,-300,-300,-300,-300,-300, ENDL,
110 -300,-300,-300,-300,-300,-300,-300,-300, ENDL,
111 -300,-300,-300,-300,-300,-300,-300,-300, ENDL,
112 -300,-300,-300,-300,-300,-300,-300,-300, ENDL,
113 -1, -4, -50,-150,-150, -50, -4, -1, ENDL,
114 0, 0, -20,-120,-120, -25, 0, 0, ENDL
117 const int endgame_king_val[128] = {
118 0, 2, 7, 7, 7, 7, 2, 0, ENDL,
119 2, 11, 19, 19, 19, 19, 11, 2, ENDL,
120 7, 19, 23, 25, 25, 23, 19, 7, ENDL,
121 7, 19, 25, 27, 27, 25, 19, 7, ENDL,
122 7, 19, 25, 27, 27, 25, 19, 7, ENDL,
123 7, 19, 23, 25, 25, 23, 19, 7, ENDL,
124 2, 11, 19, 19, 19, 19, 11, 2, ENDL,
125 0, 2, 7, 7, 7, 7, 2, 0, ENDL
128 const int queen_tropism[8] = { 0, 51, 70, 40, 10, 0, 0, 0};
129 const int rook_tropism[8] = { 0, 3, 2, 1, 0, 0, 0, 0};
130 const int knight_tropism[8] = { 0, 10, 7, 5, 2, 0, 0, 0};
131 const int bishop_tropism[8] = { 0, 3, 3, 2, 1, 0, 0, 0};
132 const int rook_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
133 const int knight_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
134 const int bishop_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
136 const int piece_val[] = { 500, 325, 975, 325, 100, 0 };
140 inline int distance(uint8_t a, uint8_t b)
142 return MAX(ABS(X(a)-X(b)), ABS(Y(a)-Y(b)));
145 int16_t Board::dummy_evaluate()
147 int material[2] = { 0, 0 };
149 int p=0;
150 for(int col=0;col<2;col++)
151 for(int i=0;i<6;i++)
152 material[col] += mat_tracking[p++].count * piece_val[i];
154 return material[IS_WHITE(color_to_move)] -
155 material[IS_WHITE(other_color)];
159 int16_t Board::evaluate(uint8_t eng_color, int16_t alpha, int16_t beta)
161 int material[2] = { 0, 0 };
162 int evaluation[2] = { 0, 0 };
163 int king_danger[2] = { 0, 0 };
164 int tropism[2] = { 0, 0 };
166 int p=0;
167 for(int col=0;col<2;col++)
168 for(int i=0;i<6;i++)
169 material[col] += mat_tracking[p++].count * piece_val[i];
171 // int matval = 15 + material[IS_WHITE(color_to_move)] -
172 // material[IS_WHITE(other_color)];
173 // if(matval > beta+200)
174 // return beta;
175 // if(matval < alpha-200)
176 // return alpha;
178 for(int is_white=0;is_white<2;is_white++)
180 uint8_t color = is_white ? WHITE : BLACK;
181 uint8_t othcol = OTHER_COLOR(color);
182 uint8_t up = up_dir[is_white];
183 uint8_t up_left = up+LEFT;
184 uint8_t up_right = up+RIGHT;
185 uint8_t othpawn = PAWN|othcol;
186 uint8_t mypawn = PAWN|color;
187 int mt = (is_white ? +5 : -1);
189 /* Evaluate bishops */
190 for(int i=mat_tracking[BISHOP+mt].count-1;i>=0;i--)
192 int16_t v = 0;
193 uint8_t pos = mat_tracking[BISHOP+mt].pos[i];
195 for(int i=3;i>=0;i--)
197 register uint8_t currpos = pos;
198 register uint8_t currinc = bishmoves[i];
200 while(1)
202 currpos += currinc;
204 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos]) == color)
205 break;
207 v += controlled_bonus[currpos];
209 if(data[currpos])
210 break;
213 if(OUT_OF_BOARD(currpos))
214 continue;
216 if(COLOR_OF(data[currpos]) == othcol)
218 uint8_t p1 = currpos + up_left;
219 uint8_t p2 = currpos + up_right;
221 /* give a bonus activity value if attacking a pawn/piece
222 that is not defended by an enemy pawn */
223 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
224 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
225 v += PIECE_OF(data[currpos])==PAWN
226 ? ATTACKING_PAWN : ATTACKING_PIECE;
227 tropism[is_white] +=
228 bishop_attack_tropism[distance(currpos, king_pos[1-is_white])];
230 else if(data[currpos] == mypawn)
232 uint8_t x = X(currpos);
233 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
235 /* give a bonus for defending passed pawns */
236 if( (x==0||!line_pawns[1-is_white][x-1].count ||
237 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
238 (x==7||!line_pawns[1-is_white][x+1].count ||
239 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
240 !line_pawns[1-is_white][x].count)
242 v += DEFEND_PASSED_PAWN/2;
246 if(v<UNDEVELOPED)
247 v = v*3 - UNDEVELOPED*2;
249 v += bishop_value[pos];
250 tropism[is_white] += bishop_tropism[distance(pos, king_pos[1-is_white])];
252 /* penalize the bishop if there are a lot of pawns around */
253 //v -= 2*(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count);
255 uint8_t x = X(pos);
256 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
257 if( (x==0||!line_pawns[!is_white][x-1].count ||
258 line_pawns[!is_white][x-1].pos[0]>=7-y) &&
259 (x==7||!line_pawns[!is_white][x+1].count ||
260 line_pawns[!is_white][x+1].pos[0]>=7-y) )
261 v += PASSED_PIECE;
263 evaluation[is_white] += v;
265 /* bonus for having both bishops */
266 if(mat_tracking[BISHOP+mt].count == 2)
267 evaluation[is_white] += TWO_BISHOPS;
269 /* Evaluate rooks */
270 for(int i=mat_tracking[ROOK+mt].count-1;i>=0;i--)
272 int16_t v = 0;
273 uint8_t pos = mat_tracking[ROOK+mt].pos[i];
275 for(int i=3;i>=0;i--)
277 register uint8_t currpos = pos;
278 register uint8_t currinc = rookmoves[i];
280 while(1)
282 currpos += currinc;
284 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos]) == color)
285 break;
287 v += controlled_bonus[currpos];
289 if(data[currpos])
290 break;
293 if(OUT_OF_BOARD(currpos))
294 continue;
296 if(COLOR_OF(data[currpos]) == othcol)
298 uint8_t p1 = currpos + up_left;
299 uint8_t p2 = currpos + up_right;
301 /* give a bonus activity value if attacking a pawn/piece
302 that is not defended by an enemy pawn */
303 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
304 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
305 v += PIECE_OF(data[currpos])==PAWN
306 ? ATTACKING_PAWN : ATTACKING_PIECE;
308 tropism[is_white] +=
309 rook_attack_tropism[distance(currpos, king_pos[1-is_white])];
311 else if(data[currpos] == mypawn)
313 uint8_t x = X(currpos);
314 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
316 /* give a bonus for defending passed pawns */
317 if( (x==0||!line_pawns[1-is_white][x-1].count ||
318 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
319 (x==7||!line_pawns[1-is_white][x+1].count ||
320 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
321 !line_pawns[1-is_white][x].count)
323 v += DEFEND_PASSED_PAWN;
326 else if((~BISHOP&data[currpos])==(ROOK|color))
327 v += CONNECTED_ROOKS;
329 if(v<UNDEVELOPED)
330 v = v*3 - UNDEVELOPED*2;
332 /* evaluate less rook activity (more important is
333 if it is on a open/close file)*/
334 v /= 2;
336 v += rook_value;
337 v += (10 - mat_tracking[PAWN-1].count - mat_tracking[PAWN+5].count)*100/32;
339 if(line_pawns[is_white][X(pos)].count == 0)
341 if(line_pawns[1-is_white][X(pos)].count == 0)
342 v += rook_open_file;
343 else
344 v += rook_semiopen_file;
346 if( ROW_OF(pos) == seventh_rank[is_white] )
347 v += rook_seventh;
349 tropism[is_white] += rook_tropism[distance(pos, king_pos[!is_white])];
351 evaluation[is_white] += v;
354 /* Evaluate queen(s) */
355 for(int i=mat_tracking[QUEEN+mt].count-1;i>=0;i--)
357 int16_t v = 0;
358 uint8_t pos = mat_tracking[QUEEN+mt].pos[i];
360 for(int i=7;i>=0;i--)
362 register uint8_t currpos = pos;
363 register uint8_t currinc = kingmoves[i];
367 currpos += currinc;
369 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos])==color)
370 break;
372 v += controlled_bonus[currpos];
374 if(data[currpos])
375 break;
377 while(!IS_OF_COLOR(data[currpos],othcol));
380 /* evaluate less queen activity, so ratta won't go
381 around with the queen all the time */
382 v /= 8;
384 /* bonus for 7th or open file */
385 if(line_pawns[is_white][X(pos)].count == 0)
387 if(line_pawns[1-is_white][X(pos)].count == 0)
388 v += queen_open_file;
389 else
390 v += queen_semiopen_file;
392 if(Y(pos) == (color==WHITE?6:1))
393 v += queen_seventh/2;
395 v += queen_value;
396 tropism[is_white] += queen_tropism[distance(pos, king_pos[1-is_white])];
398 if(color == eng_color) v += 17;
400 evaluation[is_white] += v;
403 /* Evaluate knights */
404 for(int i=mat_tracking[KNIGHT+mt].count-1;i>=0;i--)
406 int16_t v = 0;
407 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
408 KnightMove* hm = &knightmoves[pos];
410 for(int i=hm->numm;i>=0;i--)
412 register uint8_t currpos = hm->jump[i];
413 if(IS_OF_COLOR(data[currpos], color))
414 continue;
416 v += controlled_bonus[currpos];
418 if(IS_OF_COLOR(data[currpos], othcol))
420 uint8_t p1 = currpos + up_left;
421 uint8_t p2 = currpos + up_right;
423 if((OUT_OF_BOARD(p1) || data[p1]!=othpawn) &&
424 (OUT_OF_BOARD(p2) || data[p2]!=othpawn))
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;
433 tropism[is_white] +=
434 knight_attack_tropism[distance(currpos, king_pos[!is_white])];
436 else if(data[currpos] == mypawn)
438 uint8_t x = X(currpos);
439 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
441 /* give a bonus for defending passed pawns */
442 if( (x==0||!line_pawns[1-is_white][x-1].count ||
443 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
444 (x==7||!line_pawns[1-is_white][x+1].count ||
445 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
446 !line_pawns[1-is_white][x].count)
448 v += DEFEND_PASSED_PAWN/2;
452 if(v<UNDEVELOPED)
453 v = v*3 - UNDEVELOPED*2;
455 v += knight_value[pos];
456 v += (mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count-2)*100/32;
457 tropism[is_white] += knight_tropism[distance(pos, king_pos[!is_white])];
459 uint8_t x = X(pos);
460 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
461 if( (x==0||!line_pawns[!is_white][x-1].count ||
462 line_pawns[!is_white][x-1].pos[0]>=7-y) &&
463 (x==7||!line_pawns[!is_white][x+1].count ||
464 line_pawns[!is_white][x+1].pos[0]<=7-y) )
465 v += PASSED_PIECE;
467 evaluation[is_white] += v;
470 /* Evaluate pawns */
471 bool p = false;
472 for(int x=0;x<8;x++)
474 bool nextp = !!line_pawns[is_white][x].count;
475 if(nextp && !p)
476 evaluation[is_white] += pawn_insula;
477 p = nextp;
480 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
482 int16_t v = 0;
483 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
484 uint8_t x = X(pos);
485 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
487 v += (100 + pawn_value[POS_XY(x,y)]);
489 /* isulated pawn malus */
490 #if 0
491 if( (x == 0 || line_pawns[is_white][x-1].count == 0) &&
492 (x == 7 || line_pawns[is_white][x+1].count == 0) )
494 v += pawn_isulated;
495 if(COLOR_OF(data[uint8_t(up+pos)]) == othcol)
496 v += pawn_isulated_blocked;
498 #endif
500 /* backward pawn malus */
501 if( (x == 0 || line_pawns[is_white][x-1].count == 0
502 || line_pawns[is_white][x-1].pos[0] > y) &&
503 (x == 7 || line_pawns[is_white][x+1].count == 0
504 || line_pawns[is_white][x+1].pos[0] > y) )
506 v += pawn_backward[x];
507 if(!line_pawns[!is_white][x].count)
508 v += pawn_backward_open_file;
509 if(data[I(up+pos)])
510 v += pawn_backward_blocked;
513 if(x!=0 && data[LEFT_OF(pos)]==data[pos])
514 v += pawn_duo[x]*(y+2)/2;
515 if(x!=0 && (data[LEFTUP_OF(pos)]==data[pos] ||
516 data[LEFTDOWN_OF(pos)]==data[pos]))
517 v += pawn_chain;
519 /* passed pawn */
520 if( (x==0||!line_pawns[1-is_white][x-1].count ||
521 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
522 (x==7||!line_pawns[1-is_white][x+1].count ||
523 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
524 (!line_pawns[1-is_white][x].count||line_pawns[1-is_white][x].pos[0]>7-y) )
526 if(COLOR_OF(up_dir[is_white]+pos) == othcol)
527 v += MAX(y-2,1)*BLOCKED_PASSER;
528 else
529 v += MAX(y-2,1)*PASSED_PAWN;
532 /* doubled pawns */
533 if(line_pawns[is_white][x].count > 1)
534 v += pawn_doubled[x];
536 evaluation[is_white] += v;
539 /* Evaluate king */
540 for(int i=mat_tracking[KING+mt].count-1;i>=0;i--)
542 int16_t v = 0;
543 uint8_t pos = mat_tracking[KING+mt].pos[i];
544 uint8_t x = X(pos);
545 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
547 if( is_white ? !(castle_passing_mask & 0x30) :
548 !(castle_passing_mask & 0xc0) )
550 if(material[!is_white]>=1500)
552 v += king_safety[pos];
553 if((x>=5 || x<=2) && y<=1)
555 uint8_t f = x<=2 ? 2 : 5;
556 uint8_t g = x<=2 ? 1 : 6;
557 uint8_t h = x<=2 ? 0 : 7;
558 uint8_t fpawn = line_pawns[is_white][f].count ? line_pawns[is_white][f].pos[0] : 255;
559 uint8_t gpawn = line_pawns[is_white][g].count ? line_pawns[is_white][g].pos[0] : 255;
560 uint8_t hpawn = line_pawns[is_white][h].count ? line_pawns[is_white][h].pos[0] : 255;
562 if(fpawn >= 3)
563 v += -12;
564 else
565 v += -4;
566 if(gpawn >= 3)
567 v += -15;
568 else
569 v += -8;
570 if(hpawn >= 3)
571 v += -13;
572 else
573 v += -6;
574 if(fpawn==1 && gpawn>=2 && hpawn==1)
576 uint8_t start = POS_XY(x<=2 ? 1 : 6, is_white?1:6);
577 uint8_t defbish = color | BISHOP;
578 if(data[start] == defbish || data[RIGHTUP_OF(start)] == defbish ||
579 data[LEFTUP_OF(start)] == defbish || data[RIGHTDOWN_OF(start)] == defbish ||
580 data[LEFTDOWN_OF(start)] == defbish)
581 v += 5;
582 else
583 v += -13;
585 if(!line_pawns[is_white][f].count)
586 v += -10;
587 if(!line_pawns[is_white][g].count)
588 v += -16;
589 if(!line_pawns[is_white][h].count)
590 v += -16;
591 if(data[POS_XY(h, is_white?0:7)] == (color | ROOK) ||
592 data[POS_XY(h, is_white?1:6)] == (color | ROOK) )
593 v += -80;
595 else if((x<5 && x>2) && y<=1)
597 if(!line_pawns[is_white][x].count)
598 v += -26;
599 if(!line_pawns[is_white][7-x].count)
600 v += -16;
603 v = v * (MIN(material[!is_white], 2400)-1500)/900;
604 king_danger[is_white] = v;
606 if(material[!is_white]<2400)
607 v += endgame_king_val[pos] * (2400 - MAX(material[!is_white], 1500) )/900;
609 else
610 v += king_still_to_castle;
612 evaluation[is_white] += v;
617 evaluation[0] += (1500*(evaluation[0]-evaluation[1]))/
618 (2000+material[0]+material[1]);
619 evaluation[0] += tropism[0] * 200 / MAX(200 + king_danger[1], 50);
620 evaluation[1] += tropism[1] * 200 / MAX(200 + king_danger[0], 50);
622 int16_t retv = 15 + evaluation[IS_WHITE(color_to_move)] -
623 evaluation[IS_WHITE(other_color)];
625 // if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
626 // retv += color_to_move == eng_color ? -15 : 15;
627 // else if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
628 // retv += color_to_move == eng_color ? -8 : 8;
630 return retv;