Implement undo command
[bonanza.git] / attack.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include "shogi.h"
4
5
6 unsigned int
7 is_pinned_on_white_king( const tree_t * restrict ptree, int isquare,
8                         int idirec )
9 {
10   unsigned int ubb_attacks;
11   bitboard_t bb_attacks, bb_attacker;
12
13   switch ( idirec )
14     {
15     case direc_rank:
16       ubb_attacks = AttackRank( isquare );
17       if ( ubb_attacks & (BB_WKING.p[aslide[isquare].ir0]) )
18         {
19           return ubb_attacks & BB_B_RD.p[aslide[isquare].ir0];
20         }
21       break;
22
23     case direc_file:
24       bb_attacks = AttackFile( isquare );
25       if ( BBContract( bb_attacks, BB_WKING ) )
26         {
27           BBAnd( bb_attacker, BB_BLANCE, abb_plus_rays[isquare] );
28           BBOr( bb_attacker, bb_attacker, BB_B_RD );
29           return BBContract( bb_attacks, bb_attacker );  /* return! */
30         }
31       break;
32
33     case direc_diag1:
34       bb_attacks = AttackDiag1( isquare );
35       if ( BBContract( bb_attacks, BB_WKING ) )
36         {
37           return BBContract( bb_attacks, BB_B_BH );      /* return! */
38         }
39       break;
40
41     default:
42       assert( idirec == direc_diag2 );
43       bb_attacks = AttackDiag2( isquare );
44       if ( BBContract( bb_attacks, BB_WKING ) )
45         {
46           return BBContract( bb_attacks, BB_B_BH );      /* return! */
47         }
48       break;
49     }
50   
51   return 0;
52 }
53
54
55 unsigned int
56 is_pinned_on_black_king( const tree_t * restrict ptree, int isquare,
57                         int idirec )
58 {
59   unsigned int ubb_attacks;
60   bitboard_t bb_attacks, bb_attacker;
61
62   switch ( idirec )
63     {
64     case direc_rank:
65       ubb_attacks = AttackRank( isquare );
66       if ( ubb_attacks & (BB_BKING.p[aslide[isquare].ir0]) )
67         {
68           return ubb_attacks & BB_W_RD.p[aslide[isquare].ir0];
69         }
70       break;
71
72     case direc_file:
73       bb_attacks = AttackFile( isquare );
74       if ( BBContract( bb_attacks, BB_BKING ) )
75         {
76           BBAnd( bb_attacker, BB_WLANCE, abb_minus_rays[isquare] );
77           BBOr( bb_attacker, bb_attacker, BB_W_RD );
78           return BBContract( bb_attacks, bb_attacker );      /* return! */
79         }
80       break;
81
82     case direc_diag1:
83       bb_attacks = AttackDiag1( isquare );
84       if ( BBContract( bb_attacks, BB_BKING ) )
85         {
86           return BBContract( bb_attacks, BB_W_BH );          /* return! */
87         }
88       break;
89
90     default:
91       assert( idirec == direc_diag2 );
92       bb_attacks = AttackDiag2( isquare );
93       if ( BBContract( bb_attacks, BB_BKING ) )
94         {
95           return BBContract( bb_attacks, BB_W_BH );          /* return! */
96         }
97       break;
98     }
99   return 0;
100 }
101
102
103 /* perpetual check detections are omitted. */
104 int
105 is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop )
106 {
107   bitboard_t bb, bb_sum, bb_move;
108   int iwk, ito, iret, ifrom, idirec;
109
110   BBAnd( bb_sum, BB_WKNIGHT, abb_b_knight_attacks[sq_drop] );
111
112   BBAndOr( bb_sum, BB_WSILVER, abb_b_silver_attacks[sq_drop] );
113   BBAndOr( bb_sum, BB_WTGOLD, abb_b_gold_attacks[sq_drop] );
114
115   AttackBishop( bb, sq_drop );
116   BBAndOr( bb_sum, BB_W_BH, bb );
117
118   AttackRook( bb, sq_drop );
119   BBAndOr( bb_sum, BB_W_RD, bb );
120
121   BBOr( bb, BB_WHORSE, BB_WDRAGON );
122   BBAndOr( bb_sum, bb, abb_king_attacks[sq_drop] );
123
124   while ( BBToU( bb_sum ) )
125     {
126       ifrom  = FirstOne( bb_sum );
127       Xor( ifrom, bb_sum );
128
129       if ( IsDiscoverWK( ifrom, sq_drop ) ) { continue; }
130       return 0;
131     }
132
133   iwk  = SQ_WKING;
134   iret = 1;
135   Xor( sq_drop, BB_BOCCUPY );
136   XorFile( sq_drop, OCCUPIED_FILE );
137   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
138   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
139   
140   BBNot( bb_move, BB_WOCCUPY );
141   BBAnd( bb_move, bb_move, abb_king_attacks[iwk] );
142   while ( BBToU( bb_move ) )
143     {
144       ito = FirstOne( bb_move );
145       if ( ! is_white_attacked( ptree, ito ) )
146         {
147           iret = 0;
148           break;
149         }
150       Xor( ito, bb_move );
151     }
152
153   Xor( sq_drop, BB_BOCCUPY );
154   XorFile( sq_drop, OCCUPIED_FILE );
155   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
156   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
157
158   return iret;
159 }
160
161
162 int
163 is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop )
164 {
165   bitboard_t bb, bb_sum, bb_move;
166   int ibk, ito, ifrom, iret, idirec;
167
168   BBAnd( bb_sum, BB_BKNIGHT, abb_w_knight_attacks[sq_drop] );
169
170   BBAndOr( bb_sum, BB_BSILVER, abb_w_silver_attacks[sq_drop] );
171   BBAndOr( bb_sum, BB_BTGOLD,  abb_w_gold_attacks[sq_drop] );
172
173   AttackBishop( bb, sq_drop );
174   BBAndOr( bb_sum, BB_B_BH, bb );
175
176   AttackRook( bb, sq_drop );
177   BBAndOr( bb_sum, BB_B_RD, bb );
178
179   BBOr( bb, BB_BHORSE, BB_BDRAGON );
180   BBAndOr( bb_sum, bb, abb_king_attacks[sq_drop] );
181
182   while ( BBToU( bb_sum ) )
183     {
184       ifrom  = FirstOne( bb_sum );
185       Xor( ifrom, bb_sum );
186
187       if ( IsDiscoverBK( ifrom, sq_drop ) ) { continue; }
188       return 0;
189     }
190
191   ibk  = SQ_BKING;
192   iret = 1;
193   Xor( sq_drop, BB_WOCCUPY );
194   XorFile( sq_drop, OCCUPIED_FILE );
195   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
196   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
197   
198   BBNot( bb_move, BB_BOCCUPY );
199   BBAnd( bb_move, bb_move, abb_king_attacks[ibk] );
200   while ( BBToU( bb_move ) )
201     {
202       ito = FirstOne( bb_move );
203       if ( ! is_black_attacked( ptree, ito ) )
204         {
205           iret = 0;
206           break;
207         }
208       Xor( ito, bb_move );
209     }
210
211   Xor( sq_drop, BB_WOCCUPY );
212   XorFile( sq_drop, OCCUPIED_FILE );
213   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
214   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
215
216   return iret;
217 }
218
219
220 bitboard_t
221 attacks_to_piece( const tree_t * restrict ptree, int sq )
222 {
223   bitboard_t bb_ret, bb_attacks, bb;
224
225   BBIni( bb_ret );
226   if ( sq < rank9*nfile && BOARD[sq+nfile] == pawn )
227     {
228       bb_ret = abb_mask[sq+nfile];
229     }
230   if ( sq >= nfile && BOARD[sq-nfile] == -pawn )
231     {
232       BBOr( bb_ret, bb_ret, abb_mask[sq-nfile] );
233     }
234
235   BBAndOr( bb_ret, BB_BKNIGHT, abb_w_knight_attacks[sq] );
236   BBAndOr( bb_ret, BB_WKNIGHT, abb_b_knight_attacks[sq] );
237
238   BBAndOr( bb_ret, BB_BSILVER, abb_w_silver_attacks[sq] );
239   BBAndOr( bb_ret, BB_WSILVER, abb_b_silver_attacks[sq] );
240
241   BBAndOr( bb_ret, BB_BTGOLD,  abb_w_gold_attacks[sq] );
242   BBAndOr( bb_ret, BB_WTGOLD,  abb_b_gold_attacks[sq] );
243
244   BBOr( bb, BB_B_HDK, BB_W_HDK );
245   BBAndOr( bb_ret, bb, abb_king_attacks[sq] );
246
247   BBOr( bb, BB_B_BH, BB_W_BH );
248   AttackBishop( bb_attacks, sq );
249   BBAndOr( bb_ret, bb, bb_attacks );
250
251   BBOr( bb, BB_B_RD, BB_W_RD );
252   bb_ret.p[aslide[sq].ir0]
253     |= bb.p[aslide[sq].ir0] & AttackRank( sq );
254   
255   BBAndOr( bb, BB_BLANCE, abb_plus_rays[sq] );
256   BBAndOr( bb, BB_WLANCE, abb_minus_rays[sq] );
257   bb_attacks = AttackFile( sq );
258   BBAndOr( bb_ret, bb, bb_attacks );
259   
260   return bb_ret;
261 }
262
263
264 unsigned int
265 is_white_attacked( const tree_t * restrict ptree, int sq )
266 {
267   bitboard_t bb;
268   unsigned int u;
269
270   u  = BBContract( BB_BPAWN_ATK, abb_mask[sq] );
271   u |= BBContract( BB_BKNIGHT,   abb_w_knight_attacks[sq] );
272   u |= BBContract( BB_BSILVER,   abb_w_silver_attacks[sq] );
273   u |= BBContract( BB_BTGOLD,    abb_w_gold_attacks[sq] );
274   u |= BBContract( BB_B_HDK,     abb_king_attacks[sq] );
275
276   AttackBishop( bb, sq );
277   u |= BBContract( BB_B_BH, bb );
278
279   u |= BB_B_RD.p[aslide[sq].ir0] & AttackRank( sq );
280
281   bb = AttackFile( sq );
282   u |= ( ( BB_BLANCE.p[0] & abb_plus_rays[sq].p[0] )
283          | BB_B_RD.p[0] ) & bb.p[0];
284   u |= ( ( BB_BLANCE.p[1] & abb_plus_rays[sq].p[1] )
285                | BB_B_RD.p[1] ) & bb.p[1];
286   u |= ( ( BB_BLANCE.p[2] & abb_plus_rays[sq].p[2] )
287                | BB_B_RD.p[2] ) & bb.p[2];
288
289   return u;
290 }
291
292
293 unsigned int
294 is_black_attacked( const tree_t * restrict ptree, int sq )
295 {
296   bitboard_t bb;
297   unsigned int u;
298
299   u  = BBContract( BB_WPAWN_ATK, abb_mask[sq] );
300   u |= BBContract( BB_WKNIGHT,   abb_b_knight_attacks[sq] );
301   u |= BBContract( BB_WSILVER,   abb_b_silver_attacks[sq] );
302   u |= BBContract( BB_WTGOLD,    abb_b_gold_attacks[sq] );
303   u |= BBContract( BB_W_HDK,     abb_king_attacks[sq] );
304
305   AttackBishop( bb, sq );
306   u |= BBContract( BB_W_BH, bb );
307
308   u |= BB_W_RD.p[aslide[sq].ir0] & AttackRank( sq );
309
310   bb = AttackFile( sq );
311   u |= ( ( BB_WLANCE.p[0] & abb_minus_rays[sq].p[0] )
312          | BB_W_RD.p[0] ) & bb.p[0];
313   u |= ( ( BB_WLANCE.p[1] & abb_minus_rays[sq].p[1] )
314                | BB_W_RD.p[1] ) & bb.p[1];
315   u |= ( ( BB_WLANCE.p[2] & abb_minus_rays[sq].p[2] )
316                | BB_W_RD.p[2] ) & bb.p[2];
317
318   return u;
319 }