1 /*
2 Sjeng - a chess variants playing program
3 Copyright (C) 2000 Gian-Carlo Pascutto
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 File: seval.c
20 Purpose: functions for evaluating positions (suicide chess)
21
22 */
23
24 #include "sjeng.h"
25 #include "extvars.h"
26 #include "protos.h"
27
28 static int scentral[144] = {
29 0,0,0,0,0,0,0,0,0,0,0,0,
30 0,0,0,0,0,0,0,0,0,0,0,0,
31 0,0,-20,-10,-10,-10,-10,-10,-10,-20,0,0,
32 0,0,-10,0,3,5,5,3,0,-10,0,0,
33 0,0,-10,2,15,15,15,15,2,-10,0,0,
34 0,0,-10,7,15,25,25,15,7,-10,0,0,
35 0,0,-10,7,15,25,25,15,7,-10,0,0,
36 0,0,-10,2,15,15,15,15,2,-10,0,0,
37 0,0,-10,0,3,5,5,3,0,-10,0,0,
38 0,0,-20,-10,-10,-10,-10,-10,-10,-20,0,0,
39 0,0,0,0,0,0,0,0,0,0,0,0,
40 0,0,0,0,0,0,0,0,0,0,0,0};
41
42 static const int rook_o[4] = {12, -12, 1, -1};
43 static const int bishop_o[4] = {11, -11, 13, -13};
44 static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
45
s_bishop_mobility(int square)46 static int s_bishop_mobility(int square)
47 {
48 register int l;
49 register int m = 0;
50
51 for (l = square-13; board[l] == npiece; l-=13)
52 m++;
53 for (l = square-11; board[l] == npiece; l-=11)
54 m++;
55 for (l = square+11; board[l] == npiece; l+=11)
56 m++;
57 for (l = square+13; board[l] == npiece; l+=13)
58 m++;
59
60 return m << 2;
61 }
62
s_rook_mobility(int square)63 static int s_rook_mobility(int square)
64 {
65 register int l;
66 register int m = 0;
67
68 for (l = square-12; board[l] == npiece; l-=12)
69 m++;
70 for (l = square-1; board[l] == npiece; l-=1)
71 m++;
72 for (l = square+1; board[l] == npiece; l+=1)
73 m++;
74 for (l = square+12; board[l] == npiece; l+=12)
75 m++;
76
77 return m << 2;
78 }
79
s_knight_mobility(int square)80 static int s_knight_mobility(int square)
81 {
82 static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
83 register int d, m = 0;
84
85 for (d = 0; d < 8; d++)
86 {
87 if (board[square + knight_o[d]] == npiece) m++;
88 }
89
90 return m << 2;
91 }
92
s_pawn_mobility(int square)93 static int s_pawn_mobility(int square)
94 {
95 register int m = 0;
96
97 if (board[square] == wpawn)
98 {
99 if (board[square + 12] == npiece) m++;
100 }
101 else
102 {
103 if (board[square - 12] == npiece) m++;
104 }
105
106 return m << 3;
107 }
108
s_king_mobility(int square)109 static int s_king_mobility(int square)
110 {
111 static const int king_o[8] = {13, 12, 11, 1, -1, -11, -12, -13};
112 register int d, m = 0;
113
114 for (d = 0; d < 8; d++)
115 {
116 if (board[square + king_o[d]] == npiece) m++;
117 }
118
119 return m << 2;
120 }
121
black_saccers(int square)122 static int black_saccers(int square)
123 {
124 register int ndir, a_sq;
125 register int basq, i;
126 register int f = FALSE;
127
128 /* for white pawn on square, any black
129 * pieces that can sac themselves to it? */
130
131 /* check for case where is_attacked fails
132 because pawns dont move to their attacks */
133
134 if (board[square + 24] == bpawn ||
135 board[square + 22] == bpawn ||
136 board[square + 26] == bpawn)
137 {
138 return 0;
139 }
140
141 /* ok, now check pawn moves */
142
143 if ((rank(square) < 6)
144 && (board[square + 25] == bpawn
145 ||
146 board[square + 23] == bpawn))
147 {
148 f = TRUE;
149 }
150 else if (rank(square) == 4 &&
151 board[square + 35] == bpawn ||
152 board[square + 37] == bpawn)
153 {
154 f = TRUE;
155 }
156
157 if (!f)
158 {
159 f = (is_attacked(square + 11, 0) ? 1 : 0);
160 }
161 if (!f)
162 {
163 f = (is_attacked(square + 13, 0) ? 2 : 0);
164 }
165
166 if (!f)
167 {
168 return 0;
169 }
170 else
171 {
172 /* black can sac, but is the saccer defended ? */
173
174 if (f == 1)
175 {
176 if (calc_attackers(square + 11, 0) > 1)
177 {
178 /* yep */
179 return 0;
180 }
181 else
182 {
183 /* nope */
184 return 30;
185 }
186 }
187 else
188 {
189 if (calc_attackers(square + 13, 0) > 1)
190 {
191 return 0;
192 }
193 else
194 {
195 return 30;
196 }
197
198 }
199 }
200
201 }
202
white_saccers(int square)203 static int white_saccers(int square)
204 {
205 /* for black pawn on square, any black
206 * pieces that can sac themselves to it? */
207
208 register int ndir, a_sq;
209 register int basq, i;
210 register int f = FALSE;
211
212 /* for white pawn on square, any black
213 * pieces that can sac themselves to it? */
214
215 /* check for case where is_attacked fails
216 because pawns dont move to their attacks */
217
218 if (board[square - 24] == wpawn ||
219 board[square - 22] == wpawn ||
220 board[square - 26] == wpawn)
221 {
222 return 0;
223 }
224
225 /* ok, now check pawn moves */
226
227 if ((rank(square) > 3)
228 && (board[square - 25] == wpawn
229 ||
230 board[square - 23] == wpawn))
231 {
232 f = TRUE;
233 }
234 else if (rank(square) == 5 &&
235 board[square - 35] == wpawn ||
236 board[square - 37] == wpawn)
237 {
238 f = TRUE;
239 }
240
241 if (!f)
242 {
243 f = (is_attacked(square - 11, 1) ? 1 : 0);
244 }
245 if (!f)
246 {
247 f = (is_attacked(square - 13, 1) ? 2 : 0);
248 }
249
250 if (!f)
251 {
252 return 0;
253 }
254 else
255 {
256 /* black can sac, but is the saccer defended ? */
257
258 if (f == 1)
259 {
260 if (calc_attackers(square - 11, 1) > 1)
261 {
262 /* yep */
263 return 0;
264 }
265 else
266 {
267 /* nope */
268 return 30;
269 }
270 }
271 else
272 {
273 if (calc_attackers(square - 13, 1) > 1)
274 {
275 return 0;
276 }
277 else
278 {
279 return 30;
280 }
281
282 }
283 }
284
285 }
286
suicide_eval(void)287 long int suicide_eval (void) {
288
289 /* select the appropriate eval() routine: */
290 return (suicide_mid_eval ());
291 }
292
suicide_mid_eval(void)293 long int suicide_mid_eval (void) {
294
295 /* return a score for the current middlegame position: */
296
297 int srank, pawn_file, pawns[2][11], white_back_pawn[11], black_back_pawn[11];
298 int isolated, backwards, i, a, j;
299 long int score = 0;
300 int in_cache;
301 int wb = 0, bb = 0, wbc, bbc;
302 int wk = 0, bk = 0, wr = 0, br = 0;
303 int wn = 0, bn = 0, wp = 0, bp = 0;
304
305 in_cache = 0;
306
307 checkECache(&score, &in_cache);
308
309 if(in_cache)
310 {
311 if (white_to_move == 1) return score;
312 return -score;
313 }
314
315 score = Material;
316
317 /* initialize the pawns array, (files offset by one to use dummy files in
318 order to easier determine isolated status) and also initialize the
319 arrays keeping track of the rank of the most backward pawn: */
320 memset (pawns, 0, sizeof (pawns));
321 for (i = 0; i < 11; i++) {
322 white_back_pawn[i] = 7;
323 black_back_pawn[i] = 2;
324 }
325 for (j = 1, a = 1; (a <= piece_count); j++) {
326 i = pieces[j];
327
328 if (!i)
329 continue;
330 else
331 a++;
332
333 assert((i > 0) && (i < 145));
334
335 pawn_file = file (i)+1;
336 srank = rank (i);
337 if (board[i] == wpawn) {
338 pawns[1][pawn_file]++;
339 if (srank < white_back_pawn[pawn_file]) {
340 white_back_pawn[pawn_file] = srank;
341 }
342 }
343 else if (board[i] == bpawn) {
344 pawns[0][pawn_file]++;
345 if (srank > black_back_pawn[pawn_file]) {
346 black_back_pawn[pawn_file] = srank;
347 }
348 }
349 }
350
351 /* loop through the board, adding material value, as well as positional
352 bonuses for all pieces encountered: */
353 for (j = 1, a = 1; (a <= piece_count); j++) {
354 i = pieces[j];
355
356 if (!i)
357 continue;
358 else
359 a++;
360
361 pawn_file = file (i)+1;
362 srank = rank (i);
363 switch (board[i]) {
364 case (wpawn):
365 score += scentral[i];
366 score += s_pawn_mobility(i);
367 score -= black_saccers(i);
368 wp++;
369 isolated = FALSE;
370 backwards = FALSE;
371
372 /* check for backwards pawns: */
373 if (white_back_pawn[pawn_file+1] > srank
374 && white_back_pawn[pawn_file-1] > srank) {
375 score -= 8;
376 backwards = TRUE;
377 /* check to see if it is furthermore isolated: */
378 if (!pawns[1][pawn_file+1] && !pawns[1][pawn_file-1]) {
379 score -= 12;
380 isolated = TRUE;
381 }
382 }
383
384 /* give weak, exposed pawns a penalty (not as much as in the midgame,
385 since there may be no pieces to take advantage of it): */
386 if (!pawns[0][pawn_file]) {
387 if (backwards) score -= 5;
388 if (isolated) score -= 8;
389 }
390
391 /* give doubled, trippled, etc.. pawns a penalty (bigger in the
392 endgame, since they will become big targets): */
393 if (pawns[1][pawn_file] > 1)
394 score -= 15*(pawns[1][pawn_file]-1);
395
396 /* give bonuses for passed pawns (bigger in the endgame since passed
397 pawns are what wins the endgame): */
398 if (!pawns[0][pawn_file] && srank >= black_back_pawn[pawn_file-1] &&
399 srank >= black_back_pawn[pawn_file+1]) {
400 score += 30 + 3*(rank(i)-2);
401
402 /* outside passer ? */
403 if (file(i) == 1 || file(i) == 8)
404 score += 4 + 2*(rank(i)-2);
405
406 /* give an extra bonus if a connected, passed pawn: */
407 if (!isolated)
408 {
409 score += 6;
410 }
411 }
412
413 /* check for pawn islands */
414 if (!pawns[1][pawn_file-1])
415 score -= 20;
416
417 break;
418
419 case (bpawn):
420 score -= scentral[i];
421 score -= s_pawn_mobility(i);
422 score += white_saccers(i);
423 isolated = FALSE;
424 backwards = FALSE;
425 bp++;
426
427 /* in general, bonuses/penalties in the endgame evaluation will be
428 higher, since pawn structure becomes more important for the
429 creation of passed pawns */
430
431 /* check for backwards pawns: */
432 if (black_back_pawn[pawn_file+1] < srank
433 && black_back_pawn[pawn_file-1] < srank) {
434 score += 8;
435 backwards = TRUE;
436 /* check to see if it is furthermore isolated: */
437 if (!pawns[0][pawn_file+1] && !pawns[0][pawn_file-1]) {
438 score += 12;
439 isolated = TRUE;
440 }
441 }
442
443 /* give weak, exposed pawns a penalty (not as much as in the midgame,
444 since there may be no pieces to take advantage of it): */
445 if (!pawns[1][pawn_file]) {
446 if (backwards) score += 5;
447 if (isolated) score += 8;
448 }
449
450 /* give doubled, trippled, etc.. pawns a penalty (bigger in the
451 endgame, since they will become big targets): */
452 if (pawns[0][pawn_file] > 1)
453 score += 15*(pawns[0][pawn_file]-1);
454
455 /* give bonuses for passed pawns (bigger in the endgame since passed
456 pawns are what wins the endgame): */
457 if (!pawns[1][pawn_file] && srank <= white_back_pawn[pawn_file-1] &&
458 srank <= white_back_pawn[pawn_file+1]) {
459 score -= 30 + 3*(7-rank(i));
460
461 /* outside passer ? */
462 if (file(i) == 1 || file(i) == 8)
463 score -= 4 + 2*(7-rank(i));
464
465 /* give an extra bonus if a connected, passed pawn: */
466 if (!isolated)
467 {
468 score -= 6;
469 }
470 }
471
472 if (!pawns[0][pawn_file-1])
473 score += 20;
474
475 break;
476
477 case (wrook):
478 score += scentral[i];
479 score += s_rook_mobility(i);
480 wr++;
481 break;
482
483 case (brook):
484 score -= scentral[i];
485 score -= s_rook_mobility(i);
486 br++;
487 break;
488
489 case (wbishop):
490 score += scentral[i];
491 score += s_bishop_mobility(i);
492 if (wb)
493 {
494 if (sqcolor[i] != wbc)
495 wb = 99;
496 }
497 wb++;
498 wbc = sqcolor[i];
499 break;
500
501 case (bbishop):
502 score -= scentral[i];
503 score -= s_bishop_mobility(i);
504 if (bb)
505 {
506 /* two bishops, check for same color */
507 if (sqcolor[i] != bbc)
508 bb = 99;
509 }
510 bb++;
511 bbc = sqcolor[i];
512 break;
513
514 case (wknight):
515 score += scentral[i];
516 score += s_knight_mobility(i);
517 wn++;
518 break;
519
520 case (bknight):
521 score -= scentral[i];
522 score -= s_knight_mobility(i);
523 bn++;
524 break;
525
526 case (wqueen):
527 score += scentral[i];
528 score += s_rook_mobility(i);
529 score += s_bishop_mobility(i);
530 break;
531
532 case (bqueen):
533 score -= scentral[i];
534 score -= s_rook_mobility(i);
535 score -= s_bishop_mobility(i);
536 break;
537
538 case (wking):
539 score += scentral[i] >> 1;
540 score += s_king_mobility(i);
541 wk++;
542 break;
543
544 case (bking):
545 score -= scentral[i] >> 1;
546 score -= s_king_mobility(i);
547 bk++;
548 break;
549 }
550 }
551
552 /* opposite color bishops */
553 if ((wb < 99) && (bb < 99) && (wbc != bbc) && (piece_count < 32))
554 {
555 score = (int)((float)score * (float)((float)piece_count / 32.0));
556 }
557
558 storeECache(score);
559
560 /* adjust for color: */
561 if (white_to_move == 1) {
562 return score;
563 }
564 else {
565 return -score;
566 }
567
568 }
569