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: attacks.c
20     Purpose: calculate attack information
21 
22 */
23 
24 #include "sjeng.h"
25 #include "extvars.h"
26 
calc_attackers(int square,int color)27 int calc_attackers (int square, int color) {
28 
29   /* this function calculates attack information for a square */
30 
31   static const int rook_o[4] = {12, -12, 1, -1};
32   static const int bishop_o[4] = {11, -11, 13, -13};
33   static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
34   int a_sq, i;
35 
36   int attackers = 0;
37 
38   if (board[square] == frame) return 0;
39 
40   /* white attacker: */
41   if (color%2) {
42     /* rook-style moves: */
43     for (i = 0; i < 4; i++) {
44       a_sq = square + rook_o[i];
45 
46       /* the king can attack from one square away: */
47       if (board[a_sq] == wking)
48 	{
49 	  attackers++;
50 	  break;
51 	}
52       else
53 	{
54 	  /* otherwise, check for sliding pieces: */
55 	  while (board[a_sq] != frame) {
56 	    if (board[a_sq] == wrook || board[a_sq] == wqueen)
57 	      {
58 		attackers++;
59 		break;
60 	      }
61 	    else if (board[a_sq] != npiece) break;
62 	    a_sq += rook_o [i];
63 	  }
64 	}
65     }
66 
67     /* bishop-style moves: */
68     for (i = 0; i < 4; i++) {
69       a_sq = square + bishop_o[i];
70       /* check for pawn attacks: */
71       if (board[a_sq] == wpawn && i%2)
72 	{
73 	  attackers++;
74 	  break;
75 	}
76       /* the king can attack from one square away: */
77       else if (board[a_sq] == wking)
78 	{
79 	  attackers++;
80 	  break;
81 	}
82       else
83 	{
84 	  while (board[a_sq] != frame) {
85 	    if (board[a_sq] == wbishop || board[a_sq] == wqueen)
86 	      {
87 		attackers++;
88 		break;
89 	      }
90 	    else if (board[a_sq] != npiece) break;
91 	    a_sq += bishop_o [i];
92 	  }
93 	}
94     }
95 
96     /* knight-style moves: */
97     for (i = 0; i < 8; i++) {
98       a_sq = square + knight_o[i];
99       if (board[a_sq] == wknight)
100 	  attackers++;
101 
102     }
103 
104     /* if we haven't hit a white attacker by now, there are none: */
105 
106   }
107 
108   /* black attacker: */
109   else {
110     /* rook-style moves: */
111     for (i = 0; i < 4; i++) {
112       a_sq = square + rook_o[i];
113       /* the king can attack from one square away: */
114       if (board[a_sq] == bking)
115 	{
116 	  attackers++;
117 	  break;
118 	}
119       /* otherwise, check for sliding pieces: */
120       else {
121 	while (board[a_sq] != frame) {
122 	  if (board[a_sq] == brook || board[a_sq] == bqueen)
123 	    {
124 	      attackers++;
125 	      break;
126 	    };
127 	  if (board[a_sq] != npiece) break;
128 	  a_sq += rook_o [i];
129 	}
130       }
131     }
132 
133     /* bishop-style moves: */
134     for (i = 0; i < 4; i++) {
135       a_sq = square + bishop_o[i];
136       /* check for pawn attacks: */
137       if (board[a_sq] == bpawn && !(i%2))
138 	{
139 	  attackers++;
140 	  break;
141 	}
142       /* the king can attack from one square away: */
143       else if (board[a_sq] == bking)
144 	{
145 	  attackers++;
146 	  break;
147 	}
148       else {
149 	while (board[a_sq] != frame) {
150 	  if (board[a_sq] == bbishop || board[a_sq] == bqueen)
151 	    {
152 	      attackers++;
153 	      break;
154 	    }
155 	  else if (board[a_sq] != npiece) break;
156 	  a_sq += bishop_o [i];
157 	}
158       }
159     }
160 
161     /* knight-style moves: */
162     for (i = 0; i < 8; i++) {
163       a_sq = square + knight_o[i];
164       if (board[a_sq] == bknight)
165 	attackers++;
166     }
167 
168     /* if we haven't hit a black attacker by now, there are none: */
169   }
170 
171   return attackers;
172 
173 }
174 
175 #if 0
176 bool is_attacked (int square, int color)
177 {
178   int a, j, dir, i, l;
179 
180   for (a = 1, j = 1; (a <= piece_count); j++)
181   {
182     i = pieces[j];
183 
184     if (!i)
185       continue;
186     else
187       a++;
188 
189     if ((color&1) != (board[i]&1)) continue;
190 
191    if (color & 1)
192    {
193     switch (board[i])
194     {
195 	case (wpawn):
196 	  if ((i+13) == square || (i+11) == square) return TRUE;
197 	  break;
198 	case (wknight):
199 	  if ((i - 25) == square || (i-23) == square || (i-14) == square
200 	      || (i-10) == square || (i+10) == square || (i+14) == square
201 	      || (i+23) == square || (i+25) == square) return TRUE;
202 	  break;
203 	case (wbishop):
204 	  dir = abs(i - square);
205 	  if ((dir % 13) == 0)
206 	  {
207 	        dir = (i - square > 0) ? 13 : -13;
208 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
209 	  	if (i == l) return TRUE;
210 	  }
211 	  else if ((dir % 11) == 0)
212 	  {
213 	        dir = (i - square > 0) ? 11 : -11;
214 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
215 	  	if (i == l) return TRUE;
216 	  }
217 	  break;
218 	case (wrook):
219 	  if (file(i) == file(square))
220 	  {
221 	    dir = (i - square > 0) ? 12 : -12;
222 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
223 	    if (i == l) return TRUE;
224 	  }
225 	  else if (rank(i) == rank(square))
226 	  {
227 	    dir = (i - square > 0) ? 1 : -1;
228 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
229 	    if (i == l) return TRUE;
230 	  }
231 	  break;
232 	case (wqueen):
233 	  dir = abs(i - square);
234 	  if ((dir % 13) == 0)
235 	  {
236 	        dir = (i - square > 0) ? 13 : -13;
237 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
238 	  	if (i == l) return TRUE;
239 	  }
240 	  else if ((dir % 11) == 0)
241 	  {
242 	        dir = (i - square > 0) ? 11 : -11;
243 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
244 	  	if (i == l) return TRUE;
245 	  }
246 	  else if (file(i) == file(square))
247 	  {
248 	    dir = (i - square > 0) ? 12 : -12;
249 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
250 	    if (i == j) return TRUE;
251 	  }
252 	  else if (rank(i) == rank(square))
253 	  {
254 	    dir = (i - square > 0) ? 1 : -1;
255 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
256 	    if (i == l) return TRUE;
257 	  }
258 	  break;
259 	case (wking):
260 	  if (   (abs(rank(i) - rank(square)) <= 1)
261 	      && (abs(file(i) - file(square)) <= 1))
262 	    return TRUE;
263 	  break;
264       }
265    }
266    else
267    {
268      switch(board[i])
269      {
270 	case (bpawn):
271 	  if ((i-13) == square || (i-11) == square) return TRUE;
272 	  break;
273 	case (bknight):
274 	  if ((i - 25) == square || (i-23) == square || (i-14) == square
275 	      || (i-10) == square || (i+10) == square || (i+14) == square
276 	      || (i+23) == square || (i+25) == square) return TRUE;
277 	  break;
278 	case (bbishop):
279 	  dir = abs(i - square);
280 	  if ((dir % 13) == 0)
281 	  {
282 	        dir = (i - square > 0) ? 13 : -13;
283 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
284 	  	if (i == l) return TRUE;
285 	  }
286 	  else if ((dir % 11) == 0)
287 	  {
288 	        dir = (i - square > 0) ? 11 : -11;
289 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
290 	  	if (i == l) return TRUE;
291 	  }
292 	  break;
293 	case (brook):
294 	  if (file(i) == file(square))
295 	  {
296 	    dir = (i - square > 0) ? 12 : -12;
297 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
298 	    if (i == l) return TRUE;
299 	  }
300 	  else if (rank(i) == rank(square))
301 	  {
302 	    dir = (i - square > 0) ? 1 : -1;
303 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
304 	    if (i == l) return TRUE;
305 	  }
306 	  break;
307 	case (bqueen):
308 	  dir = abs(i - square);
309 	  if ((dir % 13) == 0)
310 	  {
311 	        dir = (i - square > 0) ? 13 : -13;
312 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
313 	  	if (i == l) return TRUE;
314 	  }
315 	  else if ((dir % 11) == 0)
316 	  {
317 	        dir = (i - square > 0) ? 11 : -11;
318 	  	for (l = square+dir;(board[l] == npiece) && (l != i);l += dir);
319 	  	if (i == l) return TRUE;
320 	  }
321 	  else if (file(i) == file(square))
322 	  {
323 	    dir = (i - square > 0) ? 12 : -12;
324 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
325 	    if (i == l) return TRUE;
326 	  }
327 	  else if (rank(i) == rank(square))
328 	  {
329 	    dir = (i - square > 0) ? 1 : -1;
330 	    for (l = square+dir;(board[l] == npiece) && (l != i); l += dir);
331 	    if (i == l) return TRUE;
332 	  }
333 	  break;
334 	case (bking):
335 	  if (   (abs(rank(i) - rank(square)) <= 1)
336 	      && (abs(file(i) - file(square)) <= 1))
337 	    return TRUE;
338 	  break;
339       }
340     }
341   }
342   return FALSE;
343 }
344 #endif
345 
is_attacked(int square,int color)346 bool is_attacked (int square, int color) {
347 
348   /* this function will return TRUE if square "square" is attacked by a piece
349      of color "color", and return FALSE otherwise */
350 
351   static const int rook_o[4] = {12, -12, 1, -1};
352   static const int bishop_o[4] = {11, -11, 13, -13};
353   static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
354   register int ndir, a_sq;
355   register int basq, i;
356 
357   /* white attacker: */
358   if (color&1) {
359 
360     /* bishop-style moves: */
361     for (i = 0; i < 4; i++) {
362       ndir = bishop_o[i];
363       a_sq = square+ndir;
364       basq = board[a_sq];
365       /* check for pawn attacks: */
366       if (basq == wpawn && (i&1)) return TRUE;
367       /* the king can attack from one square away: */
368       if (basq == wking) return TRUE;
369       while (basq != frame) {
370 	if (basq == wbishop || basq == wqueen) return TRUE;
371 	if (basq != npiece) break;
372 	a_sq += ndir;
373 	basq = board[a_sq];
374       }
375     }
376     /* knight-style moves: */
377     for (i = 0; i < 8; i++) {
378       if (board[square + knight_o[i]] == wknight) return TRUE;
379     }
380     /* rook-style moves: */
381     for (i = 0; i < 4; i++) {
382       ndir = rook_o[i];
383       a_sq = square + ndir;
384       basq = board[a_sq];
385       /* the king can attack from one square away: */
386       if (basq == wking) return TRUE;
387       /* otherwise, check for sliding pieces: */
388       while (basq != frame) {
389 	if (basq == wrook || basq == wqueen) return TRUE;
390 	if (basq != npiece) break;
391 	a_sq += ndir;
392 	basq = board[a_sq];
393       }
394     }
395 
396     /* if we haven't hit a white attacker by now, there are none: */
397     return FALSE;
398 
399   }
400 
401   /* black attacker: */
402   else {
403       /* bishop-style moves: */
404     for (i = 0; i < 4; i++) {
405       ndir = bishop_o[i];
406       a_sq = square + ndir;
407       basq = board[a_sq];
408       /* check for pawn attacks: */
409       if (basq == bpawn && !(i&1)) return TRUE;
410       /* the king can attack from one square away: */
411       if (basq == bking) return TRUE;
412       while (basq != frame) {
413 	if (basq == bbishop || basq == bqueen) return TRUE;
414 	if (basq != npiece) break;
415 	a_sq += ndir;
416 	basq = board[a_sq];
417       }
418     }
419 
420     /* knight-style moves: */
421     for (i = 0; i < 8; i++) {
422       if (board[square + knight_o[i]] == bknight) return TRUE;
423     }
424 
425     /* rook-style moves: */
426     for (i = 0; i < 4; i++) {
427       ndir = rook_o[i];
428       a_sq = square + rook_o[i];
429       basq = board[a_sq];
430       /* the king can attack from one square away: */
431       if (basq == bking) return TRUE;
432       /* otherwise, check for sliding pieces: */
433       while (basq != frame) {
434 	if (basq == brook || basq == bqueen) return TRUE;
435 	if (basq != npiece) break;
436 	a_sq += ndir;
437 	basq = board[a_sq];
438       }
439     }
440 
441     /* if we haven't hit a black attacker by now, there are none: */
442     return FALSE;
443 
444   }
445 
446 }
447 
nk_attacked(int square,int color)448 bool nk_attacked (int square, int color) {
449 
450   /* this function will return TRUE if square "square" is attacked by a piece
451      of color "color", and return FALSE otherwise */
452 
453   static const int rook_o[4] = {12, -12, 1, -1};
454   static const int bishop_o[4] = {11, -11, 13, -13};
455   static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
456   register int ndir, a_sq;
457   register int basq, i;
458 
459   /* white attacker: */
460   if (color&1) {
461 
462     /* bishop-style moves: */
463     for (i = 0; i < 4; i++) {
464       ndir = bishop_o[i];
465       a_sq = square+ndir;
466       basq = board[a_sq];
467       /* check for pawn attacks: */
468       if (basq == wpawn && (i&1)) return TRUE;
469       /* the king can attack from one square away: */
470       while (basq != frame) {
471 	if (basq == wbishop || basq == wqueen) return TRUE;
472 	if (basq != npiece) break;
473 	a_sq += ndir;
474 	basq = board[a_sq];
475       }
476     }
477     /* knight-style moves: */
478     for (i = 0; i < 8; i++) {
479       if (board[square + knight_o[i]] == wknight) return TRUE;
480     }
481     /* rook-style moves: */
482     for (i = 0; i < 4; i++) {
483       ndir = rook_o[i];
484       a_sq = square + ndir;
485       basq = board[a_sq];
486       /* otherwise, check for sliding pieces: */
487       while (basq != frame) {
488 	if (basq == wrook || basq == wqueen) return TRUE;
489 	if (basq != npiece) break;
490 	a_sq += ndir;
491 	basq = board[a_sq];
492       }
493     }
494 
495     /* if we haven't hit a white attacker by now, there are none: */
496     return FALSE;
497 
498   }
499 
500   /* black attacker: */
501   else {
502       /* bishop-style moves: */
503     for (i = 0; i < 4; i++) {
504       ndir = bishop_o[i];
505       a_sq = square + ndir;
506       basq = board[a_sq];
507       /* check for pawn attacks: */
508       if (basq == bpawn && !(i&1)) return TRUE;
509       /* the king can attack from one square away: */
510       while (basq != frame) {
511 	if (basq == bbishop || basq == bqueen) return TRUE;
512 	if (basq != npiece) break;
513 	a_sq += ndir;
514 	basq = board[a_sq];
515       }
516     }
517 
518     /* knight-style moves: */
519     for (i = 0; i < 8; i++) {
520       if (board[square + knight_o[i]] == bknight) return TRUE;
521     }
522 
523     /* rook-style moves: */
524     for (i = 0; i < 4; i++) {
525       ndir = rook_o[i];
526       a_sq = square + rook_o[i];
527       basq = board[a_sq];
528       /* otherwise, check for sliding pieces: */
529       while (basq != frame) {
530 	if (basq == brook || basq == bqueen) return TRUE;
531 	if (basq != npiece) break;
532 	a_sq += ndir;
533 	basq = board[a_sq];
534       }
535     }
536 
537     /* if we haven't hit a black attacker by now, there are none: */
538     return FALSE;
539 
540   }
541 
542 }
543 
544