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