6 enum { mate_king_cap_checker = 0,
13 mate_intercept_move_gen,
15 mate_intercept_weak_move,
16 mate_intercept_drop_sup };
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,
22 static int mate_weak_or( tree_t * restrict ptree, int turn, int ply,
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 );
37 is_mate_in3ply( tree_t * restrict ptree, int turn, int ply )
41 if ( ply >= PLY_MAX-2 ) { return 0; }
45 ptree->anext_move[ply].move_last = ptree->move_last[ply-1];
46 ptree->move_last[ply] = GenCheck( turn, ptree->move_last[ply-1] );
48 while ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
50 MOVE_CURR = *ptree->anext_move[ply].move_last++;
52 if ( MOVE_CURR & MOVE_CHK_CLEAR ) { flag_skip = 0; }
53 if ( flag_skip ) { continue; }
55 assert( is_move_valid( ptree, MOVE_CURR, turn ) );
56 MakeMove( turn, MOVE_CURR, ply );
59 UnMakeMove( turn, MOVE_CURR, ply );
63 value = mate3_and( ptree, Flip(turn), ply+1, 0 );
65 UnMakeMove( turn, MOVE_CURR, ply );
67 if ( value ) { return 1; }
69 if ( ( MOVE_CURR & MOVE_CHK_SET )
70 && I2To(MOVE_CURR) != I2To(ptree->current_move[ply+1]) )
81 mate3_and( tree_t * restrict ptree, int turn, int ply, int flag )
86 assert( InCheck(turn) );
88 ptree->anext_move[ply].next_phase = mate_king_cap_checker;
89 checker( ptree, asq, turn );
91 while ( gen_next_evasion_mate( ptree, asq, ply, turn, flag ) ) {
93 if ( ptree->anext_move[ply].next_phase == mate_intercept_drop_sup )
98 MakeMove( turn, MOVE_CURR, ply );
99 assert( ! InCheck(turn) );
101 if ( InCheck( Flip(turn) ) ) { move = 0; }
102 else { move = IsMateIn1Ply( Flip(turn) ); }
105 && ptree->anext_move[ply].next_phase == mate_intercept_weak_move )
107 assert( asq[1] == nsquare );
108 move = (unsigned int)mate_weak_or( ptree, Flip(turn), ply+1, asq[0],
112 UnMakeMove( turn, MOVE_CURR, ply );
114 if ( ! move ) { return 0; }
122 mate_weak_or( tree_t * restrict ptree, int turn, int ply, int from,
125 int idirec, pc, pc_cap, value, flag;
127 if ( ply >= PLY_MAX-2 ) { return 0; }
131 if ( IsDiscoverWK( from, to ) ) { return 0; }
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; }
141 if ( IsDiscoverBK( from, to ) ) { return 0; }
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; }
151 MakeMove( turn, MOVE_CURR, ply );
152 if ( I2From(MOVE_LAST) < nsquare )
156 UnMakeMove( turn, MOVE_CURR, ply );
162 assert( ! InCheck(turn) );
166 ptree->move_last[ply] = ptree->move_last[ply-1];
167 value = mate3_and( ptree, Flip(turn), ply+1, flag );
169 UnMakeMove( turn, MOVE_CURR, ply );
176 gen_next_evasion_mate( tree_t * restrict ptree, const char *psq, int ply,
179 switch ( ptree->anext_move[ply].next_phase )
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; }
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 )
192 ptree->move_last[ply]
193 = gen_move_to( ptree, psq[0], turn, ptree->move_last[ply-1] );
196 case mate_cap_checker:
197 if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
199 MOVE_CURR = *(ptree->anext_move[ply].move_last++);
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] );
210 if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
212 MOVE_CURR = *(ptree->anext_move[ply].move_last++);
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] );
223 if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
225 MOVE_CURR = *(ptree->anext_move[ply].move_last++);
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 )
237 ptree->move_last[ply] = gen_intercept( ptree, psq[0], ply, turn, &n,
238 ptree->move_last[ply-1],
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++);
248 ptree->anext_move[ply].remaining = n;
251 case mate_intercept_move:
252 if ( ptree->anext_move[ply].remaining-- )
254 MOVE_CURR = *(ptree->anext_move[ply].move_last++);
257 ptree->anext_move[ply].next_phase = mate_intercept_weak_move;
259 case mate_intercept_weak_move:
260 if ( ptree->anext_move[ply].move_last != ptree->move_last[ply] )
262 MOVE_CURR = *(ptree->anext_move[ply].move_last++);
276 checker( const tree_t * restrict ptree, char *psq, int turn )
278 bitboard_t bb, bb_checkers;
279 int n, sq0, sq1, sq_king;
284 bb_checkers = BB_BOCCUPY;
288 bb_checkers = BB_WOCCUPY;
290 bb = attacks_to_piece( ptree, sq_king );
291 BBAnd( bb, bb, bb_checkers );
301 if ( BBContract( abb_king_attacks[sq_king], abb_mask[sq1] ) )
315 gen_king_cap_checker( const tree_t * restrict ptree, int to, int turn )
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]);
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]);
335 move |= To2Move(to) | From2Move(from) | Piece2Move(king);
341 static unsigned int *
342 gen_move_to( const tree_t * restrict ptree, int to, int turn,
343 unsigned int * restrict pmove )
346 int direc, from, pc, flag_promo, flag_unpromo;
348 bb = attacks_to_piece( ptree, to );
351 BBAnd( bb, bb, BB_WOCCUPY );
352 BBNotAnd( bb, abb_mask[SQ_WKING] );
355 from = LastOne( bb );
358 direc = (int)adirec[SQ_WKING][from];
359 if ( direc && is_pinned_on_white_king( ptree, from, direc ) )
370 if ( to > I4 ) { flag_promo = 1; flag_unpromo = 0; }
373 case lance: case knight:
374 if ( to > I3 ) { flag_promo = 1; flag_unpromo = 0; }
375 else if ( to > I4 ) { flag_promo = 1; }
379 if ( to > I4 || from > I4 ) { flag_promo = 1; }
382 case bishop: case rook:
384 || from > I4 ) { flag_promo = 1; flag_unpromo = 0; }
390 assert( flag_promo || flag_unpromo );
393 *pmove++ = ( From2Move(from) | To2Move(to) | FLAG_PROMO
394 | Piece2Move(pc) | Cap2Move(BOARD[to]) );
398 *pmove++ = ( From2Move(from) | To2Move(to)
399 | Piece2Move(pc) | Cap2Move(BOARD[to]) );
404 BBAnd( bb, bb, BB_BOCCUPY );
405 BBNotAnd( bb, abb_mask[SQ_BKING] );
408 from = FirstOne( bb );
411 direc = (int)adirec[SQ_BKING][from];
412 if ( direc && is_pinned_on_black_king( ptree, from, direc ) )
423 if ( to < A6 ) { flag_promo = 1; flag_unpromo = 0; }
426 case lance: case knight:
427 if ( to < A7 ) { flag_promo = 1; flag_unpromo = 0; }
428 else if ( to < A6 ) { flag_promo = 1; }
432 if ( to < A6 || from < A6 ) { flag_promo = 1; }
435 case bishop: case rook:
437 || from < A6 ) { flag_promo = 1; flag_unpromo = 0; }
443 assert( flag_promo || flag_unpromo );
446 *pmove++ = ( From2Move(from) | To2Move(to) | FLAG_PROMO
447 | Piece2Move(pc) | Cap2Move(-BOARD[to]) );
451 *pmove++ = ( From2Move(from) | To2Move(to)
452 | Piece2Move(pc) | Cap2Move(-BOARD[to]) );
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 )
471 bb = abb_king_attacks[from];
474 BBAnd( bb, bb, BB_BOCCUPY );
475 BBNotAnd( bb, abb_mask[(int)psq[0]] );
477 else { BBNotAnd( bb, BB_BOCCUPY ); }
478 BBNotAnd( bb, BB_WOCCUPY );
482 bb = abb_king_attacks[from];
485 BBAnd( bb, bb, BB_WOCCUPY );
486 BBNotAnd( bb, abb_mask[(int)psq[0]] );
488 else { BBNotAnd( bb, BB_WOCCUPY ); }
489 BBNotAnd( bb, BB_BOCCUPY );
497 if ( psq[1] != nsquare
498 && ( adirec[from][(int)psq[1]]
499 == adirec[from][to] ) ) { continue; }
502 && adirec[from][(int)psq[0]] == adirec[from][to] ) {
503 if ( adirec[from][(int)psq[0]] & flag_cross )
505 if ( abs(BOARD[(int)psq[0]]) == lance
506 || abs(BOARD[(int)psq[0]]) == rook
507 || abs(BOARD[(int)psq[0]]) == dragon ) { continue; }
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; }
516 if ( is_white_attacked( ptree, to ) ) { continue; }
518 *pmove++ = ( From2Move(from) | To2Move(to)
519 | Piece2Move(king) | Cap2Move(BOARD[to]) );
522 if ( is_black_attacked( ptree, to ) ) { continue; }
524 *pmove++ = ( From2Move(from) | To2Move(to)
525 | Piece2Move(king) | Cap2Move(-BOARD[to]) );
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,
538 #define Drop(pc) ( To2Move(to) | Drop2Move(pc) )
540 const tree_t * restrict ptree = __ptree__;
541 bitboard_t bb_atk, bb_defender, bb;
542 unsigned int amove[16];
544 int n0, n1, inc, pc, sq_k, to, from, direc, nmove, nsup, i, min_chuai, itemp;
545 int dist, flag_promo, flag_unpromo;
551 bb_defender = BB_WOCCUPY;
552 BBNotAnd( bb_defender, abb_mask[sq_k] );
556 bb_defender = BB_BOCCUPY;
557 BBNotAnd( bb_defender, abb_mask[sq_k] );
560 switch ( adirec[sq_k][sq_checker] )
563 min_chuai = ( sq_k < A8 || I2 < sq_k ) ? 2 : 4;
573 itemp = (int)aifile[sq_k];
574 min_chuai = ( itemp == file1 || itemp == file9 ) ? 2 : 4;
579 assert( (int)adirec[sq_k][sq_checker] == direc_diag2 );
583 if ( sq_k > sq_checker ) { inc = -inc; }
585 for ( dist = 1, to = sq_k + inc;
587 dist += 1, to += inc ) {
589 assert( 0 <= to && to < nsquare && BOARD[to] == empty );
592 bb_atk = attacks_to_piece( ptree, to );
593 BBAnd( bb, bb_defender, bb_atk );
596 from = LastOne( bb );
599 direc = (int)adirec[sq_k][from];
604 if ( direc && is_pinned_on_white_king( ptree, from, direc ) )
612 if ( to > I4 ) { flag_promo = 1; flag_unpromo = 0; }
615 case lance: case knight:
616 if ( to > I3 ) { flag_promo = 1; flag_unpromo = 0; }
617 else if ( to > I4 ) { flag_promo = 1; }
621 if ( to > I4 || from > I4 ) { flag_promo = 1; }
624 case bishop: case rook:
626 || from > I4 ) { flag_promo = 1; flag_unpromo = 0; }
634 if ( direc && is_pinned_on_black_king( ptree, from, direc ) )
642 if ( to < A6 ) { flag_promo = 1; flag_unpromo = 0; }
645 case lance: case knight:
646 if ( to < A7 ) { flag_promo = 1; flag_unpromo = 0; }
647 else if ( to < A6 ) { flag_promo = 1; }
651 if ( to < A6 || from < A6 ) { flag_promo = 1; }
654 case bishop: case rook:
656 || from < A6 ) { flag_promo = 1; flag_unpromo = 0; }
663 assert( flag_promo || flag_unpromo );
666 amove[nmove++] = ( From2Move(from) | To2Move(to)
667 | FLAG_PROMO | Piece2Move(pc) );
671 amove[nmove++] = ( From2Move(from) | To2Move(to)
676 nsup = ( to == sq_k + inc ) ? nmove + 1 : nmove;
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]; }
682 else if ( nmove ) { pmove[n0 + n1++] = amove[0]; }
686 /* - tentative assumption - */
687 /* no recursive drops at non-supported square. */
688 if ( flag == 2 ) { continue; }
690 /* -tentative assumption- */
691 /* no intercept-drop at non-supported square. */
692 if ( I2To(MOVE_LAST) == sq_checker && dist > min_chuai ) { continue; }
703 if ( IsHandRook(hand) ) { amove[nmove++] = Drop(rook); }
704 else if ( IsHandLance(hand) && to < A1 )
706 amove[nmove++] = Drop(lance);
708 else if ( IsHandPawn(hand)
710 && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[to] ) )
711 && ! IsMateWPawnDrop( __ptree__, to ) )
713 amove[nmove++] = Drop(pawn);
718 if ( IsHandPawn(hand)
720 && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[to] ) )
721 && ! IsMateWPawnDrop( __ptree__, to ) )
723 amove[nmove++] = Drop(pawn);
725 if ( IsHandLance(hand) && to < A1 ) { amove[nmove++] = Drop(lance); }
726 if ( IsHandRook(hand) ) { amove[nmove++] = Drop(rook); }
729 if ( IsHandKnight(hand) && to < A2 ) { amove[nmove++] = Drop(knight); }
737 if ( IsHandRook(hand) ) { amove[nmove++] = Drop(rook); }
738 else if ( IsHandLance(hand) && to > I9 )
740 amove[nmove++] = Drop(lance);
742 else if ( IsHandPawn(hand)
744 && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[to] ) )
745 && ! IsMateBPawnDrop( __ptree__, to ) )
747 amove[nmove++] = Drop(pawn);
752 if ( IsHandPawn(hand)
754 && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[to] ) )
755 && ! IsMateBPawnDrop( __ptree__, to ) )
757 amove[nmove++] = Drop(pawn);
759 if ( IsHandLance(hand) && to > I9 ) { amove[nmove++] = Drop(lance); }
760 if ( IsHandRook(hand) ) { amove[nmove++] = Drop(rook); }
763 if ( IsHandKnight(hand) && to > I8 ) { amove[nmove++] = Drop(knight); }
766 if ( IsHandSilver(hand) ) { amove[nmove++] = Drop(silver); }
767 if ( IsHandGold(hand) ) { amove[nmove++] = Drop(gold); }
768 if ( IsHandBishop(hand) ) { amove[nmove++] = Drop(bishop); }
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 )
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]; }
785 else for ( i = 0; i < nmove; i++ ) { pmove[n0 + n1++] = amove[i]; }
789 return pmove + n0 + n1;