Fixed bug in the search, now no more near-mate values should randomly appear.
[rattatechess.git] / evaluate.cpp
blob84c6c5b59ead9e181ed1a176dc560333caf0d8fe
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 <string.h>
19 #include "board.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;
63 const int pawn_value[128] = {
64 0,0,0,0,0,0,0,0,ENDL,
65 -3,0,1,-15,-15,1,0,-3,ENDL,
66 -2,1,3, 7, 7,3,1,-2,ENDL,
67 -1,2,9,16,16,9,2,-1,ENDL,
68 0,4,11,22,22,11,4,0,ENDL,
69 1,6,13,24,24,13,6,1,ENDL,
70 2,8,15,26,26,15,8,2,ENDL,
71 0,0,0,0,0,0,0,0,ENDL
74 const int endgame_king_val[128] = {
75 0, 2, 7, 7, 7, 7, 2, 0, ENDL,
76 2, 11, 19, 19, 19, 19, 11, 2, ENDL,
77 7, 19, 23, 25, 25, 23, 19, 7, ENDL,
78 7, 19, 25, 27, 27, 25, 19, 7, ENDL,
79 7, 19, 25, 27, 27, 25, 19, 7, ENDL,
80 7, 19, 23, 25, 25, 23, 19, 7, ENDL,
81 2, 11, 19, 19, 19, 19, 11, 2, ENDL,
82 0, 2, 7, 7, 7, 7, 2, 0, ENDL
86 const int queen_tropism[8] = { 0, 51, 70, 40, 10, 0, 0, 0};
87 const int rook_tropism[8] = { 0, 3, 2, 1, 0, 0, 0, 0};
88 const int knight_tropism[8] = { 0, 10, 7, 5, 2, 0, 0, 0};
89 const int bishop_tropism[8] = { 0, 3, 3, 2, 1, 0, 0, 0};
90 const int rook_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
91 const int knight_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
92 const int bishop_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
94 const int piece_val[] = { 500, 325, 975, 325, 100, 0 };
96 inline int distance(uint8_t a, uint8_t b)
98 return MAX(ABS(X(a)-X(b)), ABS(Y(a)-Y(b)));
101 int16_t Board::dummy_evaluate()
103 int material[2] = { 0, 0 };
105 int p=0;
106 for(int col=0;col<2;col++)
107 for(int i=0;i<6;i++)
108 material[col] += mat_tracking[p++].count * piece_val[i];
110 return material[IS_WHITE(color_to_move)] -
111 material[IS_WHITE(other_color)];
114 //--------------------------------------------------------------------------
116 const int piece_value[] = { 0, 500, 325, 975, 325, 100, 0 };
118 const int controlled_bonus[128] =
120 3, 3, 3, 3, 3, 3, 3, 3, ENDL,
121 3, 4, 4, 4, 4, 4, 4, 3, ENDL,
122 3, 4, 5, 5, 5, 5, 4, 3, ENDL,
123 3, 4, 5, 5, 5, 5, 4, 3, ENDL,
124 3, 4, 5, 5, 5, 5, 4, 3, ENDL,
125 3, 4, 5, 5, 5, 5, 4, 3, ENDL,
126 3, 4, 4, 4, 4, 4, 4, 3, ENDL,
127 3, 3, 3, 3, 3, 3, 3, 3, ENDL
130 const int bishop_pair = 50;
132 const int bishop_base = 24;
133 const int bishop_middle = 20;
134 const int bishop_end = 20;
135 const uint16_t bishop_attack = (1<<10)+1;
137 const int knight_base = 16;
138 const int knight_middle = 16;
139 const int knight_end = 16;
140 const uint16_t knight_attack = (1<<10)+1;
142 const int rook_base = 28;
143 const int rook_middle = 8;
144 const int rook_end = 16;
145 const uint16_t rook_attack = (1<<10)+1;
147 const int queen_base = 52;
148 const int queen_middle = 4;
149 const int queen_end = 8;
150 const uint16_t queen_attack = (1<<7)+1;
152 const uint16_t pawn_attack = (1<<14)+1;
154 const uint16_t king_attack = (1<<6)+1;
156 int16_t Board::evaluate(uint8_t eng_color, int16_t alpha, int16_t beta)
158 int evaluation[2] = { 0, 0 };
159 int king_danger[2] = { 0, 0 };
160 int tropism[2] = { 0, 0 };
162 int material[2] = {
163 mat_tracking[PAWN-1].count * piece_value[PAWN] +
164 mat_tracking[QUEEN-1].count * piece_value[QUEEN] +
165 mat_tracking[BISHOP-1].count * piece_value[BISHOP] + ((mat_tracking[BISHOP-1].count >= 2) ? bishop_pair : 0) +
166 mat_tracking[ROOK-1].count * (piece_value[ROOK] + (10 - mat_tracking[PAWN-1].count - mat_tracking[PAWN+5].count)*100/16) +
167 mat_tracking[KNIGHT-1].count * (piece_value[KNIGHT] - (10 - mat_tracking[PAWN-1].count - mat_tracking[PAWN+5].count)*100/32),
168 mat_tracking[PAWN+5].count * piece_value[PAWN] +
169 mat_tracking[QUEEN+5].count * piece_value[QUEEN] +
170 mat_tracking[BISHOP+5].count * piece_value[BISHOP] + ((mat_tracking[BISHOP+5].count >= 2) ? bishop_pair : 0) +
171 mat_tracking[ROOK+5].count * (piece_value[ROOK] + (10 - mat_tracking[PAWN-1].count - mat_tracking[PAWN+5].count)*100/16) +
172 mat_tracking[KNIGHT+5].count * (piece_value[KNIGHT] - (10 - mat_tracking[PAWN-1].count - mat_tracking[PAWN+5].count)*100/32)
174 int activity_middle[2] = { 0, 0 };
175 int activity_end[2] = { 0, 0 };
177 union { uint16_t white[128]; struct { uint16_t pad[8]; uint16_t black[120]; }; } attacks_data;
178 uint16_t* attacks[2] = { attacks_data.white, attacks_data.black };
179 memset(attacks_data.white, 0, 128*sizeof(uint16_t));
181 for(int is_white=0;is_white<2;is_white++)
183 int is_black = !is_white;
184 uint8_t color = is_white ? WHITE : BLACK;
185 uint8_t othcol = OTHER_COLOR(color);
186 uint8_t up = up_dir[is_white];
187 uint8_t up_left = up+LEFT;
188 uint8_t up_right = up+RIGHT;
189 uint8_t othpawn = PAWN|othcol;
190 uint8_t mypawn = PAWN|color;
191 int mt = (is_white ? +5 : -1);
194 /* Evaluate bishops */
195 for(int i=mat_tracking[BISHOP+mt].count-1;i>=0;i--)
197 int16_t v = -bishop_base;
198 uint8_t pos = mat_tracking[BISHOP+mt].pos[i];
200 for(int i=3;i>=0;i--)
202 register uint8_t currpos = pos;
203 register uint8_t currinc = bishmoves[i];
205 while(1)
207 currpos += currinc;
209 if(!OUT_OF_BOARD(currpos))
210 attacks[is_white][currpos] += bishop_attack;
212 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos]) == color)
213 break;
215 v += controlled_bonus[currpos];
217 if(data[currpos])
218 break;
221 if(OUT_OF_BOARD(currpos))
222 continue;
225 activity_middle[is_white] += v * bishop_middle;
226 activity_end[is_white] += v * bishop_end;
230 /* Evaluate rooks */
231 for(int i=mat_tracking[ROOK+mt].count-1;i>=0;i--)
233 int16_t v = -rook_base;
234 uint8_t pos = mat_tracking[ROOK+mt].pos[i];
236 for(int i=3;i>=0;i--)
238 register uint8_t currpos = pos;
239 register uint8_t currinc = rookmoves[i];
241 while(1)
243 currpos += currinc;
245 if(!OUT_OF_BOARD(currpos))
246 attacks[is_white][currpos] += rook_attack;
248 if(OUT_OF_BOARD(currpos) || COLOR_OF(data[currpos]) == color)
249 break;
251 v += controlled_bonus[currpos];
253 if(data[currpos])
254 break;
257 if(OUT_OF_BOARD(currpos))
258 continue;
261 activity_middle[is_white] += v * rook_middle;
262 activity_end[is_white] += v * rook_end;
266 /* Evaluate queens */
267 for(int i=mat_tracking[QUEEN+mt].count-1;i>=0;i--)
269 int16_t v = -queen_base;
270 uint8_t pos = mat_tracking[QUEEN+mt].pos[i];
272 for(int i=7;i>=0;i--)
274 register uint8_t currpos = pos;
275 register uint8_t currinc = kingmoves[i];
277 while(1)
279 currpos += currinc;
281 if(!OUT_OF_BOARD(currpos))
282 attacks[is_white][currpos] += queen_attack;
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;
297 activity_middle[is_white] += v * queen_middle;
298 activity_end[is_white] += v * queen_end;
302 /* Evaluate knights */
303 for(int i=mat_tracking[KNIGHT+mt].count-1;i>=0;i--)
305 int16_t v = -knight_base;
306 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
307 KnightMove* hm = &knightmoves[pos];
309 for(int i=hm->numm;i>=0;i--)
311 register uint8_t currpos = hm->jump[i];
313 attacks[is_white][currpos] += knight_attack;
315 if(IS_OF_COLOR(data[currpos], color))
316 continue;
318 v += controlled_bonus[currpos];
321 activity_middle[is_white] += v * knight_middle;
322 activity_end[is_white] += v * knight_end;
325 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
327 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
328 int x = X(pos);
330 if(x<7)
331 attacks[is_white][I(pos+up_right)] += pawn_attack;
332 if(x>0)
333 attacks[is_white][I(pos+up_left)] += pawn_attack;
336 for(int i=mat_tracking[KING+mt].count-1;i>=0;i--)
338 uint8_t pos = mat_tracking[KING+mt].pos[i];
340 for(int i=7;i>=0;i--)
342 register uint8_t currpos = pos + kingmoves[i];
343 if(!OUT_OF_BOARD(currpos))
344 attacks[is_white][currpos] += king_attack;
349 #if 0
350 for(int y=7;y>=0;y--)
352 for(int is_white = 0;is_white<2;is_white++)
354 for(int x=0;x<8;x++)
355 printf(" % 4x", attacks[is_white][POS_XY(x,y)]);
356 printf("%s", is_white ? "\n" : " ");
359 #endif
361 #define N(x) ((x) & 0x1f)
362 int attackings[2] = { 0, 0 };
364 for(int is_white=0; is_white<2; is_white++)
366 int on_move = IS_WHITE(color_to_move) == is_white;
367 int is_black = !is_white;
368 int mt = (is_white ? +5 : -1);
370 /* Evaluate bishops */
371 for(int i=mat_tracking[BISHOP+mt].count-1;i>=0;i--)
373 uint8_t pos = mat_tracking[BISHOP+mt].pos[i];
374 if(attacks[is_black][pos] >= pawn_attack || attacks[is_black][pos] > attacks[is_white][pos] + bishop_attack)
375 attackings[is_white] += on_move ? -30 : -250;
376 else if(N(attacks[is_black][pos]) >= N(attacks[is_white][pos]) && attacks[is_black][pos] >= attacks[is_white][pos])
377 //else if(attacks[is_black][pos] >= attacks[is_white][pos])
378 attackings[is_white] += -20;
381 /* Evaluate rooks */
382 for(int i=mat_tracking[ROOK+mt].count-1;i>=0;i--)
384 uint8_t pos = mat_tracking[ROOK+mt].pos[i];
385 if(attacks[is_black][pos] >= pawn_attack || attacks[is_black][pos] > attacks[is_white][pos] + bishop_attack)
386 attackings[is_white] += on_move ? -35 : -340;
387 else if(N(attacks[is_black][pos]) >= N(attacks[is_white][pos]) && attacks[is_black][pos] >= attacks[is_white][pos])
388 //else if(attacks[is_black][pos] >= attacks[is_white][pos])
389 attackings[is_white] += -25;
392 /* Evaluate queens */
393 for(int i=mat_tracking[QUEEN+mt].count-1;i>=0;i--)
395 uint8_t pos = mat_tracking[QUEEN+mt].pos[i];
396 if(attacks[is_black][pos] >= bishop_attack)
397 attackings[is_white] += on_move ? -40 : -600;
400 /* Evaluate knights */
401 for(int i=mat_tracking[KNIGHT+mt].count-1;i>=0;i--)
403 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
404 if(attacks[is_black][pos] >= pawn_attack || attacks[is_black][pos] > attacks[is_white][pos] + bishop_attack)
405 attackings[is_white] += on_move ? -30 : -250;
406 else if(N(attacks[is_black][pos]) >= N(attacks[is_white][pos]) && attacks[is_black][pos] >= attacks[is_white][pos])
407 //else if(attacks[is_black][pos] >= attacks[is_white][pos])
408 attackings[is_white] += -20;
411 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
413 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
414 if(attacks[is_black][pos] >= attacks[is_white][pos])
416 if(N(attacks[is_black][pos]) > N(attacks[is_white][pos]))
417 attackings[is_white] += on_move ? -15 : -60;
418 else if(N(attacks[is_black][pos]) == N(attacks[is_white][pos]))
419 attackings[is_white] += -8;
424 int tot_mat = material[0] + material[1];
425 int max_mat = 100*16 + 325*8 + 500*4 + 975*2;
426 int eval[2] = {
427 material[0] + (activity_middle[0]*tot_mat + activity_end[0]*(max_mat-tot_mat))/(16 * max_mat),
428 material[1] + (activity_middle[1]*tot_mat + activity_end[1]*(max_mat-tot_mat))/(16 * max_mat)
431 return 7 + eval[IS_WHITE(color_to_move)] - eval[IS_WHITE(other_color)]
432 + attackings[IS_WHITE(color_to_move)] - attackings[IS_WHITE(other_color)];
435 #if 0
436 /* Evaluate pawns */
437 bool p = false;
438 for(int x=0;x<8;x++)
440 bool nextp = !!line_pawns[is_white][x].count;
441 if(nextp && !p)
442 evaluation[is_white] += pawn_insula;
443 p = nextp;
446 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
448 int16_t v = 0;
449 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
450 uint8_t x = X(pos);
451 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
453 v += (100 + pawn_value[POS_XY(x,y)]);
455 /* isulated pawn malus */
456 #if 0
457 if( (x == 0 || line_pawns[is_white][x-1].count == 0) &&
458 (x == 7 || line_pawns[is_white][x+1].count == 0) )
460 v += pawn_isulated;
461 if(COLOR_OF(data[uint8_t(up+pos)]) == othcol)
462 v += pawn_isulated_blocked;
464 #endif
466 /* backward pawn malus */
467 if( (x == 0 || line_pawns[is_white][x-1].count == 0
468 || line_pawns[is_white][x-1].pos[0] > y) &&
469 (x == 7 || line_pawns[is_white][x+1].count == 0
470 || line_pawns[is_white][x+1].pos[0] > y) )
472 v += pawn_backward[x];
473 if(!line_pawns[!is_white][x].count)
474 v += pawn_backward_open_file;
475 if(data[I(up+pos)])
476 v += pawn_backward_blocked;
479 if(x!=0 && data[LEFT_OF(pos)]==data[pos])
480 v += pawn_duo[x]*(y+2)/2;
481 if(x!=0 && (data[LEFTUP_OF(pos)]==data[pos] ||
482 data[LEFTDOWN_OF(pos)]==data[pos]))
483 v += pawn_chain;
485 /* passed pawn */
486 if( (x==0||!line_pawns[1-is_white][x-1].count ||
487 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
488 (x==7||!line_pawns[1-is_white][x+1].count ||
489 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
490 (!line_pawns[1-is_white][x].count||line_pawns[1-is_white][x].pos[0]>7-y) )
492 if(COLOR_OF(up_dir[is_white]+pos) == othcol)
493 v += MAX(y-2,1)*BLOCKED_PASSER;
494 else
495 v += MAX(y-2,1)*PASSED_PAWN;
498 /* doubled pawns */
499 if(line_pawns[is_white][x].count > 1)
500 v += pawn_doubled[x];
502 evaluation[is_white] += v;
505 /* Evaluate king */
506 for(int i=mat_tracking[KING+mt].count-1;i>=0;i--)
508 int16_t v = 0;
509 uint8_t pos = mat_tracking[KING+mt].pos[i];
510 uint8_t x = X(pos);
511 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
513 if( is_white ? !(castle_passing_mask & 0x30) :
514 !(castle_passing_mask & 0xc0) )
516 if(material[!is_white]>=1500)
518 v += king_safety[pos];
519 if((x>=5 || x<=2) && y<=1)
521 uint8_t f = x<=2 ? 2 : 5;
522 uint8_t g = x<=2 ? 1 : 6;
523 uint8_t h = x<=2 ? 0 : 7;
524 uint8_t fpawn = line_pawns[is_white][f].count ? line_pawns[is_white][f].pos[0] : 255;
525 uint8_t gpawn = line_pawns[is_white][g].count ? line_pawns[is_white][g].pos[0] : 255;
526 uint8_t hpawn = line_pawns[is_white][h].count ? line_pawns[is_white][h].pos[0] : 255;
528 if(fpawn >= 3)
529 v += -12;
530 else
531 v += -4;
532 if(gpawn >= 3)
533 v += -15;
534 else
535 v += -8;
536 if(hpawn >= 3)
537 v += -13;
538 else
539 v += -6;
540 if(fpawn==1 && gpawn>=2 && hpawn==1)
542 uint8_t start = POS_XY(x<=2 ? 1 : 6, is_white?1:6);
543 uint8_t defbish = color | BISHOP;
544 if(data[start] == defbish || data[RIGHTUP_OF(start)] == defbish ||
545 data[LEFTUP_OF(start)] == defbish || data[RIGHTDOWN_OF(start)] == defbish ||
546 data[LEFTDOWN_OF(start)] == defbish)
547 v += 5;
548 else
549 v += -13;
551 if(!line_pawns[is_white][f].count)
552 v += -10;
553 if(!line_pawns[is_white][g].count)
554 v += -16;
555 if(!line_pawns[is_white][h].count)
556 v += -16;
557 if(data[POS_XY(h, is_white?0:7)] == (color | ROOK) ||
558 data[POS_XY(h, is_white?1:6)] == (color | ROOK) )
559 v += -80;
561 else if((x<5 && x>2) && y<=1)
563 if(!line_pawns[is_white][x].count)
564 v += -26;
565 if(!line_pawns[is_white][7-x].count)
566 v += -16;
569 v = v * (MIN(material[!is_white], 2400)-1500)/900;
570 king_danger[is_white] = v;
572 if(material[!is_white]<2400)
573 v += endgame_king_val[pos] * (2400 - MAX(material[!is_white], 1500) )/900;
575 else
576 v += king_still_to_castle;
578 evaluation[is_white] += v;
583 evaluation[0] += (1500*(evaluation[0]-evaluation[1]))/
584 (2000+material[0]+material[1]);
585 evaluation[0] += tropism[0] * 200 / MAX(200 + king_danger[1], 50);
586 evaluation[1] += tropism[1] * 200 / MAX(200 + king_danger[0], 50);
588 int16_t retv = 7 + evaluation[IS_WHITE(color_to_move)] -
589 evaluation[IS_WHITE(other_color)];
591 // if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
592 // retv += color_to_move == eng_color ? -15 : 15;
593 // else if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
594 // retv += color_to_move == eng_color ? -8 : 8;
596 return retv;
598 #endif