1 /***************************************************************************
2 evaluate.cpp - description
4 begin : Wed Mar 13 2002
5 copyright : (C) 2002-2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
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. *
16 ***************************************************************************/
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] = {
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
,
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 };
107 for(int col
=0;col
<2;col
++)
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 };
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
];
209 if(!OUT_OF_BOARD(currpos
))
210 attacks
[is_white
][currpos
] += bishop_attack
;
212 if(OUT_OF_BOARD(currpos
) || COLOR_OF(data
[currpos
]) == color
)
215 v
+= controlled_bonus
[currpos
];
221 if(OUT_OF_BOARD(currpos
))
225 activity_middle
[is_white
] += v
* bishop_middle
;
226 activity_end
[is_white
] += v
* bishop_end
;
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
];
245 if(!OUT_OF_BOARD(currpos
))
246 attacks
[is_white
][currpos
] += rook_attack
;
248 if(OUT_OF_BOARD(currpos
) || COLOR_OF(data
[currpos
]) == color
)
251 v
+= controlled_bonus
[currpos
];
257 if(OUT_OF_BOARD(currpos
))
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
];
281 if(!OUT_OF_BOARD(currpos
))
282 attacks
[is_white
][currpos
] += queen_attack
;
284 if(OUT_OF_BOARD(currpos
) || COLOR_OF(data
[currpos
]) == color
)
287 v
+= controlled_bonus
[currpos
];
293 if(OUT_OF_BOARD(currpos
))
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
))
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
];
331 attacks
[is_white
][I(pos
+up_right
)] += pawn_attack
;
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;
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;
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;
410 bool nextp
= !!line_pawns
[is_white
][x
].count
;
412 evaluation
[is_white
] += pawn_insula
;
416 for(int i
=mat_tracking
[PAWN
+mt
].count
-1;i
>=0;i
--)
419 uint8_t pos
= mat_tracking
[PAWN
+mt
].pos
[i
];
421 uint8_t y
= is_white
? Y(pos
) : 7-Y(pos
);
423 v
+= (100 + pawn_value
[POS_XY(x
,y
)]);
425 /* isulated pawn malus */
427 if( (x
== 0 || line_pawns
[is_white
][x
-1].count
== 0) &&
428 (x
== 7 || line_pawns
[is_white
][x
+1].count
== 0) )
431 if(COLOR_OF(data
[uint8_t(up
+pos
)]) == othcol
)
432 v
+= pawn_isulated_blocked
;
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
;
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
]))
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
;
465 v
+= MAX(y
-2,1)*PASSED_PAWN
;
469 if(line_pawns
[is_white
][x
].count
> 1)
470 v
+= pawn_doubled
[x
];
472 evaluation
[is_white
] += v
;
476 for(int i
=mat_tracking
[KING
+mt
].count
-1;i
>=0;i
--)
479 uint8_t pos
= mat_tracking
[KING
+mt
].pos
[i
];
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;
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
)
521 if(!line_pawns
[is_white
][f
].count
)
523 if(!line_pawns
[is_white
][g
].count
)
525 if(!line_pawns
[is_white
][h
].count
)
527 if(data
[POS_XY(h
, is_white
?0:7)] == (color
| ROOK
) ||
528 data
[POS_XY(h
, is_white
?1:6)] == (color
| ROOK
) )
531 else if((x
<5 && x
>2) && y
<=1)
533 if(!line_pawns
[is_white
][x
].count
)
535 if(!line_pawns
[is_white
][7-x
].count
)
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;
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;