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 ***************************************************************************/
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] = {
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
,
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 };
106 for(int col
=0;col
<2;col
++)
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 };
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
[PAWN
+mt
].pos
[i
];
331 attacks
[is_white
][I(pos
+up_right
)] += pawn_attack
;
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
;
350 for(int y
=7;y
>=0;y
--)
352 for(int is_white
= 0;is_white
<2;is_white
++)
355 printf(" % 4x", attacks
[is_white
][POS_XY(x
,y
)]);
356 printf("%s", is_white
? "\n" : " ");
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;
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;
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
)];
440 bool nextp
= !!line_pawns
[is_white
][x
].count
;
442 evaluation
[is_white
] += pawn_insula
;
446 for(int i
=mat_tracking
[PAWN
+mt
].count
-1;i
>=0;i
--)
449 uint8_t pos
= mat_tracking
[PAWN
+mt
].pos
[i
];
451 uint8_t y
= is_white
? Y(pos
) : 7-Y(pos
);
453 v
+= (100 + pawn_value
[POS_XY(x
,y
)]);
455 /* isulated pawn malus */
457 if( (x
== 0 || line_pawns
[is_white
][x
-1].count
== 0) &&
458 (x
== 7 || line_pawns
[is_white
][x
+1].count
== 0) )
461 if(COLOR_OF(data
[uint8_t(up
+pos
)]) == othcol
)
462 v
+= pawn_isulated_blocked
;
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
;
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
]))
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
;
495 v
+= MAX(y
-2,1)*PASSED_PAWN
;
499 if(line_pawns
[is_white
][x
].count
> 1)
500 v
+= pawn_doubled
[x
];
502 evaluation
[is_white
] += v
;
506 for(int i
=mat_tracking
[KING
+mt
].count
-1;i
>=0;i
--)
509 uint8_t pos
= mat_tracking
[KING
+mt
].pos
[i
];
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;
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
)
551 if(!line_pawns
[is_white
][f
].count
)
553 if(!line_pawns
[is_white
][g
].count
)
555 if(!line_pawns
[is_white
][h
].count
)
557 if(data
[POS_XY(h
, is_white
?0:7)] == (color
| ROOK
) ||
558 data
[POS_XY(h
, is_white
?1:6)] == (color
| ROOK
) )
561 else if((x
<5 && x
>2) && y
<=1)
563 if(!line_pawns
[is_white
][x
].count
)
565 if(!line_pawns
[is_white
][7-x
].count
)
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;
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;