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