Fix pondering in XBoard mode
[bonanza.git] / mate3.c
1 #include <stdlib.h>
2 #include <limits.h>
3 #include <assert.h>
4 #include "shogi.h"
5
6 enum { mate_king_cap_checker = 0,
7        mate_cap_checker_gen,
8        mate_cap_checker,
9        mate_king_cap_gen,
10        mate_king_cap,
11        mate_king_move_gen,
12        mate_king_move,
13        mate_intercept_move_gen,
14        mate_intercept_move,
15        mate_intercept_weak_move,
16        mate_intercept_drop_sup };
17
18 static int mate3_and( tree_t * restrict ptree, int turn, int ply, int flag );
19 static void checker( const tree_t * restrict ptree, char *psq, int turn );
20 static unsigned int gen_king_cap_checker( const tree_t * restrict ptree,
21                                           int to, int turn );
22 static int mate_weak_or( tree_t * restrict ptree, int turn, int ply,
23                          int from, int to );
24 static unsigned int *gen_move_to( const tree_t * restrict ptree, int sq,
25                                   int turn, unsigned int * restrict pmove );
26 static unsigned int *gen_king_move( const tree_t * restrict ptree,
27                                     const char *psq, int turn, int is_capture,
28                                     unsigned int * restrict pmove );
29 static unsigned int *gen_intercept( tree_t * restrict __ptree__,
30                                     int sq_checker, int ply, int turn,
31                                     int * restrict premaining,
32                                     unsigned int * restrict pmove, int flag );
33 static int gen_next_evasion_mate( tree_t * restrict ptree, const char *psq,
34                                   int ply, int turn, int flag );
35
36 unsigned int
37 is_mate_in3ply( tree_t * restrict ptree, int turn, int ply )
38 {
39   int value, flag_skip;
40
41   if ( ply >= PLY_MAX-2 ) { return 0; }
42
43   flag_skip = 0;
44
45   ptree->anext_move[ply].move_last = ptree->move_last[ply-1];
46   ptree->move_last[ply] = GenCheck( turn, ptree->move_last[ply-1] );
47
48   while ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
49     {
50       MOVE_CURR = *ptree->anext_move[ply].move_last++;
51
52       if ( MOVE_CURR & MOVE_CHK_CLEAR ) { flag_skip = 0; }
53       if ( flag_skip ) { continue; }
54
55       assert( is_move_valid( ptree, MOVE_CURR, turn ) );
56       MakeMove( turn, MOVE_CURR, ply );
57       if ( InCheck(turn) )
58         {
59           UnMakeMove( turn, MOVE_CURR, ply );
60           continue;
61         }
62
63       value = mate3_and( ptree, Flip(turn), ply+1, 0 );
64       
65       UnMakeMove( turn, MOVE_CURR, ply );
66
67       if ( value ) { return 1; }
68
69       if ( ( MOVE_CURR & MOVE_CHK_SET )
70            && I2To(MOVE_CURR) != I2To(ptree->current_move[ply+1]) )
71         {
72           flag_skip = 1;
73         }
74     }
75
76   return 0;
77 }
78
79
80 static int
81 mate3_and( tree_t * restrict ptree, int turn, int ply, int flag )
82 {
83   unsigned int move;
84   char asq[2];
85
86   assert( InCheck(turn) );
87
88   ptree->anext_move[ply].next_phase = mate_king_cap_checker;
89   checker( ptree, asq, turn );
90
91   while ( gen_next_evasion_mate( ptree, asq, ply, turn, flag ) ) {
92
93     if ( ptree->anext_move[ply].next_phase == mate_intercept_drop_sup )
94       {
95         return 0;
96       }
97
98     MakeMove( turn, MOVE_CURR, ply );
99     assert( ! InCheck(turn) );
100
101     if ( InCheck( Flip(turn) ) ) { move = 0; }
102     else                         { move = IsMateIn1Ply( Flip(turn) ); }
103
104     if ( ! move
105          && ptree->anext_move[ply].next_phase == mate_intercept_weak_move )
106       {
107         assert( asq[1] == nsquare );
108         move = (unsigned int)mate_weak_or( ptree, Flip(turn), ply+1, asq[0],
109                                            I2To(MOVE_CURR) );
110       }
111
112     UnMakeMove( turn, MOVE_CURR, ply );
113       
114     if ( ! move ) { return 0; }
115   }
116   
117   return 1;
118 }
119
120
121 static int
122 mate_weak_or( tree_t * restrict ptree, int turn, int ply, int from,
123               int to )
124 {
125   int idirec, pc, pc_cap, value, flag;
126
127   if ( ply >= PLY_MAX-2 ) { return 0; }
128   
129   if ( turn )
130     {
131       if ( IsDiscoverWK( from, to ) ) { return 0; }
132
133       pc     = -BOARD[from];
134       pc_cap =  BOARD[to];
135       MOVE_CURR = ( To2Move(to) | From2Move(from)
136                       | Piece2Move(pc) | Cap2Move(pc_cap) );
137       if ( ( pc == bishop || pc == rook )
138            && ( to > I4 || from > I4 ) ) { MOVE_CURR |= FLAG_PROMO; }
139     }
140   else {
141     if ( IsDiscoverBK( from, to ) ) { return 0; }
142     
143     pc     =  BOARD[from];
144     pc_cap = -BOARD[to];
145     MOVE_CURR = ( To2Move(to) | From2Move(from) | Piece2Move(pc)
146                   | Cap2Move(pc_cap) );
147     if ( ( pc == bishop || pc == rook )
148          && ( to < A6 || from < A6 ) ) { MOVE_CURR |= FLAG_PROMO; }
149   }
150
151   MakeMove( turn, MOVE_CURR, ply );
152   if ( I2From(MOVE_LAST) < nsquare )
153     {
154       if ( InCheck(turn) )
155         {
156           UnMakeMove( turn, MOVE_CURR, ply );
157           return 0;
158         }
159       flag = 1;
160     }
161   else {
162     assert( ! InCheck(turn) );
163     flag = 2;
164   }
165   
166   ptree->move_last[ply] = ptree->move_last[ply-1];
167   value = mate3_and( ptree, Flip(turn), ply+1, flag );
168   
169   UnMakeMove( turn, MOVE_CURR, ply );
170
171   return value;
172 }
173
174
175 static int
176 gen_next_evasion_mate( tree_t * restrict ptree, const char *psq, int ply,
177                        int turn, int flag )
178 {
179   switch ( ptree->anext_move[ply].next_phase )
180     {
181     case mate_king_cap_checker:
182       ptree->anext_move[ply].next_phase = mate_cap_checker_gen;
183       MOVE_CURR = gen_king_cap_checker( ptree, psq[0], turn );
184       if ( MOVE_CURR ) { return 1; }
185
186     case mate_cap_checker_gen:
187       ptree->anext_move[ply].next_phase = mate_cap_checker;
188       ptree->anext_move[ply].move_last  = ptree->move_last[ply-1];
189       ptree->move_last[ply]             = ptree->move_last[ply-1];
190       if ( psq[1] == nsquare )
191         {
192           ptree->move_last[ply]
193             = gen_move_to( ptree, psq[0], turn, ptree->move_last[ply-1] );
194         }
195
196     case mate_cap_checker:
197       if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
198         {
199           MOVE_CURR = *(ptree->anext_move[ply].move_last++);
200           return 1;
201         }
202
203     case mate_king_cap_gen:
204       ptree->anext_move[ply].next_phase = mate_king_cap;
205       ptree->anext_move[ply].move_last  = ptree->move_last[ply-1];
206       ptree->move_last[ply]
207         = gen_king_move( ptree, psq, turn, 1, ptree->move_last[ply-1] );
208
209     case mate_king_cap:
210       if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
211         {
212           MOVE_CURR = *(ptree->anext_move[ply].move_last++);
213           return 1;
214         }
215
216     case mate_king_move_gen:
217       ptree->anext_move[ply].next_phase = mate_king_move;
218       ptree->anext_move[ply].move_last  = ptree->move_last[ply-1];
219       ptree->move_last[ply]
220         = gen_king_move( ptree, psq, turn, 0, ptree->move_last[ply-1] );
221
222     case mate_king_move:
223       if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
224         {
225           MOVE_CURR = *(ptree->anext_move[ply].move_last++);
226           return 1;
227         }
228
229     case mate_intercept_move_gen:
230       ptree->anext_move[ply].remaining  = 0;
231       ptree->anext_move[ply].next_phase = mate_intercept_move;
232       ptree->anext_move[ply].move_last  = ptree->move_last[ply-1];
233       ptree->move_last[ply]             = ptree->move_last[ply-1];
234       if ( psq[1] == nsquare && abs(BOARD[(int)psq[0]]) != knight  )
235         {
236           int n;
237           ptree->move_last[ply] = gen_intercept( ptree, psq[0], ply, turn, &n,
238                                                  ptree->move_last[ply-1],
239                                                  flag );
240           if ( n < 0 )
241             {
242               ptree->anext_move[ply].next_phase = mate_intercept_drop_sup;
243               ptree->anext_move[ply].remaining  = 0;
244               MOVE_CURR = *(ptree->anext_move[ply].move_last++);
245               return 1;
246             }
247
248           ptree->anext_move[ply].remaining = n;
249         }
250
251     case mate_intercept_move:
252       if ( ptree->anext_move[ply].remaining-- )
253         {
254           MOVE_CURR = *(ptree->anext_move[ply].move_last++);
255           return 1;
256         }
257       ptree->anext_move[ply].next_phase = mate_intercept_weak_move;
258
259     case mate_intercept_weak_move:
260       if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
261         {
262           MOVE_CURR = *(ptree->anext_move[ply].move_last++);
263           return 1;
264         }
265       break;
266
267     default:
268       assert( 0 );
269     }
270
271   return 0;
272 }
273
274
275 static void
276 checker( const tree_t * restrict ptree, char *psq, int turn )
277 {
278   bitboard_t bb, bb_checkers;
279   int n, sq0, sq1, sq_king;
280
281   if ( turn )
282     {
283       sq_king     = SQ_WKING;
284       bb_checkers = BB_BOCCUPY;
285     }
286   else {
287     sq_king     = SQ_BKING;
288     bb_checkers = BB_WOCCUPY;
289   }
290   bb = attacks_to_piece( ptree, sq_king );
291   BBAnd( bb, bb, bb_checkers );
292
293   assert( BBToU(bb) );
294   sq0 = LastOne( bb );
295   sq1 = nsquare;
296
297   Xor( sq0, bb );
298   if ( BBToU( bb ) )
299     {
300       sq1 = LastOne( bb );
301       if ( BBContract( abb_king_attacks[sq_king], abb_mask[sq1] ) )
302         {
303           n   = sq0;
304           sq0 = sq1;
305           sq1 = n;
306         }
307     }
308
309   psq[0] = (char)sq0;
310   psq[1] = (char)sq1;
311 }
312
313
314 static unsigned int
315 gen_king_cap_checker( const tree_t * restrict ptree, int to, int turn )
316 {
317   unsigned int move;
318   int from;
319
320   if ( turn )
321     {
322       from = SQ_WKING;
323       if ( ! BBContract( abb_king_attacks[from],
324                          abb_mask[to] ) )   { return 0;}
325       if ( is_white_attacked( ptree, to ) ) { return 0; }
326       move = Cap2Move(BOARD[to]);
327     }
328   else {
329     from = SQ_BKING;
330     if ( ! BBContract( abb_king_attacks[from],
331                        abb_mask[to] ) )   { return 0;}
332     if ( is_black_attacked( ptree, to ) ) { return 0; }
333     move = Cap2Move(-BOARD[to]);
334   }
335   move |= To2Move(to) | From2Move(from) | Piece2Move(king);
336
337   return move;
338 }
339
340
341 static unsigned int *
342 gen_move_to( const tree_t * restrict ptree, int to, int turn,
343              unsigned int * restrict pmove )
344 {
345   bitboard_t bb;
346   int direc, from, pc, flag_promo, flag_unpromo;
347
348   bb = attacks_to_piece( ptree, to );
349   if ( turn )
350     {
351       BBAnd( bb, bb, BB_WOCCUPY );
352       BBNotAnd( bb, abb_mask[SQ_WKING] );
353       while ( BBToU(bb) )
354         {
355           from = LastOne( bb );
356           Xor( from, bb );
357
358           direc = (int)adirec[SQ_WKING][from];
359           if ( direc && is_pinned_on_white_king( ptree, from, direc ) )
360             {
361               continue;
362             }
363
364           flag_promo   = 0;
365           flag_unpromo = 1;
366           pc           = -BOARD[from];
367           switch ( pc )
368             {
369             case pawn:
370               if ( to > I4 ) { flag_promo = 1;  flag_unpromo = 0; }
371               break;
372
373             case lance:  case knight:
374               if      ( to > I3 ) { flag_promo = 1;  flag_unpromo = 0; }
375               else if ( to > I4 ) { flag_promo = 1; }
376               break;
377
378             case silver:
379               if ( to > I4 || from > I4 ) { flag_promo = 1; }
380               break;
381
382             case bishop:  case rook:
383               if ( to > I4
384                    || from > I4 ) { flag_promo = 1;  flag_unpromo = 0; }
385               break;
386
387             default:
388               break;
389             }
390           assert( flag_promo || flag_unpromo );
391           if ( flag_promo )
392             {
393               *pmove++ = ( From2Move(from) | To2Move(to) | FLAG_PROMO
394                            | Piece2Move(pc) | Cap2Move(BOARD[to]) );
395             }
396           if ( flag_unpromo )
397             {
398               *pmove++ = ( From2Move(from) | To2Move(to)
399                            | Piece2Move(pc) | Cap2Move(BOARD[to]) );
400             }
401         }
402     }
403   else {
404     BBAnd( bb, bb, BB_BOCCUPY );
405     BBNotAnd( bb, abb_mask[SQ_BKING] );
406     while ( BBToU(bb) )
407       {
408         from = FirstOne( bb );
409         Xor( from, bb );
410         
411         direc = (int)adirec[SQ_BKING][from];
412         if ( direc && is_pinned_on_black_king( ptree, from, direc ) )
413           {
414             continue;
415           }
416
417         flag_promo   = 0;
418         flag_unpromo = 1;
419         pc           = BOARD[from];
420         switch ( pc )
421           {
422           case pawn:
423             if ( to < A6 ) { flag_promo = 1;  flag_unpromo = 0; }
424             break;
425             
426           case lance:  case knight:
427             if      ( to < A7 ) { flag_promo = 1;  flag_unpromo = 0; }
428             else if ( to < A6 ) { flag_promo = 1; }
429             break;
430             
431           case silver:
432             if ( to < A6 || from < A6 ) { flag_promo = 1; }
433             break;
434             
435           case bishop:  case rook:
436             if ( to < A6
437                  || from < A6 ) { flag_promo = 1;  flag_unpromo = 0; }
438             break;
439             
440           default:
441             break;
442           }
443         assert( flag_promo || flag_unpromo );
444         if ( flag_promo )
445           {
446             *pmove++ = ( From2Move(from) | To2Move(to) | FLAG_PROMO
447                          | Piece2Move(pc) | Cap2Move(-BOARD[to]) );
448           }
449         if ( flag_unpromo )
450           {
451             *pmove++ = ( From2Move(from) | To2Move(to)
452                          | Piece2Move(pc) | Cap2Move(-BOARD[to]) );
453           }
454       }
455   }
456
457   return pmove;
458 }
459
460
461 static unsigned int *
462 gen_king_move( const tree_t * restrict ptree, const char *psq, int turn,
463                int is_capture, unsigned int * restrict pmove )
464 {
465   bitboard_t bb;
466   int to, from;
467
468   if ( turn )
469     {
470       from = SQ_WKING;
471       bb      = abb_king_attacks[from];
472       if ( is_capture )
473         {
474           BBAnd( bb, bb, BB_BOCCUPY );
475           BBNotAnd( bb, abb_mask[(int)psq[0]] );
476         }
477       else { BBNotAnd( bb, BB_BOCCUPY ); }
478       BBNotAnd( bb, BB_WOCCUPY );
479     }
480   else {
481     from = SQ_BKING;
482     bb      = abb_king_attacks[from];
483     if ( is_capture )
484       {
485         BBAnd( bb, bb, BB_WOCCUPY );
486         BBNotAnd( bb, abb_mask[(int)psq[0]] );
487       }
488     else { BBNotAnd( bb, BB_WOCCUPY ); }
489     BBNotAnd( bb, BB_BOCCUPY );
490   }
491   
492   while ( BBToU(bb) )
493     {
494       to = LastOne( bb );
495       Xor( to, bb );
496
497       if ( psq[1] != nsquare
498            && ( adirec[from][(int)psq[1]]
499                 == adirec[from][to] ) ) { continue; }
500
501       if ( psq[0] != to
502            && adirec[from][(int)psq[0]] == adirec[from][to] ) {
503           if ( adirec[from][(int)psq[0]] & flag_cross )
504             {
505               if ( abs(BOARD[(int)psq[0]]) == lance
506                    || abs(BOARD[(int)psq[0]]) == rook
507                    || abs(BOARD[(int)psq[0]]) == dragon ) { continue; }
508             }
509           else if ( ( adirec[from][(int)psq[0]] & flag_diag )
510                     && ( abs(BOARD[(int)psq[0]]) == bishop
511                          || abs(BOARD[(int)psq[0]]) == horse ) ){ continue; }
512         }
513
514       if ( turn )
515         {
516           if ( is_white_attacked( ptree, to ) ) { continue; }
517
518           *pmove++ = ( From2Move(from) | To2Move(to)
519                        | Piece2Move(king) | Cap2Move(BOARD[to]) );
520         }
521       else {
522         if ( is_black_attacked( ptree, to ) ) { continue; }
523
524         *pmove++ = ( From2Move(from) | To2Move(to)
525                      | Piece2Move(king) | Cap2Move(-BOARD[to]) );
526       }
527     }
528
529   return pmove;
530 }
531
532
533 static unsigned int *
534 gen_intercept( tree_t * restrict __ptree__, int sq_checker, int ply, int turn,
535                int * restrict premaining, unsigned int * restrict pmove,
536                int flag )
537 {
538 #define Drop(pc) ( To2Move(to) | Drop2Move(pc) )
539
540   const tree_t * restrict ptree = __ptree__;
541   bitboard_t bb_atk, bb_defender, bb;
542   unsigned int amove[16];
543   unsigned int hand;
544   int n0, n1, inc, pc, sq_k, to, from, direc, nmove, nsup, i, min_chuai, itemp;
545   int dist, flag_promo, flag_unpromo;
546
547   n0 = n1 = 0;
548   if ( turn )
549     {
550       sq_k        = SQ_WKING;
551       bb_defender = BB_WOCCUPY;
552       BBNotAnd( bb_defender, abb_mask[sq_k] );
553     }
554   else {
555     sq_k        = SQ_BKING;
556     bb_defender = BB_BOCCUPY;
557     BBNotAnd( bb_defender, abb_mask[sq_k] );
558   }
559
560   switch ( adirec[sq_k][sq_checker] )
561     {
562     case direc_rank:
563       min_chuai = ( sq_k < A8 || I2 < sq_k ) ? 2 : 4;
564       inc       = 1;
565       break;
566
567     case direc_diag1:
568       min_chuai = 3;
569       inc       = 8;
570       break;
571
572     case direc_file:
573       itemp     = (int)aifile[sq_k];
574       min_chuai = ( itemp == file1 || itemp == file9 ) ? 2 : 4;
575       inc = 9;
576       break;
577
578     default:
579       assert( (int)adirec[sq_k][sq_checker] == direc_diag2 );
580       min_chuai = 3;
581       inc       = 10;
582     }
583   if ( sq_k > sq_checker ) { inc = -inc; }
584   
585   for ( dist = 1, to = sq_k + inc;
586         to != sq_checker;
587         dist += 1, to += inc ) {
588
589     assert( 0 <= to && to < nsquare && BOARD[to] == empty );
590
591     nmove  = 0;
592     bb_atk = attacks_to_piece( ptree, to );
593     BBAnd( bb, bb_defender, bb_atk );
594     while ( BBToU(bb) )
595       {
596         from = LastOne( bb );
597         Xor( from, bb );
598         
599         direc        = (int)adirec[sq_k][from];
600         flag_promo   = 0;
601         flag_unpromo = 1;
602         if ( turn )
603           {
604             if ( direc && is_pinned_on_white_king( ptree, from, direc ) )
605               {
606                 continue;
607               }
608             pc = -BOARD[from];
609             switch ( pc )
610               {
611               case pawn:
612                 if ( to > I4 ) { flag_promo = 1;  flag_unpromo = 0; }
613                 break;
614                 
615               case lance:  case knight:
616                 if      ( to > I3 ) { flag_promo = 1;  flag_unpromo = 0; }
617                 else if ( to > I4 ) { flag_promo = 1; }
618                 break;
619                 
620               case silver:
621                 if ( to > I4 || from > I4 ) { flag_promo = 1; }
622                 break;
623                 
624               case bishop:  case rook:
625                 if ( to > I4
626                      || from > I4 ) { flag_promo = 1;  flag_unpromo = 0; }
627                 break;
628                 
629               default:
630                 break;
631               }
632           }
633         else {
634           if ( direc && is_pinned_on_black_king( ptree, from, direc ) )
635             {
636               continue;
637             }
638           pc = BOARD[from];
639           switch ( pc )
640             {
641             case pawn:
642               if ( to < A6 ) { flag_promo = 1;  flag_unpromo = 0; }
643               break;
644               
645             case lance:  case knight:
646               if      ( to < A7 ) { flag_promo = 1;  flag_unpromo = 0; }
647               else if ( to < A6 ) { flag_promo = 1; }
648               break;
649               
650             case silver:
651               if ( to < A6 || from < A6 ) { flag_promo = 1; }
652               break;
653               
654             case bishop:  case rook:
655               if ( to < A6
656                    || from < A6 ) { flag_promo = 1;  flag_unpromo = 0; }
657               break;
658               
659             default:
660               break;
661             }
662         }
663         assert( flag_promo || flag_unpromo );
664         if ( flag_promo )
665           {
666             amove[nmove++] = ( From2Move(from) | To2Move(to)
667                                | FLAG_PROMO | Piece2Move(pc) );
668           }
669         if ( flag_unpromo )
670           {
671             amove[nmove++] = ( From2Move(from) | To2Move(to)
672                                | Piece2Move(pc) );
673           }
674       }
675     
676     nsup = ( to == sq_k + inc ) ? nmove + 1 : nmove;
677     if ( nsup > 1 )
678       {
679         for ( i = n0 + n1 - 1; i >= n0; i-- ) { pmove[i+nmove] = pmove[i]; }
680         for ( i = 0; i < nmove; i++ ) { pmove[n0++] = amove[i]; }
681       }
682     else if ( nmove ) { pmove[n0 + n1++] = amove[0]; }
683     
684     if ( ! nsup )
685       {
686         /* - tentative assumption - */
687         /* no recursive drops at non-supported square. */
688         if ( flag == 2  ) { continue; }
689         
690         /* -tentative assumption- */
691         /* no intercept-drop at non-supported square. */
692         if ( I2To(MOVE_LAST) == sq_checker && dist > min_chuai ) { continue; }
693       }
694     
695     nmove = 0;
696     
697     if ( turn ) {
698       
699       hand = HAND_W;
700       
701       if ( nsup ) {
702         
703         if ( IsHandRook(hand) ) { amove[nmove++] = Drop(rook); }
704         else if ( IsHandLance(hand) && to < A1 )
705           {
706             amove[nmove++] = Drop(lance);
707           }
708         else if ( IsHandPawn(hand)
709                   && to < A1
710                   && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[to] ) )
711                   && ! IsMateWPawnDrop( __ptree__, to ) )
712           {
713             amove[nmove++] = Drop(pawn);
714           }
715         
716       } else {
717         
718         if ( IsHandPawn(hand)
719              && to < A1
720              && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[to] ) )
721              && ! IsMateWPawnDrop( __ptree__, to ) )
722           {
723             amove[nmove++] = Drop(pawn);
724           }
725         if ( IsHandLance(hand) && to < A1 ) { amove[nmove++] = Drop(lance); }
726         if ( IsHandRook(hand) )             { amove[nmove++] = Drop(rook); }
727       }
728       
729       if ( IsHandKnight(hand) && to < A2 ) { amove[nmove++] = Drop(knight); }
730       
731     } else {
732       
733       hand = HAND_B;
734       
735       if ( nsup ) {
736         
737         if ( IsHandRook(hand) ) { amove[nmove++] = Drop(rook); }
738         else if ( IsHandLance(hand) && to > I9 )
739           {
740             amove[nmove++] = Drop(lance);
741           }
742         else if ( IsHandPawn(hand)
743                   && to > I9
744                   && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[to] ) )
745                   && ! IsMateBPawnDrop( __ptree__, to ) )
746           {
747             amove[nmove++] = Drop(pawn);
748           }
749         
750       } else {
751         
752         if ( IsHandPawn(hand)
753              && to > I9
754              && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[to] ) )
755              && ! IsMateBPawnDrop( __ptree__, to ) )
756           {
757             amove[nmove++] = Drop(pawn);
758           }
759         if ( IsHandLance(hand) && to > I9 ) { amove[nmove++] = Drop(lance); }
760         if ( IsHandRook(hand) )             { amove[nmove++] = Drop(rook); }
761       }
762       
763       if ( IsHandKnight(hand) && to > I8 ) { amove[nmove++] = Drop(knight); }
764     }
765     
766     if ( IsHandSilver(hand) ) { amove[nmove++] = Drop(silver); }
767     if ( IsHandGold(hand) )   { amove[nmove++] = Drop(gold); }
768     if ( IsHandBishop(hand) ) { amove[nmove++] = Drop(bishop); }
769     
770     if ( nsup )
771       {
772         /* - tentative assumption - */
773         /* a supported intercepter saves the king for two plies at least. */
774         if ( nmove && flag == 0 && dist > min_chuai
775              && I2From(MOVE_LAST) >= nsquare )
776             {
777               *premaining = -1;
778               pmove[0]    = amove[0];
779               return pmove + 1;
780             }
781
782         for ( i = n0 + n1 - 1; i >= n0; i-- ) { pmove[i+nmove] = pmove[i]; }
783         for ( i = 0; i < nmove; i++ ) { pmove[n0++] = amove[i]; }
784       }
785     else for ( i = 0; i < nmove; i++ ) { pmove[n0 + n1++] = amove[i]; }
786   }
787   
788   *premaining = n0;
789   return pmove + n0 + n1;
790
791 #undef Drop
792 }