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