Updating to version 1.3, release made by Mike Vanier (mvanier@bbb.caltech.edu).
[gnushogi.git] / gnushogi / attacks.c
1 /*
2  * FILE: attacks.c
3  *
4  * ----------------------------------------------------------------------
5  * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6  * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
7  *
8  * GNU SHOGI is based on GNU CHESS
9  *
10  * Copyright (c) 1988, 1989, 1990 John Stanback
11  * Copyright (c) 1992 Free Software Foundation
12  *
13  * This file is part of GNU SHOGI.
14  *
15  * GNU Shogi is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation; either version 1, or (at your option) any
18  * later version.
19  *
20  * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with GNU Shogi; see the file COPYING.  If not, write to the Free
27  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
28  * ----------------------------------------------------------------------
29  *
30  */
31
32 #include "gnushogi.h"
33
34
35 #define CHECK_DISTANCE
36
37 /*
38  * See if any piece with color 'side' attacks sq.
39  * *blockable == attack could be blocked by drop
40  */
41
42 int
43 SqAttacked(short square, short side, short *blockable)
44 {
45 #ifdef SAVE_NEXTPOS
46     short d;
47 #else
48     unsigned char *ppos, *pdir;
49 #endif
50
51     short u, ptyp;
52
53     if (MatchSignature(threats_signature[side]))
54     {
55         *blockable = true; /* don't know */
56         return Anyattack(side, square);
57     }
58
59     /*
60      * First check neighbouring squares,
61      * then check Knights.
62      * then check Bishops,
63      * then (last) check Rooks,
64      */
65
66     *blockable = false;
67
68     /* try a capture from direct neighboured squares */
69
70     ptyp = ptype[black][king];
71
72 #ifdef SAVE_NEXTPOS
73     u = first_direction(ptyp, &d, square);
74 #else
75     pdir = (*nextdir[ptyp])[square];
76     u = pdir[square];
77 #endif
78
79     do
80     {
81         if (color[u] == side) /* can piece reach square in one step ? */
82 #ifdef CHECK_DISTANCE
83         {
84             if (piece_distance(side, board[u], u, square) == 1)
85                 return true;
86         }
87 #else
88         {
89             short v;
90             short ptypv = ptype[side][board[u]];
91 #ifdef SAVE_NEXTPOS
92             short dv;
93             v = first_direction(ptypv, &dv, u);
94 #else
95             unsigned char *qdir;
96             qdir = (*nextdir[ptypv])[u];
97             v = qdir[u];
98 #endif
99             do
100             {
101                 if (v == square)
102                     return true;
103 #ifdef SAVE_NEXTPOS
104                 v = next_direction(ptypv, &dv, u);
105 #else
106                 v = qdir[v];
107 #endif
108             }
109             while (v != u);
110         }
111 #endif
112
113 #ifdef SAVE_NEXTPOS
114         u = next_direction(ptyp, &d, square);
115 #else
116         u = pdir[u];
117 #endif
118     }
119     while (u != square);
120
121     /* try a knight capture (using xside's knight moves) */
122
123     ptyp = ptype[side ^ 1][knight];
124
125 #ifdef SAVE_NEXTPOS
126     u = first_direction(ptyp, &d, square);
127 #else
128     pdir = (*nextdir[ptyp])[square];
129     u = pdir[square];
130 #endif
131
132     do
133     {
134         if (color[u] == side && board[u] == knight)
135             return true;
136
137 #ifdef SAVE_NEXTPOS
138         u = next_direction(ptyp, &d, square);
139 #else
140         u = pdir[u];
141 #endif
142     }
143     while (u != square);
144
145     *blockable = true;
146
147     /* try a (promoted) bishop capture */
148
149     ptyp = ptype[black][bishop];
150
151 #ifdef SAVE_NEXTPOS
152     u = first_direction(ptyp, &d, square);
153 #else
154     ppos = (*nextpos[ptyp])[square];
155     pdir = (*nextdir[ptyp])[square];
156     u = ppos[square];
157 #endif
158
159     do
160     {
161         if (color[u] == neutral)
162 #ifdef SAVE_NEXTPOS
163             u = next_position(ptyp, &d, square, u);
164 #else
165         u = ppos[u];
166 #endif
167         else
168         {
169             if (color[u] == side && (unpromoted[board[u]] == bishop))
170                 return true;
171
172 #ifdef SAVE_NEXTPOS
173             u = next_direction(ptyp, &d, square);
174 #else
175             u = pdir[u];
176 #endif
177         }
178     }
179     while (u != square);
180
181     /* try a (promoted) rook capture */
182
183     ptyp = ptype[black][rook];
184
185 #ifdef SAVE_NEXTPOS
186     u = first_direction(ptyp, &d, square);
187 #else
188     ppos = (*nextpos[ptyp])[square];
189     pdir = (*nextdir[ptyp])[square];
190     u = ppos[square];
191 #endif
192
193     do
194     {
195         if (color[u] == neutral)
196 #ifdef SAVE_NEXTPOS
197         {
198             u = next_position(ptyp, &d, square, u);
199         }
200 #else
201         {
202             u = ppos[u];
203         }
204 #endif
205         else
206         {
207             if (color[u] == side && (unpromoted[board[u]] == rook))
208                 return true;
209
210 #ifdef SAVE_NEXTPOS
211             u = next_direction(ptyp, &d, square);
212 #else
213             u = pdir[u];
214 #endif
215         }
216     }
217     while (u != square);
218
219     /* try a lance capture (using xside's lance moves) */
220
221     ptyp = ptype[side ^ 1][lance];
222
223 #ifdef SAVE_NEXTPOS
224     u = first_direction(ptyp, &d, square);
225 #else
226     ppos = (*nextpos[ptyp])[square];
227     u = ppos[square];
228 #endif
229
230     do
231     {
232         if (color[u] == neutral)
233 #ifdef SAVE_NEXTPOS
234         {
235             u = next_position(ptyp, &d, square, u);
236         }
237 #else
238         {
239             u = ppos[u];
240         }
241 #endif
242         else
243         {
244             if ((color[u] == side) && (board[u] == lance))
245                 return true;
246
247             u = square;
248         }
249     }
250     while (u != square);
251
252     return false;
253 }
254