Fix force mode after setboard
[bonanza.git] / attack.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include "shogi.h"
4
5 unsigned int CONV
6 is_pinned_on_white_king( const tree_t * restrict ptree, int isquare,
7                         int idirec )
8 {
9   bitboard_t bb_attacks, bb_attacker;
10
11   switch ( idirec )
12     {
13     case direc_rank:
14       bb_attacks = AttackRank( isquare );
15       if ( BBContract( bb_attacks, BB_WKING ) )
16         {
17           return BBContract( bb_attacks, BB_B_RD );
18         }
19       break;
20
21     case direc_file:
22       bb_attacks = AttackFile( isquare );
23       if ( BBContract( bb_attacks, BB_WKING ) )
24         {
25           BBAnd( bb_attacker, BB_BLANCE, abb_plus_rays[isquare] );
26           BBOr( bb_attacker, bb_attacker, BB_B_RD );
27           return BBContract( bb_attacks, bb_attacker );  /* return! */
28         }
29       break;
30
31     case direc_diag1:
32       bb_attacks = AttackDiag1( isquare );
33       if ( BBContract( bb_attacks, BB_WKING ) )
34         {
35           return BBContract( bb_attacks, BB_B_BH );      /* return! */
36         }
37       break;
38
39     default:
40       assert( idirec == direc_diag2 );
41       bb_attacks = AttackDiag2( isquare );
42       if ( BBContract( bb_attacks, BB_WKING ) )
43         {
44           return BBContract( bb_attacks, BB_B_BH );      /* return! */
45         }
46       break;
47     }
48   
49   return 0;
50 }
51
52
53 unsigned int CONV
54 is_pinned_on_black_king( const tree_t * restrict ptree, int isquare,
55                         int idirec )
56 {
57   bitboard_t bb_attacks, bb_attacker;
58
59   switch ( idirec )
60     {
61     case direc_rank:
62       bb_attacks = AttackRank( isquare );
63       if ( BBContract( bb_attacks, BB_BKING ) )
64         {
65           return BBContract( bb_attacks, BB_W_RD );
66         }
67       break;
68
69     case direc_file:
70       bb_attacks = AttackFile( isquare );
71       if ( BBContract( bb_attacks, BB_BKING ) )
72         {
73           BBAnd( bb_attacker, BB_WLANCE, abb_minus_rays[isquare] );
74           BBOr( bb_attacker, bb_attacker, BB_W_RD );
75           return BBContract( bb_attacks, bb_attacker );      /* return! */
76         }
77       break;
78
79     case direc_diag1:
80       bb_attacks = AttackDiag1( isquare );
81       if ( BBContract( bb_attacks, BB_BKING ) )
82         {
83           return BBContract( bb_attacks, BB_W_BH );          /* return! */
84         }
85       break;
86
87     default:
88       assert( idirec == direc_diag2 );
89       bb_attacks = AttackDiag2( isquare );
90       if ( BBContract( bb_attacks, BB_BKING ) )
91         {
92           return BBContract( bb_attacks, BB_W_BH );          /* return! */
93         }
94       break;
95     }
96   return 0;
97 }
98
99
100 /* perpetual check detections are omitted. */
101 int CONV
102 is_mate_b_pawn_drop( tree_t * restrict ptree, int sq_drop )
103 {
104   bitboard_t bb, bb_sum, bb_move;
105   int iwk, ito, iret, ifrom, idirec;
106
107   BBAnd( bb_sum, BB_WKNIGHT, abb_b_knight_attacks[sq_drop] );
108
109   BBAndOr( bb_sum, BB_WSILVER, abb_b_silver_attacks[sq_drop] );
110   BBAndOr( bb_sum, BB_WTGOLD, abb_b_gold_attacks[sq_drop] );
111
112   AttackBishop( bb, sq_drop );
113   BBAndOr( bb_sum, BB_W_BH, bb );
114
115   AttackRook( bb, sq_drop );
116   BBAndOr( bb_sum, BB_W_RD, bb );
117
118   BBOr( bb, BB_WHORSE, BB_WDRAGON );
119   BBAndOr( bb_sum, bb, abb_king_attacks[sq_drop] );
120
121   while ( BBTest( bb_sum ) )
122     {
123       ifrom  = FirstOne( bb_sum );
124       Xor( ifrom, bb_sum );
125
126       if ( IsDiscoverWK( ifrom, sq_drop ) ) { continue; }
127       return 0;
128     }
129
130   iwk  = SQ_WKING;
131   iret = 1;
132   Xor( sq_drop, BB_BOCCUPY );
133   XorFile( sq_drop, OCCUPIED_FILE );
134   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
135   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
136   
137   BBNotAnd( bb_move, abb_king_attacks[iwk], BB_WOCCUPY );
138   while ( BBTest( bb_move ) )
139     {
140       ito = FirstOne( bb_move );
141       if ( ! is_white_attacked( ptree, ito ) )
142         {
143           iret = 0;
144           break;
145         }
146       Xor( ito, bb_move );
147     }
148
149   Xor( sq_drop, BB_BOCCUPY );
150   XorFile( sq_drop, OCCUPIED_FILE );
151   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
152   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
153
154   return iret;
155 }
156
157
158 int CONV
159 is_mate_w_pawn_drop( tree_t * restrict ptree, int sq_drop )
160 {
161   bitboard_t bb, bb_sum, bb_move;
162   int ibk, ito, ifrom, iret, idirec;
163
164   BBAnd( bb_sum, BB_BKNIGHT, abb_w_knight_attacks[sq_drop] );
165
166   BBAndOr( bb_sum, BB_BSILVER, abb_w_silver_attacks[sq_drop] );
167   BBAndOr( bb_sum, BB_BTGOLD,  abb_w_gold_attacks[sq_drop] );
168
169   AttackBishop( bb, sq_drop );
170   BBAndOr( bb_sum, BB_B_BH, bb );
171
172   AttackRook( bb, sq_drop );
173   BBAndOr( bb_sum, BB_B_RD, bb );
174
175   BBOr( bb, BB_BHORSE, BB_BDRAGON );
176   BBAndOr( bb_sum, bb, abb_king_attacks[sq_drop] );
177
178   while ( BBTest( bb_sum ) )
179     {
180       ifrom  = FirstOne( bb_sum );
181       Xor( ifrom, bb_sum );
182
183       if ( IsDiscoverBK( ifrom, sq_drop ) ) { continue; }
184       return 0;
185     }
186
187   ibk  = SQ_BKING;
188   iret = 1;
189   Xor( sq_drop, BB_WOCCUPY );
190   XorFile( sq_drop, OCCUPIED_FILE );
191   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
192   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
193   
194   BBNotAnd( bb_move, abb_king_attacks[ibk], BB_BOCCUPY );
195   while ( BBTest( bb_move ) )
196     {
197       ito = FirstOne( bb_move );
198       if ( ! is_black_attacked( ptree, ito ) )
199         {
200           iret = 0;
201           break;
202         }
203       Xor( ito, bb_move );
204     }
205
206   Xor( sq_drop, BB_WOCCUPY );
207   XorFile( sq_drop, OCCUPIED_FILE );
208   XorDiag2( sq_drop, OCCUPIED_DIAG2 );
209   XorDiag1( sq_drop, OCCUPIED_DIAG1 );
210
211   return iret;
212 }
213
214
215 int CONV
216 is_move_check_b( const tree_t * restrict ptree, unsigned int move )
217 {
218   const int from = (int)I2From(move);
219   const int to   = (int)I2To(move);
220   int ipiece_move, idirec;
221   bitboard_t bb;
222
223   if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
224   else {
225     ipiece_move = (int)I2PieceMove(move);
226     if ( I2IsPromote(move) ) { ipiece_move += promote; }
227     
228     idirec = (int)adirec[SQ_WKING][from];
229     if ( idirec && idirec != (int)adirec[SQ_WKING][to]
230          && is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
231   }
232   
233   switch ( ipiece_move )
234     {
235     case pawn:
236       return BOARD[to-nfile] == -king;
237
238     case lance:
239       AttackBLance( bb, to );
240       return BBContract( bb, BB_WKING );
241       
242     case knight:
243       return BBContract( abb_b_knight_attacks[to], BB_WKING );
244       
245     case silver:
246       return BBContract( abb_b_silver_attacks[to], BB_WKING );
247       
248     case bishop:
249       AttackBishop( bb, to );
250       return BBContract( bb, BB_WKING );
251       
252     case rook:
253       AttackRook( bb, to );
254       return BBContract( bb, BB_WKING );
255       
256     case king:
257       return 0;
258
259     case horse:
260       AttackHorse( bb, to );
261       return BBContract( bb, BB_WKING );
262       
263     case dragon:
264       assert( ipiece_move == dragon );
265       AttackDragon( bb, to );
266       return BBContract( bb, BB_WKING );
267     }
268   /*
269     case gold:         case pro_pawn:
270     case pro_lance:    case pro_knight:
271     case pro_silver:
272   */
273   return BBContract( abb_b_gold_attacks[to], BB_WKING );
274 }
275
276
277 int CONV
278 is_move_check_w( const tree_t * restrict ptree, unsigned int move )
279 {
280   const int from = (int)I2From(move);
281   const int to   = (int)I2To(move);
282   int ipiece_move, idirec;
283   bitboard_t bb;
284
285   if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
286   else {
287     ipiece_move = (int)I2PieceMove(move);
288     if ( I2IsPromote(move) ) { ipiece_move += promote; }
289     
290     idirec = (int)adirec[SQ_BKING][from];
291     if ( idirec && idirec != (int)adirec[SQ_BKING][to]
292          && is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
293   }
294   
295   switch ( ipiece_move )
296     {
297     case pawn:
298       return BOARD[to+nfile] == king;
299       
300     case lance:
301       AttackWLance( bb, to );
302       return BBContract( bb, BB_BKING );
303       
304     case knight:
305       return BBContract( abb_w_knight_attacks[to], BB_BKING );
306       
307     case silver:
308       return BBContract( abb_w_silver_attacks[to], BB_BKING );
309       
310     case bishop:
311       AttackBishop( bb, to );
312       return BBContract( bb, BB_BKING );
313       
314     case rook:
315       AttackRook( bb, to );
316       return BBContract( bb, BB_BKING );
317
318     case king:
319       return 0;
320
321     case horse:
322       AttackHorse( bb, to );
323       return BBContract( bb, BB_BKING );
324       
325     case dragon:
326       AttackDragon( bb, to );
327       return BBContract( bb, BB_BKING );
328     }
329
330   /*
331     case gold:        case pro_pawn:
332     case pro_lance:   case pro_knight:
333     case pro_silver:
334   */
335   return BBContract( abb_w_gold_attacks[to], BB_BKING );
336 }
337
338
339 bitboard_t CONV
340 attacks_to_piece( const tree_t * restrict ptree, int sq )
341 {
342   bitboard_t bb_ret, bb_attacks, bb;
343
344   BBIni( bb_ret );
345   if ( sq < rank9*nfile && BOARD[sq+nfile] == pawn )
346     {
347       bb_ret = abb_mask[sq+nfile];
348     }
349   if ( sq >= nfile && BOARD[sq-nfile] == -pawn )
350     {
351       BBOr( bb_ret, bb_ret, abb_mask[sq-nfile] );
352     }
353
354   BBAndOr( bb_ret, BB_BKNIGHT, abb_w_knight_attacks[sq] );
355   BBAndOr( bb_ret, BB_WKNIGHT, abb_b_knight_attacks[sq] );
356   BBAndOr( bb_ret, BB_BSILVER, abb_w_silver_attacks[sq] );
357   BBAndOr( bb_ret, BB_WSILVER, abb_b_silver_attacks[sq] );
358   BBAndOr( bb_ret, BB_BTGOLD,  abb_w_gold_attacks[sq] );
359   BBAndOr( bb_ret, BB_WTGOLD,  abb_b_gold_attacks[sq] );
360
361   BBOr( bb, BB_B_HDK, BB_W_HDK );
362   BBAndOr( bb_ret, bb, abb_king_attacks[sq] );
363
364   BBOr( bb, BB_B_BH, BB_W_BH );
365   AttackBishop( bb_attacks, sq );
366   BBAndOr( bb_ret, bb, bb_attacks );
367
368   BBOr( bb, BB_B_RD, BB_W_RD );
369   BBAndOr( bb_ret, bb, AttackRank( sq ) );
370   BBAndOr( bb, BB_BLANCE, abb_plus_rays[sq] );
371   BBAndOr( bb, BB_WLANCE, abb_minus_rays[sq] );
372   BBAndOr( bb_ret, bb, AttackFile( sq ) );
373   
374   return bb_ret;
375 }
376
377
378 bitboard_t CONV
379 b_attacks_to_piece( const tree_t * restrict ptree, int sq )
380 {
381   bitboard_t bb_ret, bb_attacks, bb;
382
383   BBIni( bb_ret );
384   if ( sq < rank9*nfile && BOARD[sq+nfile] == pawn )
385     {
386       bb_ret = abb_mask[sq+nfile];
387     }
388
389   BBAndOr( bb_ret, BB_BKNIGHT, abb_w_knight_attacks[sq] );
390   BBAndOr( bb_ret, BB_BSILVER, abb_w_silver_attacks[sq] );
391   BBAndOr( bb_ret, BB_BTGOLD,  abb_w_gold_attacks[sq] );
392   BBAndOr( bb_ret, BB_B_HDK,   abb_king_attacks[sq] );
393
394   AttackBishop( bb_attacks, sq );
395   BBAndOr( bb_ret, BB_B_BH, bb_attacks );
396
397   bb = BB_B_RD;
398   BBAndOr( bb_ret, bb, AttackRank(sq) );
399   BBAndOr( bb, BB_BLANCE, abb_plus_rays[sq] );
400   BBAndOr( bb_ret, bb, AttackFile(sq) );
401   
402   return bb_ret;
403 }
404
405
406 bitboard_t CONV
407 w_attacks_to_piece( const tree_t * restrict ptree, int sq )
408 {
409   bitboard_t bb_ret, bb_attacks, bb;
410
411   BBIni( bb_ret );
412   if ( nfile <= sq && BOARD[sq-nfile] == -pawn )
413     {
414       bb_ret = abb_mask[sq-nfile];
415     }
416
417   BBAndOr( bb_ret, BB_WKNIGHT, abb_b_knight_attacks[sq] );
418   BBAndOr( bb_ret, BB_WSILVER, abb_b_silver_attacks[sq] );
419   BBAndOr( bb_ret, BB_WTGOLD,  abb_b_gold_attacks[sq] );
420   BBAndOr( bb_ret, BB_W_HDK,   abb_king_attacks[sq] );
421
422   AttackBishop( bb_attacks, sq );
423   BBAndOr( bb_ret, BB_W_BH, bb_attacks );
424
425   bb = BB_W_RD;
426   BBAndOr( bb_ret, bb, AttackRank(sq) );
427   BBAndOr( bb, BB_WLANCE, abb_minus_rays[sq] );
428   BBAndOr( bb_ret, bb, AttackFile(sq) );
429   
430   return bb_ret;
431 }
432
433
434 unsigned int CONV
435 is_white_attacked( const tree_t * restrict ptree, int sq )
436 {
437   bitboard_t bb, bb1, bb_atk;
438
439   BBAnd  ( bb, BB_BPAWN_ATK, abb_mask[sq] );
440   BBAndOr( bb, BB_BKNIGHT,   abb_w_knight_attacks[sq] );
441   BBAndOr( bb, BB_BSILVER,   abb_w_silver_attacks[sq] );
442   BBAndOr( bb, BB_BTGOLD,    abb_w_gold_attacks[sq] );
443   BBAndOr( bb, BB_B_HDK,     abb_king_attacks[sq] );
444
445   AttackBishop( bb_atk, sq );
446   BBAndOr( bb, BB_B_BH, bb_atk );
447
448   bb1 = BB_B_RD;
449   BBAndOr( bb1, BB_BLANCE, abb_plus_rays[sq] );
450   BBAndOr( bb, bb1, AttackFile( sq ) );
451   BBAndOr( bb, BB_B_RD, AttackRank( sq ) );
452
453   return BBToU(bb);
454 }
455
456
457 unsigned int CONV
458 is_black_attacked( const tree_t * restrict ptree, int sq )
459 {
460   bitboard_t bb, bb1, bb_atk;
461
462   BBAnd  ( bb, BB_WPAWN_ATK, abb_mask[sq] );
463   BBAndOr( bb, BB_WKNIGHT,   abb_b_knight_attacks[sq] );
464   BBAndOr( bb, BB_WSILVER,   abb_b_silver_attacks[sq] );
465   BBAndOr( bb, BB_WTGOLD,    abb_b_gold_attacks[sq] );
466   BBAndOr( bb, BB_W_HDK,     abb_king_attacks[sq] );
467
468   AttackBishop( bb_atk, sq );
469   BBAndOr( bb, BB_W_BH, bb_atk );
470
471   bb1 = BB_W_RD;
472   BBAndOr( bb1, BB_WLANCE, abb_minus_rays[sq] );
473   BBAndOr( bb, bb1, AttackFile( sq ) );
474   BBAndOr( bb, BB_W_RD, AttackRank( sq ) );
475
476   return BBTest(bb);
477 }