Reduce analysis randomness
[rattatechess.git] / evaluate.cpp
bloba1b4711e87849325e63a10afbcd7465e5b0c3072
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 uint8_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 uint8_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 uint8_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 uint8_t queen_attack = (1<<7)+1;
152 const uint8_t pawn_attack = (1<<14)+1;
154 const uint8_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 #define N(x) ((x) & 0x1f)
350 int attackings[2] = { 0, 0 };
352 for(int is_white=0; is_white<2; is_white++)
354 int on_move = IS_WHITE(color_to_move) == is_white;
355 int is_black = !is_white;
356 int mt = (is_white ? +5 : -1);
358 /* Evaluate bishops */
359 for(int i=mat_tracking[BISHOP+mt].count-1;i>=0;i--)
361 uint8_t pos = mat_tracking[BISHOP+mt].pos[i];
362 if(attacks[is_black][pos] >= pawn_attack || attacks[is_black][pos] > attacks[is_white][pos] + bishop_attack)
363 attackings[is_white] += on_move ? -30 : -250;
364 else if(N(attacks[is_black][pos]) >= N(attacks[is_white][pos]) && attacks[is_black][pos] >= attacks[is_white][pos])
365 //else if(attacks[is_black][pos] >= attacks[is_white][pos])
366 attackings[is_white] += -20;
369 /* Evaluate rooks */
370 for(int i=mat_tracking[ROOK+mt].count-1;i>=0;i--)
372 uint8_t pos = mat_tracking[ROOK+mt].pos[i];
373 if(attacks[is_black][pos] >= pawn_attack || attacks[is_black][pos] > attacks[is_white][pos] + bishop_attack)
374 attackings[is_white] += on_move ? -35 : -340;
375 else if(N(attacks[is_black][pos]) >= N(attacks[is_white][pos]) && attacks[is_black][pos] >= attacks[is_white][pos])
376 //else if(attacks[is_black][pos] >= attacks[is_white][pos])
377 attackings[is_white] += -25;
380 /* Evaluate queens */
381 for(int i=mat_tracking[QUEEN+mt].count-1;i>=0;i--)
383 uint8_t pos = mat_tracking[QUEEN+mt].pos[i];
384 if(attacks[is_black][pos] >= bishop_attack)
385 attackings[is_white] += on_move ? -40 : -600;
388 /* Evaluate knights */
389 for(int i=mat_tracking[KNIGHT+mt].count-1;i>=0;i--)
391 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
392 if(attacks[is_black][pos] >= pawn_attack || attacks[is_black][pos] > attacks[is_white][pos] + bishop_attack)
393 attackings[is_white] += on_move ? -30 : -250;
394 else if(N(attacks[is_black][pos]) >= N(attacks[is_white][pos]) && attacks[is_black][pos] >= attacks[is_white][pos])
395 //else if(attacks[is_black][pos] >= attacks[is_white][pos])
396 attackings[is_white] += -20;
399 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
401 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
402 if(attacks[is_black][pos] >= attacks[is_white][pos])
404 if(N(attacks[is_black][pos]) > N(attacks[is_white][pos]))
405 attackings[is_white] += on_move ? -15 : -60;
406 else if(N(attacks[is_black][pos]) == N(attacks[is_white][pos]))
407 attackings[is_white] += -8;
412 int tot_mat = material[0] + material[1];
413 int max_mat = 100*16 + 325*8 + 500*4 + 975*2;
414 int eval[2] = {
415 material[0] + (activity_middle[0]*tot_mat + activity_end[0]*(max_mat-tot_mat))/(16 * max_mat),
416 material[1] + (activity_middle[1]*tot_mat + activity_end[1]*(max_mat-tot_mat))/(16 * max_mat)
419 return 7 + eval[IS_WHITE(color_to_move)] - eval[IS_WHITE(other_color)]
420 + attackings[IS_WHITE(color_to_move)] - attackings[IS_WHITE(other_color)];
423 #if 0
424 /* Evaluate pawns */
425 bool p = false;
426 for(int x=0;x<8;x++)
428 bool nextp = !!line_pawns[is_white][x].count;
429 if(nextp && !p)
430 evaluation[is_white] += pawn_insula;
431 p = nextp;
434 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
436 int16_t v = 0;
437 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
438 uint8_t x = X(pos);
439 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
441 v += (100 + pawn_value[POS_XY(x,y)]);
443 /* isulated pawn malus */
444 #if 0
445 if( (x == 0 || line_pawns[is_white][x-1].count == 0) &&
446 (x == 7 || line_pawns[is_white][x+1].count == 0) )
448 v += pawn_isulated;
449 if(COLOR_OF(data[uint8_t(up+pos)]) == othcol)
450 v += pawn_isulated_blocked;
452 #endif
454 /* backward pawn malus */
455 if( (x == 0 || line_pawns[is_white][x-1].count == 0
456 || line_pawns[is_white][x-1].pos[0] > y) &&
457 (x == 7 || line_pawns[is_white][x+1].count == 0
458 || line_pawns[is_white][x+1].pos[0] > y) )
460 v += pawn_backward[x];
461 if(!line_pawns[!is_white][x].count)
462 v += pawn_backward_open_file;
463 if(data[I(up+pos)])
464 v += pawn_backward_blocked;
467 if(x!=0 && data[LEFT_OF(pos)]==data[pos])
468 v += pawn_duo[x]*(y+2)/2;
469 if(x!=0 && (data[LEFTUP_OF(pos)]==data[pos] ||
470 data[LEFTDOWN_OF(pos)]==data[pos]))
471 v += pawn_chain;
473 /* passed pawn */
474 if( (x==0||!line_pawns[1-is_white][x-1].count ||
475 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
476 (x==7||!line_pawns[1-is_white][x+1].count ||
477 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
478 (!line_pawns[1-is_white][x].count||line_pawns[1-is_white][x].pos[0]>7-y) )
480 if(COLOR_OF(up_dir[is_white]+pos) == othcol)
481 v += MAX(y-2,1)*BLOCKED_PASSER;
482 else
483 v += MAX(y-2,1)*PASSED_PAWN;
486 /* doubled pawns */
487 if(line_pawns[is_white][x].count > 1)
488 v += pawn_doubled[x];
490 evaluation[is_white] += v;
493 /* Evaluate king */
494 for(int i=mat_tracking[KING+mt].count-1;i>=0;i--)
496 int16_t v = 0;
497 uint8_t pos = mat_tracking[KING+mt].pos[i];
498 uint8_t x = X(pos);
499 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
501 if( is_white ? !(castle_passing_mask & 0x30) :
502 !(castle_passing_mask & 0xc0) )
504 if(material[!is_white]>=1500)
506 v += king_safety[pos];
507 if((x>=5 || x<=2) && y<=1)
509 uint8_t f = x<=2 ? 2 : 5;
510 uint8_t g = x<=2 ? 1 : 6;
511 uint8_t h = x<=2 ? 0 : 7;
512 uint8_t fpawn = line_pawns[is_white][f].count ? line_pawns[is_white][f].pos[0] : 255;
513 uint8_t gpawn = line_pawns[is_white][g].count ? line_pawns[is_white][g].pos[0] : 255;
514 uint8_t hpawn = line_pawns[is_white][h].count ? line_pawns[is_white][h].pos[0] : 255;
516 if(fpawn >= 3)
517 v += -12;
518 else
519 v += -4;
520 if(gpawn >= 3)
521 v += -15;
522 else
523 v += -8;
524 if(hpawn >= 3)
525 v += -13;
526 else
527 v += -6;
528 if(fpawn==1 && gpawn>=2 && hpawn==1)
530 uint8_t start = POS_XY(x<=2 ? 1 : 6, is_white?1:6);
531 uint8_t defbish = color | BISHOP;
532 if(data[start] == defbish || data[RIGHTUP_OF(start)] == defbish ||
533 data[LEFTUP_OF(start)] == defbish || data[RIGHTDOWN_OF(start)] == defbish ||
534 data[LEFTDOWN_OF(start)] == defbish)
535 v += 5;
536 else
537 v += -13;
539 if(!line_pawns[is_white][f].count)
540 v += -10;
541 if(!line_pawns[is_white][g].count)
542 v += -16;
543 if(!line_pawns[is_white][h].count)
544 v += -16;
545 if(data[POS_XY(h, is_white?0:7)] == (color | ROOK) ||
546 data[POS_XY(h, is_white?1:6)] == (color | ROOK) )
547 v += -80;
549 else if((x<5 && x>2) && y<=1)
551 if(!line_pawns[is_white][x].count)
552 v += -26;
553 if(!line_pawns[is_white][7-x].count)
554 v += -16;
557 v = v * (MIN(material[!is_white], 2400)-1500)/900;
558 king_danger[is_white] = v;
560 if(material[!is_white]<2400)
561 v += endgame_king_val[pos] * (2400 - MAX(material[!is_white], 1500) )/900;
563 else
564 v += king_still_to_castle;
566 evaluation[is_white] += v;
571 evaluation[0] += (1500*(evaluation[0]-evaluation[1]))/
572 (2000+material[0]+material[1]);
573 evaluation[0] += tropism[0] * 200 / MAX(200 + king_danger[1], 50);
574 evaluation[1] += tropism[1] * 200 / MAX(200 + king_danger[0], 50);
576 int16_t retv = 7 + evaluation[IS_WHITE(color_to_move)] -
577 evaluation[IS_WHITE(other_color)];
579 // if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
580 // retv += color_to_move == eng_color ? -15 : 15;
581 // else if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
582 // retv += color_to_move == eng_color ? -8 : 8;
584 return retv;
586 #endif