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 ***************************************************************************/
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 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;
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] = {
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
,
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, 975, 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 };
150 for(int col
=0;col
<2;col
++)
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 };
167 for(int col
=0;col
<2;col
++)
169 material
[col
] += mat_tracking
[p
++].count
* piece_val
[i
];
171 // int matval = 15 + material[IS_WHITE(color_to_move)] -
172 // material[IS_WHITE(other_color)];
173 // if(matval > beta+200)
175 // if(matval < alpha-200)
178 for(int is_white
=0;is_white
<2;is_white
++)
180 uint8_t color
= is_white
? WHITE
: BLACK
;
181 uint8_t othcol
= OTHER_COLOR(color
);
182 uint8_t up
= up_dir
[is_white
];
183 uint8_t up_left
= up
+LEFT
;
184 uint8_t up_right
= up
+RIGHT
;
185 uint8_t othpawn
= PAWN
|othcol
;
186 uint8_t mypawn
= PAWN
|color
;
187 int mt
= (is_white
? +5 : -1);
189 /* Evaluate bishops */
190 for(int i
=mat_tracking
[BISHOP
+mt
].count
-1;i
>=0;i
--)
193 uint8_t pos
= mat_tracking
[BISHOP
+mt
].pos
[i
];
195 for(int i
=3;i
>=0;i
--)
197 register uint8_t currpos
= pos
;
198 register uint8_t currinc
= bishmoves
[i
];
204 if(OUT_OF_BOARD(currpos
) || COLOR_OF(data
[currpos
]) == color
)
207 v
+= controlled_bonus
[currpos
];
213 if(OUT_OF_BOARD(currpos
))
216 if(COLOR_OF(data
[currpos
]) == othcol
)
218 uint8_t p1
= currpos
+ up_left
;
219 uint8_t p2
= currpos
+ up_right
;
221 /* give a bonus activity value if attacking a pawn/piece
222 that is not defended by an enemy pawn */
223 if( (OUT_OF_BOARD(p1
) || data
[p1
]!=othpawn
)
224 && (OUT_OF_BOARD(p2
) || data
[p2
]!=othpawn
) )
225 v
+= PIECE_OF(data
[currpos
])==PAWN
226 ? ATTACKING_PAWN
: ATTACKING_PIECE
;
228 bishop_attack_tropism
[distance(currpos
, king_pos
[1-is_white
])];
230 else if(data
[currpos
] == mypawn
)
232 uint8_t x
= X(currpos
);
233 uint8_t y
= is_white
? Y(currpos
) : 7-Y(currpos
);
235 /* give a bonus for defending passed pawns */
236 if( (x
==0||!line_pawns
[1-is_white
][x
-1].count
||
237 line_pawns
[1-is_white
][x
-1].pos
[0]>=7-y
) &&
238 (x
==7||!line_pawns
[1-is_white
][x
+1].count
||
239 line_pawns
[1-is_white
][x
+1].pos
[0]>=7-y
) &&
240 !line_pawns
[1-is_white
][x
].count
)
242 v
+= DEFEND_PASSED_PAWN
/2;
247 v
= v
*3 - UNDEVELOPED
*2;
249 v
+= bishop_value
[pos
];
250 tropism
[is_white
] += bishop_tropism
[distance(pos
, king_pos
[1-is_white
])];
252 /* penalize the bishop if there are a lot of pawns around */
253 //v -= 2*(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count);
256 uint8_t y
= is_white
? Y(pos
) : 7-Y(pos
);
257 if( (x
==0||!line_pawns
[!is_white
][x
-1].count
||
258 line_pawns
[!is_white
][x
-1].pos
[0]>=7-y
) &&
259 (x
==7||!line_pawns
[!is_white
][x
+1].count
||
260 line_pawns
[!is_white
][x
+1].pos
[0]>=7-y
) )
263 evaluation
[is_white
] += v
;
265 /* bonus for having both bishops */
266 if(mat_tracking
[BISHOP
+mt
].count
== 2)
267 evaluation
[is_white
] += TWO_BISHOPS
;
270 for(int i
=mat_tracking
[ROOK
+mt
].count
-1;i
>=0;i
--)
273 uint8_t pos
= mat_tracking
[ROOK
+mt
].pos
[i
];
275 for(int i
=3;i
>=0;i
--)
277 register uint8_t currpos
= pos
;
278 register uint8_t currinc
= rookmoves
[i
];
284 if(OUT_OF_BOARD(currpos
) || COLOR_OF(data
[currpos
]) == color
)
287 v
+= controlled_bonus
[currpos
];
293 if(OUT_OF_BOARD(currpos
))
296 if(COLOR_OF(data
[currpos
]) == othcol
)
298 uint8_t p1
= currpos
+ up_left
;
299 uint8_t p2
= currpos
+ up_right
;
301 /* give a bonus activity value if attacking a pawn/piece
302 that is not defended by an enemy pawn */
303 if( (OUT_OF_BOARD(p1
) || data
[p1
]!=othpawn
)
304 && (OUT_OF_BOARD(p2
) || data
[p2
]!=othpawn
) )
305 v
+= PIECE_OF(data
[currpos
])==PAWN
306 ? ATTACKING_PAWN
: ATTACKING_PIECE
;
309 rook_attack_tropism
[distance(currpos
, king_pos
[1-is_white
])];
311 else if(data
[currpos
] == mypawn
)
313 uint8_t x
= X(currpos
);
314 uint8_t y
= is_white
? Y(currpos
) : 7-Y(currpos
);
316 /* give a bonus for defending passed pawns */
317 if( (x
==0||!line_pawns
[1-is_white
][x
-1].count
||
318 line_pawns
[1-is_white
][x
-1].pos
[0]>=7-y
) &&
319 (x
==7||!line_pawns
[1-is_white
][x
+1].count
||
320 line_pawns
[1-is_white
][x
+1].pos
[0]>=7-y
) &&
321 !line_pawns
[1-is_white
][x
].count
)
323 v
+= DEFEND_PASSED_PAWN
;
326 else if((~BISHOP
&data
[currpos
])==(ROOK
|color
))
327 v
+= CONNECTED_ROOKS
;
330 v
= v
*3 - UNDEVELOPED
*2;
332 /* evaluate less rook activity (more important is
333 if it is on a open/close file)*/
337 v
+= (10 - mat_tracking
[PAWN
-1].count
- mat_tracking
[PAWN
+5].count
)*100/32;
339 if(line_pawns
[is_white
][X(pos
)].count
== 0)
341 if(line_pawns
[1-is_white
][X(pos
)].count
== 0)
344 v
+= rook_semiopen_file
;
346 if( ROW_OF(pos
) == seventh_rank
[is_white
] )
349 tropism
[is_white
] += rook_tropism
[distance(pos
, king_pos
[!is_white
])];
351 evaluation
[is_white
] += v
;
354 /* Evaluate queen(s) */
355 for(int i
=mat_tracking
[QUEEN
+mt
].count
-1;i
>=0;i
--)
358 uint8_t pos
= mat_tracking
[QUEEN
+mt
].pos
[i
];
360 for(int i
=7;i
>=0;i
--)
362 register uint8_t currpos
= pos
;
363 register uint8_t currinc
= kingmoves
[i
];
369 if(OUT_OF_BOARD(currpos
) || COLOR_OF(data
[currpos
])==color
)
372 v
+= controlled_bonus
[currpos
];
377 while(!IS_OF_COLOR(data
[currpos
],othcol
));
380 /* evaluate less queen activity, so ratta won't go
381 around with the queen all the time */
384 /* bonus for 7th or open file */
385 if(line_pawns
[is_white
][X(pos
)].count
== 0)
387 if(line_pawns
[1-is_white
][X(pos
)].count
== 0)
388 v
+= queen_open_file
;
390 v
+= queen_semiopen_file
;
392 if(Y(pos
) == (color
==WHITE
?6:1))
393 v
+= queen_seventh
/2;
396 tropism
[is_white
] += queen_tropism
[distance(pos
, king_pos
[1-is_white
])];
398 if(color
== eng_color
) v
+= 17;
400 evaluation
[is_white
] += v
;
403 /* Evaluate knights */
404 for(int i
=mat_tracking
[KNIGHT
+mt
].count
-1;i
>=0;i
--)
407 uint8_t pos
= mat_tracking
[KNIGHT
+mt
].pos
[i
];
408 KnightMove
* hm
= &knightmoves
[pos
];
410 for(int i
=hm
->numm
;i
>=0;i
--)
412 register uint8_t currpos
= hm
->jump
[i
];
413 if(IS_OF_COLOR(data
[currpos
], color
))
416 v
+= controlled_bonus
[currpos
];
418 if(IS_OF_COLOR(data
[currpos
], othcol
))
420 uint8_t p1
= currpos
+ up_left
;
421 uint8_t p2
= currpos
+ up_right
;
423 if((OUT_OF_BOARD(p1
) || data
[p1
]!=othpawn
) &&
424 (OUT_OF_BOARD(p2
) || data
[p2
]!=othpawn
))
426 /* give a bonus activity value if attacking a pawn/piece
427 that is not defended by an enemy pawn */
428 if(IS_OF_COLOR(data
[currpos
], othcol
))
429 v
+= PIECE_OF(data
[currpos
])==PAWN
430 ? ATTACKING_PAWN
: ATTACKING_PIECE
;
434 knight_attack_tropism
[distance(currpos
, king_pos
[!is_white
])];
436 else if(data
[currpos
] == mypawn
)
438 uint8_t x
= X(currpos
);
439 uint8_t y
= is_white
? Y(currpos
) : 7-Y(currpos
);
441 /* give a bonus for defending passed pawns */
442 if( (x
==0||!line_pawns
[1-is_white
][x
-1].count
||
443 line_pawns
[1-is_white
][x
-1].pos
[0]>=7-y
) &&
444 (x
==7||!line_pawns
[1-is_white
][x
+1].count
||
445 line_pawns
[1-is_white
][x
+1].pos
[0]>=7-y
) &&
446 !line_pawns
[1-is_white
][x
].count
)
448 v
+= DEFEND_PASSED_PAWN
/2;
453 v
= v
*3 - UNDEVELOPED
*2;
455 v
+= knight_value
[pos
];
456 v
+= (mat_tracking
[PAWN
-1].count
+ mat_tracking
[PAWN
+5].count
-2)*100/32;
457 tropism
[is_white
] += knight_tropism
[distance(pos
, king_pos
[!is_white
])];
460 uint8_t y
= is_white
? Y(pos
) : 7-Y(pos
);
461 if( (x
==0||!line_pawns
[!is_white
][x
-1].count
||
462 line_pawns
[!is_white
][x
-1].pos
[0]>=7-y
) &&
463 (x
==7||!line_pawns
[!is_white
][x
+1].count
||
464 line_pawns
[!is_white
][x
+1].pos
[0]<=7-y
) )
467 evaluation
[is_white
] += v
;
474 bool nextp
= !!line_pawns
[is_white
][x
].count
;
476 evaluation
[is_white
] += pawn_insula
;
480 for(int i
=mat_tracking
[PAWN
+mt
].count
-1;i
>=0;i
--)
483 uint8_t pos
= mat_tracking
[PAWN
+mt
].pos
[i
];
485 uint8_t y
= is_white
? Y(pos
) : 7-Y(pos
);
487 v
+= (100 + pawn_value
[POS_XY(x
,y
)]);
489 /* isulated pawn malus */
491 if( (x
== 0 || line_pawns
[is_white
][x
-1].count
== 0) &&
492 (x
== 7 || line_pawns
[is_white
][x
+1].count
== 0) )
495 if(COLOR_OF(data
[uint8_t(up
+pos
)]) == othcol
)
496 v
+= pawn_isulated_blocked
;
500 /* backward pawn malus */
501 if( (x
== 0 || line_pawns
[is_white
][x
-1].count
== 0
502 || line_pawns
[is_white
][x
-1].pos
[0] > y
) &&
503 (x
== 7 || line_pawns
[is_white
][x
+1].count
== 0
504 || line_pawns
[is_white
][x
+1].pos
[0] > y
) )
506 v
+= pawn_backward
[x
];
507 if(!line_pawns
[!is_white
][x
].count
)
508 v
+= pawn_backward_open_file
;
510 v
+= pawn_backward_blocked
;
513 if(x
!=0 && data
[LEFT_OF(pos
)]==data
[pos
])
514 v
+= pawn_duo
[x
]*(y
+2)/2;
515 if(x
!=0 && (data
[LEFTUP_OF(pos
)]==data
[pos
] ||
516 data
[LEFTDOWN_OF(pos
)]==data
[pos
]))
520 if( (x
==0||!line_pawns
[1-is_white
][x
-1].count
||
521 line_pawns
[1-is_white
][x
-1].pos
[0]>=7-y
) &&
522 (x
==7||!line_pawns
[1-is_white
][x
+1].count
||
523 line_pawns
[1-is_white
][x
+1].pos
[0]>=7-y
) &&
524 (!line_pawns
[1-is_white
][x
].count
||line_pawns
[1-is_white
][x
].pos
[0]>7-y
) )
526 if(COLOR_OF(up_dir
[is_white
]+pos
) == othcol
)
527 v
+= MAX(y
-2,1)*BLOCKED_PASSER
;
529 v
+= MAX(y
-2,1)*PASSED_PAWN
;
533 if(line_pawns
[is_white
][x
].count
> 1)
534 v
+= pawn_doubled
[x
];
536 evaluation
[is_white
] += v
;
540 for(int i
=mat_tracking
[KING
+mt
].count
-1;i
>=0;i
--)
543 uint8_t pos
= mat_tracking
[KING
+mt
].pos
[i
];
545 uint8_t y
= is_white
? Y(pos
) : 7-Y(pos
);
547 if( is_white
? !(castle_passing_mask
& 0x30) :
548 !(castle_passing_mask
& 0xc0) )
550 if(material
[!is_white
]>=1500)
552 v
+= king_safety
[pos
];
553 if((x
>=5 || x
<=2) && y
<=1)
555 uint8_t f
= x
<=2 ? 2 : 5;
556 uint8_t g
= x
<=2 ? 1 : 6;
557 uint8_t h
= x
<=2 ? 0 : 7;
558 uint8_t fpawn
= line_pawns
[is_white
][f
].count
? line_pawns
[is_white
][f
].pos
[0] : 255;
559 uint8_t gpawn
= line_pawns
[is_white
][g
].count
? line_pawns
[is_white
][g
].pos
[0] : 255;
560 uint8_t hpawn
= line_pawns
[is_white
][h
].count
? line_pawns
[is_white
][h
].pos
[0] : 255;
574 if(fpawn
==1 && gpawn
>=2 && hpawn
==1)
576 uint8_t start
= POS_XY(x
<=2 ? 1 : 6, is_white
?1:6);
577 uint8_t defbish
= color
| BISHOP
;
578 if(data
[start
] == defbish
|| data
[RIGHTUP_OF(start
)] == defbish
||
579 data
[LEFTUP_OF(start
)] == defbish
|| data
[RIGHTDOWN_OF(start
)] == defbish
||
580 data
[LEFTDOWN_OF(start
)] == defbish
)
585 if(!line_pawns
[is_white
][f
].count
)
587 if(!line_pawns
[is_white
][g
].count
)
589 if(!line_pawns
[is_white
][h
].count
)
591 if(data
[POS_XY(h
, is_white
?0:7)] == (color
| ROOK
) ||
592 data
[POS_XY(h
, is_white
?1:6)] == (color
| ROOK
) )
595 else if((x
<5 && x
>2) && y
<=1)
597 if(!line_pawns
[is_white
][x
].count
)
599 if(!line_pawns
[is_white
][7-x
].count
)
603 v
= v
* (MIN(material
[!is_white
], 2400)-1500)/900;
604 king_danger
[is_white
] = v
;
606 if(material
[!is_white
]<2400)
607 v
+= endgame_king_val
[pos
] * (2400 - MAX(material
[!is_white
], 1500) )/900;
610 v
+= king_still_to_castle
;
612 evaluation
[is_white
] += v
;
617 evaluation
[0] += (1500*(evaluation
[0]-evaluation
[1]))/
618 (2000+material
[0]+material
[1]);
619 evaluation
[0] += tropism
[0] * 200 / MAX(200 + king_danger
[1], 50);
620 evaluation
[1] += tropism
[1] * 200 / MAX(200 + king_danger
[0], 50);
622 int16_t retv
= 15 + evaluation
[IS_WHITE(color_to_move
)] -
623 evaluation
[IS_WHITE(other_color
)];
625 // if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
626 // retv += color_to_move == eng_color ? -15 : 15;
627 // else if(mat_tracking[PAWN-1].count + mat_tracking[PAWN+5].count >= 15)
628 // retv += color_to_move == eng_color ? -8 : 8;