Fix force mode after setboard
[bonanza.git] / genchk.c
1 #include <assert.h>
2 #include "shogi.h"
3
4
5 static void CONV add_behind_attacks( bitboard_t * restrict pbb, int idirec,
6                                      int ik );
7
8 unsigned int * CONV
9 b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
10 {
11   bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
12   bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
13   bitboard_t bb_rank_chk;
14   const tree_t * restrict ptree = __ptree__;
15   unsigned int u0, u1, u2;
16   int from, to, sq_wk, idirec;
17
18   sq_wk = SQ_WKING;
19   bb_file_chk = AttackFile( sq_wk );
20   bb_rank_chk = AttackRank( sq_wk );
21   BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
22
23   bb_diag1_chk = AttackDiag1( sq_wk );
24   bb_diag2_chk = AttackDiag2( sq_wk );
25   BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
26   BBNot( bb_move_to, BB_BOCCUPY );
27   BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
28   BBNot( bb_drop_to, bb_drop_to );
29
30   from  = SQ_BKING;
31   idirec = (int)adirec[sq_wk][from];
32   if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
33     {
34       BBIni( bb_chk );
35       add_behind_attacks( &bb_chk, idirec, sq_wk );
36       BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
37       BBAnd( bb_chk, bb_chk, bb_move_to );
38       
39       while( BBTest( bb_chk ) )
40         {
41           to = LastOne( bb_chk );
42           Xor( to, bb_chk );
43           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
44             | Cap2Move(-BOARD[to]);
45         }
46     }
47   
48   
49   bb_piece = BB_BDRAGON;
50   while( BBTest( bb_piece ) )
51     {
52       from = LastOne( bb_piece );
53       Xor( from, bb_piece );
54
55       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
56       idirec = (int)adirec[sq_wk][from];
57       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
58         {
59           add_behind_attacks( &bb_chk, idirec, sq_wk );
60         }
61
62       AttackDragon( bb_desti, from );
63       BBAnd( bb_chk, bb_chk, bb_desti );
64       BBAnd( bb_chk, bb_chk, bb_move_to );
65
66       while( BBTest( bb_chk ) )
67         {
68           to = LastOne( bb_chk );
69           Xor( to, bb_chk );
70           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
71             | Cap2Move(-BOARD[to]);
72         }
73     }
74
75   bb_piece = BB_BHORSE;
76   while( BBTest( bb_piece ) )
77     {
78       from = LastOne( bb_piece );
79       Xor( from, bb_piece );
80
81       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
82       idirec = (int)adirec[sq_wk][from];
83       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
84         {
85           add_behind_attacks( &bb_chk, idirec, sq_wk );
86         }
87
88       AttackHorse( bb_desti, from );
89       BBAnd( bb_chk, bb_chk, bb_desti );
90       BBAnd( bb_chk, bb_chk, bb_move_to );
91
92       while( BBTest( bb_chk ) )
93         {
94           to = LastOne( bb_chk );
95           Xor( to, bb_chk );
96           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
97             | Cap2Move(-BOARD[to]);
98         }
99     }
100
101   u1 = BB_BROOK.p[1];
102   u2 = BB_BROOK.p[2];
103   while( u1 | u2 )
104     {
105       from = last_one12( u1, u2 );
106       u1   ^= abb_mask[from].p[1];
107       u2   ^= abb_mask[from].p[2];
108
109       AttackRook( bb_desti, from );
110
111       idirec = (int)adirec[sq_wk][from];
112       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
113         {
114           BBAnd( bb_chk, bb_desti, bb_move_to );
115         }
116       else {
117         bb_chk       = bb_rook_chk;
118         bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
119         BBAnd( bb_chk, bb_chk, bb_desti );
120         BBAnd( bb_chk, bb_chk, bb_move_to );
121       }
122
123       while ( bb_chk.p[0] )
124         {
125           to          = last_one0( bb_chk.p[0] );
126           bb_chk.p[0] ^= abb_mask[to].p[0];
127           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
128             | Cap2Move(-BOARD[to]) | FLAG_PROMO;
129         }
130
131       while( bb_chk.p[1] | bb_chk.p[2] )
132         {
133           to          = last_one12( bb_chk.p[1], bb_chk.p[2] );
134           bb_chk.p[1] ^= abb_mask[to].p[1];
135           bb_chk.p[2] ^= abb_mask[to].p[2];
136           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
137             | Cap2Move(-BOARD[to]);
138         }
139     }
140
141   u0 = BB_BROOK.p[0];
142   while( u0 )
143     {
144       from = last_one0( u0 );
145       u0   ^= abb_mask[from].p[0];
146       
147       AttackRook( bb_desti, from );
148
149       idirec = (int)adirec[sq_wk][from];
150       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
151         {
152           BBAnd( bb_chk, bb_desti, bb_move_to );
153         }
154       else {
155         BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
156         BBAnd( bb_chk, bb_chk, bb_desti );
157         BBAnd( bb_chk, bb_chk, bb_move_to );
158       }
159
160       while( BBTest( bb_chk ) )
161         {
162           to = LastOne( bb_chk );
163           Xor( to, bb_chk );
164           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
165             | Cap2Move(-BOARD[to]) | FLAG_PROMO;
166         }
167     }
168
169   u1 = BB_BBISHOP.p[1];
170   u2 = BB_BBISHOP.p[2];
171   while( u1 | u2 )
172     {
173       from = last_one12( u1, u2 );
174       u1   ^= abb_mask[from].p[1];
175       u2   ^= abb_mask[from].p[2];
176
177       AttackBishop( bb_desti, from );
178
179       idirec = (int)adirec[sq_wk][from];
180       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
181         {
182           BBAnd( bb_chk, bb_desti, bb_move_to );
183         }
184       else {
185         bb_chk       = bb_bishop_chk;
186         bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
187         BBAnd( bb_chk, bb_chk, bb_desti );
188         BBAnd( bb_chk, bb_chk, bb_move_to );
189       }
190
191       while ( bb_chk.p[0] )
192         {
193           to          = last_one0( bb_chk.p[0] );
194           bb_chk.p[0] ^= abb_mask[to].p[0];
195           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
196             | Cap2Move(-BOARD[to]) | FLAG_PROMO;
197         }
198
199       while( bb_chk.p[1] | bb_chk.p[2] )
200         {
201           to          = last_one12( bb_chk.p[1], bb_chk.p[2] );
202           bb_chk.p[1] ^= abb_mask[to].p[1];
203           bb_chk.p[2] ^= abb_mask[to].p[2];
204           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
205             | Cap2Move(-BOARD[to]);
206         }
207     }
208
209   u0 = BB_BBISHOP.p[0];
210   while( u0 )
211     {
212       from = last_one0( u0 );
213       u0   ^= abb_mask[from].p[0];
214       
215       AttackBishop( bb_desti, from );
216
217       idirec = (int)adirec[sq_wk][from];
218       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
219         {
220           BBAnd( bb_chk, bb_desti, bb_move_to );
221         }
222       else {
223         BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
224         BBAnd( bb_chk, bb_chk, bb_desti );
225         BBAnd( bb_chk, bb_chk, bb_move_to );
226       }
227
228       while( BBTest( bb_chk ) )
229         {
230           to = LastOne( bb_chk );
231           Xor( to, bb_chk );
232           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
233             | Cap2Move(-BOARD[to]) | FLAG_PROMO;
234         }
235     }
236
237
238   bb_piece = BB_BTGOLD;
239   while( BBTest( bb_piece ) )
240     {
241       from = LastOne( bb_piece );
242       Xor( from, bb_piece );
243
244       bb_chk = abb_w_gold_attacks[sq_wk];
245
246       idirec = (int)adirec[sq_wk][from];
247       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
248         {
249           add_behind_attacks( &bb_chk, idirec, sq_wk );
250         }
251
252       BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
253       BBAnd( bb_chk, bb_chk, bb_move_to );
254
255       while( BBTest( bb_chk ) )
256         {
257           to = LastOne( bb_chk );
258           Xor( to, bb_chk );
259           *pmove++ = ( To2Move(to) | From2Move(from)
260                        | Piece2Move(BOARD[from])
261                        | Cap2Move(-BOARD[to]) );
262         }
263     }
264   
265
266   u0 = BB_BSILVER.p[0];
267   while( u0 )
268     {
269       from = last_one0( u0 );
270       u0   ^= abb_mask[from].p[0];
271
272       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
273       bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
274       bb_chk.p[2] = 0;
275
276       idirec = (int)adirec[sq_wk][from];
277       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
278         {
279           add_behind_attacks( &bb_chk, idirec, sq_wk );
280         }
281
282       bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
283       bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
284
285       while( bb_chk.p[0] | bb_chk.p[1] )
286         {
287           to          = last_one01( bb_chk.p[0], bb_chk.p[1] );
288           bb_chk.p[0] ^= abb_mask[to].p[0];
289           bb_chk.p[1] ^= abb_mask[to].p[1];
290           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
291             | Cap2Move(-BOARD[to]) | FLAG_PROMO;
292         }
293     }
294   
295
296   u1 = BB_BSILVER.p[1] & 0x7fc0000U;
297   while( u1 )
298     {
299       from = last_one1( u1 );
300       u1   ^= abb_mask[from].p[1];
301       
302       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
303       bb_chk.p[1] = bb_chk.p[2] = 0;
304       
305       idirec = (int)adirec[sq_wk][from];
306       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
307         {
308           add_behind_attacks( &bb_chk, idirec, sq_wk );
309         }
310
311       bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
312       while ( bb_chk.p[0] )
313         {
314           to          = last_one0( bb_chk.p[0] );
315           bb_chk.p[0] ^= abb_mask[to].p[0];
316           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
317             | Cap2Move(-BOARD[to]) | FLAG_PROMO;
318         }
319     }
320   
321
322   bb_piece = BB_BSILVER;
323   while( BBTest( bb_piece ) )
324     {
325       from = LastOne( bb_piece );
326       Xor( from, bb_piece );
327
328       bb_chk = abb_w_silver_attacks[sq_wk];
329
330       idirec = (int)adirec[sq_wk][from];
331       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
332         {
333           add_behind_attacks( &bb_chk, idirec, sq_wk );
334         }
335
336       BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
337       BBAnd( bb_chk, bb_chk, bb_move_to );
338
339       while( BBTest( bb_chk ) )
340         {
341           to = LastOne( bb_chk );
342           Xor( to, bb_chk );
343           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
344             | Cap2Move(-BOARD[to]);
345         }
346     }
347   
348
349   u0 = BB_BKNIGHT.p[0];
350   u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
351   while( u0 | u1 )
352     {
353       from = last_one01( u0, u1 );
354       u0   ^= abb_mask[from].p[0];
355       u1   ^= abb_mask[from].p[1];
356
357       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
358       bb_chk.p[1] = bb_chk.p[2] = 0;
359
360       idirec = (int)adirec[sq_wk][from];
361       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
362         {
363           add_behind_attacks( &bb_chk, idirec, sq_wk );
364         }
365
366       bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
367
368       while( bb_chk.p[0] )
369         {
370           to          = last_one0( bb_chk.p[0] );
371           bb_chk.p[0] ^= abb_mask[to].p[0];
372           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
373                        | Cap2Move(-BOARD[to]) | FLAG_PROMO;
374         }
375     }
376   
377
378   u2 = BB_BKNIGHT.p[2];
379   u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
380   while( u2 | u1 )
381     {
382       from = last_one12( u1, u2 );
383       u2   ^= abb_mask[from].p[2];
384       u1   ^= abb_mask[from].p[1];
385
386       bb_chk = abb_w_knight_attacks[sq_wk];
387
388       idirec = (int)adirec[sq_wk][from];
389       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
390         {
391           add_behind_attacks( &bb_chk, idirec, sq_wk );
392         }
393
394       BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
395       BBAnd( bb_chk, bb_chk, bb_move_to );
396
397       while( BBTest( bb_chk ) )
398         {
399           to = LastOne( bb_chk );
400           Xor( to, bb_chk );
401           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
402             | Cap2Move(-BOARD[to]);
403         }
404     }
405
406
407   bb_piece = BB_BLANCE;
408   while( BBTest( bb_piece ) )
409     {
410       from = LastOne( bb_piece );
411       Xor( from, bb_piece );
412
413       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
414       bb_chk.p[1] = bb_chk.p[2] = 0;
415
416       idirec = (int)adirec[sq_wk][from];
417       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
418         {
419           add_behind_attacks( &bb_chk, idirec, sq_wk );
420         }
421
422       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
423       BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
424       BBAnd( bb_chk, bb_chk, bb_move_to );
425
426       while( BBTest( bb_chk ) )
427         {
428           to = LastOne( bb_chk );
429           Xor( to, bb_chk );
430           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
431             | Cap2Move(-BOARD[to]) | FLAG_PROMO;
432         }
433     }
434   
435
436   u1 = BB_BLANCE.p[1];
437   u2 = BB_BLANCE.p[2];
438   while( u1| u2 )
439     {
440       from = last_one12( u1, u2 );
441       u1   ^= abb_mask[from].p[1];
442       u2   ^= abb_mask[from].p[2];
443
444       bb_chk = bb_file_chk;
445       idirec = (int)adirec[sq_wk][from];
446       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
447         {
448           add_behind_attacks( &bb_chk, idirec, sq_wk );
449           BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
450         }
451       else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
452
453       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
454       BBAnd( bb_chk, bb_chk, bb_move_to );
455       bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
456
457       while( BBTest( bb_chk ) )
458         {
459           to = LastOne( bb_chk );
460           Xor( to, bb_chk );
461           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
462             | Cap2Move(-BOARD[to]);
463         }
464     }
465
466   BBIni( bb_chk );
467   bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
468   if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); }
469   BBAnd( bb_chk, bb_chk, bb_move_to );
470   BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
471
472   BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
473   while ( BBTest(bb_piece) )
474     {
475       from = LastOne( bb_piece );
476       Xor( from, bb_piece );
477       
478       to = from - nfile;
479       if ( BOARD[to] > 0 ) { continue; }
480
481       bb_desti = AttackDiag1( from );
482       if ( BBContract( bb_desti, BB_B_BH ) )
483         {
484           BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
485
486           *pmove = To2Move(to) | From2Move(from)
487             | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
488           if ( from < A5 ) { *pmove |= FLAG_PROMO; }
489           pmove += 1;
490         }
491     }
492
493   BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
494   while ( BBTest(bb_piece) )
495     {
496       from = LastOne( bb_piece );
497       Xor( from, bb_piece );
498       
499       to = from - nfile;
500       if ( BOARD[to] > 0 ) { continue; }
501
502       bb_desti = AttackDiag2( from );
503       if ( BBContract( bb_desti, BB_B_BH ) )
504         {
505           BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
506
507           *pmove = To2Move(to) | From2Move(from)
508             | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
509           if ( from < A5 ) { *pmove |= FLAG_PROMO; }
510           pmove += 1;
511         }
512     }
513
514   BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
515   while ( BBTest(bb_piece) )
516     {
517       from = LastOne( bb_piece );
518       Xor( from, bb_piece );
519       
520       to = from - nfile;
521       if ( BOARD[to] > 0 ) { continue; }
522
523       bb_desti = AttackRank( from );
524       if ( BBContract( bb_desti, BB_B_RD ) )
525         {
526           BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
527
528           *pmove = To2Move(to) | From2Move(from)
529             | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
530           if ( from < A5 ) { *pmove |= FLAG_PROMO; }
531           pmove += 1;
532         }
533     }
534
535   while ( BBTest(bb_chk) )
536     {
537       to = LastOne( bb_chk );
538       Xor( to, bb_chk );
539
540       from = to + nfile;
541       *pmove = To2Move(to) | From2Move(from)
542         | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
543       if ( from < A5 ) { *pmove |= FLAG_PROMO; }
544       pmove += 1;
545     }
546
547
548   if ( IsHandGold(HAND_B) )
549     {
550       BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
551       while( BBTest( bb_chk ) )
552         {
553           to = LastOne( bb_chk );
554           Xor( to, bb_chk );
555           *pmove++ = To2Move(to) | Drop2Move(gold);
556         }
557     }
558   
559
560   if ( IsHandSilver(HAND_B) )
561     {
562       BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
563       while( BBTest( bb_chk ) )
564         {
565           to = LastOne( bb_chk );
566           Xor( to, bb_chk );
567           *pmove++ = To2Move(to) | Drop2Move(silver);
568         }
569     }
570   
571
572   if ( IsHandKnight(HAND_B) && sq_wk < A2 )
573     {
574       to = sq_wk + 2*nfile - 1;
575       if ( aifile[sq_wk] != file1 && BOARD[to] == empty )
576         {
577           *pmove++ = To2Move(to) | Drop2Move(knight);
578         }
579
580       to = sq_wk + 2*nfile + 1;
581       if ( aifile[sq_wk] != file9 && BOARD[to] == empty )
582         {
583           *pmove++ = To2Move(to) | Drop2Move(knight);
584         }
585     }
586
587
588   if ( IsHandPawn(HAND_B)
589        && sq_wk < A1
590        && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )
591     {
592       to = sq_wk + nfile;
593       if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )
594         {
595           *pmove++ = To2Move(to) | Drop2Move(pawn);
596         }
597     }
598
599
600   if ( IsHandLance(HAND_B) )
601     {
602       unsigned int move;
603       int dist, min_dist;
604
605       if ( (int)aifile[sq_wk] == file1
606            || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
607       else                                  { min_dist = 3; }
608
609       for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
610             to += nfile, dist += 1 )
611         {
612           move = To2Move(to) | Drop2Move(lance);
613           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
614           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
615           *pmove++ = move;
616         }
617     }
618
619
620   if ( IsHandRook(HAND_B) )
621     {
622       unsigned int move;
623       int file, dist, min_dist;
624
625       if ( (int)aifile[sq_wk] == file1
626            || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
627       else                                  { min_dist = 3; }
628
629       for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
630             to += nfile, dist += 1 )
631         {
632           move = To2Move(to) | Drop2Move(rook);
633           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
634           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
635           *pmove++ = move;
636         }
637
638       for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;
639             file >= file1 && BOARD[to] == empty;
640             file -= 1, to -= 1, dist += 1 )
641         {
642           move = To2Move(to) | Drop2Move(rook);
643           if      ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
644           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
645           *pmove++ = move;
646         }
647
648       if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }
649       else                            { min_dist = 3; }
650
651       for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;
652             file <= file9 && BOARD[to] == empty;
653             file += 1, to += 1, dist += 1 )
654         {
655           move = To2Move(to) | Drop2Move(rook);
656           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
657           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
658           *pmove++ = move;
659         }
660
661       for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
662             to -= nfile, dist += 1 )
663         {
664           move = To2Move(to) | Drop2Move(rook);
665           if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }
666           if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }
667           else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }
668           *pmove++ = move;
669         }
670     }
671
672
673   if ( IsHandBishop(HAND_B) )
674     {
675       unsigned int move;
676       int file, rank, dist;
677
678       to   = sq_wk;
679       file = (int)aifile[sq_wk];
680       rank = (int)airank[sq_wk];
681       for ( to -= 10, file -= 1, rank -= 1, dist = 1;
682             file >= 0 && rank >= 0 && BOARD[to] == empty;
683             to -= 10, file -= 1, rank -= 1, dist += 1 )
684         {
685           move = To2Move(to) | Drop2Move(bishop);
686           if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
687           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
688           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
689           *pmove++ = move;
690         }
691
692       to   = sq_wk;
693       file = (int)aifile[sq_wk];
694       rank = (int)airank[sq_wk];
695       for ( to -= 8, file += 1, rank -= 1, dist = 1;
696             file <= file9 && rank >= 0 && BOARD[to] == empty;
697             to -= 8, file += 1, rank -= 1, dist += 1 )
698         {
699           move = To2Move(to) | Drop2Move(bishop);
700           if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
701           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
702           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
703           *pmove++ = move;
704         }
705
706       to   = sq_wk;
707       file = (int)aifile[sq_wk];
708       rank = (int)airank[sq_wk];
709       for ( to += 8, file -= 1, rank += 1, dist = 1;
710             file >= 0 && rank <= rank9 && BOARD[to] == empty;
711             to += 8, file -= 1, rank += 1, dist += 1 )
712         {
713           move = To2Move(to) | Drop2Move(bishop);
714           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
715           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
716           *pmove++ = move;
717         }
718
719       to   = sq_wk;
720       file = (int)aifile[sq_wk];
721       rank = (int)airank[sq_wk];
722       for ( to += 10, file += 1, rank += 1, dist = 1;
723             file <= file9 && rank <= rank9 && BOARD[to] == empty;
724             to += 10, file += 1, rank += 1, dist += 1 )
725         {
726           move = To2Move(to) | Drop2Move(bishop);
727           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
728           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
729           *pmove++ = move;
730         }
731     }
732
733
734   return pmove;
735 }
736
737
738 unsigned int * CONV
739 w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
740 {
741   bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
742   bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
743   bitboard_t bb_rank_chk;
744   const tree_t * restrict ptree = __ptree__;
745   unsigned int u0, u1, u2;
746   int from, to, sq_bk, idirec;
747
748   sq_bk = SQ_BKING;
749   bb_file_chk = AttackFile( sq_bk );
750   bb_rank_chk = AttackRank( sq_bk );
751   BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
752
753   bb_diag1_chk = AttackDiag1( sq_bk );
754   bb_diag2_chk = AttackDiag2( sq_bk );
755   BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
756   BBNot( bb_move_to, BB_WOCCUPY );
757   BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
758   BBNot( bb_drop_to, bb_drop_to );
759
760
761   from  = SQ_WKING;
762   idirec = (int)adirec[sq_bk][from];
763   if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
764     {
765       BBIni( bb_chk );
766       add_behind_attacks( &bb_chk, idirec, sq_bk );
767       BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
768       BBAnd( bb_chk, bb_chk, bb_move_to );
769
770       while( BBTest( bb_chk ) )
771         {
772           to = FirstOne( bb_chk );
773           Xor( to, bb_chk );
774           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
775             | Cap2Move(BOARD[to]);
776         }
777     }
778
779
780   bb_piece = BB_WDRAGON;
781   while( BBTest( bb_piece ) )
782     {
783       from = FirstOne( bb_piece );
784       Xor( from, bb_piece );
785
786       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
787       idirec = (int)adirec[sq_bk][from];
788       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
789         {
790           add_behind_attacks( &bb_chk, idirec, sq_bk );
791         }
792
793       AttackDragon( bb_desti, from );
794       BBAnd( bb_chk, bb_chk, bb_desti );
795       BBAnd( bb_chk, bb_chk, bb_move_to );
796
797       while( BBTest( bb_chk ) )
798         {
799           to = LastOne( bb_chk );
800           Xor( to, bb_chk );
801           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
802             | Cap2Move(BOARD[to]);
803         }
804     }
805
806
807   bb_piece = BB_WHORSE;
808   while( BBTest( bb_piece ) )
809     {
810       from = FirstOne( bb_piece );
811       Xor( from, bb_piece );
812
813       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
814       idirec = (int)adirec[sq_bk][from];
815       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
816         {
817           add_behind_attacks( &bb_chk, idirec, sq_bk );
818         }
819
820       AttackHorse( bb_desti, from );
821       BBAnd( bb_chk, bb_chk, bb_desti );
822       BBAnd( bb_chk, bb_chk, bb_move_to );
823
824       while( BBTest( bb_chk ) )
825         {
826           to = FirstOne( bb_chk );
827           Xor( to, bb_chk );
828           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
829             | Cap2Move(BOARD[to]);
830         }
831     }
832
833   u0 = BB_WROOK.p[0];
834   u1 = BB_WROOK.p[1];
835   while( u0 | u1 )
836     {
837       from = first_one01( u0, u1 );
838       u0   ^= abb_mask[from].p[0];
839       u1   ^= abb_mask[from].p[1];
840
841       AttackRook( bb_desti, from );
842
843       idirec = (int)adirec[sq_bk][from];
844       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
845         {
846           BBAnd( bb_chk, bb_desti, bb_move_to );
847         }
848       else {
849         bb_chk       = bb_rook_chk;
850         bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
851         BBAnd( bb_chk, bb_chk, bb_desti );
852         BBAnd( bb_chk, bb_chk, bb_move_to );
853       }
854
855       while ( bb_chk.p[2] )
856         {
857           to          = first_one2( bb_chk.p[2] );
858           bb_chk.p[2] ^= abb_mask[to].p[2];
859           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
860             | Cap2Move(BOARD[to]) | FLAG_PROMO;
861         }
862
863       while( bb_chk.p[0] | bb_chk.p[1] )
864         {
865           to          = first_one01( bb_chk.p[0], bb_chk.p[1] );
866           bb_chk.p[0] ^= abb_mask[to].p[0];
867           bb_chk.p[1] ^= abb_mask[to].p[1];
868           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
869             | Cap2Move(BOARD[to]);
870         }
871     }
872
873   u2 = BB_WROOK.p[2];
874   while( u2 )
875     {
876       from = first_one2( u2 );
877       u2   ^= abb_mask[from].p[2];
878       
879       AttackRook( bb_desti, from );
880
881       idirec = (int)adirec[sq_bk][from];
882       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
883         {
884           BBAnd( bb_chk, bb_desti, bb_move_to );
885         }
886       else {
887         BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
888         BBAnd( bb_chk, bb_chk, bb_desti );
889         BBAnd( bb_chk, bb_chk, bb_move_to );
890       }
891
892       while( BBTest( bb_chk ) )
893         {
894           to = FirstOne( bb_chk );
895           Xor( to, bb_chk );
896           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
897             | Cap2Move(BOARD[to]) | FLAG_PROMO;
898         }
899     }
900
901   u0 = BB_WBISHOP.p[0];
902   u1 = BB_WBISHOP.p[1];
903   while( u0 | u1 )
904     {
905       from = first_one01( u0, u1 );
906       u0   ^= abb_mask[from].p[0];
907       u1   ^= abb_mask[from].p[1];
908
909       AttackBishop( bb_desti, from );
910
911       idirec = (int)adirec[sq_bk][from];
912       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
913         {
914           BBAnd( bb_chk, bb_desti, bb_move_to );
915         }
916       else {
917         bb_chk       = bb_bishop_chk;
918         bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
919         BBAnd( bb_chk, bb_chk, bb_desti );
920         BBAnd( bb_chk, bb_chk, bb_move_to );
921       }
922
923       while ( bb_chk.p[2] )
924         {
925           to          = first_one2( bb_chk.p[2] );
926           bb_chk.p[2] ^= abb_mask[to].p[2];
927           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
928             | Cap2Move(BOARD[to]) | FLAG_PROMO;
929         }
930
931       while( bb_chk.p[0] | bb_chk.p[1] )
932         {
933           to          = first_one01( bb_chk.p[0], bb_chk.p[1] );
934           bb_chk.p[0] ^= abb_mask[to].p[0];
935           bb_chk.p[1] ^= abb_mask[to].p[1];
936           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
937             | Cap2Move(BOARD[to]);
938         }
939     }
940
941   u2 = BB_WBISHOP.p[2];
942   while( u2 )
943     {
944       from = first_one2( u2 );
945       u2   ^= abb_mask[from].p[2];
946       
947       AttackBishop( bb_desti, from );
948
949       idirec = (int)adirec[sq_bk][from];
950       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
951         {
952           BBAnd( bb_chk, bb_desti, bb_move_to );
953         }
954       else {
955         BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
956         BBAnd( bb_chk, bb_chk, bb_desti );
957         BBAnd( bb_chk, bb_chk, bb_move_to );
958       }
959
960       while( BBTest( bb_chk ) )
961         {
962           to = FirstOne( bb_chk );
963           Xor( to, bb_chk );
964           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
965             | Cap2Move(BOARD[to]) | FLAG_PROMO;
966         }
967     }
968
969
970   bb_piece = BB_WTGOLD;
971   while( BBTest( bb_piece ) )
972     {
973       from = FirstOne( bb_piece );
974       Xor( from, bb_piece );
975
976       bb_chk = abb_b_gold_attacks[sq_bk];
977
978       idirec = (int)adirec[sq_bk][from];
979       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
980         {
981           add_behind_attacks( &bb_chk, idirec, sq_bk );
982         }
983
984       BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
985       BBAnd( bb_chk, bb_chk, bb_move_to );
986
987       while( BBTest( bb_chk ) )
988         {
989           to = FirstOne( bb_chk );
990           Xor( to, bb_chk );
991           *pmove++ = ( To2Move(to) | From2Move(from)
992                        | Piece2Move(-BOARD[from])
993                        | Cap2Move(BOARD[to]) );
994         }
995     }
996
997   
998   u2 = BB_WSILVER.p[2];
999   while( u2 )
1000     {
1001       from = first_one2( u2 );
1002       u2   ^= abb_mask[from].p[2];
1003
1004       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
1005       bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
1006       bb_chk.p[0] = 0;
1007
1008       idirec = (int)adirec[sq_bk][from];
1009       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
1010         {
1011           add_behind_attacks( &bb_chk, idirec, sq_bk );
1012         }
1013
1014       bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
1015       bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
1016
1017       while( bb_chk.p[2] | bb_chk.p[1] )
1018         {
1019           to          = first_one12( bb_chk.p[1], bb_chk.p[2] );
1020           bb_chk.p[1] ^= abb_mask[to].p[1];
1021           bb_chk.p[2] ^= abb_mask[to].p[2];
1022           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
1023             | Cap2Move(BOARD[to]) | FLAG_PROMO;
1024         }
1025     }
1026   
1027
1028   u1 = BB_WSILVER.p[1] & 0x1ffU;
1029   while( u1 )
1030     {
1031       from = first_one1( u1 );
1032       u1   ^= abb_mask[from].p[1];
1033       
1034       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
1035       bb_chk.p[1] = bb_chk.p[0] = 0;
1036       
1037       idirec = (int)adirec[sq_bk][from];
1038       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
1039         {
1040           add_behind_attacks( &bb_chk, idirec, sq_bk );
1041         }
1042
1043       bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
1044       while ( bb_chk.p[2] )
1045         {
1046           to          = first_one2( bb_chk.p[2] );
1047           bb_chk.p[2] ^= abb_mask[to].p[2];
1048           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
1049             | Cap2Move(BOARD[to]) | FLAG_PROMO;
1050         }
1051     }
1052   
1053
1054   bb_piece = BB_WSILVER;
1055   while( BBTest( bb_piece ) )
1056     {
1057       from = FirstOne( bb_piece );
1058       Xor( from, bb_piece );
1059
1060       bb_chk = abb_b_silver_attacks[sq_bk];
1061
1062       idirec = (int)adirec[sq_bk][from];
1063       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
1064         {
1065           add_behind_attacks( &bb_chk, idirec, sq_bk );
1066         }
1067
1068       BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
1069       BBAnd( bb_chk, bb_chk, bb_move_to );
1070
1071       while( BBTest( bb_chk ) )
1072         {
1073           to = FirstOne( bb_chk );
1074           Xor( to, bb_chk );
1075           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
1076             | Cap2Move(BOARD[to]);
1077         }
1078     }
1079
1080   
1081   u2 = BB_WKNIGHT.p[2];
1082   u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
1083   while( u2 | u1 )
1084     {
1085       from = first_one12( u1, u2 );
1086       u2   ^= abb_mask[from].p[2];
1087       u1   ^= abb_mask[from].p[1];
1088
1089       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
1090       bb_chk.p[1] = bb_chk.p[0] = 0;
1091
1092       idirec = (int)adirec[sq_bk][from];
1093       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
1094         {
1095           add_behind_attacks( &bb_chk, idirec, sq_bk );
1096         }
1097
1098       bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
1099
1100       while( bb_chk.p[2] )
1101         {
1102           to          = first_one2( bb_chk.p[2] );
1103           bb_chk.p[2] ^= abb_mask[to].p[2];
1104           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
1105                        | Cap2Move(BOARD[to]) | FLAG_PROMO;
1106         }
1107     }
1108   
1109
1110   u0 = BB_WKNIGHT.p[0];
1111   u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
1112   while( u0 | u1 )
1113     {
1114       from = first_one01( u0, u1 );
1115       u0   ^= abb_mask[from].p[0];
1116       u1   ^= abb_mask[from].p[1];
1117
1118       bb_chk = abb_b_knight_attacks[sq_bk];
1119
1120       idirec = (int)adirec[sq_bk][from];
1121       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
1122         {
1123           add_behind_attacks( &bb_chk, idirec, sq_bk );
1124         }
1125
1126       BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
1127       BBAnd( bb_chk, bb_chk, bb_move_to );
1128
1129       while( BBTest( bb_chk ) )
1130         {
1131           to = FirstOne( bb_chk );
1132           Xor( to, bb_chk );
1133           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
1134             | Cap2Move(BOARD[to]);
1135         }
1136     }
1137
1138
1139   bb_piece = BB_WLANCE;
1140   while( BBTest( bb_piece ) )
1141     {
1142       from = FirstOne( bb_piece );
1143       Xor( from, bb_piece );
1144
1145       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
1146       bb_chk.p[1] = bb_chk.p[0] = 0;
1147
1148       idirec = (int)adirec[sq_bk][from];
1149       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
1150         {
1151           add_behind_attacks( &bb_chk, idirec, sq_bk );
1152         }
1153
1154       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
1155       BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
1156       BBAnd( bb_chk, bb_chk, bb_move_to );
1157
1158       while( BBTest( bb_chk ) )
1159         {
1160           to = FirstOne( bb_chk );
1161           Xor( to, bb_chk );
1162           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
1163             | Cap2Move(BOARD[to]) | FLAG_PROMO;
1164         }
1165     }
1166   
1167
1168   u0 = BB_WLANCE.p[0];
1169   u1 = BB_WLANCE.p[1];
1170   while( u0 | u1 )
1171     {
1172       from = first_one01( u0, u1 );
1173       u0   ^= abb_mask[from].p[0];
1174       u1   ^= abb_mask[from].p[1];
1175
1176       bb_chk = bb_file_chk;
1177       idirec = (int)adirec[sq_bk][from];
1178       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
1179         {
1180           add_behind_attacks( &bb_chk, idirec, sq_bk );
1181           BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
1182         }
1183       else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
1184
1185       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
1186       BBAnd( bb_chk, bb_chk, bb_move_to );
1187       bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
1188
1189       while( BBTest( bb_chk ) )
1190         {
1191           to = FirstOne( bb_chk );
1192           Xor( to, bb_chk );
1193           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
1194             | Cap2Move(BOARD[to]);
1195         }
1196     }
1197
1198   BBIni( bb_chk );
1199   bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
1200   if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); }
1201   BBAnd( bb_chk, bb_chk, bb_move_to );
1202   BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
1203
1204   BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
1205   while ( BBTest(bb_piece) )
1206     {
1207       from = FirstOne( bb_piece );
1208       Xor( from, bb_piece );
1209       
1210       to = from + nfile;
1211       if ( BOARD[to] < 0 ) { continue; }
1212
1213       bb_desti = AttackDiag1( from );
1214       if ( BBContract( bb_desti, BB_W_BH ) )
1215         {
1216           BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
1217
1218           *pmove = To2Move(to) | From2Move(from)
1219             | Piece2Move(pawn) | Cap2Move(BOARD[to]);
1220           if ( from > I5 ) { *pmove |= FLAG_PROMO; }
1221           pmove += 1;
1222         }
1223     }
1224
1225   BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
1226   while ( BBTest(bb_piece) )
1227     {
1228       from = FirstOne( bb_piece );
1229       Xor( from, bb_piece );
1230       
1231       to = from + nfile;
1232       if ( BOARD[to] < 0 ) { continue; }
1233
1234       bb_desti = AttackDiag2( from );
1235       if ( BBContract( bb_desti, BB_W_BH ) )
1236         {
1237           BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
1238
1239           *pmove = To2Move(to) | From2Move(from)
1240             | Piece2Move(pawn) | Cap2Move(BOARD[to]);
1241           if ( from > I5 ) { *pmove |= FLAG_PROMO; }
1242           pmove += 1;
1243         }
1244     }
1245
1246   BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
1247   while ( BBTest(bb_piece) )
1248     {
1249       from = FirstOne( bb_piece );
1250       Xor( from, bb_piece );
1251       
1252       to = from + nfile;
1253       if ( BOARD[to] < 0 ) { continue; }
1254
1255       bb_desti = AttackRank( from );
1256       if ( BBContract( bb_desti, BB_W_RD ) )
1257         {
1258           BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
1259
1260           *pmove = To2Move(to) | From2Move(from)
1261             | Piece2Move(pawn) | Cap2Move(BOARD[to]);
1262           if ( from > I5 ) { *pmove |= FLAG_PROMO; }
1263           pmove += 1;
1264         }
1265     }
1266
1267   while ( BBTest(bb_chk) )
1268     {
1269       to = FirstOne( bb_chk );
1270       Xor( to, bb_chk );
1271
1272       from = to - nfile;
1273       *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)
1274         | Cap2Move(BOARD[to]);
1275       if ( from > I5 ) { *pmove |= FLAG_PROMO; }
1276       pmove += 1;
1277     }
1278
1279
1280   if ( IsHandGold(HAND_W) )
1281     {
1282       BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
1283       while( BBTest( bb_chk ) )
1284         {
1285           to = FirstOne( bb_chk );
1286           Xor( to, bb_chk );
1287           *pmove++ = To2Move(to) | Drop2Move(gold);
1288         }
1289     }
1290   
1291
1292   if ( IsHandSilver(HAND_W) )
1293     {
1294       BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
1295       while( BBTest( bb_chk ) )
1296         {
1297           to = FirstOne( bb_chk );
1298           Xor( to, bb_chk );
1299           *pmove++ = To2Move(to) | Drop2Move(silver);
1300         }
1301     }
1302   
1303
1304   if ( IsHandKnight(HAND_W) && sq_bk > I8 )
1305     {
1306       to = sq_bk - 2*nfile - 1;
1307       if ( aifile[sq_bk] != file1 && BOARD[to] == empty )
1308         {
1309           *pmove++ = To2Move(to) | Drop2Move(knight);
1310         }
1311
1312       to = sq_bk - 2*nfile + 1;
1313       if ( aifile[sq_bk] != file9 && BOARD[to] == empty )
1314         {
1315           *pmove++ = To2Move(to) | Drop2Move(knight);
1316         }
1317     }
1318
1319
1320   if ( IsHandPawn(HAND_W)
1321        && sq_bk > I9
1322        && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )
1323     {
1324       to = sq_bk - nfile;
1325       if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )
1326         {
1327           *pmove++ = To2Move(to) | Drop2Move(pawn);
1328         }
1329     }
1330
1331
1332   if ( IsHandLance(HAND_W) )
1333     {
1334       unsigned int move;
1335       int dist, min_dist;
1336
1337       if ( (int)aifile[sq_bk] == file1
1338            || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
1339       else                                  { min_dist = 3; }
1340
1341       for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
1342             to -= nfile, dist += 1 )
1343         {
1344           move = To2Move(to) | Drop2Move(lance);
1345           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
1346           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
1347           *pmove++ = move;
1348         }
1349     }
1350
1351
1352   if ( IsHandRook(HAND_W) )
1353     {
1354       unsigned int move;
1355       int file, dist, min_dist;
1356
1357       if ( (int)aifile[sq_bk] == file1
1358            || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
1359       else                                  { min_dist = 3; }
1360
1361       for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
1362             to -= nfile, dist += 1 )
1363         {
1364           move = To2Move(to) | Drop2Move(rook);
1365           if      ( dist == 1 )        { move |= MOVE_CHK_CLEAR; }
1366           else if ( dist > min_dist )  { move |= MOVE_CHK_SET; }
1367           *pmove++ = move;
1368         }
1369
1370       for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
1371             to += nfile, dist += 1 )
1372         {
1373           move = To2Move(to) | Drop2Move(rook);
1374           if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }
1375           if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }
1376           else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }
1377           *pmove++ = move;
1378         }
1379
1380
1381       if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }
1382       else                            { min_dist = 3; }
1383
1384       for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;
1385             file <= file9 && BOARD[to] == empty;
1386             file += 1, to += 1, dist += 1 )
1387         {
1388           move = To2Move(to) | Drop2Move(rook);
1389           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }
1390           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
1391           *pmove++ = move;
1392         }
1393
1394       for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;
1395             file >= file1 && BOARD[to] == empty;
1396             file -= 1, to -= 1, dist += 1 )
1397         {
1398           move = To2Move(to) | Drop2Move(rook);
1399           if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }
1400           else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }
1401           *pmove++ = move;
1402         }
1403     }
1404
1405
1406   if ( IsHandBishop(HAND_W) )
1407     {
1408       unsigned int move;
1409       int file, rank, dist;
1410
1411       to   = sq_bk;
1412       file = (int)aifile[sq_bk];
1413       rank = (int)airank[sq_bk];
1414       for ( to += 10, file += 1, rank += 1, dist = 1;
1415             file <= file9 && rank <= rank9 && BOARD[to] == empty;
1416             to += 10, file += 1, rank += 1, dist += 1 )
1417         {
1418           move = To2Move(to) | Drop2Move(bishop);
1419           if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
1420           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
1421           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
1422           *pmove++ = move;
1423         }
1424
1425       to   = sq_bk;
1426       file = (int)aifile[sq_bk];
1427       rank = (int)airank[sq_bk];
1428       for ( to += 8, file -= 1, rank += 1, dist = 1;
1429             file >= 0 && rank <= rank9 && BOARD[to] == empty;
1430             to += 8, file -= 1, rank += 1, dist += 1 )
1431         {
1432           move = To2Move(to) | Drop2Move(bishop);
1433           if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
1434           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
1435           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
1436           *pmove++ = move;
1437         }
1438
1439       to   = sq_bk;
1440       file = (int)aifile[sq_bk];
1441       rank = (int)airank[sq_bk];
1442       for ( to -= 8, file += 1, rank -= 1, dist = 1;
1443             file <= file9 && rank >= 0 && BOARD[to] == empty;
1444             to -= 8, file += 1, rank -= 1, dist += 1 )
1445         {
1446           move = To2Move(to) | Drop2Move(bishop);
1447           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
1448           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
1449           *pmove++ = move;
1450         }
1451
1452       to   = sq_bk;
1453       file = (int)aifile[sq_bk];
1454       rank = (int)airank[sq_bk];
1455       for ( to -= 10, file -= 1, rank -= 1, dist = 1;
1456             file >= 0 && rank >= 0 && BOARD[to] == empty;
1457             to -= 10, file -= 1, rank -= 1, dist += 1 )
1458         {
1459           move = To2Move(to) | Drop2Move(bishop);
1460           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }
1461           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
1462           *pmove++ = move;
1463         }
1464     }
1465
1466
1467   return pmove;
1468 }
1469
1470
1471 int CONV b_have_checks( tree_t * restrict __ptree__ )
1472 {
1473   bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
1474   bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
1475   bitboard_t bb_rank_chk;
1476   const tree_t * restrict ptree = __ptree__;
1477   unsigned int u0, u1, u2;
1478   int from, to, sq_wk, idirec;
1479
1480   sq_wk = SQ_WKING;
1481   BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
1482   BBNot( bb_drop_to, bb_drop_to );
1483
1484   if ( IsHandGold(HAND_B) )
1485     {
1486       BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
1487       if ( BBTest( bb_chk ) ) { return 1; }
1488     }
1489
1490   if ( IsHandSilver(HAND_B) )
1491     {
1492       BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
1493       if ( BBTest( bb_chk ) ) { return 1; }
1494     }
1495
1496   if ( IsHandKnight(HAND_B) && sq_wk < A2 )
1497     {
1498       if ( aifile[sq_wk] != file1
1499            && BOARD[sq_wk + 2*nfile - 1] == empty ) { return 1; }
1500
1501       if ( aifile[sq_wk] != file9
1502            && BOARD[sq_wk + 2*nfile + 1] == empty ) { return 1; }
1503     }
1504
1505   if ( IsHandLance(HAND_B)
1506        && sq_wk + nfile < nsquare
1507        && BOARD[sq_wk + nfile] == empty ) { return 1; }
1508
1509   if ( IsHandRook(HAND_B) )
1510     {
1511       if ( sq_wk + nfile < nsquare
1512            && BOARD[sq_wk + nfile] == empty ) { return 1; }
1513
1514       if ( file1 < (int)aifile[sq_wk]
1515            && BOARD[sq_wk - 1] == empty ) { return 1; }
1516
1517       if ( (int)aifile[sq_wk] < file9
1518            && BOARD[sq_wk + 1] == empty ) { return 1; }
1519
1520       if ( 0 <= sq_wk - nfile
1521            && BOARD[sq_wk - nfile] == empty ) { return 1; }
1522     }
1523
1524   if ( IsHandBishop(HAND_B) )
1525     {
1526       if ( 0 < (int)aifile[sq_wk]
1527            && 0 < (int)airank[sq_wk]
1528            && BOARD[sq_wk - 10] == empty ) { return 1; }
1529
1530       if ( (int)aifile[sq_wk] < file9
1531            && 0 < (int)airank[sq_wk]
1532            && BOARD[sq_wk - 8] == empty ) { return 1; }
1533
1534       if ( 0 < (int)aifile[sq_wk]
1535            && (int)airank[sq_wk] < rank9
1536            && BOARD[sq_wk + 8] == empty ) { return 1; }
1537
1538       if ( (int)aifile[sq_wk] < file9
1539            && (int)airank[sq_wk] < rank9
1540            && BOARD[sq_wk + 10] == empty ) { return 1; }
1541     }
1542
1543   if ( IsHandPawn(HAND_B)
1544        && sq_wk < A1
1545        && BOARD[sq_wk+nfile] == empty
1546        && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) )
1547        && ! is_mate_b_pawn_drop( __ptree__, sq_wk+nfile ) )
1548     {
1549       return 1;
1550     }
1551   
1552   
1553   bb_file_chk = AttackFile( sq_wk );
1554   bb_rank_chk = AttackRank( sq_wk );
1555   BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
1556
1557   bb_diag1_chk = AttackDiag1( sq_wk );
1558   bb_diag2_chk = AttackDiag2( sq_wk );
1559   BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
1560   BBNot( bb_move_to, BB_BOCCUPY );
1561
1562   from  = SQ_BKING;
1563   idirec = (int)adirec[sq_wk][from];
1564   if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1565     {
1566       BBIni( bb_chk );
1567       add_behind_attacks( &bb_chk, idirec, sq_wk );
1568       BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
1569       BBAnd( bb_chk, bb_chk, bb_move_to );
1570
1571       if ( BBTest( bb_chk ) ) { return 1; }
1572     }
1573
1574
1575   bb_piece = BB_BDRAGON;
1576   while( BBTest( bb_piece ) )
1577     {
1578       from = LastOne( bb_piece );
1579       Xor( from, bb_piece );
1580
1581       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
1582       idirec = (int)adirec[sq_wk][from];
1583       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1584         {
1585           add_behind_attacks( &bb_chk, idirec, sq_wk );
1586         }
1587
1588       AttackDragon( bb_desti, from );
1589       BBAnd( bb_chk, bb_chk, bb_desti );
1590       BBAnd( bb_chk, bb_chk, bb_move_to );
1591
1592       if ( BBTest( bb_chk ) ) { return 1; }
1593     }
1594
1595   bb_piece = BB_BHORSE;
1596   while( BBTest( bb_piece ) )
1597     {
1598       from = LastOne( bb_piece );
1599       Xor( from, bb_piece );
1600
1601       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
1602       idirec = (int)adirec[sq_wk][from];
1603       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1604         {
1605           add_behind_attacks( &bb_chk, idirec, sq_wk );
1606         }
1607
1608       AttackHorse( bb_desti, from );
1609       BBAnd( bb_chk, bb_chk, bb_desti );
1610       BBAnd( bb_chk, bb_chk, bb_move_to );
1611
1612       if ( BBTest( bb_chk ) ) { return 1; }
1613     }
1614
1615   u1 = BB_BROOK.p[1];
1616   u2 = BB_BROOK.p[2];
1617   while( u1 | u2 )
1618     {
1619       from = last_one12( u1, u2 );
1620       u1   ^= abb_mask[from].p[1];
1621       u2   ^= abb_mask[from].p[2];
1622
1623       AttackRook( bb_desti, from );
1624
1625       idirec = (int)adirec[sq_wk][from];
1626       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1627         {
1628           BBAnd( bb_chk, bb_desti, bb_move_to );
1629         }
1630       else {
1631         bb_chk       = bb_rook_chk;
1632         bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
1633         BBAnd( bb_chk, bb_chk, bb_desti );
1634         BBAnd( bb_chk, bb_chk, bb_move_to );
1635       }
1636
1637       if ( BBTest( bb_chk ) ) { return 1; }
1638     }
1639
1640   u0 = BB_BROOK.p[0];
1641   while( u0 )
1642     {
1643       from = last_one0( u0 );
1644       u0   ^= abb_mask[from].p[0];
1645       
1646       AttackRook( bb_desti, from );
1647
1648       idirec = (int)adirec[sq_wk][from];
1649       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1650         {
1651           BBAnd( bb_chk, bb_desti, bb_move_to );
1652         }
1653       else {
1654         BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
1655         BBAnd( bb_chk, bb_chk, bb_desti );
1656         BBAnd( bb_chk, bb_chk, bb_move_to );
1657       }
1658
1659       if ( BBTest( bb_chk ) ) { return 1; }
1660     }
1661
1662   u1 = BB_BBISHOP.p[1];
1663   u2 = BB_BBISHOP.p[2];
1664   while( u1 | u2 )
1665     {
1666       from = last_one12( u1, u2 );
1667       u1   ^= abb_mask[from].p[1];
1668       u2   ^= abb_mask[from].p[2];
1669
1670       AttackBishop( bb_desti, from );
1671
1672       idirec = (int)adirec[sq_wk][from];
1673       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1674         {
1675           BBAnd( bb_chk, bb_desti, bb_move_to );
1676         }
1677       else {
1678         bb_chk       = bb_bishop_chk;
1679         bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
1680         BBAnd( bb_chk, bb_chk, bb_desti );
1681         BBAnd( bb_chk, bb_chk, bb_move_to );
1682       }
1683
1684       if ( BBTest( bb_chk ) ) { return 1; }
1685     }
1686
1687   u0 = BB_BBISHOP.p[0];
1688   while( u0 )
1689     {
1690       from = last_one0( u0 );
1691       u0   ^= abb_mask[from].p[0];
1692       
1693       AttackBishop( bb_desti, from );
1694
1695       idirec = (int)adirec[sq_wk][from];
1696       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1697         {
1698           BBAnd( bb_chk, bb_desti, bb_move_to );
1699         }
1700       else {
1701         BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
1702         BBAnd( bb_chk, bb_chk, bb_desti );
1703         BBAnd( bb_chk, bb_chk, bb_move_to );
1704       }
1705
1706       if ( BBTest( bb_chk ) ) { return 1; }
1707     }
1708
1709
1710   bb_piece = BB_BTGOLD;
1711   while( BBTest( bb_piece ) )
1712     {
1713       from = LastOne( bb_piece );
1714       Xor( from, bb_piece );
1715
1716       bb_chk = abb_w_gold_attacks[sq_wk];
1717
1718       idirec = (int)adirec[sq_wk][from];
1719       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1720         {
1721           add_behind_attacks( &bb_chk, idirec, sq_wk );
1722         }
1723
1724       BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
1725       BBAnd( bb_chk, bb_chk, bb_move_to );
1726
1727       if ( BBTest( bb_chk ) ) { return 1; }
1728     }
1729   
1730
1731   u0 = BB_BSILVER.p[0];
1732   while( u0 )
1733     {
1734       from = last_one0( u0 );
1735       u0   ^= abb_mask[from].p[0];
1736
1737       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
1738       bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
1739       bb_chk.p[2] = 0;
1740
1741       idirec = (int)adirec[sq_wk][from];
1742       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1743         {
1744           add_behind_attacks( &bb_chk, idirec, sq_wk );
1745         }
1746
1747       bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
1748       bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
1749
1750       if ( bb_chk.p[0] | bb_chk.p[1] ) { return 1; }
1751     }
1752   
1753
1754   u1 = BB_BSILVER.p[1] & 0x7fc0000U;
1755   while( u1 )
1756     {
1757       from = last_one1( u1 );
1758       u1   ^= abb_mask[from].p[1];
1759       
1760       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
1761       bb_chk.p[1] = bb_chk.p[2] = 0;
1762       
1763       idirec = (int)adirec[sq_wk][from];
1764       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1765         {
1766           add_behind_attacks( &bb_chk, idirec, sq_wk );
1767         }
1768
1769       bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
1770
1771       if ( bb_chk.p[0] ) { return 1; }
1772     }
1773   
1774
1775   bb_piece = BB_BSILVER;
1776   while( BBTest( bb_piece ) )
1777     {
1778       from = LastOne( bb_piece );
1779       Xor( from, bb_piece );
1780
1781       bb_chk = abb_w_silver_attacks[sq_wk];
1782
1783       idirec = (int)adirec[sq_wk][from];
1784       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1785         {
1786           add_behind_attacks( &bb_chk, idirec, sq_wk );
1787         }
1788
1789       BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
1790       BBAnd( bb_chk, bb_chk, bb_move_to );
1791
1792       if ( BBTest( bb_chk ) ) { return 1; }
1793     }
1794   
1795
1796   u0 = BB_BKNIGHT.p[0];
1797   u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
1798   while( u0 | u1 )
1799     {
1800       from = last_one01( u0, u1 );
1801       u0   ^= abb_mask[from].p[0];
1802       u1   ^= abb_mask[from].p[1];
1803
1804       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
1805       bb_chk.p[1] = bb_chk.p[2] = 0;
1806
1807       idirec = (int)adirec[sq_wk][from];
1808       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1809         {
1810           add_behind_attacks( &bb_chk, idirec, sq_wk );
1811         }
1812
1813       bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
1814
1815       if ( bb_chk.p[0] ) { return 1; }
1816     }
1817   
1818
1819   u2 = BB_BKNIGHT.p[2];
1820   u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
1821   while( u2 | u1 )
1822     {
1823       from = last_one12( u1, u2 );
1824       u2   ^= abb_mask[from].p[2];
1825       u1   ^= abb_mask[from].p[1];
1826
1827       bb_chk = abb_w_knight_attacks[sq_wk];
1828
1829       idirec = (int)adirec[sq_wk][from];
1830       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1831         {
1832           add_behind_attacks( &bb_chk, idirec, sq_wk );
1833         }
1834
1835       BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
1836       BBAnd( bb_chk, bb_chk, bb_move_to );
1837
1838       if ( BBTest( bb_chk ) ) { return 1; }
1839     }
1840
1841
1842   bb_piece = BB_BLANCE;
1843   while( BBTest( bb_piece ) )
1844     {
1845       from = LastOne( bb_piece );
1846       Xor( from, bb_piece );
1847
1848       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
1849       bb_chk.p[1] = bb_chk.p[2] = 0;
1850
1851       idirec = (int)adirec[sq_wk][from];
1852       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1853         {
1854           add_behind_attacks( &bb_chk, idirec, sq_wk );
1855         }
1856
1857       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
1858       BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
1859       BBAnd( bb_chk, bb_chk, bb_move_to );
1860
1861       if ( BBTest( bb_chk ) ) { return 1; }
1862     }
1863   
1864
1865   u1 = BB_BLANCE.p[1];
1866   u2 = BB_BLANCE.p[2];
1867   while( u1| u2 )
1868     {
1869       from = last_one12( u1, u2 );
1870       u1   ^= abb_mask[from].p[1];
1871       u2   ^= abb_mask[from].p[2];
1872
1873       bb_chk = bb_file_chk;
1874       idirec = (int)adirec[sq_wk][from];
1875       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
1876         {
1877           add_behind_attacks( &bb_chk, idirec, sq_wk );
1878           BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
1879         }
1880       else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
1881
1882       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
1883       BBAnd( bb_chk, bb_chk, bb_move_to );
1884       bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
1885
1886       if ( BBTest( bb_chk ) ) { return 1; }
1887     }
1888
1889   BBIni( bb_chk );
1890   bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
1891   if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };
1892   BBAnd( bb_chk, bb_chk, bb_move_to );
1893   BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
1894   if ( BBTest(bb_chk) ) { return 1; }
1895
1896   BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
1897   while ( BBTest(bb_piece) )
1898     {
1899       from = LastOne( bb_piece );
1900       Xor( from, bb_piece );
1901       
1902       to = from - nfile;
1903       if ( BOARD[to] > 0 ) { continue; }
1904
1905       bb_desti = AttackDiag1( from );
1906
1907       if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
1908     }
1909
1910   BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
1911   while ( BBTest(bb_piece) )
1912     {
1913       from = LastOne( bb_piece );
1914       Xor( from, bb_piece );
1915       
1916       to = from - nfile;
1917       if ( BOARD[to] > 0 ) { continue; }
1918
1919       bb_desti = AttackDiag2( from );
1920
1921       if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
1922     }
1923   
1924   BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
1925   while ( BBTest(bb_piece) )
1926     {
1927       from = LastOne( bb_piece );
1928       Xor( from, bb_piece );
1929       
1930       to = from - nfile;
1931       if ( BOARD[to] > 0 ) { continue; }
1932       
1933       bb_desti = AttackRank( from );
1934       if ( BBContract( bb_desti, BB_B_RD ) ) { return 1; }
1935     }
1936
1937   return 0;
1938 }
1939
1940
1941 int CONV w_have_checks( tree_t * restrict __ptree__ )
1942 {
1943   bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
1944   bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
1945   bitboard_t bb_rank_chk;
1946   const tree_t * restrict ptree = __ptree__;
1947   unsigned int u0, u1, u2;
1948   int from, to, sq_bk, idirec;
1949
1950   sq_bk = SQ_BKING;
1951   BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
1952   BBNot( bb_drop_to, bb_drop_to );
1953
1954   if ( IsHandGold(HAND_W) )
1955     {
1956       BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
1957       if ( BBTest( bb_chk ) ) { return 1; }
1958     }
1959
1960   if ( IsHandSilver(HAND_W) )
1961     {
1962       BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
1963       if ( BBTest( bb_chk ) ) { return 1; }
1964     }
1965
1966   if ( IsHandKnight(HAND_W) && sq_bk > I8 )
1967     {
1968       if ( aifile[sq_bk] != file1
1969            && BOARD[sq_bk - 2*nfile - 1] == empty ) { return 1; }
1970
1971       if ( aifile[sq_bk] != file9
1972            && BOARD[sq_bk - 2*nfile + 1] == empty ) { return 1; }
1973     }
1974
1975   if ( IsHandLance(HAND_W)
1976        && 0 <= sq_bk - nfile
1977        && BOARD[sq_bk - nfile] == empty ) { return 1; }
1978
1979   if ( IsHandRook(HAND_W) )
1980     {
1981       if ( sq_bk + nfile < nsquare
1982            && BOARD[sq_bk + nfile] == empty ) { return 1; }
1983
1984       if ( file1 < (int)aifile[sq_bk]
1985            && BOARD[sq_bk - 1] == empty ) { return 1; }
1986
1987       if ( (int)aifile[sq_bk] < file9
1988            && BOARD[sq_bk + 1] == empty ) { return 1; }
1989
1990       if ( 0 <= sq_bk - nfile
1991            && BOARD[sq_bk - nfile] == empty ) { return 1; }
1992     }
1993
1994   if ( IsHandBishop(HAND_W) )
1995     {
1996       if ( 0 < (int)aifile[sq_bk]
1997            && 0 < (int)airank[sq_bk]
1998            && BOARD[sq_bk - 10] == empty ) { return 1; }
1999
2000       if ( (int)aifile[sq_bk] < file9
2001            && 0 < (int)airank[sq_bk]
2002            && BOARD[sq_bk - 8] == empty ) { return 1; }
2003
2004       if ( 0 < (int)aifile[sq_bk]
2005            && (int)airank[sq_bk] < rank9
2006            && BOARD[sq_bk + 8] == empty ) { return 1; }
2007
2008       if ( (int)aifile[sq_bk] < file9
2009            && (int)airank[sq_bk] < rank9
2010            && BOARD[sq_bk + 10] == empty ) { return 1; }
2011     }
2012
2013   if ( IsHandPawn(HAND_W)
2014        && sq_bk > I9
2015        && BOARD[sq_bk - nfile] == empty
2016        && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) )
2017        && ! is_mate_w_pawn_drop( __ptree__, sq_bk - nfile ) )
2018     {
2019       return 1;
2020     }
2021
2022
2023   bb_file_chk = AttackFile( sq_bk );
2024   bb_rank_chk = AttackRank( sq_bk );
2025   BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
2026
2027   bb_diag1_chk = AttackDiag1( sq_bk );
2028   bb_diag2_chk = AttackDiag2( sq_bk );
2029   BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
2030   BBNot( bb_move_to, BB_WOCCUPY );
2031
2032
2033   from  = SQ_WKING;
2034   idirec = (int)adirec[sq_bk][from];
2035   if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2036     {
2037       BBIni( bb_chk );
2038       add_behind_attacks( &bb_chk, idirec, sq_bk );
2039       BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
2040       BBAnd( bb_chk, bb_chk, bb_move_to );
2041
2042       if ( BBTest( bb_chk ) ) { return 1; }
2043     }
2044
2045
2046   bb_piece = BB_WDRAGON;
2047   while( BBTest( bb_piece ) )
2048     {
2049       from = FirstOne( bb_piece );
2050       Xor( from, bb_piece );
2051
2052       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
2053       idirec = (int)adirec[sq_bk][from];
2054       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2055         {
2056           add_behind_attacks( &bb_chk, idirec, sq_bk );
2057         }
2058
2059       AttackDragon( bb_desti, from );
2060       BBAnd( bb_chk, bb_chk, bb_desti );
2061       BBAnd( bb_chk, bb_chk, bb_move_to );
2062
2063       if ( BBTest( bb_chk ) ) { return 1; }
2064     }
2065
2066
2067   bb_piece = BB_WHORSE;
2068   while( BBTest( bb_piece ) )
2069     {
2070       from = FirstOne( bb_piece );
2071       Xor( from, bb_piece );
2072
2073       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
2074       idirec = (int)adirec[sq_bk][from];
2075       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2076         {
2077           add_behind_attacks( &bb_chk, idirec, sq_bk );
2078         }
2079
2080       AttackHorse( bb_desti, from );
2081       BBAnd( bb_chk, bb_chk, bb_desti );
2082       BBAnd( bb_chk, bb_chk, bb_move_to );
2083
2084       if ( BBTest( bb_chk ) ) { return 1; }
2085     }
2086
2087   u0 = BB_WROOK.p[0];
2088   u1 = BB_WROOK.p[1];
2089   while( u0 | u1 )
2090     {
2091       from = first_one01( u0, u1 );
2092       u0   ^= abb_mask[from].p[0];
2093       u1   ^= abb_mask[from].p[1];
2094
2095       AttackRook( bb_desti, from );
2096
2097       idirec = (int)adirec[sq_bk][from];
2098       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2099         {
2100           BBAnd( bb_chk, bb_desti, bb_move_to );
2101         }
2102       else {
2103         bb_chk       = bb_rook_chk;
2104         bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
2105         BBAnd( bb_chk, bb_chk, bb_desti );
2106         BBAnd( bb_chk, bb_chk, bb_move_to );
2107       }
2108
2109       if ( BBTest( bb_chk ) ) { return 1; }
2110     }
2111
2112   u2 = BB_WROOK.p[2];
2113   while( u2 )
2114     {
2115       from = first_one2( u2 );
2116       u2   ^= abb_mask[from].p[2];
2117       
2118       AttackRook( bb_desti, from );
2119
2120       idirec = (int)adirec[sq_bk][from];
2121       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2122         {
2123           BBAnd( bb_chk, bb_desti, bb_move_to );
2124         }
2125       else {
2126         BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
2127         BBAnd( bb_chk, bb_chk, bb_desti );
2128         BBAnd( bb_chk, bb_chk, bb_move_to );
2129       }
2130
2131       if ( BBTest( bb_chk ) ) { return 1; }
2132     }
2133
2134   u0 = BB_WBISHOP.p[0];
2135   u1 = BB_WBISHOP.p[1];
2136   while( u0 | u1 )
2137     {
2138       from = first_one01( u0, u1 );
2139       u0   ^= abb_mask[from].p[0];
2140       u1   ^= abb_mask[from].p[1];
2141
2142       AttackBishop( bb_desti, from );
2143
2144       idirec = (int)adirec[sq_bk][from];
2145       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2146         {
2147           BBAnd( bb_chk, bb_desti, bb_move_to );
2148         }
2149       else {
2150         bb_chk       = bb_bishop_chk;
2151         bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
2152         BBAnd( bb_chk, bb_chk, bb_desti );
2153         BBAnd( bb_chk, bb_chk, bb_move_to );
2154       }
2155
2156       if ( BBTest( bb_chk ) ) { return 1; }
2157     }
2158
2159   u2 = BB_WBISHOP.p[2];
2160   while( u2 )
2161     {
2162       from = first_one2( u2 );
2163       u2   ^= abb_mask[from].p[2];
2164       
2165       AttackBishop( bb_desti, from );
2166
2167       idirec = (int)adirec[sq_bk][from];
2168       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2169         {
2170           BBAnd( bb_chk, bb_desti, bb_move_to );
2171         }
2172       else {
2173         BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
2174         BBAnd( bb_chk, bb_chk, bb_desti );
2175         BBAnd( bb_chk, bb_chk, bb_move_to );
2176       }
2177
2178       if ( BBTest( bb_chk ) ) { return 1; }
2179     }
2180
2181
2182   bb_piece = BB_WTGOLD;
2183   while( BBTest( bb_piece ) )
2184     {
2185       from = FirstOne( bb_piece );
2186       Xor( from, bb_piece );
2187
2188       bb_chk = abb_b_gold_attacks[sq_bk];
2189
2190       idirec = (int)adirec[sq_bk][from];
2191       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2192         {
2193           add_behind_attacks( &bb_chk, idirec, sq_bk );
2194         }
2195
2196       BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
2197       BBAnd( bb_chk, bb_chk, bb_move_to );
2198
2199       if ( BBTest( bb_chk ) ) { return 1; }
2200     }
2201
2202   
2203   u2 = BB_WSILVER.p[2];
2204   while( u2 )
2205     {
2206       from = first_one2( u2 );
2207       u2   ^= abb_mask[from].p[2];
2208
2209       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
2210       bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
2211       bb_chk.p[0] = 0;
2212
2213       idirec = (int)adirec[sq_bk][from];
2214       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2215         {
2216           add_behind_attacks( &bb_chk, idirec, sq_bk );
2217         }
2218
2219       bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
2220       bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
2221
2222       if ( bb_chk.p[2] | bb_chk.p[1] ) { return 1; }
2223     }
2224   
2225
2226   u1 = BB_WSILVER.p[1] & 0x1ffU;
2227   while( u1 )
2228     {
2229       from = first_one1( u1 );
2230       u1   ^= abb_mask[from].p[1];
2231       
2232       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
2233       bb_chk.p[1] = bb_chk.p[0] = 0;
2234       
2235       idirec = (int)adirec[sq_bk][from];
2236       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2237         {
2238           add_behind_attacks( &bb_chk, idirec, sq_bk );
2239         }
2240
2241       bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
2242
2243       if ( bb_chk.p[2] ) { return 1; }
2244     }
2245   
2246
2247   bb_piece = BB_WSILVER;
2248   while( BBTest( bb_piece ) )
2249     {
2250       from = FirstOne( bb_piece );
2251       Xor( from, bb_piece );
2252
2253       bb_chk = abb_b_silver_attacks[sq_bk];
2254
2255       idirec = (int)adirec[sq_bk][from];
2256       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2257         {
2258           add_behind_attacks( &bb_chk, idirec, sq_bk );
2259         }
2260
2261       BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
2262       BBAnd( bb_chk, bb_chk, bb_move_to );
2263
2264       if ( BBTest( bb_chk ) ) { return 1; }
2265     }
2266
2267   
2268   u2 = BB_WKNIGHT.p[2];
2269   u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
2270   while( u2 | u1 )
2271     {
2272       from = first_one12( u1, u2 );
2273       u2   ^= abb_mask[from].p[2];
2274       u1   ^= abb_mask[from].p[1];
2275
2276       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
2277       bb_chk.p[1] = bb_chk.p[0] = 0;
2278
2279       idirec = (int)adirec[sq_bk][from];
2280       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2281         {
2282           add_behind_attacks( &bb_chk, idirec, sq_bk );
2283         }
2284
2285       bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
2286
2287       if ( bb_chk.p[2] ) { return 1; }
2288     }
2289   
2290
2291   u0 = BB_WKNIGHT.p[0];
2292   u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
2293   while( u0 | u1 )
2294     {
2295       from = first_one01( u0, u1 );
2296       u0   ^= abb_mask[from].p[0];
2297       u1   ^= abb_mask[from].p[1];
2298
2299       bb_chk = abb_b_knight_attacks[sq_bk];
2300
2301       idirec = (int)adirec[sq_bk][from];
2302       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2303         {
2304           add_behind_attacks( &bb_chk, idirec, sq_bk );
2305         }
2306
2307       BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
2308       BBAnd( bb_chk, bb_chk, bb_move_to );
2309
2310       if ( BBTest( bb_chk ) ) { return 1; }
2311     }
2312
2313
2314   bb_piece = BB_WLANCE;
2315   while( BBTest( bb_piece ) )
2316     {
2317       from = FirstOne( bb_piece );
2318       Xor( from, bb_piece );
2319
2320       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
2321       bb_chk.p[1] = bb_chk.p[0] = 0;
2322
2323       idirec = (int)adirec[sq_bk][from];
2324       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2325         {
2326           add_behind_attacks( &bb_chk, idirec, sq_bk );
2327         }
2328
2329       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
2330       BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
2331       BBAnd( bb_chk, bb_chk, bb_move_to );
2332
2333       if ( BBTest( bb_chk ) ) { return 1; }
2334     }
2335   
2336
2337   u0 = BB_WLANCE.p[0];
2338   u1 = BB_WLANCE.p[1];
2339   while( u0 | u1 )
2340     {
2341       from = first_one01( u0, u1 );
2342       u0   ^= abb_mask[from].p[0];
2343       u1   ^= abb_mask[from].p[1];
2344
2345       bb_chk = bb_file_chk;
2346       idirec = (int)adirec[sq_bk][from];
2347       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
2348         {
2349           add_behind_attacks( &bb_chk, idirec, sq_bk );
2350           BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
2351         }
2352       else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
2353
2354       BBAnd( bb_chk, bb_chk, AttackFile( from ) );
2355       BBAnd( bb_chk, bb_chk, bb_move_to );
2356       bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
2357
2358       if ( BBTest( bb_chk ) ) { return 1; }
2359     }
2360
2361   BBIni( bb_chk );
2362   bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
2363   if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };
2364   BBAnd( bb_chk, bb_chk, bb_move_to );
2365   BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
2366   if ( BBTest( bb_chk ) ) { return 1; }
2367
2368   BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
2369   while ( BBTest(bb_piece) )
2370     {
2371       from = FirstOne( bb_piece );
2372       Xor( from, bb_piece );
2373       
2374       to = from + nfile;
2375       if ( BOARD[to] < 0 ) { continue; }
2376
2377       bb_desti = AttackDiag1( from );
2378
2379       if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
2380     }
2381
2382   BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
2383   while ( BBTest(bb_piece) )
2384     {
2385       from = FirstOne( bb_piece );
2386       Xor( from, bb_piece );
2387       
2388       to = from + nfile;
2389       if ( BOARD[to] < 0 ) { continue; }
2390
2391       bb_desti = AttackDiag2( from );
2392
2393       if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
2394     }
2395
2396   BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
2397   while ( BBTest(bb_piece) )
2398     {
2399       from = FirstOne( bb_piece );
2400       Xor( from, bb_piece );
2401       
2402       to = from + nfile;
2403       if ( BOARD[to] < 0 ) { continue; }
2404
2405       bb_desti = AttackRank( from );
2406       if ( BBContract( bb_desti, BB_W_RD ) ) { return 1; }
2407     }
2408
2409   return 0;
2410 }
2411
2412
2413 static void CONV
2414 add_behind_attacks( bitboard_t * restrict pbb, int idirec, int ik )
2415 {
2416   bitboard_t bb_tmp;
2417
2418   if ( idirec == direc_diag1 )
2419     {
2420       bb_tmp = abb_bishop_attacks_rr45[ik][0];
2421     }
2422   else if ( idirec == direc_diag2 )
2423     {
2424       bb_tmp = abb_bishop_attacks_rl45[ik][0];
2425     }
2426   else if ( idirec == direc_file )
2427     {
2428       bb_tmp = abb_file_attacks[ik][0];
2429     }
2430   else {
2431     assert( idirec == direc_rank );
2432     bb_tmp = abb_rank_attacks[ik][0];
2433   }
2434   BBNot( bb_tmp, bb_tmp );
2435   BBOr( *pbb, *pbb, bb_tmp );
2436 }