6f54d573edbf79db07ba823bcfcf461a7dc97772
[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 3 of the License,
18  * or (at your option) any 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, see
27  * <http://www.gnu.org/licenses/>.
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 #ifndef MINISHOGI
122     /* try a knight capture (using xside's knight moves) */
123
124     ptyp = ptype[side ^ 1][knight];
125
126 #ifdef SAVE_NEXTPOS
127     u = first_direction(ptyp, &d, square);
128 #else
129     pdir = (*nextdir[ptyp])[square];
130     u = pdir[square];
131 #endif
132
133     do
134     {
135         if (color[u] == side && board[u] == knight)
136             return true;
137
138 #ifdef SAVE_NEXTPOS
139         u = next_direction(ptyp, &d, square);
140 #else
141         u = pdir[u];
142 #endif
143     }
144     while (u != square);
145 #endif  /* MINISHOGI */
146
147     *blockable = true;
148
149     /* try a (promoted) bishop capture */
150
151     ptyp = ptype[black][bishop];
152
153 #ifdef SAVE_NEXTPOS
154     u = first_direction(ptyp, &d, square);
155 #else
156     ppos = (*nextpos[ptyp])[square];
157     pdir = (*nextdir[ptyp])[square];
158     u = ppos[square];
159 #endif
160
161     do
162     {
163         if (color[u] == neutral)
164 #ifdef SAVE_NEXTPOS
165             u = next_position(ptyp, &d, square, u);
166 #else
167         u = ppos[u];
168 #endif
169         else
170         {
171             if (color[u] == side && (unpromoted[board[u]] == bishop))
172                 return true;
173
174 #ifdef SAVE_NEXTPOS
175             u = next_direction(ptyp, &d, square);
176 #else
177             u = pdir[u];
178 #endif
179         }
180     }
181     while (u != square);
182
183     /* try a (promoted) rook capture */
184
185     ptyp = ptype[black][rook];
186
187 #ifdef SAVE_NEXTPOS
188     u = first_direction(ptyp, &d, square);
189 #else
190     ppos = (*nextpos[ptyp])[square];
191     pdir = (*nextdir[ptyp])[square];
192     u = ppos[square];
193 #endif
194
195     do
196     {
197         if (color[u] == neutral)
198 #ifdef SAVE_NEXTPOS
199         {
200             u = next_position(ptyp, &d, square, u);
201         }
202 #else
203         {
204             u = ppos[u];
205         }
206 #endif
207         else
208         {
209             if (color[u] == side && (unpromoted[board[u]] == rook))
210                 return true;
211
212 #ifdef SAVE_NEXTPOS
213             u = next_direction(ptyp, &d, square);
214 #else
215             u = pdir[u];
216 #endif
217         }
218     }
219     while (u != square);
220
221 #ifndef MINISHOGI
222     /* try a lance capture (using xside's lance moves) */
223
224     ptyp = ptype[side ^ 1][lance];
225
226 #ifdef SAVE_NEXTPOS
227     u = first_direction(ptyp, &d, square);
228 #else
229     ppos = (*nextpos[ptyp])[square];
230     u = ppos[square];
231 #endif
232
233     do
234     {
235         if (color[u] == neutral)
236 #ifdef SAVE_NEXTPOS
237         {
238             u = next_position(ptyp, &d, square, u);
239         }
240 #else
241         {
242             u = ppos[u];
243         }
244 #endif
245         else
246         {
247             if ((color[u] == side) && (board[u] == lance))
248                 return true;
249
250             u = square;
251         }
252     }
253     while (u != square);
254 #endif  /* MINISHOGI */
255
256     return false;
257 }
258