1 /* the evaluation functions */
2
3 #include "includes.h"
4 #include "knightcap.h"
5 #if LARGE_ETYPE
6 #include "large_coeffs.h"
7 #else
8 #include "small_coeffs.h"
9 #endif
10
11 #define EVAL_ALL_DEPTH 2
12
13 #define EVAL_SHORTCUT_THRESHOLD (2.0*STATIC_PAWN_VALUE)
14 #define EVAL_SHORTCUT_OFFSET (1.5*STATIC_PAWN_VALUE)
15
16 /* coefficients we don't want changed by TD(lambda) (multiplicative factors,
17 the value of a pawn, the value of a king, and the value of a draw */
18 int dont_change[] = {};
19
20 etype new_coefficients[__TOTAL_COEFFS__];
21 etype *coefficients;
22
23 extern int learning;
24 extern int mulling;
25 extern struct state *state;
26 int debug;
27
28 /* this is the value of pawns on open files as they move up the board
29 - it is doubled for passed pawns */
30 #define pawn_advance (coefficients + IPAWN_ADVANCE)
31 #define pawn_advance1 (coefficients + IPAWN_ADVANCE1)
32 #define pawn_advance2 (coefficients + IPAWN_ADVANCE2)
33
34 /* the value of controlling the squares in front of a passed pawn */
35 #define passed_pawn_control (coefficients + IPASSED_PAWN_CONTROL)
36
37 /* index into the passed_pawn_control array */
38 static etype passed_pawn_index[] = {0, 6, 11, 15, 18, 20};
39
40 /* value of pawn configurations around the king */
41 #define pawn_defence (coefficients + IPAWN_DEFENCE)
42 static unsigned char black_pawn_loc[8];
43 static unsigned char white_pawn_loc[8];
44
45 #define PAWN_LOC(player) (player>0?white_pawn_loc:black_pawn_loc)
46
47 int pop_count[256];
48
init_eval_tables(void)49 void init_eval_tables(void)
50 {
51 struct stat st;
52 static int initialised;
53 int fd;
54 extern char *coeffs_file;
55 int i;
56
57 if (initialised) return;
58 initialised = 1;
59
60 state->rating_change = -2;
61
62 for (i=0;i<256;i++) {
63 pop_count[i] = bit_count(i);
64 }
65
66 if (sizeof(orig_coefficients) != __TOTAL_COEFFS__ *
67 sizeof(orig_coefficients[0])) {
68 lprintf(0,"coefficients table corrupt! %d %d\n",
69 __TOTAL_COEFFS__,
70 sizeof(orig_coefficients) / sizeof(orig_coefficients[0]));
71 exit(1);
72 }
73
74
75 memcpy(&(new_coefficients[0]), &(orig_coefficients[0]),
76 sizeof(orig_coefficients));
77 coefficients = &(new_coefficients[0]);
78
79 if (!coeffs_file) {
80 td_dump("coeffs.dat");
81 return;
82 }
83
84 fd = open(coeffs_file, O_RDONLY);
85 if (fd == -1) {
86 lprintf(0,"Failed to open %s\n", coeffs_file);
87 td_dump("coeffs.dat");
88 return;
89 }
90
91 if (fstat(fd, &st) != 0 &&
92 st.st_size != __TOTAL_COEFFS__*sizeof(coefficients[0])) {
93 lprintf(0,"%s is corrupt\n", coeffs_file);
94 return;
95 }
96
97 if (Read(fd, (char *)coefficients,st.st_size) != st.st_size) {
98 lprintf(0,"failed to read coefficients\n");
99 close(fd);
100 return;
101 }
102
103 lprintf(0,"Loaded coefficients from %s\n", coeffs_file);
104 close(fd);
105
106
107 }
108
109
110 #define pawn_pos_value (coefficients + IPAWN_POS)
111
112 /* this corrects the unstoppable pawn evaluation on null moves */
update_pawns(Position * b)113 void update_pawns(Position *b)
114 {
115 if (whites_move(b)) {
116 b->eval_result += (pop_count32(b->null_stoppable_pawn & BPAWN_MASK) +
117 pop_count32(b->null_unstoppable_pawn & WPAWN_MASK))*
118 UNSTOPPABLE_PAWN;
119 } else {
120 b->eval_result -= (pop_count32(b->null_stoppable_pawn & WPAWN_MASK) +
121 pop_count32(b->null_unstoppable_pawn & BPAWN_MASK))*
122 UNSTOPPABLE_PAWN;
123 }
124 }
125
get_control(Position * b,uint32 topieces,int piece,Square sq)126 static int get_control(Position *b, uint32 topieces,
127 int piece, Square sq)
128 {
129 int nw, nb;
130 /* the following masks select pieces that are of lower than
131 value than a piece */
132 static const uint32 masks[2*KING+1] =
133 {0xFFFE, 0xFFFC, 0xFFF0, 0xFF00, 0xFF00, 0,
134 0,
135 0, 0xFF000000, 0xFF000000, 0xFFF00000, 0xFFFC0000, 0xFFFE0000};
136
137 if (!topieces) return 0;
138
139 if (topieces & masks[piece+KING])
140 return -piece;
141
142 /* compare pawn counts */
143 nw = pop_count[(topieces >> 8) & 0xFF];
144 nb = pop_count[(topieces >> 24) & 0xFF];
145 if (nw - nb) return nw - nb;
146
147 /* compare piece counts */
148 nw = pop_count[topieces & 0xFF];
149 nb = pop_count[(topieces >> 16) & 0xFF];
150
151 #if USE_SLIDING_CONTROL
152 nw += pop_count[b->xray_topieces[sq] & 0xFF];
153 nb += pop_count[(b->xray_topieces[sq] >> 16) & 0xFF];
154 #endif
155 return (nw - nb);
156 }
157
158 #define weak_pawn_attack_value (coefficients + IWEAK_PAWN_ATTACK_VALUE)
159 /* this evaluates a pawn - its more valuable if its a passed
160 pawn or on an open file. In those cases it gains value
161 as it moves up the board */
eval_white_pawn(Position * b,int pi)162 static etype eval_white_pawn(Position *b, int pi)
163 {
164 PieceStruct *piece = b->pieces + pi;
165 etype ret=0;
166 int num = 0;
167 int x = XPOS(piece->pos);
168 int y = YPOS(piece->pos);
169 etype advance = 0;
170 int weak = 0;
171 Square pos;
172
173 b->wpassed_pawn_mask &= ~(1<<pi);
174
175 ret = pawn_pos_value[piece->pos];
176
177 if ((x != 0 && b->board[piece->pos+WEST] == PAWN) ||
178 (x != 7 && b->board[piece->pos+EAST] == PAWN)) {
179 ret += ADJACENT_PAWN;
180 }
181
182 /* a pawn is weak if it isn't supported by a pawn and can't
183 move to a place where it is supported by a pawn */
184
185 if (b->topieces[piece->pos] & WPAWN_MASK)
186 goto not_weak;
187
188 /* penalize slightly unsupported pawns */
189 ret -= UNSUPPORTED_PAWN;
190 if (debug)
191 lprintf(0,"unsupported %s\n", posstr(piece->pos));
192
193 if ((b->topieces[piece->pos+NORTH] & WPAWN_MASK) &&
194 abs(b->board[piece->pos+NORTH]) != PAWN)
195 goto not_weak;
196
197 if (y == 1 && !(b->topieces[piece->pos+NORTH] & BPAWN_MASK) &&
198 (b->topieces[piece->pos+2*NORTH] & WPAWN_MASK) &&
199 (abs(b->board[piece->pos+NORTH]) != PAWN) &&
200 (abs(b->board[piece->pos+2*NORTH]) != PAWN))
201 goto not_weak;
202
203 if (debug)
204 lprintf(0,"weak %s\n", posstr(piece->pos));
205 weak = 1;
206
207 ret -= WEAK_PAWN;
208
209 /* if its on a half open file then its even weaker */
210 if (black_pawn_loc[x] == 0)
211 ret -= MEGA_WEAK_PAWN;
212
213 /* attacks on weak pawns are worth something */
214 if (((b->topieces[piece->pos] & ~b->pinned_mask)>>16) & 0xFF) {
215 num = pop_count[((b->topieces[piece->pos] &
216 ~b->pinned_mask)>>16) & 0xFF];
217 ret -= weak_pawn_attack_value[num];
218 }
219
220 not_weak:
221
222 if (black_pawn_loc[x] < y) {
223 int n = 7-y;
224 if (!weak) {
225 advance = pawn_advance2[n];
226 }
227 if ((x==0 || black_pawn_loc[x-1] <= y) &&
228 (x==7 || black_pawn_loc[x+1] <= y)) {
229 Square wkpos = WHITEPIECES(b)[IKING].pos;
230 Square bkpos = BLACKPIECES(b)[IKING].pos;
231 int a, control;
232 uint32 rook_support = 0;
233 uint32 topieces;
234
235 b->wpassed_pawn_mask |= (1<<pi);
236 pos = piece->pos;
237
238 advance += pawn_advance[n];
239
240 if (YPOS(bkpos) >= y && abs(XPOS(bkpos) - x) <= 1)
241 advance -= KING_PASSED_PAWN_DEFENCE;
242
243 if (YPOS(wkpos) >= y && abs(XPOS(wkpos) - x) <= 1)
244 advance += KING_PASSED_PAWN_SUPPORT;
245
246 if (b->board[pos+NORTH] < 0)
247 advance -= BLOCKED_PASSED_PAWN;
248
249 if ((b->topieces[pos] & ~b->pinned_mask & BKROOK_MASK) &&
250 XPOS(BLACKPIECES(b)[IKROOK].pos) == x &&
251 YPOS(BLACKPIECES(b)[IKROOK].pos) < y) {
252 /* there is a black king rook
253 behind our passed pawn */
254 advance -= PASSED_PAWN_ROOK_ATTACK;
255 }
256
257 if ((b->topieces[pos] & ~b->pinned_mask & BQROOK_MASK) &&
258 XPOS(BLACKPIECES(b)[IQROOK].pos) == x &&
259 YPOS(BLACKPIECES(b)[IQROOK].pos) < y) {
260 /* there is a black queen rook
261 behind our passed pawn */
262 advance -= PASSED_PAWN_ROOK_ATTACK;
263 }
264
265 if ((b->topieces[pos] & ~b->pinned_mask & WKROOK_MASK) &&
266 XPOS(WHITEPIECES(b)[IKROOK].pos) == x &&
267 YPOS(WHITEPIECES(b)[IKROOK].pos) < y) {
268 /* there is a white king rook
269 behind our passed pawn */
270 rook_support = WKROOK_MASK;
271 advance += PASSED_PAWN_ROOK_SUPPORT;
272 }
273
274 if ((b->topieces[pos] & ~b->pinned_mask & WQROOK_MASK) &&
275 XPOS(WHITEPIECES(b)[IQROOK].pos) == x &&
276 YPOS(WHITEPIECES(b)[IQROOK].pos) < y) {
277 /* there is a white queen rook
278 behind our passed pawn */
279 rook_support = WQROOK_MASK;
280 advance += PASSED_PAWN_ROOK_SUPPORT;
281 }
282
283 a = passed_pawn_index[y-1];
284 while (!off_board(pos,NORTH)) {
285 pos += NORTH;
286 /* if rook_support == 1 we have to adjust the control
287 of the squares in front of the pawn */
288 if (!rook_support) {
289 control = b->cont[pos];
290 } else {
291 topieces = b->topieces[pos] & (~b->pinned_mask);
292 topieces |= rook_support;
293 control = get_control(b, topieces, b->board[pos], pos);
294 }
295 if (control >= 0) {
296 advance += passed_pawn_control[a];
297 ++a;
298 } else {
299 break;
300 }
301 }
302
303 if (x != 0 && white_pawn_loc[x-1] &&
304 abs(y - white_pawn_loc[x-1]) <= 1) {
305 advance += pawn_advance1[n];
306 }
307
308 if (x != 7 && white_pawn_loc[x+1] &&
309 abs(y - white_pawn_loc[x+1]) <= 1) {
310 advance += pawn_advance1[n];
311 }
312
313
314 /* a special case - is it unstoppable? */
315 if ((b->piece_mask & BLACK_MASK) == BKING_MASK) {
316 int kpos = BLACKPIECES(b)[IKING].pos;
317 int kmoves = imax(abs(XPOS(kpos) - x), 7-YPOS(kpos));
318 int pmoves = 7-y;
319 if (blacks_move(b)) kmoves--;
320 if (kmoves > pmoves) {
321 /* its a candidate for unstopppability, but we need to
322 count all pieces that have to move out of the way,
323 except those on the queening square. If we find a pawn
324 in front then we assume the current pawn is stoppable */
325
326 Square pos = piece->pos;
327
328 while (!off_board(pos+NORTH,NORTH)) {
329 pos += NORTH;
330 if (b->board[pos]) {
331 if (b->board[pos] == PAWN)
332 pmoves += 10;
333 else
334 ++pmoves;
335 if (pmoves >= kmoves)
336 break;
337 }
338 }
339 if (kmoves > pmoves) {
340 ret += UNSTOPPABLE_PAWN;
341 if (debug)
342 lprintf(0,"unstoppable %s\n",
343 posstr(piece->pos));
344 /* would it become stoppable after a null move? */
345 if (whites_move(b) && kmoves == pmoves+1) {
346 b->null_stoppable_pawn |= (1<<pi);
347 if (debug)
348 lprintf(0,"null stoppable %s\n",
349 posstr(piece->pos));
350 }
351 /* would it become unstoppable after a null move? */
352 } else if (blacks_move(b) && kmoves == pmoves) {
353 b->null_unstoppable_pawn |= (1<<pi);
354 if (debug)
355 lprintf(0,"null unstoppable %s\n",
356 posstr(piece->pos));
357 }
358 }
359 }
360
361 if (n < 4 && (ret + advance < pawn_advance[5])) {
362 /* passed pawns always have some value */
363 advance = pawn_advance[5] - ret;
364 }
365 }
366 ret += advance;
367 }
368
369 if (white_pawn_loc[x] != y)
370 ret -= DOUBLED_PAWN;
371
372 if (x==0 && white_pawn_loc[x+1] == 0)
373 ret -= ISOLATED_PAWN;
374 else if (x==7 && white_pawn_loc[x-1] == 0)
375 ret -= ISOLATED_PAWN;
376 else if (white_pawn_loc[x-1] == 0 && white_pawn_loc[x+1] == 0)
377 ret -= ISOLATED_PAWN;
378
379 /* get rid of this because its not calculated incrementally and not clear
380 that its really useful */
381 #if 0
382 if (b->stage == ENDING) {
383 if ((b->piece_mask & WBISHOP_MASK) == WKBISHOP_MASK) {
384 if (!white_square(piece->pos)) ret += ODD_BISHOPS_PAWN_POS;
385 } else if ((b->piece_mask & WBISHOP_MASK) == WQBISHOP_MASK) {
386 if (white_square(piece->pos)) ret += ODD_BISHOPS_PAWN_POS;
387 }
388 }
389 #endif
390 return ret;
391 }
392
eval_black_pawn(Position * b,int pi)393 static etype eval_black_pawn(Position *b, int pi)
394 {
395 PieceStruct *piece = b->pieces + pi;
396 etype ret=0;
397 int num = 0;
398 int x = XPOS(piece->pos);
399 int y = YPOS(piece->pos);
400 etype advance = 0;
401 int weak = 0;
402 Square pos;
403
404 b->bpassed_pawn_mask &= ~(1<<pi);
405
406 ret = pawn_pos_value[mirror_square(piece->pos)];
407
408 /* a pawn is weak if it isn't supported by a pawn and can't
409 move to a place where it is supported by a pawn */
410
411 if ((x != 0 && b->board[piece->pos+WEST] == -PAWN) ||
412 (x != 7 && b->board[piece->pos+EAST] == -PAWN)) {
413 ret += ADJACENT_PAWN;
414 }
415
416 if (b->topieces[piece->pos] & BPAWN_MASK)
417 goto not_weak;
418
419 ret -= UNSUPPORTED_PAWN;
420 if (debug)
421 lprintf(0, "unsupported %s\n", posstr(piece->pos));
422
423 if ((b->topieces[piece->pos+SOUTH] & BPAWN_MASK) &&
424 abs(b->board[piece->pos+SOUTH]) != PAWN)
425 goto not_weak;
426
427
428 if (y == 6 && !(b->topieces[piece->pos+SOUTH] & WPAWN_MASK) &&
429 (b->topieces[piece->pos+2*SOUTH] & BPAWN_MASK) &&
430 (abs(b->board[piece->pos+SOUTH]) != PAWN) &&
431 (abs(b->board[piece->pos+2*SOUTH]) != PAWN))
432 goto not_weak;
433
434 if (debug)
435 lprintf(0,"weak %s\n", posstr(piece->pos));
436 weak = 1;
437 ret -= WEAK_PAWN;
438
439 /* if its on a half open file then its even weaker */
440 if (white_pawn_loc[x] == 0)
441 ret -= MEGA_WEAK_PAWN;
442
443 /* attacks on weak pawns are worth something */
444 if (b->topieces[piece->pos] & ~b->pinned_mask & 0xFF) {
445 num = pop_count[b->topieces[piece->pos] &
446 ~b->pinned_mask & 0xFF];
447 ret -= weak_pawn_attack_value[num];
448 }
449
450 not_weak:
451
452 if (white_pawn_loc[x] == 0 || white_pawn_loc[x] > y) {
453 int n = y;
454 if (!weak) {
455 advance = pawn_advance2[n];
456 }
457 if ((x==0 || white_pawn_loc[x-1]==0 ||
458 white_pawn_loc[x-1] >= y) &&
459 (x==7 || white_pawn_loc[x+1]==0 ||
460 white_pawn_loc[x+1] >= y)) {
461 Square wkpos = WHITEPIECES(b)[IKING].pos;
462 Square bkpos = BLACKPIECES(b)[IKING].pos;
463 int a, control;
464 uint32 rook_support = 0;
465 uint32 topieces;
466
467 b->bpassed_pawn_mask |= (1<<pi);
468 pos = piece->pos;
469
470 advance += pawn_advance[n];
471
472
473 if (YPOS(wkpos) <= y && abs(XPOS(wkpos) - x) <= 1)
474 advance -= KING_PASSED_PAWN_DEFENCE;
475
476 if (YPOS(bkpos) <= y && abs(XPOS(bkpos) - x) <= 1)
477 advance += KING_PASSED_PAWN_SUPPORT;
478
479 if (b->board[piece->pos+SOUTH] > 0) {
480 advance -= BLOCKED_PASSED_PAWN;
481 }
482
483 if (x != 0 && black_pawn_loc[x-1] &&
484 abs(y - black_pawn_loc[x-1]) <= 1) {
485 advance += pawn_advance1[n];
486 }
487
488 if (x != 7 && black_pawn_loc[x+1] &&
489 abs(y - black_pawn_loc[x+1]) <= 1) {
490 advance += pawn_advance1[n];
491 }
492
493 if ((b->topieces[piece->pos] & ~b->pinned_mask & WKROOK_MASK) &&
494 XPOS(WHITEPIECES(b)[IKROOK].pos) == x &&
495 YPOS(WHITEPIECES(b)[IKROOK].pos) > y) {
496 /* there is a white king rook
497 behind our passed pawn */
498 advance -= PASSED_PAWN_ROOK_ATTACK;
499 }
500
501 if ((b->topieces[piece->pos] & ~b->pinned_mask & WQROOK_MASK) &&
502 XPOS(WHITEPIECES(b)[IQROOK].pos) == x &&
503 YPOS(WHITEPIECES(b)[IQROOK].pos) > y) {
504 /* there is a white queen rook
505 behind our passed pawn */
506 advance -= PASSED_PAWN_ROOK_ATTACK;
507 }
508
509
510 if ((b->topieces[piece->pos] & ~b->pinned_mask & BKROOK_MASK) &&
511 XPOS(BLACKPIECES(b)[IKROOK].pos) == x &&
512 YPOS(BLACKPIECES(b)[IKROOK].pos) > y) {
513 /* there is a black king rook
514 behind our passed pawn */
515 rook_support = BKROOK_MASK;
516 advance += PASSED_PAWN_ROOK_SUPPORT;
517 }
518
519 if ((b->topieces[piece->pos] & ~b->pinned_mask & BQROOK_MASK) &&
520 XPOS(BLACKPIECES(b)[IQROOK].pos) == x &&
521 YPOS(BLACKPIECES(b)[IQROOK].pos) > y) {
522 /* there is a black queen rook
523 behind our passed pawn */
524 rook_support = BQROOK_MASK;
525 advance += PASSED_PAWN_ROOK_SUPPORT;
526 }
527
528
529 a = passed_pawn_index[7-y-1];
530 while (!off_board(pos,SOUTH)) {
531 pos += SOUTH;
532 if (!rook_support) {
533 control = b->cont[pos];
534 } else {
535 topieces = b->topieces[pos] & (~b->pinned_mask);
536 topieces |= rook_support;
537 control = get_control(b, topieces, b->board[pos], pos);
538 }
539 if (control <= 0) {
540 advance += passed_pawn_control[a];
541 ++a;
542 } else {
543 break;
544 }
545 }
546
547 /* a special case - is it unstoppable? */
548 if ((b->piece_mask & WHITE_MASK) == WKING_MASK) {
549 int kpos = WHITEPIECES(b)[IKING].pos;
550 int kmoves = imax(abs(XPOS(kpos) - x), YPOS(kpos));
551 int pmoves = y;
552 if (whites_move(b)) kmoves--;
553 if (kmoves > pmoves) {
554 /* its a candidate for unstopppability, but we need to
555 count all pieces that have to move out of the way,
556 except those on the queening square. */
557
558 Square pos = piece->pos;
559
560 while (!off_board(pos+SOUTH,SOUTH)) {
561 pos += SOUTH;
562 if (b->board[pos] != 0) {
563 if (b->board[pos] == -PAWN)
564 pmoves += 10;
565 else
566 ++pmoves;
567 if (pmoves >= kmoves)
568 break;
569 }
570 }
571 if (kmoves > pmoves) {
572 ret += UNSTOPPABLE_PAWN;
573 if (debug)
574 lprintf(0,"unstoppable %s %d %d\n",
575 posstr(piece->pos),
576 kmoves, pmoves);
577 /* would it become stoppable after a null move? */
578 if (blacks_move(b) && kmoves == pmoves+1) {
579 b->null_stoppable_pawn |= (1<<pi);
580 if (debug)
581 lprintf(0,"null stoppable %s\n",
582 posstr(piece->pos));
583 }
584 /* would it become unstoppable after a null move? */
585 } else if (whites_move(b) && kmoves == pmoves) {
586 b->null_unstoppable_pawn |= (1<<pi);
587 if (debug)
588 lprintf(0,"null unstoppable %s\n",
589 posstr(piece->pos));
590 }
591 }
592 }
593 if (n < 4 && (ret + advance < pawn_advance[5])) {
594 /* passed pawns always have some value */
595 advance = pawn_advance[5] - ret;
596 }
597 }
598 if (debug)
599 lprintf(0,"%s advance: %e\n", posstr(piece->pos), advance);
600 ret += advance;
601 }
602
603 if (black_pawn_loc[x] != y)
604 ret -= DOUBLED_PAWN;
605
606 if (x==0 && black_pawn_loc[x+1] == 0)
607 ret -= ISOLATED_PAWN;
608 else if (x==7 && black_pawn_loc[x-1] == 0)
609 ret -= ISOLATED_PAWN;
610 else if (black_pawn_loc[x-1] == 0 && black_pawn_loc[x+1] == 0)
611 ret -= ISOLATED_PAWN;
612
613 #if 0
614 if (b->stage == ENDING)
615 if ((b->piece_mask & BBISHOP_MASK) == BKBISHOP_MASK) {
616 if (white_square(piece->pos)) ret += ODD_BISHOPS_PAWN_POS;
617 } else if ((b->piece_mask & BBISHOP_MASK) == BQBISHOP_MASK) {
618 if (!white_square(piece->pos)) ret += ODD_BISHOPS_PAWN_POS;
619 }
620 #endif
621 return ret;
622 }
623
624
625 /* these are adjustments for king position in the opening and
626 ending - they try to encourage a central king in the ending */
627 #define ending_kpos (coefficients + IENDING_KPOS)
628 #define opening_king_advance (coefficients + IOPENING_KING_ADVANCE)
629 #define mid_king_advance (coefficients + IMID_KING_ADVANCE)
630 #define king_proximity (coefficients + IKING_PROXIMITY)
631 /* the king likes to be near an edge at the start of the game and
632 near the middle at the end */
eval_white_king(Position * b,int pi)633 static etype eval_white_king(Position *b, int pi)
634 {
635 PieceStruct *piece = b->pieces + pi;
636 etype ret=0;
637
638 if (b->piece_mask & BQUEEN_MASK) {
639 if (b->stage == OPENING) {
640 if (YPOS(piece->pos) != 0)
641 ret -= opening_king_advance[YPOS(piece->pos)];
642 } if (b->stage == MIDDLE) {
643 if (YPOS(piece->pos) != 0)
644 ret -= mid_king_advance[YPOS(piece->pos)];
645 }
646 } else {
647 if (b->stage == MATING) {
648 if (b->w_material < b->b_material - STATIC_PAWN_VALUE) {
649 ret += 10*(ending_kpos[XPOS(piece->pos)] +
650 ending_kpos[YPOS(piece->pos)]);
651 } else {
652 int kpos = BLACKPIECES(b)[IKING].pos;
653 int kmoves = imax(abs(XPOS(kpos) - XPOS(piece->pos)),
654 abs(YPOS(kpos) - YPOS(piece->pos)));
655 ret -= king_proximity[kmoves];
656 }
657
658 } else {
659 ret += ending_kpos[XPOS(piece->pos)] +
660 ending_kpos[YPOS(piece->pos)];
661 }
662 }
663
664 if (b->stage >= ENDING)
665 return ret;
666
667 if (b->flags & WHITE_CASTLED) {
668 ret += CASTLE_BONUS;
669 } else if (!(b->flags & (WHITE_CASTLE_SHORT|WHITE_CASTLE_LONG))) {
670 ret -= CASTLE_BONUS;
671 }
672
673 /* forget about pawn defence once the queens are off! */
674 if (!(b->material_mask & BQUEEN_MASK))
675 return ret;
676
677 if (YPOS(piece->pos) == 0 &&
678 (XPOS(piece->pos) > 4 || (b->flags & WHITE_CASTLE_SHORT))) {
679 if (b->board[F2] == PAWN)
680 ret += pawn_defence[FPAWN];
681 if (b->board[G2] == PAWN)
682 ret += pawn_defence[GPAWN];
683 if (b->board[H2] == PAWN)
684 ret += pawn_defence[HPAWN];
685 if (b->board[H3] == PAWN && b->board[G2] == PAWN)
686 ret += pawn_defence[HGPAWN];
687 if (b->board[G3] == PAWN && b->board[H2] == PAWN &&
688 !(b->material_mask & BQBISHOP_MASK))
689 ret += pawn_defence[GHPAWN];
690 if (b->board[F3] == PAWN && b->board[G2] == PAWN &&
691 !(b->material_mask & BKBISHOP_MASK))
692 ret += pawn_defence[FGPAWN];
693 }
694
695 if (YPOS(piece->pos) == 0 && XPOS(piece->pos) < 3) {
696 if (b->board[A2] == PAWN)
697 ret += pawn_defence[APAWN];
698 if (b->board[B2] == PAWN)
699 ret += pawn_defence[BPAWN];
700 if (b->board[C2] == PAWN)
701 ret += pawn_defence[CPAWN];
702 if (b->board[A3] == PAWN && b->board[B2] == PAWN)
703 ret += pawn_defence[ABPAWN];
704 if (b->board[B3] == PAWN && b->board[A2] == PAWN &&
705 !(b->material_mask & BKBISHOP_MASK))
706 ret += pawn_defence[BAPAWN];
707 if (b->board[C3] == PAWN && b->board[B2] == PAWN &&
708 !(b->material_mask & BQBISHOP_MASK))
709 ret += pawn_defence[CBPAWN];
710 }
711
712 return ret;
713 }
714
715
eval_black_king(Position * b,int pi)716 static etype eval_black_king(Position *b, int pi)
717 {
718 PieceStruct *piece = b->pieces + pi;
719 etype ret=0;
720
721 if (b->piece_mask & WQUEEN_MASK) {
722 if (b->stage == OPENING) {
723 if (YPOS(piece->pos) != 7)
724 ret -= opening_king_advance[7-YPOS(piece->pos)];
725 } if (b->stage == MIDDLE) {
726 if (YPOS(piece->pos) != 7)
727 ret -= mid_king_advance[7-YPOS(piece->pos)];
728 }
729 } else {
730 if (b->stage == MATING) {
731 if (b->b_material < b->w_material - STATIC_PAWN_VALUE) {
732 ret += 10*(ending_kpos[XPOS(piece->pos)] +
733 ending_kpos[YPOS(piece->pos)]);
734 } else {
735 int kpos = WHITEPIECES(b)[IKING].pos;
736 int kmoves = imax(abs(XPOS(kpos) - XPOS(piece->pos)),
737 abs(YPOS(kpos)-YPOS(piece->pos)));
738 ret -= king_proximity[kmoves];
739 }
740 } else {
741 ret += ending_kpos[XPOS(piece->pos)] +
742 ending_kpos[YPOS(piece->pos)];
743 }
744 }
745
746 if (b->stage >= ENDING)
747 return ret;
748
749 if (b->flags & BLACK_CASTLED) {
750 ret += CASTLE_BONUS;
751 } else if (!(b->flags & (BLACK_CASTLE_SHORT|BLACK_CASTLE_LONG))) {
752 ret -= CASTLE_BONUS;
753 }
754
755 /* forget about pawn defence once the queens are off! */
756 if (!(b->material_mask & WQUEEN_MASK))
757 return ret;
758
759 if (YPOS(piece->pos) == 7 &&
760 (XPOS(piece->pos) > 4 || (b->flags & BLACK_CASTLE_SHORT))) {
761 if (b->board[F7] == -PAWN)
762 ret += pawn_defence[FPAWN];
763 if (b->board[G7] == -PAWN)
764 ret += pawn_defence[GPAWN];
765 if (b->board[H7] == -PAWN)
766 ret += pawn_defence[HPAWN];
767 if (b->board[H6] == -PAWN && b->board[G7] == -PAWN)
768 ret += pawn_defence[HGPAWN];
769 if (b->board[G6] == -PAWN && b->board[H7] == -PAWN &&
770 !(b->material_mask & WQBISHOP_MASK))
771 ret += pawn_defence[GHPAWN];
772 if (b->board[F6] == -PAWN && b->board[G7] == -PAWN &&
773 !(b->material_mask & WKBISHOP_MASK))
774 ret += pawn_defence[FGPAWN];
775 }
776
777 if (YPOS(piece->pos) == 7 && XPOS(piece->pos) < 3) {
778 if (b->board[A7] == -PAWN)
779 ret += pawn_defence[APAWN];
780 if (b->board[B7] == -PAWN)
781 ret += pawn_defence[BPAWN];
782 if (b->board[C7] == -PAWN)
783 ret += pawn_defence[CPAWN];
784 if (b->board[A6] == -PAWN && b->board[B7] == -PAWN)
785 ret += pawn_defence[ABPAWN];
786 if (b->board[B6] == -PAWN && b->board[A7] == -PAWN &&
787 !(b->material_mask & WKBISHOP_MASK))
788 ret += pawn_defence[BAPAWN];
789 if (b->board[C6] == -PAWN && b->board[B7] == -PAWN &&
790 !(b->material_mask & WQBISHOP_MASK))
791 ret += pawn_defence[CBPAWN];
792 }
793
794 return ret;
795 }
796
797
798
eval_queen(Position * b,int pi)799 static etype eval_queen(Position *b, int pi)
800 {
801 PieceStruct *p = b->pieces + pi;
802 etype ret=0;
803
804 /* penalize early queen movement */
805 if (b->stage == OPENING) {
806 if ((p->p > 0 && YPOS(p->pos) > 2) ||
807 (p->p < 0 && YPOS(p->pos) < 5))
808 ret -= EARLY_QUEEN_MOVEMENT;
809 }
810
811 return ret;
812 }
813
eval_rook(Position * b,int pi)814 static etype eval_rook(Position *b, int pi)
815 {
816 etype *pos_value = coefficients + IROOK_POS;
817 PieceStruct *p = b->pieces + pi;
818 etype ret=0;
819 uint32 mask;
820
821 if (p->p > 0)
822 ret += pos_value[p->pos];
823 else
824 ret += pos_value[mirror_square(p->pos)];
825
826 if (p->p > 0) {
827 if ((mask = (b->topieces[p->pos] & ~b->pinned_mask & WROOK_MASK))) {
828 ret += CONNECTED_ROOKS;
829 if (YPOS(p->pos) == 6 && YPOS(b->pieces[ff_one(mask)].pos) == 6)
830 ret += SEVENTH_RANK_ROOKS;
831 }
832 } else {
833 if ((mask = (b->topieces[p->pos] & ~b->pinned_mask & BROOK_MASK))) {
834 ret += CONNECTED_ROOKS;
835 if (YPOS(p->pos) == 1 && YPOS(b->pieces[ff_one(mask)].pos) == 1)
836 ret += SEVENTH_RANK_ROOKS;
837 }
838 }
839
840 return ret;
841 }
842
843
eval_bishop_xray(Position * b,int pi)844 static etype eval_bishop_xray(Position *b, int pi)
845 {
846 PieceStruct *p = b->pieces + pi;
847 etype ret=0;
848 int xray=0;
849 PieceStruct *p2;
850 etype *xray_bonus = coefficients + IBISHOP_XRAY;
851
852 /* bishops get a bonus for Xray attacks on kings, queens or rooks */
853 p2 = &PIECES(b, -p->p)[IKING];
854 if (capture_map[p->p+KING][p->pos][p2->pos])
855 xray++;
856
857 p2 = &PIECES(b, -p->p)[IQUEEN];
858 if (p2->p && capture_map[p->p+KING][p->pos][p2->pos])
859 xray++;
860
861 p2 = &PIECES(b, -p->p)[IQROOK];
862 if (p2->p && capture_map[p->p+KING][p->pos][p2->pos])
863 xray++;
864
865 p2 = &PIECES(b, -p->p)[IKROOK];
866 if (p2->p && capture_map[p->p+KING][p->pos][p2->pos])
867 xray++;
868
869 ret += xray_bonus[xray];
870
871 return ret;
872 }
873
eval_bishop(Position * b,int pi)874 static etype eval_bishop(Position *b, int pi)
875 {
876 etype ret=0;
877 PieceStruct *p = b->pieces + pi;
878 int x = XPOS(p->pos);
879 int y = YPOS(p->pos);
880
881 /* bishops are good on outposts */
882 if (p->p > 0) {
883 if (y < 6 && y > 3 &&
884 (x == 0 || black_pawn_loc[x-1] <= y) &&
885 (x == 7 || black_pawn_loc[x+1] <= y)) {
886 ret += BISHOP_OUTPOST;
887 if ((x>0 && b->board[p->pos+SOUTH_WEST] == PAWN) ||
888 (x<7 && b->board[p->pos+SOUTH_EAST] == PAWN)) {
889 ret += SUPPORTED_BISHOP_OUTPOST;
890 }
891 }
892 } else {
893 if (y > 1 && y < 4 &&
894 (x == 0 || white_pawn_loc[x-1] == 0 ||
895 white_pawn_loc[x-1] >= y) &&
896 (x == 7 || white_pawn_loc[x+1] == 0 ||
897 white_pawn_loc[x+1] >= y)) {
898 ret += BISHOP_OUTPOST;
899 if ((x>0 && b->board[p->pos+NORTH_WEST] == -PAWN) ||
900 (x<7 && b->board[p->pos+NORTH_EAST] == -PAWN)) {
901 ret += SUPPORTED_BISHOP_OUTPOST;
902 }
903 }
904 }
905
906
907 #if 1
908 ret += eval_bishop_xray(b, pi);
909 #endif
910 return ret;
911 }
912
913
eval_knight(Position * b,int pi)914 static etype eval_knight(Position *b, int pi)
915 {
916 PieceStruct *p = b->pieces + pi;
917 etype ret=0;
918 int x = XPOS(p->pos);
919 int y = YPOS(p->pos);
920 etype *pos_value = coefficients + IKNIGHT_POS;
921
922 if (p->p > 0)
923 ret += pos_value[p->pos];
924 else
925 ret += pos_value[mirror_square(p->pos)];
926
927 /* knights are great on outposts */
928 if (p->p > 0) {
929 if (y < 6 && y > 3 &&
930 (x == 0 || black_pawn_loc[x-1] <= y) &&
931 (x == 7 || black_pawn_loc[x+1] <= y)) {
932 ret += KNIGHT_OUTPOST;
933 if ((x>0 && b->board[p->pos+SOUTH_WEST] == PAWN) ||
934 (x<7 && b->board[p->pos+SOUTH_EAST] == PAWN)) {
935 ret += SUPPORTED_KNIGHT_OUTPOST;
936 }
937 }
938 } else {
939 if (y > 1 && y < 4 &&
940 (x == 0 || white_pawn_loc[x-1] == 0 ||
941 white_pawn_loc[x-1] >= y) &&
942 (x == 7 || white_pawn_loc[x+1] == 0 ||
943 white_pawn_loc[x+1] >= y)) {
944 ret += KNIGHT_OUTPOST;
945 if ((x>0 && b->board[p->pos+NORTH_WEST] == -PAWN) ||
946 (x<7 && b->board[p->pos+NORTH_EAST] == -PAWN)) {
947 ret += SUPPORTED_KNIGHT_OUTPOST;
948 }
949 }
950 }
951
952 return ret;
953 }
954
955
956 /* build a table of the most backward pawns in each file for each color */
build_pawn_loc(Position * b)957 static void build_pawn_loc(Position *b)
958 {
959 int i;
960 PieceStruct *p;
961
962 memset(white_pawn_loc, 0, sizeof(white_pawn_loc));
963 memset(black_pawn_loc, 0, sizeof(black_pawn_loc));
964
965 p = &WHITEPIECES(b)[8];
966 for (i=0;i<8;i++, p++)
967 if (p->p == PAWN) {
968 int x = XPOS(p->pos);
969 int y = YPOS(p->pos);
970 if (white_pawn_loc[x] == 0 ||
971 white_pawn_loc[x] > y)
972 white_pawn_loc[x] = y;
973 }
974
975 p = &BLACKPIECES(b)[8];
976 for (i=0;i<8;i++, p++)
977 if (p->p == -PAWN) {
978 int x = XPOS(p->pos);
979 int y = YPOS(p->pos);
980 black_pawn_loc[x] = imax(black_pawn_loc[x], y);
981 }
982 }
983
984
estimate_game_stage(Position * b,int root_node)985 void estimate_game_stage(Position *b, int root_node)
986 {
987 int count;
988 int last_stage = b->stage;
989 if (!root_node)
990 return;
991
992 count = pop_count[b->piece_mask & 0xFF] +
993 pop_count[(b->piece_mask >> 16) & 0xFF];
994
995 if ((b->piece_mask & QUEEN_MASK) == QUEEN_MASK)
996 count += 2;
997
998 if (b->piece_mask == b->material_mask) {
999 b->stage = MATING;
1000 } else if (count <= 6) {
1001 b->stage = ENDING;
1002 } else if (count >= 16 && (b->flags & FLAG_CAN_CASTLE)) {
1003 b->stage = OPENING;
1004 } else {
1005 b->stage = MIDDLE;
1006 }
1007
1008 coefficients = new_coefficients + b->stage*__COEFFS_PER_STAGE__;
1009 b->piece_change |= KING_MASK;
1010 b->piece_change |= (QUEEN_MASK & b->piece_mask);
1011
1012 if (b->stage != last_stage) {
1013 lprintf(0, "*** Entering stage %d (%d)\n", b->stage, last_stage);
1014 hash_reset();
1015 }
1016 }
1017
1018
1019 /* try to discourage specific positional features - particularly in
1020 the opening */
specifics(Position * b)1021 static etype specifics(Position *b)
1022 {
1023 etype ret = 0;
1024
1025 /* blocking the e or d pawn is a bad idea */
1026 if (b->board[D3] && b->board[D2] == PAWN)
1027 ret -= BLOCKED_DPAWN;
1028
1029 if (b->board[E3] && b->board[E2] == PAWN)
1030 ret -= BLOCKED_EPAWN;
1031
1032 if (b->board[D6] && b->board[D7] == -PAWN)
1033 ret -= -BLOCKED_DPAWN;
1034
1035 if (b->board[E6] && b->board[E7] == -PAWN)
1036 ret -= -BLOCKED_EPAWN;
1037
1038
1039 /* blocking in knights is a bad idea */
1040 if (b->board[C3] && b->board[B1] == KNIGHT)
1041 ret -= BLOCKED_KNIGHT;
1042
1043 if (b->board[F3] && b->board[G1] == KNIGHT)
1044 ret -= BLOCKED_KNIGHT;
1045
1046 if (b->board[C6] && b->board[B8] == -KNIGHT)
1047 ret -= -BLOCKED_KNIGHT;
1048
1049 if (b->board[F6] && b->board[G8] == -KNIGHT)
1050 ret -= -BLOCKED_KNIGHT;
1051
1052 /* pairs of bishops are good */
1053 if ((b->piece_mask & WBISHOP_MASK) == WBISHOP_MASK)
1054 ret += BISHOP_PAIR;
1055
1056 if ((b->piece_mask & BBISHOP_MASK) == BBISHOP_MASK)
1057 ret -= BISHOP_PAIR;
1058
1059 /* opposite bishops is drawish */
1060 if ((b->piece_mask & BISHOP_MASK) == (WKBISHOP_MASK | BKBISHOP_MASK) ||
1061 (b->piece_mask & BISHOP_MASK) == (WQBISHOP_MASK | BQBISHOP_MASK)) {
1062 if (b->b_material > b->w_material + STATIC_PAWN_VALUE/2)
1063 ret += OPPOSITE_BISHOPS;
1064 else if (b->w_material > b->b_material + STATIC_PAWN_VALUE/2)
1065 ret -= OPPOSITE_BISHOPS;
1066 }
1067
1068 /* these are some specialist endgame things */
1069 if (b->w_material < b->b_material - STATIC_PAWN_VALUE &&
1070 b->stage == MATING) {
1071 int kpos = WHITEPIECES(b)[IKING].pos;
1072
1073 ret -= NO_MATERIAL;
1074
1075 if ((b->piece_mask & BBISHOP_MASK) == BKBISHOP_MASK) {
1076 ret -= (7-corner_distance(kpos)) * MATING_POSITION;
1077 }
1078 if ((b->piece_mask & BBISHOP_MASK) == BQBISHOP_MASK) {
1079 ret -= (7-corner_distance(mirror_square(kpos))) * MATING_POSITION;
1080 }
1081 }
1082
1083 if (b->b_material < b->w_material - STATIC_PAWN_VALUE &&
1084 b->stage == MATING) {
1085 int kpos = BLACKPIECES(b)[IKING].pos;
1086
1087 ret += NO_MATERIAL;
1088
1089 if ((b->piece_mask & WBISHOP_MASK) == WQBISHOP_MASK) {
1090 ret += (7-corner_distance(kpos)) * MATING_POSITION;
1091 }
1092 if ((b->piece_mask & WBISHOP_MASK) == WKBISHOP_MASK) {
1093 ret += (7-corner_distance(mirror_square(kpos))) * MATING_POSITION;
1094 }
1095 }
1096
1097
1098 return ret;
1099 }
1100
1101
1102 #define base_pos_value (coefficients + IPOS_BASE)
1103
1104 static etype null_pos_value[NUM_SQUARES];
1105
1106
1107 #define white_king_side (coefficients + IPOS_KINGSIDE)
1108 #define white_queen_side (coefficients + IPOS_QUEENSIDE)
1109
1110 static etype black_king_side[NUM_SQUARES];
1111 static etype black_queen_side[NUM_SQUARES];
1112
1113 static int new_pos_values;
1114 static etype *sq_p1, *sq_p2;
1115
recalc_pos_values(Position * b)1116 static void recalc_pos_values(Position *b)
1117 {
1118 Square wkpos, bkpos;
1119 int flags = 0;
1120
1121 wkpos = WHITEPIECES(b)[IKING].pos;
1122 bkpos = BLACKPIECES(b)[IKING].pos;
1123
1124 sq_p1 = null_pos_value;
1125 sq_p2 = null_pos_value;
1126
1127 if (b->material_mask & QUEEN_MASK) {
1128 if (XPOS(wkpos) > 3 && YPOS(wkpos) < 3) {
1129 sq_p1 = white_king_side;
1130 flags |= FLAG_WHITE_KINGSIDE;
1131 } else if (XPOS(wkpos) < 3 && YPOS(wkpos) < 3) {
1132 sq_p1 = white_queen_side;
1133 flags |= FLAG_WHITE_QUEENSIDE;
1134 }
1135
1136 if (XPOS(bkpos) > 3 && YPOS(bkpos) > 4) {
1137 sq_p2 = black_king_side;
1138 flags |= FLAG_BLACK_KINGSIDE;
1139 } else if (XPOS(bkpos) < 3 && YPOS(bkpos) > 4) {
1140 sq_p2 = black_queen_side;
1141 flags |= FLAG_BLACK_QUEENSIDE;
1142 }
1143 }
1144
1145 if ((b->flags & FLAG_KQ_SIDE) == flags)
1146 return;
1147
1148 invert(black_king_side, white_king_side);
1149 invert(black_queen_side, white_queen_side);
1150
1151 new_pos_values = 1;
1152
1153 b->flags &= ~FLAG_KQ_SIDE;
1154 b->flags |= flags;
1155 }
1156
1157
1158 /* this basically tries to answer the question "can one of the players
1159 profitably capture on that square, assuming there was something there
1160 to capture */
1161
board_control1(Position * b)1162 static etype board_control1(Position *b)
1163 {
1164 Square i, j;
1165 int control;
1166 etype total, v;
1167 uint32 topieces, oldflight, fchange, mchange, old_pin_mask, pin_mask;
1168 uint32 oldtopieces, xray_topieces, oldxray_topieces;
1169 uint64 white_holes, black_holes, oldwhite_holes, oldblack_holes;
1170 uint32 *top, *oldtop, *xray_top, *oldxray_top, *flight;
1171 Piece *oldboard;
1172
1173 /* this is a mask which governs what piece can fly to a square
1174 given the smallest attacker on the square, so for example, the
1175 0x00FC0000 entry means that any black piece except a queen
1176 or king can fly to a square that is controlled by black if
1177 the square is covered by a white rook */
1178 static const uint32 flight_mask[32] = {
1179 0x00FE0000, 0x00FE0000, 0x00FC0000, 0x00FC0000,
1180 0x00F00000, 0x00F00000, 0x00F00000, 0x00F00000,
1181 0x00000000, 0x00000000, 0x00000000, 0x00000000,
1182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
1183
1184 0x00FE, 0x00FE, 0x00FC, 0x00FC,
1185 0x00F0, 0x00F0, 0x00F0, 0x00F0,
1186 0x0000, 0x0000, 0x0000, 0x0000,
1187 0x0000, 0x0000, 0x0000, 0x0000
1188 };
1189
1190 if (b->stage == MATING)
1191 return 0;
1192
1193 top = b->topieces;
1194 #if USE_SLIDING_CONTROL
1195 xray_top = b->xray_topieces;
1196 #endif
1197 flight = b->flight;
1198
1199 white_holes = b->white_holes;
1200 black_holes = b->black_holes;
1201
1202 recalc_pos_values(b);
1203
1204 if (b->oldb && (b->oldb->flags & FLAG_EVAL_DONE) && !new_pos_values) {
1205 oldtop = b->oldb->topieces;
1206 #if USE_SLIDING_CONTROL
1207 oldxray_top = b->oldb->xray_topieces;
1208 #endif
1209 oldwhite_holes = b->oldb->white_holes;
1210 oldblack_holes = b->oldb->black_holes;
1211 oldboard = b->oldb->board;
1212 old_pin_mask = ~b->oldb->pinned_mask;
1213 memcpy(b->mobility, b->oldb->mobility, sizeof(b->mobility));
1214 } else {
1215 static uint32 dummy[64];
1216 static Piece dummy2[64];
1217 #if USE_SLIDING_CONTROL
1218 static uint32 xray_dummy[64];
1219 oldxray_top = xray_dummy;
1220 #endif
1221 oldtop = dummy;
1222
1223 oldboard = dummy2;
1224 b->board_control = 0;
1225 b->attacking_mask = 0;
1226 old_pin_mask = ~0;
1227 memset(b->cont, 0, sizeof(b->cont));
1228 memset(b->control, 0, sizeof(b->control));
1229 memset(b->flight, 0, sizeof(b->flight));
1230 memset(b->mobility, 0, sizeof(b->mobility));
1231 memset(b->safe_mobility, 0, sizeof(b->safe_mobility));
1232 b->white_moves = b->black_moves = 0;
1233 new_pos_values = 0;
1234 }
1235
1236 pin_mask = ~b->pinned_mask;
1237
1238 total = b->board_control;
1239
1240 for (i=A1;i<=H8;i++) {
1241 topieces = top[i] & pin_mask;
1242 oldtopieces = oldtop[i] & old_pin_mask;
1243 #if USE_SLIDING_CONTROL
1244 xray_topieces = xray_top[i];
1245 oldxray_topieces = oldxray_top[i];
1246 #endif
1247
1248 if (topieces == oldtopieces && b->board[i] == oldboard[i]
1249 #if USE_SLIDING_CONTROL
1250 && xray_topieces == oldxray_topieces
1251 #endif
1252 ) {
1253 continue;
1254 }
1255
1256 /* if there is something on the square then recalc that piece
1257 as well */
1258 if (b->board[i])
1259 b->piece_change |= (1<<b->pboard[i]);
1260
1261 /* something has changed on the square - we need to recalculate
1262 everything */
1263
1264 oldflight = flight[i];
1265
1266 /* we define two control values, one taking into
1267 account whites pins,
1268 and the other taking into account blacks pins */
1269 control = get_control(b, topieces, b->board[i], i);
1270 #if 0
1271 if (debug)
1272 lprintf(0,"control %s %d\n", posstr(i), control);
1273 #endif
1274 /* now the trapped pieces stuff. we need to work out what
1275 pieces can flee to this square
1276
1277 a square can be used as a flight square only if the
1278 piece would not be hung when it moves there.
1279
1280 we use the flight mask to shortcut this calculation
1281 */
1282 if (control > 0 && b->board[i] <= 0) {
1283 if (topieces & BLACK_MASK) {
1284 flight[i] = flight_mask[fl_one(topieces&BLACK_MASK)] & topieces & pin_mask;
1285 } else {
1286 flight[i] = WHITE_MASK & topieces & pin_mask;
1287 }
1288 } else if (control < 0 && b->board[i] >= 0) {
1289 if (topieces & WHITE_MASK) {
1290 flight[i] = flight_mask[fl_one(topieces&WHITE_MASK)] & topieces & pin_mask;
1291 } else {
1292 flight[i] = BLACK_MASK & topieces & pin_mask;
1293 }
1294 } else {
1295 flight[i] = 0;
1296 }
1297
1298 flight[i] &= b->piece_mask;
1299
1300 /* this xor tells us what pieces have changed in their
1301 safe mobility */
1302 fchange = (oldflight ^ flight[i]) & b->piece_mask;
1303
1304 while (fchange & WHITE_MASK) {
1305 j = ff_one(fchange & WHITE_MASK);
1306 fchange &= ~(1<<j);
1307 if (flight[i] & (1<<j)) {
1308 b->safe_mobility[j]++;
1309 b->white_moves++;
1310 } else {
1311 b->safe_mobility[j]--;
1312 b->white_moves--;
1313 }
1314 }
1315
1316 while (fchange) {
1317 j = ff_one(fchange);
1318 fchange &= ~(1<<j);
1319 if (flight[i] & (1<<j)) {
1320 b->safe_mobility[j]++;
1321 b->black_moves++;
1322 } else {
1323 b->safe_mobility[j]--;
1324 b->black_moves--;
1325 }
1326 }
1327
1328 /* this xor tells us what pieces have changed in their
1329 mobility */
1330 mchange = (oldtopieces ^ topieces) & b->piece_mask;
1331
1332 while (mchange & WHITE_MASK) {
1333 j = ff_one(mchange & WHITE_MASK);
1334 mchange &= ~(1<<j);
1335 if (topieces & (1<<j)) {
1336 b->mobility[j]++;
1337 } else {
1338 b->mobility[j]--;
1339 }
1340 }
1341
1342 while (mchange) {
1343 j = ff_one(mchange);
1344 mchange &= ~(1<<j);
1345 if (topieces & (1<<j)) {
1346 b->mobility[j]++;
1347 } else {
1348 b->mobility[j]--;
1349 }
1350 }
1351
1352 /* the board control itself */
1353 if (control > 0) {
1354 v = base_pos_value[i] + sq_p1[i];
1355 } else if (control < 0) {
1356 v = -(base_pos_value[mirror_square(i)] + sq_p2[i]);
1357 } else {
1358 v = 0;
1359 }
1360
1361 b->cont[i] = SIGN(control);
1362 if (control == 0)
1363 b->cont[i] = 0;
1364 total += v - b->control[i];
1365 b->control[i] = v;
1366 }
1367
1368 b->board_control = total;
1369
1370 return total;
1371 }
1372
1373 #define attack_value (coefficients + IATTACK_VALUE)
board_control2(Position * b)1374 static etype board_control2(Position *b)
1375 {
1376 Square i, j;
1377 int numblack, numwhite;
1378 etype ret;
1379 uint32 hung, attacking;
1380
1381 numblack = 0;
1382 numwhite = 0;
1383 hung = 0;
1384 attacking = 0;
1385
1386 if (b->stage == MATING)
1387 return 0;
1388
1389 for (i=1;i<16;i++) {
1390 if (!b->pieces[i].p) continue;
1391 j = b->pieces[i].pos;
1392
1393 if (b->topieces[j] & BLACK_MASK) {
1394 attacking |= b->topieces[j] & BLACK_MASK;
1395 numblack += pop_count[(b->topieces[j]>>16) & 0xFF];
1396 if (b->control[j] <= 0) {
1397 if (b->control[j] < 0)
1398 hung |= (1<<i);
1399 }
1400 }
1401 }
1402
1403 for (i=17;i<32;i++) {
1404 if (!b->pieces[i].p) continue;
1405 j = b->pieces[i].pos;
1406
1407 if (b->topieces[j] & WHITE_MASK) {
1408 attacking |= b->topieces[j] & WHITE_MASK;
1409 numwhite += pop_count[b->topieces[j] & 0xFF];
1410 if (b->control[j] >= 0) {
1411 if (b->control[j] > 0)
1412 hung |= (1<<i);
1413 }
1414 }
1415 }
1416
1417 ret = attack_value[numwhite] - attack_value[numblack];
1418
1419 attacking &= b->piece_mask;
1420 b->piece_change |= b->attacking_mask ^ attacking;
1421 b->hung_mask = hung;
1422 b->attacking_mask = attacking;
1423
1424 if (debug) {
1425 lprintf(0,"attacking_mask=%08x\n", b->attacking_mask);
1426 lprintf(0,"hung_mask=%08x\n", b->hung_mask);
1427 }
1428
1429 return ret;
1430 }
1431
1432
empty_line(Position * b,int sq1,int sq2)1433 static int empty_line(Position *b, int sq1, int sq2)
1434 {
1435 int dir, dx, dy;
1436
1437 dx = XPOS(sq1) - XPOS(sq2);
1438 dy = YPOS(sq1) - YPOS(sq2);
1439
1440 dir = 0;
1441 if (dy > 0)
1442 dir += SOUTH;
1443 else if (dy < 0)
1444 dir += NORTH;
1445
1446 if (dx > 0)
1447 dir += WEST;
1448 else if (dx < 0)
1449 dir += EAST;
1450
1451 sq1 += dir;
1452
1453 while (sq1 != sq2) {
1454 if (b->board[sq1]) return 0;
1455 sq1 += dir;
1456 }
1457
1458 return 1;
1459 }
1460
1461 #define trapped_step (coefficients + ITRAPPED_STEP)
1462
mobility_fn(Position * b,int pi)1463 static etype mobility_fn(Position *b, int pi)
1464 {
1465 static const int mobility_threshold[KING+1] = {0, 0, 6, 5, 4, 6, 0};
1466 int mobility;
1467 etype ret=0;
1468 Piece p = abs(b->pieces[pi].p);
1469 Square pos = b->pieces[pi].pos;
1470 int y = YPOS(b->pieces[pi].pos);
1471 etype *mobility_table[KING+1] = {NULL, NULL,
1472 &coefficients[IKNIGHT_MOBILITY],
1473 &coefficients[IBISHOP_MOBILITY],
1474 &coefficients[IROOK_MOBILITY],
1475 &coefficients[IQUEEN_MOBILITY],
1476 &coefficients[IKING_MOBILITY]};
1477
1478 etype *safe_mobility_table[KING+1] =
1479 {NULL, NULL, &coefficients[IKNIGHT_SMOBILITY],
1480 &coefficients[IBISHOP_SMOBILITY],
1481 &coefficients[IROOK_SMOBILITY],
1482 &coefficients[IQUEEN_SMOBILITY],
1483 &coefficients[IKING_SMOBILITY]};
1484
1485 if (p != b->pieces[pi].p)
1486 y = 7-y;
1487
1488 mobility = b->mobility[pi];
1489 if (mobility >= 10) {
1490 mobility = 9;
1491 }
1492
1493 if (mobility_table[p]) {
1494 ret = mobility_table[p][y*10+mobility];
1495 }
1496
1497 if (b->mobility[pi] < mobility_threshold[p] &&
1498 !(b->attacking_mask & (1<<pi))) {
1499 if (debug)
1500 lprintf(0,"useless %s\n",
1501 posstr(pos));
1502 ret -= USELESS_PIECE;
1503 }
1504
1505 mobility = b->safe_mobility[pi];
1506 if (mobility >= 10) {
1507 mobility = 9;
1508 }
1509
1510 if (safe_mobility_table[p])
1511 ret += safe_mobility_table[p][y*10+mobility];
1512
1513 if (b->safe_mobility[pi] == 0) {
1514 if (b->pieces[pi].p > 0) {
1515 ret -= trapped_step[YPOS(pos)];
1516 } else {
1517 ret -= trapped_step[(7-YPOS(pos))];
1518 }
1519 }
1520
1521 return ret;
1522 }
1523
1524
piece_values(Position * b)1525 static etype piece_values(Position *b)
1526 {
1527 etype v;
1528 etype total;
1529 int i;
1530 uint32 piece_change;
1531
1532 piece_change = b->piece_change;
1533
1534 total = 0;
1535
1536 for (i=0;i<32;i++) {
1537 if (!b->pieces[i].p) continue;
1538 if (!(piece_change & (1<<i)) && b->oldb) {
1539 total += b->piece_values[i];
1540 } else {
1541 switch (b->pieces[i].p) {
1542 case PAWN:
1543 v = eval_white_pawn(b, i);
1544 break;
1545 case KNIGHT:
1546 v = eval_knight(b, i);
1547 break;
1548 case BISHOP:
1549 v = eval_bishop(b, i);
1550 break;
1551 case ROOK:
1552 v = eval_rook(b, i);
1553 break;
1554 case QUEEN:
1555 v = eval_queen(b, i);
1556 break;
1557 case KING:
1558 v = eval_white_king(b, i);
1559 break;
1560 case -PAWN:
1561 v = -eval_black_pawn(b, i);
1562 break;
1563 case -KNIGHT:
1564 v = -eval_knight(b, i);
1565 break;
1566 case -BISHOP:
1567 v = -eval_bishop(b, i);
1568 break;
1569 case -ROOK:
1570 v = -eval_rook(b, i);
1571 break;
1572 case -QUEEN:
1573 v = -eval_queen(b, i);
1574 break;
1575 case -KING:
1576 v = -eval_black_king(b, i);
1577 break;
1578 default:
1579 v = 0;
1580 lprintf(0,"no piece? i=%d pos=%s p=%d\n",
1581 i, posstr(b->pieces[i].pos),
1582 b->pieces[i].p);
1583 #if 0
1584 beep(20);
1585 sleep(120);
1586 #endif
1587 break;
1588 }
1589
1590 total += v;
1591 b->piece_values[i] = v;
1592 }
1593 }
1594
1595 if (debug) {
1596 lprintf(0,"white pvalues: \n");
1597 for (i=0;i<16;i++)
1598 if (b->pieces[i].p)
1599 lprintf(0,"%+3d ", b->piece_values[i]);
1600 else
1601 lprintf(0,"*** ");
1602 lprintf(0,"\n");
1603 lprintf(0,"black pvalues: \n");
1604 for (i=16;i<32;i++)
1605 if (b->pieces[i].p)
1606 lprintf(0,"%+3d ", -b->piece_values[i]);
1607 else
1608 lprintf(0,"*** ");
1609 lprintf(0,"\n");
1610 }
1611
1612 b->piece_change = 0;
1613
1614 return total;
1615 }
1616
1617
eval_mobility(Position * b)1618 static etype eval_mobility(Position *b)
1619 {
1620 int i;
1621 etype total;
1622
1623 total = 0;
1624
1625 if (b->stage == MATING)
1626 return 0;
1627
1628 for (i=0;i<16;i++) {
1629 if (!(b->piece_mask & (1<<i))) continue;
1630 total += mobility_fn(b, i);
1631 }
1632
1633 for (i=16;i<32;i++) {
1634 if (!(b->piece_mask & (1<<i))) continue;
1635 total -= mobility_fn(b, i);
1636 }
1637
1638 if (debug) {
1639 lprintf(0,"white safe mobility: \n");
1640 for (i=0;i<16;i++)
1641 if (b->pieces[i].p)
1642 lprintf(0,"%+3d ", b->safe_mobility[i]);
1643 else
1644 lprintf(0,"*** ");
1645 lprintf(0,"\n");
1646 lprintf(0,"black safe mobility: \n");
1647 for (i=16;i<32;i++)
1648 if (b->pieces[i].p)
1649 lprintf(0,"%+3d ", b->safe_mobility[i]);
1650 else
1651 lprintf(0,"*** ");
1652 lprintf(0,"\n");
1653 lprintf(0,"white mobility: \n");
1654 for (i=0;i<16;i++)
1655 if (b->pieces[i].p)
1656 lprintf(0,"%+3d ", b->mobility[i]);
1657 else
1658 lprintf(0,"*** ");
1659 lprintf(0,"\n");
1660 lprintf(0,"black mobility: \n");
1661 for (i=16;i<32;i++)
1662 if (b->pieces[i].p)
1663 lprintf(0,"%+3d ", b->mobility[i]);
1664 else
1665 lprintf(0,"*** ");
1666 lprintf(0,"\n");
1667 }
1668
1669 return total;
1670 }
1671
egtb(Position * b)1672 int egtb(Position *b)
1673 {
1674 int ret = 0;
1675
1676 #if USE_EGTB
1677 if (pop_count32(b->material_mask) < 5 ||
1678 (pop_count32(b->material_mask) == 5 &&
1679 ((b->w_material == KING_VALUE + ROOK_VALUE + KNIGHT_VALUE &&
1680 b->b_material == KING_VALUE + ROOK_VALUE) ||
1681 (b->b_material == KING_VALUE + ROOK_VALUE + KNIGHT_VALUE &&
1682 b->w_material == KING_VALUE + ROOK_VALUE) ||
1683 (b->w_material == KING_VALUE + ROOK_VALUE + BISHOP_VALUE &&
1684 b->b_material == KING_VALUE + ROOK_VALUE) ||
1685 (b->b_material == KING_VALUE + ROOK_VALUE + BISHOP_VALUE &&
1686 b->w_material == KING_VALUE + ROOK_VALUE))))
1687 ret = 1;
1688 #endif
1689 return ret;
1690 }
1691
1692
no_material(Position * b)1693 int no_material(Position *b)
1694 {
1695
1696 if (((b->material_mask & WHITE_MASK) == (b->piece_mask & WHITE_MASK) &&
1697 (b->w_material <= emax(KING_VALUE+BISHOP_VALUE, KING_VALUE+KNIGHT_VALUE) ||
1698 b->w_material == KING_VALUE+2*KNIGHT_VALUE)) &&
1699 ((b->material_mask & BLACK_MASK) == (b->piece_mask & BLACK_MASK) &&
1700 (b->b_material <= emax(KING_VALUE+BISHOP_VALUE, KING_VALUE+KNIGHT_VALUE) ||
1701 b->b_material == KING_VALUE+2*KNIGHT_VALUE))) {
1702 return 1;
1703 }
1704
1705 return 0;
1706 }
1707
1708 #define piece_trade_bonus (coefficients + IPIECE_TRADE_BONUS)
1709 #define pawn_trade_bonus (coefficients + IPAWN_TRADE_BONUS)
1710
1711 /* this is called only when there are no pawns on the board.
1712 eval_tactics must already have been called */
check_material(Position * b,etype ret0)1713 static etype check_material(Position *b, etype ret0)
1714 {
1715 etype ret = ret0;
1716 int num = 0;
1717 etype v, vdraw = draw_value(b);
1718
1719 #if USE_EGTB
1720 if (pop_count32(b->material_mask) < 5 ||
1721 (pop_count32(b->material_mask) == 5 &&
1722 ((b->w_material == KING_VALUE + ROOK_VALUE + KNIGHT_VALUE &&
1723 b->b_material == KING_VALUE + ROOK_VALUE) ||
1724 (b->b_material == KING_VALUE + ROOK_VALUE + KNIGHT_VALUE &&
1725 b->w_material == KING_VALUE + ROOK_VALUE) ||
1726 (b->w_material == KING_VALUE + ROOK_VALUE + BISHOP_VALUE &&
1727 b->b_material == KING_VALUE + ROOK_VALUE) ||
1728 (b->b_material == KING_VALUE + ROOK_VALUE + BISHOP_VALUE &&
1729 b->w_material == KING_VALUE + ROOK_VALUE)))) {
1730
1731 EGInit();
1732 if (EGTBScore(b, &v)) {
1733 if (v == 0)
1734 ret = vdraw;
1735 else
1736 ret = next_to_play(b)*v;
1737 if (debug)
1738 lprintf(0, "EGTB: %d\n", ret);
1739 b->flags |= FLAG_EGTB_EVAL;
1740 return ret - ret0;
1741 }
1742 }
1743 #endif
1744
1745 if (b->material_mask == b->piece_mask && b->tactics == 0) {
1746 /* queen and king vs queen and king is probably a draw */
1747 if (b->w_material == KING_VALUE+QUEEN_VALUE &&
1748 b->b_material == KING_VALUE+QUEEN_VALUE) {
1749 ret = vdraw * 2;
1750 b->flags |= FLAG_ACCEPT_DRAW;
1751 return ret - ret0;
1752 }
1753
1754 /* king and rook vs king and rook is almost always a draw */
1755 if (b->w_material == KING_VALUE+ROOK_VALUE &&
1756 b->b_material == KING_VALUE+ROOK_VALUE) {
1757 ret = vdraw * 2;
1758 b->flags |= FLAG_ACCEPT_DRAW;
1759 return ret - ret0;
1760 }
1761 }
1762
1763 /* rook vs bishop or knight (+ pawn) is not good for whoever has the rook */
1764 if (b->w_material == KING_VALUE+ROOK_VALUE &&
1765 b->b_material <= KING_VALUE+ROOK_VALUE &&
1766 (b->piece_mask & BMINOR_MASK)) {
1767 ret = -NEAR_DRAW_VALUE;
1768 return ret - ret0;
1769 }
1770 if (b->b_material == KING_VALUE+ROOK_VALUE &&
1771 b->w_material <= KING_VALUE+ROOK_VALUE &&
1772 (b->piece_mask & WMINOR_MASK)) {
1773 ret = NEAR_DRAW_VALUE;
1774 return ret - ret0;
1775 }
1776
1777 /* rook and minor vs rook and pawns is unlikely to be good
1778 for the guy with the rook and minor */
1779 if ((b->w_material == KING_VALUE+ROOK_VALUE+BISHOP_VALUE ||
1780 b->w_material == KING_VALUE+ROOK_VALUE+KNIGHT_VALUE) &&
1781 b->b_material <= KING_VALUE+ROOK_VALUE+BISHOP_VALUE &&
1782 (b->piece_mask & BROOK_MASK)) {
1783 ret = -NEAR_DRAW_VALUE;
1784 return ret - ret0;
1785 }
1786
1787 if ((b->b_material == KING_VALUE+ROOK_VALUE+BISHOP_VALUE ||
1788 b->b_material == KING_VALUE+ROOK_VALUE+KNIGHT_VALUE) &&
1789 b->w_material <= KING_VALUE+ROOK_VALUE+BISHOP_VALUE &&
1790 (b->piece_mask & WROOK_MASK)) {
1791 ret = NEAR_DRAW_VALUE;
1792 return ret - ret0;
1793 }
1794
1795 if ((b->material_mask & WHITE_MASK) == (b->piece_mask & WHITE_MASK) &&
1796 (b->w_material <= emax(KING_VALUE+BISHOP_VALUE, KING_VALUE+KNIGHT_VALUE) ||
1797 b->w_material == KING_VALUE+2*KNIGHT_VALUE)) {
1798 /* white has insufficient material to mate */
1799 ret = emin(ret, vdraw);
1800 }
1801
1802 if ((b->material_mask & BLACK_MASK) == (b->piece_mask & BLACK_MASK) &&
1803 (b->b_material <= emax(KING_VALUE+BISHOP_VALUE, KING_VALUE+KNIGHT_VALUE) ||
1804 b->b_material == KING_VALUE+2*KNIGHT_VALUE)) {
1805 /* black has insufficient material to mate */
1806 ret = emax(ret, vdraw);
1807 }
1808
1809 if (ret == vdraw && ret0 != ret) {
1810 b->flags |= FLAG_ACCEPT_DRAW;
1811 if (debug)
1812 lprintf(0,"will accept draw\n");
1813 return ret - ret0;
1814 } else {
1815 b->flags &= ~FLAG_ACCEPT_DRAW;
1816 }
1817
1818 /* push it nearer a draw as the fifty move mark approaches */
1819 if (b->stage != MATING && ret != 0 && b->fifty_count > 20) {
1820 ret = ((128 - (b->fifty_count-20)) * ret) / 128;
1821 }
1822
1823 if (b->w_material >= b->b_material + (0.8*STATIC_PAWN_VALUE)) {
1824 /* encourage piece trading but not pawn trading */
1825 num = pop_count32(b->piece_mask);
1826 ret += piece_trade_bonus[num];
1827 num = pop_count32(b->material_mask & ~b->piece_mask);
1828 ret -= pawn_trade_bonus[num];
1829 }
1830
1831 if (b->b_material >= b->w_material + (0.8*STATIC_PAWN_VALUE)) {
1832 /* encourage pawn trading but not piece trading */
1833 num = pop_count32(b->piece_mask);
1834 ret -= piece_trade_bonus[num];
1835 num = pop_count32(b->material_mask & ~b->piece_mask);
1836 ret += pawn_trade_bonus[num];
1837 }
1838
1839 return ret - ret0;
1840 }
1841
1842 #define q_king_attack_computer (coefficients + IQ_KING_ATTACK_COMPUTER)
1843 #define q_king_attack_opponent (coefficients + IQ_KING_ATTACK_OPPONENT)
1844 #define noq_king_attack_computer (coefficients + INOQ_KING_ATTACK_COMPUTER)
1845 #define noq_king_attack_opponent (coefficients + INOQ_KING_ATTACK_OPPONENT)
1846
white_king_safety(Position * b)1847 static etype white_king_safety(Position *b)
1848 {
1849 etype *king_attack_computer, *king_attack_opponent;
1850 etype file_safety;
1851 etype ret=0;
1852 int num = 0;
1853 Square x1, x2, y1, y2, kpos, x, y, pos;
1854 uint32 mask=0;
1855
1856 if (!(b->piece_mask & BQUEEN_MASK)) {
1857 king_attack_computer = q_king_attack_computer;
1858 king_attack_opponent = q_king_attack_opponent;
1859 file_safety = QUEEN_FILE_SAFETY;
1860 } else {
1861 king_attack_computer = noq_king_attack_computer;
1862 king_attack_opponent = noq_king_attack_opponent;
1863 file_safety = NOQUEEN_FILE_SAFETY;
1864 }
1865
1866 /* the opponents queen is on the board, we need to worry about
1867 king safety. The major components is "king attack", which
1868 is proportional to the number of attacks made by enemy
1869 pieces on the king. To find this we need to loop over the squares
1870 around the king */
1871
1872 kpos = WHITEPIECES(b)[IKING].pos;
1873
1874 if (XPOS(kpos) == 0) {
1875 x1 = 0; x2 = 1;
1876 } else if (XPOS(kpos) == 7) {
1877 x1 = 6; x2 = 7;
1878 } else {
1879 x1 = XPOS(kpos)-1; x2 = x1+2;
1880 }
1881
1882 if (YPOS(kpos) == 0) {
1883 y1 = 0; y2 = 1;
1884 } else if (YPOS(kpos) == 7) {
1885 y1 = 6; y2 = 7;
1886 } else {
1887 y1 = YPOS(kpos)-1; y2 = y1+2;
1888 }
1889
1890 for (x=x1;x<=x2;x++)
1891 for (y=y1;y<=y2;y++) {
1892 pos = POSN(x, y);
1893 mask |= ((b->topieces[pos] & ~BKING_MASK) >> 16) & 0xFF;
1894 #if USE_SLIDING_CONTROL
1895 mask |= (b->xray_topieces[pos] >> 16) & 0xFF;
1896 #endif
1897 }
1898
1899 num = pop_count[mask];
1900 if ((BROOK_MASK >> 16) & mask)
1901 ++num;
1902
1903 if (b->flags & FLAG_COMPUTER_WHITE) {
1904 ret = -king_attack_computer[num];
1905 } else {
1906 ret = -king_attack_opponent[num];
1907 }
1908
1909 /* now check for open files next to the king */
1910
1911 for (x=x1; x<=x2; x++) {
1912 if (white_pawn_loc[x] == 0 && black_pawn_loc[x] == 0)
1913 ret -= file_safety;
1914 }
1915
1916 return ret;
1917 }
1918
black_king_safety(Position * b)1919 static etype black_king_safety(Position *b)
1920 {
1921 etype *king_attack_computer, *king_attack_opponent;
1922 etype file_safety;
1923 etype ret=0;
1924 int num = 0;
1925 uint32 mask=0;
1926 Square x1, x2, y1, y2, kpos, x, y, pos;
1927
1928 if (!(b->piece_mask & WQUEEN_MASK)) {
1929 king_attack_computer = q_king_attack_computer;
1930 king_attack_opponent = q_king_attack_opponent;
1931 file_safety = QUEEN_FILE_SAFETY;
1932 } else {
1933 king_attack_computer = noq_king_attack_computer;
1934 king_attack_opponent = noq_king_attack_opponent;
1935 file_safety = NOQUEEN_FILE_SAFETY;
1936 }
1937
1938 /* the opponents queen is on the board, we need to worry about
1939 king safety. The major components is "king attack", which
1940 is proportional to the number of attacks made by enemy
1941 pieces on the king. To find this we need to loop over the squares
1942 around the king */
1943
1944 kpos = BLACKPIECES(b)[IKING].pos;
1945
1946 if (XPOS(kpos) == 0) {
1947 x1 = 0; x2 = 1;
1948 } else if (XPOS(kpos) == 7) {
1949 x1 = 6; x2 = 7;
1950 } else {
1951 x1 = XPOS(kpos)-1; x2 = x1+2;
1952 }
1953
1954 if (YPOS(kpos) == 0) {
1955 y1 = 0; y2 = 1;
1956 } else if (YPOS(kpos) == 7) {
1957 y1 = 6; y2 = 7;
1958 } else {
1959 y1 = YPOS(kpos)-1; y2 = y1+2;
1960 }
1961
1962 for (x=x1;x<=x2;x++)
1963 for (y=y1;y<=y2;y++) {
1964 pos = POSN(x, y);
1965 mask |= b->topieces[pos] & ~WKING_MASK & 0xFF;
1966 #if USE_SLIDING_CONTROL
1967 mask |= b->xray_topieces[pos] & 0xFF;
1968 #endif
1969 }
1970
1971 num = pop_count[mask];
1972 if (mask & WROOK_MASK)
1973 ++num;
1974
1975 if (b->flags & FLAG_COMPUTER_WHITE)
1976 ret = -king_attack_opponent[num];
1977 else
1978 ret = -king_attack_computer[num];
1979
1980 /* now check for open files next to the king */
1981
1982 for (x=x1; x<=x2; x++) {
1983 if (black_pawn_loc[x] == 0 && white_pawn_loc[x] == 0)
1984 ret -= file_safety;
1985 }
1986
1987 return ret;
1988 }
1989
king_safety(Position * b)1990 static etype king_safety(Position *b)
1991 {
1992 return white_king_safety(b) - black_king_safety(b);
1993 }
1994
1995 /* an overloaded piece p is one that defends more than one other piece
1996 or pawn that would become hung if p's support was removed */
1997
1998 #define overloaded_penalty (coefficients + IOVERLOADED_PENALTY)
overloaded_pieces(Position * b)1999 static etype overloaded_pieces(Position *b)
2000 {
2001 unsigned pi;
2002 etype ret = 0;
2003 int i;
2004 Square pos;
2005 uint32 mask;
2006 int white_overloaded[8];
2007 int black_overloaded[8];
2008
2009 memset(white_overloaded, 0, sizeof(white_overloaded));
2010 memset(black_overloaded, 0, sizeof(black_overloaded));
2011
2012 for (i=0;i<32;i++) {
2013 if (!b->pieces[i].p) continue;
2014 pos = b->pieces[i].pos;
2015 if (b->cont[pos] != 0 || b->topieces[pos] == 0)
2016 continue;
2017 if (b->board[pos] > 0) {
2018 mask = b->topieces[pos] & WPIECE_MASK;
2019 while (mask) {
2020 pi = ff_one(mask);
2021 mask &= ~(1<<pi);
2022 ++white_overloaded[pi];
2023 }
2024 } else {
2025 mask = (b->topieces[pos] & BPIECE_MASK) >> 16;
2026 while (mask) {
2027 pi = ff_one(mask);
2028 mask &= ~(1<<pi);
2029 ++black_overloaded[pi];
2030 }
2031 }
2032 }
2033
2034 for (pi=0; pi<8; pi++) {
2035 if (white_overloaded[pi] > 1) {
2036 ret -= overloaded_penalty[white_overloaded[pi]-2];
2037 }
2038 if (black_overloaded[pi] > 1) {
2039 ret += overloaded_penalty[black_overloaded[pi]-2];
2040 }
2041 }
2042
2043 return ret;
2044 }
2045
2046
2047
2048
draw_value(Position * b)2049 etype draw_value(Position *b)
2050 {
2051 etype ret = DRAW_VALUE;
2052
2053 #if (LEARN_EVAL && !NO_STALEMATE_LEARN)
2054 if (state->computer > 0)
2055 return ret;
2056 else
2057 return -ret;
2058 #endif
2059 if (state->computer > 0)
2060 ret += 0.05*STATIC_PAWN_VALUE*state->rating_change;
2061 else
2062 ret -= 0.05*STATIC_PAWN_VALUE*state->rating_change;
2063
2064 if (ABS(ret) > STATIC_PAWN_VALUE)
2065 ret = SIGN(ret)*STATIC_PAWN_VALUE;
2066
2067 return ret;
2068 }
2069
2070
find_pins(Position * b)2071 static etype find_pins(Position *b)
2072 {
2073 int i, j, k;
2074 uint32 pinner_mask;
2075
2076 /* to find pins we loop over all pieces, looking for pieces
2077 that are under attack by sliding pieces (but not if they
2078 themselves are sliding pieces of the same type!). Then we
2079 check to see if the sliding piece would attack another
2080 piece, making it hung, if moved.
2081
2082 This is an expensive procedure! */
2083
2084 b->pinned_mask = 0;
2085
2086 if (b->stage == MATING)
2087 return 0;
2088
2089 for (i=2;i<16;i++) {
2090 if (!b->pieces[i].p) continue;
2091
2092 pinner_mask = b->topieces[b->pieces[i].pos] &
2093 b->sliding_mask & BLACK_MASK;
2094
2095 while (pinner_mask) {
2096 j = ff_one(pinner_mask);
2097 pinner_mask &= ~(1<<j);
2098
2099 /* If the pinned piece is attacking the pinner then
2100 it isn't a pin! It might be a skewer tho.
2101 */
2102 if (b->topieces[b->pieces[j].pos] & (1<<i))
2103 continue;
2104
2105 /* look for a piece that this bit is pinned against */
2106 for (k=0;k<8;k++) {
2107 if (!b->pieces[k].p) continue;
2108 if (k == i) continue;
2109 if (!same_line(b->pieces[j].pos, b->pieces[i].pos,
2110 b->pieces[k].pos)) continue;
2111 if (!empty_line(b, b->pieces[i].pos,
2112 b->pieces[k].pos))
2113 continue;
2114
2115 /* we have a likely pin. Now we need
2116 to confirm that if the pinner could attack
2117 the pinnedto piece then that piece
2118 would be hung */
2119 if (get_control(b,
2120 b->topieces[b->pieces[k].pos] | (1<<j),
2121 b->pieces[k].p,
2122 b->pieces[k].pos) < 0) {
2123 b->pinned_mask |= (1<<i);
2124 if (debug)
2125 lprintf(0,"w pinned %s -> %s -> %s\n",
2126 posstr(b->pieces[j].pos),
2127 posstr(b->pieces[i].pos),
2128 posstr(b->pieces[k].pos)
2129 );
2130 }
2131 }
2132 }
2133 }
2134
2135
2136 for (i=18;i<32;i++) {
2137 if (!b->pieces[i].p) continue;
2138
2139 pinner_mask = b->topieces[b->pieces[i].pos] &
2140 b->sliding_mask & WHITE_MASK;
2141
2142 while (pinner_mask) {
2143 j = ff_one(pinner_mask);
2144 pinner_mask &= ~(1<<j);
2145
2146 /* If the pinned piece is attacking the pinner then
2147 it isn't a pin! It might be a skewer tho.
2148 */
2149 if (b->topieces[b->pieces[j].pos] & (1<<i))
2150 continue;
2151
2152 /* look for a piece that this bit is pinned against */
2153 for (k=16;k<24;k++) {
2154 if (!b->pieces[k].p) continue;
2155 if (k == i) continue;
2156 if (!same_line(b->pieces[j].pos, b->pieces[i].pos,
2157 b->pieces[k].pos)) continue;
2158 if (!empty_line(b, b->pieces[i].pos,
2159 b->pieces[k].pos))
2160 continue;
2161
2162 /* we have a likely pin. Now we need
2163 to confirm that if the pinner could attack
2164 the pinnedto piece then that piece
2165 would be hung */
2166 if (get_control(b,
2167 b->topieces[b->pieces[k].pos] | (1<<j),
2168 b->pieces[k].p,
2169 b->pieces[k].pos) > 0) {
2170 b->pinned_mask |= (1<<i);
2171 if (debug)
2172 lprintf(0,"b pinned %s -> %s -> %s\n",
2173 posstr(b->pieces[j].pos),
2174 posstr(b->pieces[i].pos),
2175 posstr(b->pieces[k].pos)
2176 );
2177 }
2178 }
2179 }
2180 }
2181
2182 return 0;
2183 }
2184
2185
eval_etype(Position * b,etype testv,int depth)2186 etype eval_etype(Position *b, etype testv, int depth)
2187 {
2188 etype ret, v, pv, pinv;
2189 int player = next_to_play(b);
2190 etype material;
2191 uint32 pieces_done;
2192
2193 #if TEST_EVAL_SHORTCUT
2194 etype shortcut_ret = INFINITY;
2195 static int shortcut_total, shortcut_ok, eval_total;
2196 #endif
2197 if (b->stage > MATING || b->stage < OPENING)
2198 lprintf(0, "Stage error: %d\n", b->stage);
2199
2200 if ((b->flags & FLAG_EVAL_DONE)) {
2201 return b->eval_result * player;
2202 }
2203
2204 if (b->flags & FLAG_NEED_PART2) {
2205 lprintf(0,"WARNING: NEED_PART2 in eval\n");
2206 }
2207
2208 if (learning && !mulling) {
2209 if ((b->flags & FLAG_FORCED_DRAW) && !debug) {
2210 b->flags |= FLAG_EVAL_DONE;
2211 b->eval_result = draw_value(b);
2212 return b->eval_result * player;
2213 }
2214 }
2215
2216 init_eval_tables();
2217
2218 /* passed pawns always get reevaluated, so stopppability does also */
2219 b->null_stoppable_pawn = 0;
2220 b->null_unstoppable_pawn = 0;
2221
2222 if (b->oldb && !(b->oldb->flags & FLAG_EVAL_DONE)) {
2223 eval(b->oldb, testv, 1);
2224 }
2225
2226 material = b->w_material - b->b_material;
2227
2228 if (debug)
2229 lprintf(0,"w_material=%e b_material=%e\n",
2230 b->w_material, b->b_material);
2231
2232 if (material > MAX_MATERIAL)
2233 material = MAX_MATERIAL;
2234
2235 if (material < -MAX_MATERIAL)
2236 material = -MAX_MATERIAL;
2237
2238 if (testv == INFINITY) {
2239 b->piece_change = b->material_mask;
2240 b->oldb = NULL;
2241 } else if (depth >= EVAL_ALL_DEPTH) {
2242 b->piece_change = b->material_mask;
2243 } else if (b->oldb) {
2244 Square last_from = b->last_move.from;
2245 Square last_to = b->last_move.to;
2246 int fromy = YPOS(last_from);
2247 int toy = YPOS(last_to);
2248
2249 /* we need to recalc a king if a pawn moves, as pawn
2250 defence is critical */
2251 if ((b->oldb->board[last_from] == PAWN) ||
2252 (b->oldb->board[last_to] == PAWN))
2253 b->piece_change |= WKING_MASK;
2254
2255 if ((b->oldb->board[last_from] == -PAWN) ||
2256 (b->oldb->board[last_to] == -PAWN))
2257 b->piece_change |= BKING_MASK;
2258
2259 if (b->oldb->board[last_from] == KING)
2260 b->piece_change |= (b->material_mask & ~b->piece_mask);
2261
2262 if (b->oldb->board[last_from] == -KING)
2263 b->piece_change |= (b->material_mask & ~b->piece_mask);
2264
2265 if (b->oldb->board[last_to] == QUEEN)
2266 b->piece_change |= BKING_MASK;
2267
2268 if (b->oldb->board[last_to] == -QUEEN)
2269 b->piece_change |= WKING_MASK;
2270
2271 /* need to recalc king if bishops are captured */
2272 if (b->oldb->board[last_to] == BISHOP)
2273 b->piece_change |= BKING_MASK;
2274
2275 if (b->oldb->board[last_to] == -BISHOP)
2276 b->piece_change |= WKING_MASK;
2277
2278 #if 0
2279 /* Changes in any pawn on the first rank may create
2280 bishop or knight outosts on the two squares a
2281 knight's move in front of the pawn */
2282
2283 if (b->oldb->board[last_from] == PAWN && fromy == 1 &&
2284 !(toy == 2 && tox == fromx)) {
2285 if (tox > 0) {
2286 b->piece_change |= (BMINOR_MASK &
2287 (1<<b->pboard[last_from+WEST+
2288 2*NORTH]));
2289 }
2290 if (tox < 7) {
2291 b->piece_change |= (BMINOR_MASK &
2292 (1<<b->pboard[last_from+EAST+
2293 2*NORTH]));
2294 }
2295 } else if (b->oldb->board[last_to] == PAWN && toy == 1) {
2296 if (tox > 0) {
2297 b->piece_change |= (BMINOR_MASK &
2298 (1<<b->pboard[last_to+WEST+
2299 2*NORTH]));
2300 }
2301 if (tox < 7) {
2302 b->piece_change |= (BMINOR_MASK &
2303 (1<<b->pboard[last_to+EAST+
2304 2*NORTH]));
2305 }
2306 }
2307
2308 if (b->oldb->board[last_from] == -PAWN &&
2309 fromy == 6 && !(toy == 5 && tox == fromx)) {
2310 if (tox > 0) {
2311 b->piece_change |= (WMINOR_MASK &
2312 (1<<b->pboard[last_from+WEST+
2313 2*SOUTH]));
2314 }
2315 if (tox < 7) {
2316 b->piece_change |= (WMINOR_MASK &
2317 (1<<b->pboard[last_from+EAST+
2318 2*SOUTH]));
2319 }
2320 } else if (b->oldb->board[last_to] == -PAWN && toy == 6) {
2321 if (tox > 0) {
2322 b->piece_change |= (WMINOR_MASK &
2323 (1<<b->pboard[last_to+WEST+
2324 2*SOUTH]));
2325 }
2326 if (tox < 7) {
2327 b->piece_change |= (WMINOR_MASK &
2328 (1<<b->pboard[last_to+EAST+
2329 2*SOUTH]));
2330 }
2331
2332 }
2333 #endif
2334 b->piece_change |= MINOR_MASK;
2335
2336 /* blocking and unblocking passed pawns */
2337 if (toy>1 &&
2338 (b->wpassed_pawn_mask & (1<<b->pboard[last_to+SOUTH])) &&
2339 ((b->board[last_to] < 0 && b->oldb->board[last_to]==0) ||
2340 b->oldb->board[last_to])) {
2341 b->piece_change |= (1<<b->pboard[last_to+SOUTH]);
2342 }
2343 if (toy<6 &&
2344 (b->bpassed_pawn_mask & (1<<b->pboard[last_to+NORTH])) &&
2345 ((b->board[last_to] > 0 && b->oldb->board[last_to]==0) ||
2346 b->oldb->board[last_to])) {
2347 b->piece_change |= (1<<b->pboard[last_to+NORTH]);
2348 }
2349
2350 if (fromy>1 &&
2351 (b->wpassed_pawn_mask & (1<<b->pboard[last_from+SOUTH])) &&
2352 b->board[last_to] < 0) {
2353 b->piece_change |= (1<<b->pboard[last_from+SOUTH]);
2354 }
2355 if (fromy<6 &&
2356 (b->bpassed_pawn_mask & (1<<b->pboard[last_from+NORTH])) &&
2357 b->board[last_to] > 0) {
2358 b->piece_change |= (1<<b->pboard[last_from+NORTH]);
2359 }
2360
2361 /* unstoppable pawns can easily become stoppable, so
2362 we should recalculate all unstoppable pawns.
2363 Do this by recalculating all passed pawns */
2364 if ((b->piece_mask & WHITE_MASK) == WKING_MASK) {
2365 b->piece_change |= b->bpassed_pawn_mask;
2366 }
2367 if ((b->piece_mask & BLACK_MASK) == BKING_MASK) {
2368 b->piece_change |= b->wpassed_pawn_mask;
2369 }
2370
2371 }
2372
2373 ret = 0;
2374
2375 /* need pins to compute various attack values (e.g weak pawn
2376 attack) correctly */
2377 pinv = find_pins(b);
2378
2379 build_pawn_loc(b);
2380
2381 v = specifics(b);
2382 ret += v;
2383 if (debug)
2384 lprintf(0,"specifics = %e\n", v);
2385
2386 pieces_done = b->piece_change;
2387 pv = v = piece_values(b);
2388 ret += v;
2389 if (debug)
2390 lprintf(0,"piece values = %e\n", v);
2391
2392 v = king_safety(b);
2393 ret += v;
2394 if (debug)
2395 lprintf(0,"king safety = %e\n", v);
2396
2397 v = eval_tactics(b);
2398 ret += v;
2399 if (debug)
2400 lprintf(0,"tactics = %e\n", v);
2401
2402 #if USE_EVAL_SHORTCUT
2403 if (depth <= 0 &&
2404 b->oldb &&
2405 abs(b->expensive) < EVAL_SHORTCUT_THRESHOLD &&
2406 (ret + material + b->expensive) * player >
2407 testv + EVAL_SHORTCUT_THRESHOLD && !egtb(b)) {
2408 etype ret2 = (ret + material + b->expensive) * player;
2409
2410 ret2 -= EVAL_SHORTCUT_OFFSET;
2411 ret2 *= player;
2412
2413 ret2 += check_material(b, ret2);
2414
2415 ret2 *= player;
2416
2417 if (ret2 >= testv) {
2418 #if TEST_EVAL_SHORTCUT
2419 shortcut_ret = ret2;
2420 #else
2421 return ret2;
2422 #endif
2423 }
2424 }
2425 #endif
2426
2427 b->expensive = 0;
2428
2429 b->expensive += pinv;
2430 ret += pinv;
2431
2432 v = board_control1(b);
2433 b->expensive += v;
2434 ret += v;
2435 if (debug)
2436 lprintf(0,"board control1 = %e\n", v);
2437
2438 v = board_control2(b);
2439 b->expensive += v;
2440 ret += v;
2441 if (debug)
2442 lprintf(0,"board control2 = %e\n", v);
2443
2444 b->piece_change &= ~pieces_done;
2445 b->piece_change |= (b->wpassed_pawn_mask | b->bpassed_pawn_mask);
2446 v = piece_values(b);
2447 ret += (v - pv);
2448
2449 v = eval_mobility(b);
2450 b->expensive += v;
2451 ret += v;
2452 if (debug)
2453 lprintf(0,"mobility = %e\n", v);
2454
2455 if (debug)
2456 lprintf(0,"pos value = %e\n", ret);
2457
2458 #if USE_OVERLOADED
2459 v = overloaded_pieces(b);
2460 ret += v;
2461 if (debug)
2462 lprintf(0, "overloaded = %e\n", v);
2463 #endif
2464 b->flags |= FLAG_EVAL_DONE;
2465
2466 ret += material;
2467 ret += check_material(b, ret);
2468
2469 if (debug) {
2470 lprintf(0,"eval = %e\n", ret);
2471 if (b->flags & FLAG_ACCEPT_DRAW)
2472 lprintf(0, "Will accept draw\n\n");
2473 }
2474
2475 #if TEST_EVAL_SHORTCUT
2476 if (shortcut_ret != INFINITY) {
2477 etype ret2 = ret * player;
2478
2479 shortcut_total++;
2480
2481 if ((ret2 < testv && shortcut_ret > testv) ||
2482 (ret2 > testv && shortcut_ret < testv)) {
2483 lprintf(0,"shortcut: %d/%d/%d ret=%e shortcut_ret=%e testv=%d move=%s\n",
2484 shortcut_ok, shortcut_total, eval_total,
2485 ret2, shortcut_ret, testv,
2486 short_movestr(b, &b->last_move));
2487 print_board(b->board);
2488 } else {
2489 shortcut_ok++;
2490 }
2491 }
2492 eval_total++;
2493 #endif
2494
2495 b->eval_result = ret;
2496 return b->eval_result * player;
2497 }
2498
2499
eval(Position * b,etype testv,int depth)2500 Eval eval(Position *b, etype testv, int depth)
2501 {
2502 Eval ret = makeeval(b, eval_etype(b, testv, depth));
2503
2504 if (!(b->flags & FLAG_EGTB_EVAL)) {
2505 if (ret.v > MAX_EVAL)
2506 ret.v = MAX_EVAL;
2507 if (ret.v < -MAX_EVAL)
2508 ret.v = -MAX_EVAL;
2509 }
2510 return ret;
2511 }
2512
eval1(Position * b,etype testv,int depth)2513 Eval eval1(Position *b, etype testv, int depth)
2514 {
2515 Eval ret1, ret2;
2516 Position b1, b2, b3;
2517
2518 b1 = (*b);
2519 b2 = (*b);
2520 b3 = (*b);
2521
2522 ret1 = eval1(b, testv, depth);
2523 ret2 = eval1(&b1, INFINITY, depth);
2524
2525 if (!(b->flags & FLAG_PROMOTE) &&
2526 ret1.v != ret2.v) {
2527 lprintf(0,"****%d %d\n", ret1.v, ret2.v);
2528
2529 if (b->oldb)
2530 print_board(b->oldb->board);
2531 print_board(b->board);
2532
2533 debug = 1;
2534 lprintf(0, "*** INCREMENTAL b ***\n");
2535 ret1 = eval1(&b2, testv, depth);
2536 lprintf(0, "*** NON-INCREMENTAL b ***\n");
2537 b3.flags &= ~FLAG_EVAL_DONE;
2538 ret2 = eval1(&b3, INFINITY, depth);
2539 debug = 0;
2540 exit(1);
2541
2542 }
2543
2544 return ret1;
2545 }
2546
2547
eval_debug(Position * b)2548 void eval_debug(Position *b)
2549 {
2550 regen_moves(b);
2551
2552 debug = 1;
2553
2554 lprintf(0,"white_moves=%d black_moves=%d\n",
2555 b->white_moves, b->black_moves);
2556
2557 b->flags |= FLAG_COMPUTER_WHITE;
2558 b->flags &= ~FLAG_EVAL_DONE;
2559 eval(b, INFINITY, MAX_DEPTH);
2560 b->flags &= ~FLAG_COMPUTER_WHITE;
2561 b->flags &= ~FLAG_EVAL_DONE;
2562 eval(b, INFINITY, MAX_DEPTH);
2563
2564 debug = 0;
2565 }
2566
2567
eval_speed(Position * b,int loops)2568 void eval_speed(Position *b, int loops)
2569 {
2570 int i;
2571 float t;
2572
2573 t = gettime();
2574
2575 for (i=0;i<loops;i++) {
2576 b->flags &= ~FLAG_EVAL_DONE;
2577 eval(b, INFINITY, MAX_DEPTH);
2578 }
2579
2580 t = gettime() - t;
2581
2582 lprintf(0,"%d full eval calls in %g secs - %g eval/sec\n",
2583 loops, t, loops/t);
2584 }
2585