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