Make static all history-related arrays.
[rattatechess.git] / evaluate.cpp
blob65dcaa3c26815f0954a7367422094475e6e7918c
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"
20 #include "evaluations.h"
23 #define PASSED_PAWN 30
24 #define BLOCKED_PASSER 12
25 #define PASSED_PIECE 11
26 #define ATTACKING_PIECE 7
27 #define ATTACKING_PAWN 5
28 #define DEFEND_PASSED_PAWN 13
29 #define CONNECTED_ROOKS 21
30 #define UNDEVELOPED 10
31 #define TWO_BISHOPS 45
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 = -120;
42 const int pawn_chain = 5;
43 const int pawn_insula = -18;
44 const int pawn_isulated = -10;
45 const int pawn_isulated_blocked = -17;
46 const int pawn_backward_open_file = -6;
47 const int pawn_backward_blocked = -9;
48 const int pawn_backward[8] = { -2, -3, -5, -7, -7, -5, -3, -2 };
49 const int pawn_doubled[8] = { -7, -5, -3, -2, -2, -3, -5, -7 }; //counted twice
50 const int pawn_duo[7] = { 2, 3, 4, 5, 4, 3, 2 }; //counted x the row, x2, x3, etc
52 const int queen_value = 975;
53 const int queen_seventh = 9;
54 const int queen_open_file = 7;
55 const int queen_semiopen_file = 5;
57 const int rook_value = 500;
58 const int rook_seventh = 19;
59 const int rook_open_file = 14;
60 const int rook_semiopen_file = 10;
64 const int pawn_value[128] = {
65 0,0,0,0,0,0,0,0,ENDL,
66 -3,0,1,-15,-15,1,0,-3,ENDL,
67 -2,1,3, 7, 7,3,1,-2,ENDL,
68 -1,2,9,16,16,9,2,-1,ENDL,
69 0,4,11,22,22,11,4,0,ENDL,
70 1,6,13,24,24,13,6,1,ENDL,
71 2,8,15,26,26,15,8,2,ENDL,
72 0,0,0,0,0,0,0,0,ENDL
75 const int endgame_king_val[128] = {
76 0, 2, 7, 7, 7, 7, 2, 0, ENDL,
77 2, 11, 19, 19, 19, 19, 11, 2, ENDL,
78 7, 19, 23, 25, 25, 23, 19, 7, ENDL,
79 7, 19, 25, 27, 27, 25, 19, 7, ENDL,
80 7, 19, 25, 27, 27, 25, 19, 7, ENDL,
81 7, 19, 23, 25, 25, 23, 19, 7, ENDL,
82 2, 11, 19, 19, 19, 19, 11, 2, ENDL,
83 0, 2, 7, 7, 7, 7, 2, 0, ENDL
87 const int queen_tropism[8] = { 0, 51, 70, 40, 10, 0, 0, 0};
88 const int rook_tropism[8] = { 0, 3, 2, 1, 0, 0, 0, 0};
89 const int knight_tropism[8] = { 0, 10, 7, 5, 2, 0, 0, 0};
90 const int bishop_tropism[8] = { 0, 3, 3, 2, 1, 0, 0, 0};
91 const int rook_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
92 const int knight_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
93 const int bishop_attack_tropism[8] = { 0, 5, 3, 0, 0, 0, 0, 0};
95 const int piece_val[] = { 500, 325, 975, 325, 100, 0 };
97 inline int distance(uint8_t a, uint8_t b)
99 return MAX(ABS(X(a)-X(b)), ABS(Y(a)-Y(b)));
102 int16_t Board::dummy_evaluate()
104 int material[2] = { 0, 0 };
106 int p=0;
107 for(int col=0;col<2;col++)
108 for(int i=0;i<6;i++)
109 material[col] += mat_tracking[p++].count * piece_val[i];
111 return material[IS_WHITE(color_to_move)] -
112 material[IS_WHITE(other_color)];
115 //--------------------------------------------------------------------------
117 const int piece_value[] = { 0, 500, 325, 975, 325, 100, 0 };
119 const int controlled_bonus[128] =
121 3, 3, 3, 3, 3, 3, 3, 3, ENDL,
122 3, 4, 4, 4, 4, 4, 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, 5, 5, 5, 5, 4, 3, ENDL,
127 3, 4, 4, 4, 4, 4, 4, 3, ENDL,
128 3, 3, 3, 3, 3, 3, 3, 3, ENDL
131 const int bishop_pair = 50;
133 const int bishop_base = 24;
134 const int bishop_middle = 20;
135 const int bishop_end = 20;
136 const int bishop_attack = 10;
138 const int knight_base = 16;
139 const int knight_middle = 16;
140 const int knight_end = 16;
141 const int knight_attack = 10;
143 const int rook_base = 28;
144 const int rook_middle = 8;
145 const int rook_end = 16;
146 const int rook_attack = 10;
148 const int queen_base = 52;
149 const int queen_middle = 4;
150 const int queen_end = 8;
151 const int queen_attack = 1;
153 const int pawn_attack = 100;
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[KNIGHT+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;
338 int attackings[2] = { 0, 0 };
340 for(int is_white=0; is_white<2; is_white++)
342 int on_move = IS_WHITE(color_to_move) == is_white;
343 int is_black = !is_white;
344 int mt = (is_white ? +5 : -1);
346 /* Evaluate bishops */
347 for(int i=mat_tracking[BISHOP+mt].count-1;i>=0;i--)
349 uint8_t pos = mat_tracking[BISHOP+mt].pos[i];
350 if(attacks[is_black][pos] > attacks[is_white][pos])
351 attackings[is_white] += on_move ? -30 : -90;
352 if(attacks[is_black][pos] == attacks[is_white][pos])
353 attackings[is_white] += -15;
356 /* Evaluate rooks */
357 for(int i=mat_tracking[ROOK+mt].count-1;i>=0;i--)
359 uint8_t pos = mat_tracking[ROOK+mt].pos[i];
360 if(attacks[is_black][pos] > attacks[is_white][pos])
361 attackings[is_white] += on_move ? -30 : -90;
362 if(attacks[is_black][pos] == attacks[is_white][pos])
363 attackings[is_white] += -15;
366 /* Evaluate queens */
367 for(int i=mat_tracking[QUEEN+mt].count-1;i>=0;i--)
369 uint8_t pos = mat_tracking[QUEEN+mt].pos[i];
370 if(attacks[is_black][pos] >= attacks[is_white][pos])
371 attackings[is_white] += on_move ? -30 : -250;
374 /* Evaluate knights */
375 for(int i=mat_tracking[KNIGHT+mt].count-1;i>=0;i--)
377 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
378 if(attacks[is_black][pos] > attacks[is_white][pos])
379 attackings[is_white] += on_move ? -30 : -90;
380 if(attacks[is_black][pos] == attacks[is_white][pos])
381 attackings[is_white] += -15;
384 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
386 uint8_t pos = mat_tracking[KNIGHT+mt].pos[i];
387 if(attacks[is_black][pos] > attacks[is_white][pos])
388 attackings[is_white] += on_move ? -20 : -50;
389 if(attacks[is_black][pos] == attacks[is_white][pos])
390 attackings[is_white] += -10;
394 int tot_mat = material[0] + material[1];
395 int max_mat = 100*16 + 325*8 + 500*4 + 975*2;
396 int eval[2] = {
397 material[0] + (activity_middle[0]*tot_mat + activity_end[0]*(max_mat-tot_mat))/(16 * max_mat),
398 material[1] + (activity_middle[1]*tot_mat + activity_end[1]*(max_mat-tot_mat))/(16 * max_mat)
401 return 7 + eval[IS_WHITE(color_to_move)] - eval[IS_WHITE(other_color)]
402 + (attackings[IS_WHITE(color_to_move)] - attackings[IS_WHITE(other_color)])*4;
405 #if 0
406 /* Evaluate pawns */
407 bool p = false;
408 for(int x=0;x<8;x++)
410 bool nextp = !!line_pawns[is_white][x].count;
411 if(nextp && !p)
412 evaluation[is_white] += pawn_insula;
413 p = nextp;
416 for(int i=mat_tracking[PAWN+mt].count-1;i>=0;i--)
418 int16_t v = 0;
419 uint8_t pos = mat_tracking[PAWN+mt].pos[i];
420 uint8_t x = X(pos);
421 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
423 v += (100 + pawn_value[POS_XY(x,y)]);
425 /* isulated pawn malus */
426 #if 0
427 if( (x == 0 || line_pawns[is_white][x-1].count == 0) &&
428 (x == 7 || line_pawns[is_white][x+1].count == 0) )
430 v += pawn_isulated;
431 if(COLOR_OF(data[uint8_t(up+pos)]) == othcol)
432 v += pawn_isulated_blocked;
434 #endif
436 /* backward pawn malus */
437 if( (x == 0 || line_pawns[is_white][x-1].count == 0
438 || line_pawns[is_white][x-1].pos[0] > y) &&
439 (x == 7 || line_pawns[is_white][x+1].count == 0
440 || line_pawns[is_white][x+1].pos[0] > y) )
442 v += pawn_backward[x];
443 if(!line_pawns[!is_white][x].count)
444 v += pawn_backward_open_file;
445 if(data[I(up+pos)])
446 v += pawn_backward_blocked;
449 if(x!=0 && data[LEFT_OF(pos)]==data[pos])
450 v += pawn_duo[x]*(y+2)/2;
451 if(x!=0 && (data[LEFTUP_OF(pos)]==data[pos] ||
452 data[LEFTDOWN_OF(pos)]==data[pos]))
453 v += pawn_chain;
455 /* passed pawn */
456 if( (x==0||!line_pawns[1-is_white][x-1].count ||
457 line_pawns[1-is_white][x-1].pos[0]>=7-y) &&
458 (x==7||!line_pawns[1-is_white][x+1].count ||
459 line_pawns[1-is_white][x+1].pos[0]>=7-y) &&
460 (!line_pawns[1-is_white][x].count||line_pawns[1-is_white][x].pos[0]>7-y) )
462 if(COLOR_OF(up_dir[is_white]+pos) == othcol)
463 v += MAX(y-2,1)*BLOCKED_PASSER;
464 else
465 v += MAX(y-2,1)*PASSED_PAWN;
468 /* doubled pawns */
469 if(line_pawns[is_white][x].count > 1)
470 v += pawn_doubled[x];
472 evaluation[is_white] += v;
475 /* Evaluate king */
476 for(int i=mat_tracking[KING+mt].count-1;i>=0;i--)
478 int16_t v = 0;
479 uint8_t pos = mat_tracking[KING+mt].pos[i];
480 uint8_t x = X(pos);
481 uint8_t y = is_white ? Y(pos) : 7-Y(pos);
483 if( is_white ? !(castle_passing_mask & 0x30) :
484 !(castle_passing_mask & 0xc0) )
486 if(material[!is_white]>=1500)
488 v += king_safety[pos];
489 if((x>=5 || x<=2) && y<=1)
491 uint8_t f = x<=2 ? 2 : 5;
492 uint8_t g = x<=2 ? 1 : 6;
493 uint8_t h = x<=2 ? 0 : 7;
494 uint8_t fpawn = line_pawns[is_white][f].count ? line_pawns[is_white][f].pos[0] : 255;
495 uint8_t gpawn = line_pawns[is_white][g].count ? line_pawns[is_white][g].pos[0] : 255;
496 uint8_t hpawn = line_pawns[is_white][h].count ? line_pawns[is_white][h].pos[0] : 255;
498 if(fpawn >= 3)
499 v += -12;
500 else
501 v += -4;
502 if(gpawn >= 3)
503 v += -15;
504 else
505 v += -8;
506 if(hpawn >= 3)
507 v += -13;
508 else
509 v += -6;
510 if(fpawn==1 && gpawn>=2 && hpawn==1)
512 uint8_t start = POS_XY(x<=2 ? 1 : 6, is_white?1:6);
513 uint8_t defbish = color | BISHOP;
514 if(data[start] == defbish || data[RIGHTUP_OF(start)] == defbish ||
515 data[LEFTUP_OF(start)] == defbish || data[RIGHTDOWN_OF(start)] == defbish ||
516 data[LEFTDOWN_OF(start)] == defbish)
517 v += 5;
518 else
519 v += -13;
521 if(!line_pawns[is_white][f].count)
522 v += -10;
523 if(!line_pawns[is_white][g].count)
524 v += -16;
525 if(!line_pawns[is_white][h].count)
526 v += -16;
527 if(data[POS_XY(h, is_white?0:7)] == (color | ROOK) ||
528 data[POS_XY(h, is_white?1:6)] == (color | ROOK) )
529 v += -80;
531 else if((x<5 && x>2) && y<=1)
533 if(!line_pawns[is_white][x].count)
534 v += -26;
535 if(!line_pawns[is_white][7-x].count)
536 v += -16;
539 v = v * (MIN(material[!is_white], 2400)-1500)/900;
540 king_danger[is_white] = v;
542 if(material[!is_white]<2400)
543 v += endgame_king_val[pos] * (2400 - MAX(material[!is_white], 1500) )/900;
545 else
546 v += king_still_to_castle;
548 evaluation[is_white] += v;
553 evaluation[0] += (1500*(evaluation[0]-evaluation[1]))/
554 (2000+material[0]+material[1]);
555 evaluation[0] += tropism[0] * 200 / MAX(200 + king_danger[1], 50);
556 evaluation[1] += tropism[1] * 200 / MAX(200 + king_danger[0], 50);
558 int16_t retv = 7 + evaluation[IS_WHITE(color_to_move)] -
559 evaluation[IS_WHITE(other_color)];
561 // if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
562 // retv += color_to_move == eng_color ? -15 : 15;
563 // else if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
564 // retv += color_to_move == eng_color ? -8 : 8;
566 return retv;
568 #endif