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