Various tunings.
[rattatechess.git] / evaluate.cpp
blob40c60004f4a7f3fd2ab3439914aa21f7347786c6
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 23
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 = 960;
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 = 490;
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, 1000, 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 for(int is_white=0;is_white<2;is_white++)
173 uint8_t color = is_white ? WHITE : BLACK;
174 uint8_t othcol = OTHER_COLOR(color);
175 uint8_t up = up_dir[is_white];
176 uint8_t up_left = up+LEFT;
177 uint8_t up_right = up+RIGHT;
178 uint8_t othpawn = PAWN|othcol;
179 uint8_t mypawn = PAWN|color;
180 int mt = (is_white ? +5 : -1);
182 /* Evaluate bishops */
183 for(int i=mat_tracking[BISHOP+mt].count-1;i>=0;i--)
185 int16_t v = 0;
186 uint8_t pos = mat_tracking[BISHOP+mt].pos[i];
188 for(int i=3;i>=0;i--)
190 register uint8_t currpos = pos;
191 register uint8_t currinc = bishmoves[i];
193 while(1)
195 currpos += currinc;
197 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos]) == color)
198 break;
200 v += controlled_bonus[currpos];
202 if(data[currpos])
203 break;
206 if(OUT_OF_BOARD(currpos))
207 continue;
209 if(COLOR_OF(data[currpos]) == othcol)
211 uint8_t p1 = currpos + up_left;
212 uint8_t p2 = currpos + up_right;
214 /* give a bonus activity value if attacking a pawn/piece
215 that is not defended by an enemy pawn */
216 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
217 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
218 v += PIECE_OF(data[currpos])==PAWN
219 ? ATTACKING_PAWN : ATTACKING_PIECE;
220 tropism[is_white] +=
221 bishop_attack_tropism[distance(currpos, king_pos[1-is_white])];
223 else if(data[currpos] == mypawn)
225 uint8_t x = X(currpos);
226 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
228 /* give a bonus for defending passed pawns */
229 if( (x==0||!line_pawns[1-is_white][x-1].count ||
230 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
231 (x==7||!line_pawns[1-is_white][x+1].count ||
232 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
233 !line_pawns[1-is_white][x].count)
235 v += DEFEND_PASSED_PAWN/2;
239 if(v<UNDEVELOPED)
240 v = v*3 - UNDEVELOPED*2;
242 v += bishop_value[pos];
243 tropism[is_white] += bishop_tropism[distance(pos, king_pos[1-is_white])];
245 /* penalize the bishop if there are a lot of pawns around */
246 //v -= 2*(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count);
248 uint8_t x = X(pos);
249 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
250 if( (x==0||!line_pawns[!is_white][x-1].count ||
251 line_pawns[!is_white][x-1].pos[0]>=7-y) &&
252 (x==7||!line_pawns[!is_white][x+1].count ||
253 line_pawns[!is_white][x+1].pos[0]>=7-y) )
254 v += PASSED_PIECE;
256 evaluation[is_white] += v;
258 /* bonus for having both bishops */
259 if(mat_tracking[BISHOP+mt].count == 2)
260 evaluation[is_white] += TWO_BISHOPS;
262 /* Evaluate rooks */
263 for(int i=mat_tracking[ROOK+mt].count-1;i>=0;i--)
265 int16_t v = 0;
266 uint8_t pos = mat_tracking[ROOK+mt].pos[i];
268 for(int i=3;i>=0;i--)
270 register uint8_t currpos = pos;
271 register uint8_t currinc = rookmoves[i];
273 while(1)
275 currpos += currinc;
277 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos]) == color)
278 break;
280 v += controlled_bonus[currpos];
282 if(data[currpos])
283 break;
286 if(OUT_OF_BOARD(currpos))
287 continue;
289 if(COLOR_OF(data[currpos]) == othcol)
291 uint8_t p1 = currpos + up_left;
292 uint8_t p2 = currpos + up_right;
294 /* give a bonus activity value if attacking a pawn/piece
295 that is not defended by an enemy pawn */
296 if( (OUT_OF_BOARD(p1) || data[p1]!=othpawn)
297 && (OUT_OF_BOARD(p2) || data[p2]!=othpawn) )
298 v += PIECE_OF(data[currpos])==PAWN
299 ? ATTACKING_PAWN : ATTACKING_PIECE;
301 tropism[is_white] +=
302 rook_attack_tropism[distance(currpos, king_pos[1-is_white])];
304 else if(data[currpos] == mypawn)
306 uint8_t x = X(currpos);
307 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
309 /* give a bonus for defending passed pawns */
310 if( (x==0||!line_pawns[1-is_white][x-1].count ||
311 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
312 (x==7||!line_pawns[1-is_white][x+1].count ||
313 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
314 !line_pawns[1-is_white][x].count)
316 v += DEFEND_PASSED_PAWN;
319 else if((~BISHOP&data[currpos])==(ROOK|color))
320 v += CONNECTED_ROOKS;
322 if(v<UNDEVELOPED)
323 v = v*3 - UNDEVELOPED*2;
325 /* evaluate less rook activity (more important is
326 if it is on a open/close file)*/
327 v /= 2;
329 v += rook_value;
331 if(line_pawns[is_white][X(pos)].count == 0)
333 if(line_pawns[1-is_white][X(pos)].count == 0)
334 v += rook_open_file;
335 else
336 v += rook_semiopen_file;
338 if( ROW_OF(pos) == seventh_rank[is_white] )
339 v += rook_seventh;
341 tropism[is_white] += rook_tropism[distance(pos, king_pos[!is_white])];
343 evaluation[is_white] += v;
346 /* Evaluate queen(s) */
347 for(int i=mat_tracking[QUEEN+mt].count-1;i>=0;i--)
349 int16_t v = 0;
350 uint8_t pos = mat_tracking[QUEEN+mt].pos[i];
352 for(int i=7;i>=0;i--)
354 register uint8_t currpos = pos;
355 register uint8_t currinc = kingmoves[i];
359 currpos += currinc;
361 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos])==color)
362 break;
364 v += controlled_bonus[currpos];
366 if(data[currpos])
367 break;
369 while(!IS_OF_COLOR(data[currpos],othcol));
372 /* evaluate less queen activity, so ratta won't go
373 around with the queen all the time */
374 v /= 8;
376 /* bonus for 7th or open file */
377 if(line_pawns[is_white][X(pos)].count == 0)
379 if(line_pawns[1-is_white][X(pos)].count == 0)
380 v += queen_open_file;
381 else
382 v += queen_semiopen_file;
384 if(Y(pos) == (color==WHITE?6:1))
385 v += queen_seventh/2;
387 v += queen_value;
388 tropism[is_white] += queen_tropism[distance(pos, king_pos[1-is_white])];
390 if(color == eng_color) v += 17;
392 evaluation[is_white] += v;
395 /* Evaluate knights */
396 for(int i=mat_tracking[KNIGHT+mt].count-1;i>=0;i--)
398 int16_t v = 0;
399 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
400 KnightMove* hm = &knightmoves[pos];
402 for(int i=hm->numm;i>=0;i--)
404 register uint8_t currpos = hm->jump[i];
405 if(IS_OF_COLOR(data[currpos], color))
406 continue;
408 v += controlled_bonus[currpos];
410 if(IS_OF_COLOR(data[currpos], othcol))
412 uint8_t p1 = currpos + up_left;
413 uint8_t p2 = currpos + up_right;
415 if((OUT_OF_BOARD(p1) || data[p1]!=othpawn) &&
416 (OUT_OF_BOARD(p2) || data[p2]!=othpawn))
418 /* give a bonus activity value if attacking a pawn/piece
419 that is not defended by an enemy pawn */
420 if(IS_OF_COLOR(data[currpos], othcol))
421 v += PIECE_OF(data[currpos])==PAWN
422 ? ATTACKING_PAWN : ATTACKING_PIECE;
425 tropism[is_white] +=
426 knight_attack_tropism[distance(currpos, king_pos[!is_white])];
428 else if(data[currpos] == mypawn)
430 uint8_t x = X(currpos);
431 uint8_t y = is_white ? Y(currpos) : 7-Y(currpos);
433 /* give a bonus for defending passed pawns */
434 if( (x==0||!line_pawns[1-is_white][x-1].count ||
435 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
436 (x==7||!line_pawns[1-is_white][x+1].count ||
437 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
438 !line_pawns[1-is_white][x].count)
440 v += DEFEND_PASSED_PAWN/2;
444 if(v<UNDEVELOPED)
445 v = v*3 - UNDEVELOPED*2;
447 v += knight_value[pos];
448 tropism[is_white] += knight_tropism[distance(pos, king_pos[!is_white])];
450 uint8_t x = X(pos);
451 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
452 if( (x==0||!line_pawns[!is_white][x-1].count ||
453 line_pawns[!is_white][x-1].pos[0]>=7-y) &&
454 (x==7||!line_pawns[!is_white][x+1].count ||
455 line_pawns[!is_white][x+1].pos[0]<=7-y) )
456 v += PASSED_PIECE;
458 evaluation[is_white] += v;
461 /* Evaluate pawns */
462 bool p = false;
463 for(int x=0;x<8;x++)
465 bool nextp = !!line_pawns[is_white][x].count;
466 if(nextp && !p)
467 evaluation[is_white] += pawn_insula;
468 p = nextp;
471 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
473 int16_t v = 0;
474 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
475 uint8_t x = X(pos);
476 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
478 v += (100 + pawn_value[POS_XY(x,y)]);
480 /* isulated pawn malus */
481 #if 0
482 if( (x == 0 || line_pawns[is_white][x-1].count == 0) &&
483 (x == 7 || line_pawns[is_white][x+1].count == 0) )
485 v += pawn_isulated;
486 if(COLOR_OF(data[uint8_t(up+pos)]) == othcol)
487 v += pawn_isulated_blocked;
489 #endif
491 /* backward pawn malus */
492 if( (x == 0 || line_pawns[is_white][x-1].count == 0
493 || line_pawns[is_white][x-1].pos[0] > y) &&
494 (x == 7 || line_pawns[is_white][x+1].count == 0
495 || line_pawns[is_white][x+1].pos[0] > y) )
497 v += pawn_backward[x];
498 if(!line_pawns[!is_white][x].count)
499 v += pawn_backward_open_file;
500 if(data[I(up+pos)])
501 v += pawn_backward_blocked;
504 if(x!=0 && data[LEFT_OF(pos)]==data[pos])
505 v += pawn_duo[x]*(y+2)/2;
506 if(x!=0 && (data[LEFTUP_OF(pos)]==data[pos] ||
507 data[LEFTDOWN_OF(pos)]==data[pos]))
508 v += pawn_chain;
510 /* passed pawn */
511 if( (x==0||!line_pawns[1-is_white][x-1].count ||
512 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
513 (x==7||!line_pawns[1-is_white][x+1].count ||
514 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
515 (!line_pawns[1-is_white][x].count||line_pawns[1-is_white][x].pos[0]>7-y) )
517 if(COLOR_OF(up_dir[is_white]+pos) == othcol)
518 v += MAX(y-2,1)*BLOCKED_PASSER;
519 else
520 v += MAX(y-2,1)*PASSED_PAWN;
523 /* doubled pawns */
524 if(line_pawns[is_white][x].count > 1)
525 v += pawn_doubled[x];
527 evaluation[is_white] += v;
530 /* Evaluate king */
531 for(int i=mat_tracking[KING+mt].count-1;i>=0;i--)
533 int16_t v = 0;
534 uint8_t pos = mat_tracking[KING+mt].pos[i];
535 uint8_t x = X(pos);
536 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
538 if( is_white ? !(castle_passing_mask & 0x30) :
539 !(castle_passing_mask & 0xc0) )
541 if(material[!is_white]>=1500)
543 v += king_safety[pos];
544 if((x>=5 || x<=2) && y<=1)
546 uint8_t f = x<=2 ? 2 : 5;
547 uint8_t g = x<=2 ? 1 : 6;
548 uint8_t h = x<=2 ? 0 : 7;
549 uint8_t fpawn = line_pawns[is_white][f].count ? line_pawns[is_white][f].pos[0] : 255;
550 uint8_t gpawn = line_pawns[is_white][g].count ? line_pawns[is_white][g].pos[0] : 255;
551 uint8_t hpawn = line_pawns[is_white][h].count ? line_pawns[is_white][h].pos[0] : 255;
553 if(fpawn >= 3)
554 v += -12;
555 else
556 v += -4;
557 if(gpawn >= 3)
558 v += -15;
559 else
560 v += -8;
561 if(hpawn >= 3)
562 v += -13;
563 else
564 v += -6;
565 if(fpawn==1 && gpawn>=2 && hpawn==1)
567 uint8_t start = POS_XY(x<=2 ? 1 : 6, is_white?1:6);
568 uint8_t defbish = color | BISHOP;
569 if(data[start] == defbish || data[RIGHTUP_OF(start)] == defbish ||
570 data[LEFTUP_OF(start)] == defbish || data[RIGHTDOWN_OF(start)] == defbish ||
571 data[LEFTDOWN_OF(start)] == defbish)
572 v += 5;
573 else
574 v += -13;
576 if(!line_pawns[is_white][f].count)
577 v += -10;
578 if(!line_pawns[is_white][g].count)
579 v += -16;
580 if(!line_pawns[is_white][h].count)
581 v += -16;
582 if(data[POS_XY(h, is_white?0:7)] == (color | ROOK) ||
583 data[POS_XY(h, is_white?1:6)] == (color | ROOK) )
584 v += -80;
586 else if((x<5 && x>2) && y<=1)
588 if(!line_pawns[is_white][x].count)
589 v += -26;
590 if(!line_pawns[is_white][7-x].count)
591 v += -16;
594 v = v * (MIN(material[!is_white], 2400)-1500)/900;
595 king_danger[is_white] = v;
597 if(material[!is_white]<2400)
598 v += endgame_king_val[pos] * (2400 - MAX(material[!is_white], 1500) )/900;
600 else
601 v += king_still_to_castle;
603 evaluation[is_white] += v;
608 evaluation[0] += (1500*(evaluation[0]-evaluation[1]))/
609 (2000+material[0]+material[1]);
610 evaluation[0] += tropism[0] * 200 / MAX(200 + king_danger[1], 50);
611 evaluation[1] += tropism[1] * 200 / MAX(200 + king_danger[0], 50);
613 int16_t retv = 15 + evaluation[IS_WHITE(color_to_move)] -
614 evaluation[IS_WHITE(other_color)];
616 // if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
617 // retv += color_to_move == eng_color ? -15 : 15;
618 // else if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
619 // retv += color_to_move == eng_color ? -8 : 8;
621 return retv;