Fix force mode after setboard
[bonanza.git] / genevasn.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "shogi.h"
4
5
6 unsigned int * CONV
7 b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove )
8 {
9   bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
10   unsigned int hand, ubb_target0a, ubb_target0b, ubb_pawn_cmp, utemp;
11   unsigned ais_pawn[nfile];
12   int nchecker, sq_bk, to, sq_check, idirec;
13   int nhand, i, nolance, noknight, from;
14   int ahand[6];
15   
16   /* move the king */
17   sq_bk = SQ_BKING;
18   
19   Xor( sq_bk, BB_BOCCUPY );
20   XorFile( sq_bk, OCCUPIED_FILE );
21   XorDiag2( sq_bk, OCCUPIED_DIAG2 );
22   XorDiag1( sq_bk, OCCUPIED_DIAG1 );
23
24   BBNotAnd( bb_desti, abb_king_attacks[sq_bk], BB_BOCCUPY );
25   utemp = From2Move(sq_bk) | Piece2Move(king);
26   while ( BBTest( bb_desti ) )
27     {
28       to = LastOne( bb_desti );
29       if ( ! is_black_attacked( ptree, to ) )
30         {
31           *pmove++ = To2Move(to) | Cap2Move(-BOARD[to]) | utemp;
32         }
33       Xor( to, bb_desti );
34     }
35   
36   Xor( sq_bk, BB_BOCCUPY );
37   XorFile( sq_bk, OCCUPIED_FILE );
38   XorDiag2( sq_bk, OCCUPIED_DIAG2 );
39   XorDiag1( sq_bk, OCCUPIED_DIAG1 );
40   
41   bb_checker = w_attacks_to_piece( ptree, sq_bk );
42   nchecker = PopuCount( bb_checker );
43   if ( nchecker == 2 ) { return pmove; }
44   
45   sq_check = LastOne( bb_checker );
46   bb_inter = abb_obstacle[sq_bk][sq_check];
47
48   /* move other pieces */
49   BBOr( bb_target, bb_inter, bb_checker );
50   
51   BBAnd( bb_desti, bb_target, BB_BPAWN_ATK );
52   while ( BBTest( bb_desti ) )
53     {
54       to = LastOne( bb_desti );
55       Xor( to, bb_desti );
56
57       from = to + 9;
58       idirec = (int)adirec[sq_bk][from];
59       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
60         {
61           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(pawn)
62                     | Cap2Move(-BOARD[to]) );
63           if ( to < A6 ) { utemp |= FLAG_PROMO; }
64           *pmove++ = utemp;
65         }
66     }
67
68   bb_piece = BB_BLANCE;
69   while ( BBTest( bb_piece ) )
70     {
71       from = LastOne( bb_piece );
72       Xor( from, bb_piece );
73
74       bb_desti = AttackFile( from );
75       BBAnd( bb_desti, bb_desti, abb_minus_rays[from] );
76       BBAnd( bb_desti, bb_desti, bb_target );
77       if ( ! BBTest( bb_desti ) ) { continue; }
78
79       idirec = (int)adirec[sq_bk][from];
80       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
81         {
82           to = LastOne( bb_desti );
83
84           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(lance)
85                     | Cap2Move(-BOARD[to]) );
86           if ( to <  A6 ) { *pmove++ = utemp | FLAG_PROMO; }
87           if ( to >= A7 ) { *pmove++ = utemp; }
88         }
89     }
90
91   bb_piece = BB_BKNIGHT;
92   while ( BBTest( bb_piece ) )
93     {
94       from = LastOne( bb_piece );
95       Xor( from, bb_piece );
96
97       BBAnd( bb_desti, bb_target, abb_b_knight_attacks[from] );
98       if ( ! BBTest( bb_desti ) ) { continue; }
99
100       idirec = (int)adirec[sq_bk][from];
101       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
102         do {
103           to = LastOne( bb_desti );
104           Xor( to, bb_desti );
105
106           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(knight)
107                     | Cap2Move(-BOARD[to]) );
108           if ( to <  A6 ) { *pmove++ = utemp | FLAG_PROMO; }
109           if ( to >= A7 ) { *pmove++ = utemp; }
110           
111         } while ( BBTest( bb_desti ) );
112     }
113
114   bb_piece = BB_BSILVER;
115   while ( BBTest( bb_piece ) )
116     {
117       from = LastOne( bb_piece );
118       Xor( from, bb_piece );
119       
120       BBAnd( bb_desti, bb_target, abb_b_silver_attacks[from] );
121       if ( ! BBTest( bb_desti ) ) { continue; }
122
123       idirec = (int)adirec[sq_bk][from];
124       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
125         do {
126           to = LastOne( bb_desti );
127           Xor( to, bb_desti );
128           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(silver)
129                     | Cap2Move(-BOARD[to]) );
130           if ( from < A6 || to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
131           *pmove++ = utemp;
132         } while ( BBTest( bb_desti ) );
133     }
134
135   bb_piece = BB_BTGOLD;
136   while( BBTest( bb_piece ) )
137     {
138       from  = LastOne( bb_piece );
139       Xor( from, bb_piece );
140
141       BBAnd( bb_desti, bb_target, abb_b_gold_attacks[from] );
142       if ( ! BBTest(bb_desti) ) { continue; }
143
144       idirec = (int)adirec[sq_bk][from];
145       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
146         do {
147           to = LastOne( bb_desti );
148           Xor( to, bb_desti );
149           *pmove++ = ( To2Move(to) | From2Move(from)
150                        | Piece2Move(BOARD[from])
151                        | Cap2Move(-BOARD[to]) );
152         } while( BBTest( bb_desti ) );
153     }
154
155   bb_piece = BB_BBISHOP;
156   while ( BBTest( bb_piece ) )
157     {
158       from = LastOne( bb_piece );
159       Xor( from, bb_piece );
160
161       AttackBishop( bb_desti, from );
162       BBAnd( bb_desti, bb_desti, bb_target );
163       if ( ! BBTest( bb_desti ) ) { continue; }
164       idirec = (int)adirec[sq_bk][from];
165       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
166         do {
167           to = LastOne( bb_desti );
168           Xor( to, bb_desti );
169
170           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(bishop)
171                     | Cap2Move(-BOARD[to]) );
172           if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
173           *pmove++ = utemp;
174         } while ( BBTest( bb_desti ) );
175     }
176
177   bb_piece = BB_BROOK;
178   while ( BBTest( bb_piece ) )
179     {
180       from = LastOne( bb_piece );
181       Xor( from, bb_piece );
182
183       AttackRook( bb_desti, from );
184       BBAnd( bb_desti, bb_desti, bb_target );
185       if ( ! BBTest( bb_desti ) ) { continue; }
186       idirec = (int)adirec[sq_bk][from];
187       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
188         do {
189           to = LastOne( bb_desti );
190           Xor( to, bb_desti );
191
192           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(rook)
193                     | Cap2Move(-BOARD[to]) );
194           if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
195           *pmove++ = utemp;
196         } while ( BBTest( bb_desti ) );
197     }
198
199   bb_piece = BB_BHORSE;
200   while( BBTest( bb_piece ) )
201     {
202       from = LastOne( bb_piece );
203       Xor( from, bb_piece );
204
205       AttackHorse( bb_desti, from );
206       BBAnd( bb_desti, bb_desti, bb_target );
207       if ( ! BBTest(bb_desti) ) { continue; }
208
209       idirec = (int)adirec[sq_bk][from];
210       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
211         do {
212           to = LastOne( bb_desti );
213           Xor( to, bb_desti);
214           *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
215                        | Cap2Move(-BOARD[to]) );
216         } while ( BBTest( bb_desti ) );
217     }
218   
219   bb_piece = BB_BDRAGON;
220   while( BBTest( bb_piece ) )
221     {
222       from = LastOne( bb_piece );
223       Xor( from, bb_piece );
224
225       AttackDragon( bb_desti, from );
226       BBAnd( bb_desti, bb_desti, bb_target );
227       if ( ! BBTest(bb_desti) ) { continue; }
228
229       idirec = (int)adirec[sq_bk][from];
230       if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
231         do {
232           to = LastOne( bb_desti );
233           Xor( to, bb_desti );
234           *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
235                        | Cap2Move(-BOARD[to]) );
236         } while ( BBTest( bb_desti ) );
237     }
238
239   if ( ! HAND_B )          { return pmove; }
240   if ( ! BBTest(bb_inter) ) { return pmove; }
241
242   /* drops */
243   bb_target = bb_inter;
244   ubb_target0a = bb_target.p[0] & 0x7fc0000U;
245   ubb_target0b = bb_target.p[0] & 0x003fe00U;
246   bb_target.p[0] &= 0x00001ffU;
247   bb_target.p[1] &= 0x7ffffffU;
248   bb_target.p[2] &= 0x7ffffffU;
249
250   hand = HAND_B;
251   nhand = 0;
252   if ( IsHandKnight( hand ) ) { ahand[ nhand++ ] = Drop2Move(knight); }
253   noknight = nhand;
254   if ( IsHandLance( hand ) )  { ahand[ nhand++ ] = Drop2Move(lance); }
255   nolance  = nhand;
256   if ( IsHandSilver( hand ) ) { ahand[ nhand++ ] = Drop2Move(silver); }
257   if ( IsHandGold( hand ) )   { ahand[ nhand++ ] = Drop2Move(gold); }
258   if ( IsHandBishop( hand ) ) { ahand[ nhand++ ] = Drop2Move(bishop); }
259   if ( IsHandRook( hand ) )   { ahand[ nhand++ ] = Drop2Move(rook); }
260
261   if ( IsHandPawn( hand ) )
262     {
263       ubb_pawn_cmp= BBToU( BB_BPAWN_ATK );
264       ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
265       ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
266       ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
267       ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
268       ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
269       ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
270       ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
271       ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
272       ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
273  
274       while ( BBTest( bb_target ) )
275         {
276           to = LastOne( bb_target );
277           utemp = To2Move(to);
278           if ( ! ais_pawn[aifile[to]] && ! IsMateBPawnDrop( ptree, to ) )
279             {
280               *pmove++ = utemp | Drop2Move(pawn);
281             }
282           for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
283           Xor( to, bb_target );
284         }
285
286       while ( ubb_target0b )
287         {
288           to = last_one0( ubb_target0b );
289           utemp = To2Move(to);
290           if ( ! ais_pawn[aifile[to]] && ! IsMateBPawnDrop( ptree, to ) )
291             {
292               *pmove++ = utemp | Drop2Move(pawn);
293             }
294           for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
295           ubb_target0b ^= abb_mask[ to ].p[0];
296         }
297     }
298   else {
299     while ( BBTest( bb_target ) )
300       {
301         to = LastOne( bb_target );
302         utemp = To2Move(to);
303         for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
304         Xor( to, bb_target );
305       }
306
307     while ( ubb_target0b )
308       {
309         to = last_one0( ubb_target0b );
310         utemp = To2Move(to);
311         for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
312         ubb_target0b ^= abb_mask[ to ].p[0];
313       }
314   }
315
316   while ( ubb_target0a )
317     {
318       to = last_one0( ubb_target0a );
319       utemp = To2Move(to);
320       for ( i = nolance; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
321       ubb_target0a ^= abb_mask[ to ].p[0];
322     }
323
324   return pmove;
325 }
326
327
328 unsigned int * CONV
329 w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove )
330 {
331   bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
332   unsigned int hand, ubb_target2a, ubb_target2b, ubb_pawn_cmp, utemp;
333   unsigned int ais_pawn[nfile];
334   int nchecker, sq_wk, to, sq_check, idirec;
335   int nhand, i, nolance, noknight, from;
336   int ahand[6];
337
338   /* move the king */
339   sq_wk = SQ_WKING;
340
341   Xor( sq_wk, BB_WOCCUPY );
342   XorFile( sq_wk, OCCUPIED_FILE );
343   XorDiag2( sq_wk, OCCUPIED_DIAG2 );
344   XorDiag1( sq_wk, OCCUPIED_DIAG1 );
345
346   BBNotAnd( bb_desti, abb_king_attacks[sq_wk], BB_WOCCUPY );
347   utemp = From2Move(sq_wk) | Piece2Move(king);
348   while ( BBTest( bb_desti ) )
349     {
350       to = FirstOne( bb_desti );
351       if ( ! is_white_attacked( ptree, to ) )
352         {
353           *pmove++ = To2Move(to) | Cap2Move(BOARD[to]) | utemp;
354         }
355       Xor( to, bb_desti );
356     }
357
358   Xor( sq_wk, BB_WOCCUPY );
359   XorFile( sq_wk, OCCUPIED_FILE );
360   XorDiag2( sq_wk, OCCUPIED_DIAG2 );
361   XorDiag1( sq_wk, OCCUPIED_DIAG1 );
362
363   bb_checker = b_attacks_to_piece( ptree, sq_wk );
364   nchecker = PopuCount( bb_checker );
365   if ( nchecker == 2 ) { return pmove; }
366
367   sq_check = FirstOne( bb_checker );
368   bb_inter = abb_obstacle[sq_wk][sq_check];
369
370   /* move other pieces */
371   BBOr( bb_target, bb_inter, bb_checker );
372
373   BBAnd( bb_desti, bb_target, BB_WPAWN_ATK );
374   while ( BBTest( bb_desti ) )
375     {
376       to = FirstOne( bb_desti );
377       Xor( to, bb_desti );
378
379       from = to - 9;
380       idirec = (int)adirec[sq_wk][from];
381       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
382         {
383           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(pawn)
384                     | Cap2Move(BOARD[to]) );
385           if ( to > I4 ) { utemp |= FLAG_PROMO; }
386           *pmove++ = utemp;
387         }
388     }
389
390   bb_piece = BB_WLANCE;
391   while ( BBTest( bb_piece ) )
392     {
393       from = FirstOne( bb_piece );
394       Xor( from, bb_piece );
395
396       bb_desti = AttackFile( from );
397       BBAnd( bb_desti, bb_desti, abb_plus_rays[from] );
398       BBAnd( bb_desti, bb_desti, bb_target );
399       if ( ! BBTest( bb_desti ) ) { continue; }
400
401       idirec = (int)adirec[sq_wk][from];
402       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
403         {
404           to = FirstOne( bb_desti );
405
406           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(lance)
407                     | Cap2Move(BOARD[to]) );
408           if ( to >  I4 ) { *pmove++ = utemp | FLAG_PROMO; }
409           if ( to <= I3 ) { *pmove++ = utemp; }
410         }
411     }
412
413   bb_piece = BB_WKNIGHT;
414   while ( BBTest( bb_piece ) )
415     {
416       from = FirstOne( bb_piece );
417       Xor( from, bb_piece );
418
419       BBAnd( bb_desti, bb_target, abb_w_knight_attacks[from] );
420       if ( ! BBTest( bb_desti ) ) { continue; }
421
422       idirec = (int)adirec[sq_wk][from];
423       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
424         do {
425           to = FirstOne( bb_desti );
426           Xor( to, bb_desti );
427
428           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(knight)
429                     | Cap2Move(BOARD[to]) );
430           if ( to >  I4 ) { *pmove++ = utemp | FLAG_PROMO; }
431           if ( to <= I3 ) { *pmove++ = utemp; }
432         } while ( BBTest( bb_desti ) );
433     }
434
435   bb_piece = BB_WSILVER;
436   while ( BBTest( bb_piece ) )
437     {
438       from = FirstOne( bb_piece );
439       Xor( from, bb_piece );
440       
441       BBAnd( bb_desti, bb_target, abb_w_silver_attacks[from] );
442       if ( ! BBTest( bb_desti ) ) { continue; }
443
444       idirec = (int)adirec[sq_wk][from];
445       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
446         do {
447           to = FirstOne( bb_desti );
448           Xor( to, bb_desti );
449           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(silver)
450                     | Cap2Move(BOARD[to]) );
451           if ( from > I4 || to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
452           *pmove++ = utemp;
453         } while ( BBTest( bb_desti ) );
454     }
455
456   bb_piece = BB_WTGOLD;
457   while( BBTest( bb_piece ) )
458     {
459       from  = FirstOne( bb_piece );
460       Xor( from, bb_piece );
461
462       BBAnd( bb_desti, bb_target, abb_w_gold_attacks[from] );
463       if ( ! BBTest(bb_desti) ) { continue; }
464
465       idirec = (int)adirec[sq_wk][from];
466       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
467         do {
468           to = FirstOne( bb_desti );
469           Xor( to, bb_desti );
470           *pmove++ = ( To2Move(to) | From2Move(from)
471                        | Piece2Move(-BOARD[from])
472                        | Cap2Move(BOARD[to]) );
473         } while( BBTest( bb_desti ) );
474     }
475
476   bb_piece = BB_WBISHOP;
477   while ( BBTest( bb_piece ) )
478     {
479       from = FirstOne( bb_piece );
480       Xor( from, bb_piece );
481
482       AttackBishop( bb_desti, from );
483       BBAnd( bb_desti, bb_desti, bb_target );
484       if ( ! BBTest( bb_desti ) ) { continue; }
485
486       idirec = (int)adirec[sq_wk][from];
487       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
488         do {
489           to = FirstOne( bb_desti );
490           Xor( to, bb_desti );
491
492           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(bishop)
493                     | Cap2Move(BOARD[to]) );
494           if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
495           *pmove++ = utemp;
496         } while ( BBTest( bb_desti ) );
497     }
498
499   bb_piece = BB_WROOK;
500   while ( BBTest( bb_piece ) )
501     {
502       from = FirstOne( bb_piece );
503       Xor( from, bb_piece );
504
505       AttackRook( bb_desti, from );
506       BBAnd( bb_desti, bb_desti, bb_target );
507       if ( ! BBTest( bb_desti ) ) { continue; }
508       idirec = (int)adirec[sq_wk][from];
509       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
510         do {
511           to = FirstOne( bb_desti );
512           Xor( to, bb_desti );
513
514           utemp = ( To2Move(to) | From2Move(from) | Piece2Move(rook)
515                     | Cap2Move(BOARD[to]) );
516           if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
517           *pmove++ = utemp;
518         } while ( BBTest( bb_desti ) );
519     }
520
521   bb_piece = BB_WHORSE;
522   while( BBTest( bb_piece ) )
523     {
524       from = FirstOne( bb_piece );
525       Xor( from, bb_piece );
526
527       AttackHorse( bb_desti, from );
528       BBAnd( bb_desti, bb_desti, bb_target );
529       if ( ! BBTest(bb_desti) ) { continue; }
530
531       idirec = (int)adirec[sq_wk][from];
532       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
533         do {
534           to = FirstOne( bb_desti );
535           Xor( to, bb_desti);
536           *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
537                        | Cap2Move(BOARD[to]) );
538         } while ( BBTest( bb_desti ) );
539     }
540   
541   bb_piece = BB_WDRAGON;
542   while( BBTest( bb_piece ) )
543     {
544       from = FirstOne( bb_piece );
545       Xor( from, bb_piece );
546
547       AttackDragon( bb_desti, from );
548       BBAnd( bb_desti, bb_desti, bb_target );
549       if ( ! BBTest(bb_desti) ) { continue; }
550
551       idirec = (int)adirec[sq_wk][from];
552       if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
553         do {
554           to = FirstOne( bb_desti );
555           Xor( to, bb_desti );
556           *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
557                        | Cap2Move(BOARD[to]) );
558         } while ( BBTest( bb_desti ) );
559     }
560
561   if ( ! HAND_W )          { return pmove; }
562   if ( ! BBTest(bb_inter) ) { return pmove; }
563
564   /* drop */
565   bb_target = bb_inter;
566   ubb_target2a = bb_target.p[2] & 0x00001ffU;
567   ubb_target2b = bb_target.p[2] & 0x003fe00U;
568   bb_target.p[0] &= 0x7ffffffU;
569   bb_target.p[1] &= 0x7ffffffU;
570   bb_target.p[2] &= 0x7fc0000U;
571
572   hand = HAND_W;
573   nhand = 0;
574   if ( IsHandKnight( hand ) ) { ahand[ nhand++ ] = Drop2Move(knight); }
575   noknight = nhand;
576   if ( IsHandLance( hand ) )  { ahand[ nhand++ ] = Drop2Move(lance); }
577   nolance  = nhand;
578   if ( IsHandSilver( hand ) ) { ahand[ nhand++ ] = Drop2Move(silver); }
579   if ( IsHandGold( hand ) )   { ahand[ nhand++ ] = Drop2Move(gold); }
580   if ( IsHandBishop( hand ) ) { ahand[ nhand++ ] = Drop2Move(bishop); }
581   if ( IsHandRook( hand ) )   { ahand[ nhand++ ] = Drop2Move(rook); }
582
583   if ( IsHandPawn( hand ) )
584     {
585       ubb_pawn_cmp= BBToU( BB_WPAWN_ATK );
586       ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
587       ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
588       ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
589       ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
590       ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
591       ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
592       ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
593       ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
594       ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
595  
596       while ( BBTest( bb_target ) )
597         {
598           to = FirstOne( bb_target );
599           utemp = To2Move(to);
600           if ( ! ais_pawn[aifile[to]] && ! IsMateWPawnDrop( ptree, to ) )
601             {
602               *pmove++ = utemp | Drop2Move(pawn);
603             }
604           for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
605           Xor( to, bb_target );
606         }
607
608       while ( ubb_target2b )
609         {
610           to = first_one2( ubb_target2b );
611           utemp = To2Move(to);
612           if ( ! ais_pawn[aifile[to]] && ! IsMateWPawnDrop( ptree, to ) )
613             {
614               *pmove++ = utemp | Drop2Move(pawn);
615             }
616           for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
617           ubb_target2b ^= abb_mask[ to ].p[2];
618         }
619     }
620   else {
621     while ( BBTest( bb_target ) )
622       {
623         to = FirstOne( bb_target );
624         utemp = To2Move(to);
625         for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
626         Xor( to, bb_target );
627       }
628
629     while ( ubb_target2b )
630       {
631         to = first_one2( ubb_target2b );
632         utemp = To2Move(to);
633         for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
634         ubb_target2b ^= abb_mask[ to ].p[2];
635       }
636   }
637
638   while ( ubb_target2a )
639     {
640       to = first_one2( ubb_target2a );
641       utemp = To2Move(to);
642       for ( i = nolance; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
643       ubb_target2a ^= abb_mask[ to ].p[2];
644     }
645
646   return pmove;
647 }
648
649
650 int CONV b_have_evasion( tree_t * restrict ptree )
651 {
652   bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
653   unsigned int ubb_pawn_cmp;
654   unsigned int ais_pawn[nfile];
655   int nchecker, sq_bk, to, sq_check, idirec, flag, from;
656   
657   /* move the king */
658   flag  = 0;
659   sq_bk = SQ_BKING;
660   
661   Xor( sq_bk, BB_BOCCUPY );
662   XorFile( sq_bk, OCCUPIED_FILE );
663   XorDiag2( sq_bk, OCCUPIED_DIAG2 );
664   XorDiag1( sq_bk, OCCUPIED_DIAG1 );
665
666   BBNotAnd( bb_desti, abb_king_attacks[sq_bk], BB_BOCCUPY );
667
668   while ( BBTest( bb_desti ) )
669     {
670       to = LastOne( bb_desti );
671       Xor( to, bb_desti );
672
673       if ( ! is_black_attacked( ptree, to ) )
674         {
675           flag = 1;
676           break;
677         }
678     }
679
680   Xor( sq_bk, BB_BOCCUPY );
681   XorFile( sq_bk, OCCUPIED_FILE );
682   XorDiag2( sq_bk, OCCUPIED_DIAG2 );
683   XorDiag1( sq_bk, OCCUPIED_DIAG1 );
684   
685   if ( flag ) { return 1; }
686
687
688   bb_checker = w_attacks_to_piece( ptree, sq_bk );
689   nchecker   = PopuCount( bb_checker );
690   if ( nchecker == 2 ) { return 0; }
691   
692   sq_check = LastOne( bb_checker );
693   bb_inter = abb_obstacle[sq_bk][sq_check];
694
695   /* move other pieces */
696   BBOr( bb_target, bb_inter, bb_checker );
697   
698   BBAnd( bb_desti, bb_target, BB_BPAWN_ATK );
699   while ( BBTest( bb_desti ) )
700     {
701       to = LastOne( bb_desti );
702       Xor( to, bb_desti );
703
704       from = to + 9;
705       idirec = (int)adirec[sq_bk][from];
706       if ( ! idirec
707            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
708     }
709
710   bb_piece = BB_BLANCE;
711   while ( BBTest( bb_piece ) )
712     {
713       from = LastOne( bb_piece );
714       Xor( from, bb_piece );
715
716       bb_desti = AttackFile( from );
717       BBAnd( bb_desti, bb_desti, abb_minus_rays[from] );
718       BBAnd( bb_desti, bb_desti, bb_target );
719       if ( ! BBTest( bb_desti ) ) { continue; }
720
721       idirec = (int)adirec[sq_bk][from];
722       if ( ! idirec
723            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
724     }
725
726   bb_piece = BB_BKNIGHT;
727   while ( BBTest( bb_piece ) )
728     {
729       from = LastOne( bb_piece );
730       Xor( from, bb_piece );
731
732       BBAnd( bb_desti, bb_target, abb_b_knight_attacks[from] );
733       if ( ! BBTest( bb_desti ) ) { continue; }
734
735       idirec = (int)adirec[sq_bk][from];
736       if ( ! idirec
737            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
738     }
739
740   bb_piece = BB_BSILVER;
741   while ( BBTest( bb_piece ) )
742     {
743       from = LastOne( bb_piece );
744       Xor( from, bb_piece );
745       
746       BBAnd( bb_desti, bb_target, abb_b_silver_attacks[from] );
747       if ( ! BBTest( bb_desti ) ) { continue; }
748
749       idirec = (int)adirec[sq_bk][from];
750       if ( ! idirec
751            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
752     }
753
754   bb_piece = BB_BTGOLD;
755   while( BBTest( bb_piece ) )
756     {
757       from  = LastOne( bb_piece );
758       Xor( from, bb_piece );
759
760       BBAnd( bb_desti, bb_target, abb_b_gold_attacks[from] );
761       if ( ! BBTest(bb_desti) ) { continue; }
762
763       idirec = (int)adirec[sq_bk][from];
764       if ( ! idirec
765            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
766     }
767
768   bb_piece = BB_BBISHOP;
769   while ( BBTest( bb_piece ) )
770     {
771       from = LastOne( bb_piece );
772       Xor( from, bb_piece );
773
774       AttackBishop( bb_desti, from );
775       BBAnd( bb_desti, bb_desti, bb_target );
776       if ( ! BBTest( bb_desti ) ) { continue; }
777
778       idirec = (int)adirec[sq_bk][from];
779       if ( ! idirec
780            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
781     }
782
783   bb_piece = BB_BROOK;
784   while ( BBTest( bb_piece ) )
785     {
786       from = LastOne( bb_piece );
787       Xor( from, bb_piece );
788
789       AttackRook( bb_desti, from );
790       BBAnd( bb_desti, bb_desti, bb_target );
791       if ( ! BBTest( bb_desti ) ) { continue; }
792
793       idirec = (int)adirec[sq_bk][from];
794       if ( ! idirec
795            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
796     }
797
798   bb_piece = BB_BHORSE;
799   while( BBTest( bb_piece ) )
800     {
801       from = LastOne( bb_piece );
802       Xor( from, bb_piece );
803
804       AttackHorse( bb_desti, from );
805       BBAnd( bb_desti, bb_desti, bb_target );
806       if ( ! BBTest(bb_desti) ) { continue; }
807
808       idirec = (int)adirec[sq_bk][from];
809       if ( ! idirec
810            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
811     }
812   
813   bb_piece = BB_BDRAGON;
814   while( BBTest( bb_piece ) )
815     {
816       from = LastOne( bb_piece );
817       Xor( from, bb_piece );
818
819       AttackDragon( bb_desti, from );
820       BBAnd( bb_desti, bb_desti, bb_target );
821       if ( ! BBTest(bb_desti) ) { continue; }
822
823       idirec = (int)adirec[sq_bk][from];
824       if ( ! idirec
825            || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
826     }
827
828   /* drops */
829   if ( ! BBTest(bb_inter) ) { return 0; }
830
831   if ( IsHandSGBR(HAND_B) ) { return 1; }
832
833   bb_inter.p[0] &= 0x003ffffU;
834   if ( ! BBTest(bb_inter) ) { return 0; }
835
836   if ( IsHandLance(HAND_B) ) { return 1; }
837
838   if ( IsHandKnight(HAND_B) )
839     {
840       bb_target       = bb_inter;
841       bb_target.p[0] &= 0x00001ffU;
842       if ( BBTest(bb_target) ) { return 1; }
843     }
844
845   if ( IsHandPawn(HAND_B) )
846     {
847       bb_target = bb_inter;
848       ubb_pawn_cmp= BBToU( BB_BPAWN_ATK );
849       ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
850       ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
851       ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
852       ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
853       ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
854       ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
855       ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
856       ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
857       ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
858  
859       while ( BBTest( bb_target ) )
860         {
861           to = LastOne( bb_target );
862           Xor( to, bb_target );
863           
864           if ( ! ais_pawn[aifile[to]]
865                && ! IsMateBPawnDrop( ptree, to ) ) { return 1; }
866         }
867     }
868
869   return 0;
870 }
871
872
873 int CONV w_have_evasion( tree_t * restrict ptree )
874 {
875   bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
876   unsigned int ubb_pawn_cmp;
877   unsigned int ais_pawn[nfile];
878   int nchecker, sq_wk, to, sq_check, idirec, flag, from;
879
880   /* move the king */
881   flag  = 0;
882   sq_wk = SQ_WKING;
883
884   Xor( sq_wk, BB_WOCCUPY );
885   XorFile( sq_wk, OCCUPIED_FILE );
886   XorDiag2( sq_wk, OCCUPIED_DIAG2 );
887   XorDiag1( sq_wk, OCCUPIED_DIAG1 );
888
889   BBNotAnd( bb_desti, abb_king_attacks[sq_wk], BB_WOCCUPY );
890   while ( BBTest( bb_desti ) )
891     {
892       to = FirstOne( bb_desti );
893       Xor( to, bb_desti );
894
895       if ( ! is_white_attacked( ptree, to ) )
896         {
897           flag = 1;
898           break;
899         }
900     }
901
902   Xor( sq_wk, BB_WOCCUPY );
903   XorFile( sq_wk, OCCUPIED_FILE );
904   XorDiag2( sq_wk, OCCUPIED_DIAG2 );
905   XorDiag1( sq_wk, OCCUPIED_DIAG1 );
906
907   if ( flag ) { return 1; }
908
909
910   bb_checker = b_attacks_to_piece( ptree, sq_wk );
911   nchecker   = PopuCount( bb_checker );
912   if ( nchecker == 2 ) { return 0; }
913
914   sq_check = FirstOne( bb_checker );
915   bb_inter = abb_obstacle[sq_wk][sq_check];
916
917   /* move other pieces */
918   BBOr( bb_target, bb_inter, bb_checker );
919
920   BBAnd( bb_desti, bb_target, BB_WPAWN_ATK );
921   while ( BBTest( bb_desti ) )
922     {
923       to = FirstOne( bb_desti );
924       Xor( to, bb_desti );
925
926       from = to - 9;
927       idirec = (int)adirec[sq_wk][from];
928       if ( ! idirec
929            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
930     }
931
932   bb_piece = BB_WLANCE;
933   while ( BBTest( bb_piece ) )
934     {
935       from = FirstOne( bb_piece );
936       Xor( from, bb_piece );
937
938       bb_desti = AttackFile( from );
939       BBAnd( bb_desti, bb_desti, abb_plus_rays[from] );
940       BBAnd( bb_desti, bb_desti, bb_target );
941       if ( ! BBTest( bb_desti ) ) { continue; }
942
943       idirec = (int)adirec[sq_wk][from];
944       if ( ! idirec
945            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
946     }
947
948   bb_piece = BB_WKNIGHT;
949   while ( BBTest( bb_piece ) )
950     {
951       from = FirstOne( bb_piece );
952       Xor( from, bb_piece );
953
954       BBAnd( bb_desti, bb_target, abb_w_knight_attacks[from] );
955       if ( ! BBTest( bb_desti ) ) { continue; }
956
957       idirec = (int)adirec[sq_wk][from];
958       if ( ! idirec
959            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
960     }
961
962   bb_piece = BB_WSILVER;
963   while ( BBTest( bb_piece ) )
964     {
965       from = FirstOne( bb_piece );
966       Xor( from, bb_piece );
967       
968       BBAnd( bb_desti, bb_target, abb_w_silver_attacks[from] );
969       if ( ! BBTest( bb_desti ) ) { continue; }
970
971       idirec = (int)adirec[sq_wk][from];
972       if ( ! idirec
973            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
974     }
975
976   bb_piece = BB_WTGOLD;
977   while( BBTest( bb_piece ) )
978     {
979       from  = FirstOne( bb_piece );
980       Xor( from, bb_piece );
981
982       BBAnd( bb_desti, bb_target, abb_w_gold_attacks[from] );
983       if ( ! BBTest(bb_desti) ) { continue; }
984
985       idirec = (int)adirec[sq_wk][from];
986       if ( ! idirec
987            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
988     }
989
990   bb_piece = BB_WBISHOP;
991   while ( BBTest( bb_piece ) )
992     {
993       from = FirstOne( bb_piece );
994       Xor( from, bb_piece );
995
996       AttackBishop( bb_desti, from );
997       BBAnd( bb_desti, bb_desti, bb_target );
998       if ( ! BBTest( bb_desti ) ) { continue; }
999
1000       idirec = (int)adirec[sq_wk][from];
1001       if ( ! idirec
1002            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1003     }
1004
1005   bb_piece = BB_WROOK;
1006   while ( BBTest( bb_piece ) )
1007     {
1008       from = FirstOne( bb_piece );
1009       Xor( from, bb_piece );
1010
1011       AttackRook( bb_desti, from );
1012       BBAnd( bb_desti, bb_desti, bb_target );
1013       if ( ! BBTest( bb_desti ) ) { continue; }
1014
1015       idirec = (int)adirec[sq_wk][from];
1016       if ( ! idirec
1017            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1018     }
1019
1020   bb_piece = BB_WHORSE;
1021   while( BBTest( bb_piece ) )
1022     {
1023       from = FirstOne( bb_piece );
1024       Xor( from, bb_piece );
1025
1026       AttackHorse( bb_desti, from );
1027       BBAnd( bb_desti, bb_desti, bb_target );
1028       if ( ! BBTest(bb_desti) ) { continue; }
1029
1030       idirec = (int)adirec[sq_wk][from];
1031       if ( ! idirec
1032            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1033     }
1034   
1035   bb_piece = BB_WDRAGON;
1036   while( BBTest( bb_piece ) )
1037     {
1038       from = FirstOne( bb_piece );
1039       Xor( from, bb_piece );
1040
1041       AttackDragon( bb_desti, from );
1042       BBAnd( bb_desti, bb_desti, bb_target );
1043       if ( ! BBTest(bb_desti) ) { continue; }
1044
1045       idirec = (int)adirec[sq_wk][from];
1046       if ( ! idirec
1047            || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1048     }
1049
1050   /* drop */
1051   if ( ! BBTest(bb_inter) ) { return 0; }
1052
1053   if ( IsHandSGBR(HAND_W) ) { return 1; }
1054
1055   bb_inter.p[2] &= 0x7fffe00U;
1056   if ( ! BBTest(bb_inter) ) { return 0; }
1057
1058   if ( IsHandLance(HAND_W) ) { return 1; }
1059
1060   if ( IsHandKnight(HAND_W) )
1061     {
1062       bb_target       = bb_inter;
1063       bb_target.p[2] &= 0x7fc0000U;
1064       if ( BBTest(bb_target) ) { return 1; }
1065     }
1066
1067   if ( IsHandPawn(HAND_W) )
1068     {
1069       bb_target = bb_inter;
1070       ubb_pawn_cmp= BBToU( BB_WPAWN_ATK );
1071       ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
1072       ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
1073       ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
1074       ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
1075       ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
1076       ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
1077       ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
1078       ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
1079       ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
1080  
1081       while ( BBTest( bb_target ) )
1082         {
1083           to = FirstOne( bb_target );
1084           Xor( to, bb_target );
1085
1086           if ( ! ais_pawn[aifile[to]]
1087                && ! IsMateWPawnDrop( ptree, to ) ) { return 1; }
1088         }
1089     }
1090
1091   return 0;
1092 }