Initial commit based on GNU Shogi 1.2 patchlevel 3.
[gnushogi.git] / src / ataks.c
1 /*
2  * ataks.c - C source for GNU SHOGI
3  *
4  * Copyright (c) 1993, 1994, 1995 Matthias Mutz
5  *
6  * GNU SHOGI is based on GNU CHESS
7  *
8  * Copyright (c) 1988,1989,1990 John Stanback
9  * Copyright (c) 1992 Free Software Foundation
10  *
11  * This file is part of GNU SHOGI.
12  *
13  * GNU Shogi is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation.
16  *
17  * GNU Shogi is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with GNU Shogi; see the file COPYING.  If not, write to
24  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26 #include "gnushogi.h"
27
28 #ifdef DEBUG
29 #include <assert.h>
30 #endif
31
32
33 #if defined DEBUG
34
35 void 
36 ataks (short int side, long int *a)
37 /*
38  * Fill array atak[][] with info about ataks to a square.  Bits 16-31 are set
39  * if the piece (king..pawn) ataks the square.  Bits 0-15 contain a count of
40  * total ataks to the square.
41  */  
42                                                             
43 {
44   register short u, sq;
45   long int c;
46 #ifdef SAVE_NEXTPOS
47   short d;
48 #else
49   register unsigned char *ppos, *pdir;
50 #endif
51   short i, piece; 
52   small_short *PL;
53
54   array_zero (a, NO_SQUARES * sizeof (a[0]));
55
56   PL = PieceList[side];
57   for (i = PieceCnt[side]; i >= 0; i--)
58     { short ptyp;
59       sq = PL[i];
60       piece = board[sq];
61       ptyp = ptype[side][piece];
62       c = control[piece];
63 #ifdef SAVE_NEXTPOS
64       u = first_direction(ptyp,&d,sq);
65 #else
66       ppos = (*nextpos[ptyp])[sq];
67       pdir = (*nextdir[ptyp])[sq];
68       u = ppos[sq];
69 #endif
70       do {
71           a[u] = ((a[u]+1) | c);
72 #ifdef SAVE_NEXTPOS
73           u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u)
74                                      : next_direction(ptyp,&d,sq));
75 #else
76           u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
77 #endif
78       } while (u != sq);
79    }
80 }
81
82 #endif
83
84
85 #if defined DEBUG || defined DEBUG_EVAL
86
87 void
88 debug_ataks (FILE *D, long *atk)
89 {              
90         short l,c,i;         
91         fprintf(D, "\n");
92         for (l = NO_ROWS-1; l >= 0; l--) {
93           for (c = 0; c < NO_COLS; c++) {
94             short sq = (l * NO_COLS) + c;
95             long  v = atk[sq];
96             short n = (short)(v & CNT_MASK);
97             char s[20];
98             fprintf(D,"%2d",n);
99             strcpy(s,"");
100             if ( v & ctlP  ) strcat(s,"P"); 
101             if ( v & ctlPp ) strcat(s,"+P");
102             if ( v & ctlL  ) strcat(s,"L"); 
103             if ( v & ctlLp ) strcat(s,"+L"); 
104             if ( v & ctlN  ) strcat(s,"N"); 
105             if ( v & ctlNp ) strcat(s,"+N"); 
106             if ( v & ctlS  ) strcat(s,"S"); 
107             if ( v & ctlSp ) strcat(s,"+S"); 
108             if ( v & ctlG  ) strcat(s,"G"); 
109             if ( v & ctlB  ) strcat(s,"B"); 
110             if ( v & ctlBp ) strcat(s,"+B"); 
111             if ( v & ctlR  ) strcat(s,"R"); 
112             if ( v & ctlRp ) strcat(s,"+R"); 
113             if ( v & ctlK  ) strcat(s,"K");
114             fprintf(D,s);
115             for (i = strlen(s); i < 5; i++)
116                 fprintf(D," ");
117             fprintf(D," "); 
118           }                               
119           fprintf(D,"\n");
120         }
121         fprintf(D, "\n");
122 }
123
124 #endif
125
126
127 #define CHECK_DISTANCE
128
129
130 int
131 SqAtakd (short int square, short int side, short int *blockable)
132
133 /*
134  * See if any piece with color 'side' ataks sq.
135  * *blockable == attack could be blocked by drop  
136  */
137
138 {
139 #ifdef SAVE_NEXTPOS
140   short d;
141 #else
142   register unsigned char *ppos, *pdir;
143 #endif
144   register short u, ptyp;
145
146   if ( MatchSignature(threats_signature[side]) ) {
147 #ifdef DEBUG  
148     short i,n, sq;
149     long int a[NO_SQUARES];
150     ataks(side,a);
151     for ( i = 0, n = -1; i < NO_SQUARES; i++ ) 
152       if (a[i] != atak[side][i]) {
153         n = i; printf("atak #check error on square %d\n",i);
154       }
155     if ( n >= 0 ) {
156       debug_ataks (stdout, a);
157       debug_ataks (stdout, atak[side]);
158       debug_position (stdout);
159       printf("%d pieces\n",PieceCnt[side]);
160       for ( i = PieceCnt[side]; i>= 0; i-- ) {
161         short sq, piece;
162         sq = PieceList[side][i];
163         piece = board[sq];
164         printf("square %d is %d with piece %d\n", i, sq, piece);
165       }
166       printf("hashkey = %ld hashbd = %ld\n",hashkey,hashbd);
167       assert(a[n] == atak[side][n]);
168     }
169 #endif  
170 #ifdef notdef
171     printf("atak array for %s available for SqAtakd!\n",ColorStr[side]);
172 #endif
173     *blockable = true; /* don't know */
174     return(Anyatak(side,square));
175   }
176
177  /*
178   * First check neigboured squares,
179   * then check Knights.
180   * then check Bishops,
181   * last check Rooks,
182   */                                         
183
184   *blockable = false;          
185
186   /* try a capture from direct neighboured squares */
187
188   ptyp = ptype[black][king];
189 #ifdef SAVE_NEXTPOS
190   u = first_direction(ptyp,&d,square);
191 #else
192   pdir = (*nextdir[ptyp])[square];
193   u = pdir[square];
194 #endif
195   do
196     {
197       if (color[u] == side)
198         /* can piece reach square in one step ? */
199 #ifdef CHECK_DISTANCE
200         if ( piece_distance(side,board[u],u,square) == 1 )
201           return(true);
202 #else   
203         {
204           short v;
205           short ptypv = ptype[side][board[u]];
206 #ifdef SAVE_NEXTPOS
207           short dv;
208           v = first_direction(ptypv,&dv,u);
209 #else 
210           unsigned char *qdir;
211           qdir = (*nextdir[ptypv])[u];
212           v = qdir[u];
213 #endif 
214           do
215             {
216               if (v == square)
217                 return (true);
218 #ifdef SAVE_NEXTPOS
219               v = next_direction(ptypv,&dv,u);
220 #else
221               v = qdir[v];
222 #endif
223           } while (v != u);
224         }
225 #endif
226 #ifdef SAVE_NEXTPOS
227       u = next_direction(ptyp,&d,square);
228 #else
229       u = pdir[u];
230 #endif
231   } while (u != square);
232
233   /* try a knight capture (using xside's knight moves) */
234
235   ptyp = ptype[side ^ 1][knight];
236 #ifdef SAVE_NEXTPOS
237   u = first_direction(ptyp,&d,square);
238 #else
239   pdir = (*nextdir[ptyp])[square];
240   u = pdir[square];
241 #endif
242   do
243     {
244       if (color[u] == side && board[u] == knight)
245         return (true);
246 #ifdef SAVE_NEXTPOS
247       u = next_direction(ptyp,&d,square);
248 #else
249       u = pdir[u];
250 #endif
251   } while (u != square);
252
253   *blockable = true;
254
255   /* try a (promoted) bishop capture */
256
257   ptyp = ptype[black][bishop];
258 #ifdef SAVE_NEXTPOS
259   u = first_direction(ptyp,&d,square);
260 #else
261   ppos = (*nextpos[ptyp])[square];
262   pdir = (*nextdir[ptyp])[square];
263   u = ppos[square];
264 #endif
265   do
266     {
267       if (color[u] == neutral)
268 #ifdef SAVE_NEXTPOS
269         u = next_position(ptyp,&d,square,u);
270 #else
271         u = ppos[u];
272 #endif
273       else
274         {
275           if (color[u] == side && (unpromoted[board[u]] == bishop))
276             return (true);
277 #ifdef SAVE_NEXTPOS
278           u = next_direction(ptyp,&d,square);
279 #else
280           u = pdir[u];
281 #endif
282         }
283   } while (u != square);
284
285   /* try a (promoted) rook capture */
286
287   ptyp = ptype[black][rook];
288 #ifdef SAVE_NEXTPOS
289   u = first_direction(ptyp,&d,square);
290 #else
291   ppos = (*nextpos[ptyp])[square];
292   pdir = (*nextdir[ptyp])[square];
293   u = ppos[square];
294 #endif
295   do
296     {
297       if (color[u] == neutral)
298 #ifdef SAVE_NEXTPOS
299         u = next_position(ptyp,&d,square,u);
300 #else
301         u = ppos[u];
302 #endif
303       else
304         {
305           if (color[u] == side && (unpromoted[board[u]] == rook))
306             return (true);
307 #ifdef SAVE_NEXTPOS
308           u = next_direction(ptyp,&d,square);
309 #else
310           u = pdir[u];
311 #endif
312         }
313   } while (u != square);
314
315   /* try a lance capture (using xside's lance moves) */
316
317   ptyp = ptype[side ^ 1][lance];
318 #ifdef SAVE_NEXTPOS
319   u = first_direction(ptyp,&d,square);
320 #else
321   ppos = (*nextpos[ptyp])[square];
322   u = ppos[square];
323 #endif
324   do
325     {
326       if (color[u] == neutral)
327 #ifdef SAVE_NEXTPOS
328         u = next_position(ptyp,&d,square,u);
329 #else
330         u = ppos[u];
331 #endif
332       else
333         {
334           if (color[u] == side && (board[u] == lance))
335             return (true);
336           u = square;
337         }
338   } while (u != square);
339                      
340   return (false);
341
342 }