-#include <assert.h>\r
-#include "shogi.h"\r
-\r
-\r
-static bitboard_t add_behind_attacks( int idirec, int ik, bitboard_t bb );\r
-\r
-\r
-unsigned int *\r
-b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
-{\r
- bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
- bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
- const tree_t * restrict ptree = __ptree__;\r
- unsigned int u0, u1, u2;\r
- int from, to, sq_wk, idirec;\r
-\r
- sq_wk = SQ_WKING;\r
- bb_rook_chk = bb_file_chk = AttackFile( sq_wk );\r
- bb_rook_chk.p[aslide[sq_wk].ir0] |= AttackRank( sq_wk );\r
- bb_diag1_chk = AttackDiag1( sq_wk );\r
- bb_diag2_chk = AttackDiag2( sq_wk );\r
- BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );\r
- BBNot( bb_move_to, BB_BOCCUPY );\r
- BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
- BBNot( bb_drop_to, bb_drop_to );\r
-\r
- from = SQ_BKING;\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBIni( bb_chk );\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_BDRAGON;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- AttackDragon( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- bb_piece = BB_BHORSE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- AttackHorse( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- u1 = BB_BROOK.p[1];\r
- u2 = BB_BROOK.p[2];\r
- while( u1 | u2 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u1 ^= abb_mask[from].p[1];\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_rook_chk;\r
- bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[1] | bb_chk.p[2] )\r
- {\r
- to = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- u0 = BB_BROOK.p[0];\r
- while( u0 )\r
- {\r
- from = last_one0( u0 );\r
- u0 ^= abb_mask[from].p[0];\r
- \r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
- u1 = BB_BBISHOP.p[1];\r
- u2 = BB_BBISHOP.p[2];\r
- while( u1 | u2 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u1 ^= abb_mask[from].p[1];\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_bishop_chk;\r
- bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[1] | bb_chk.p[2] )\r
- {\r
- to = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
- u0 = BB_BBISHOP.p[0];\r
- while( u0 )\r
- {\r
- from = last_one0( u0 );\r
- u0 ^= abb_mask[from].p[0];\r
- \r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_BTGOLD;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_w_gold_attacks[sq_wk];\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = ( To2Move(to) | From2Move(from)\r
- | Piece2Move(BOARD[from])\r
- | Cap2Move(-BOARD[to]) );\r
- }\r
- }\r
- \r
-\r
- u0 = BB_BSILVER.p[0];\r
- while( u0 )\r
- {\r
- from = last_one0( u0 );\r
- u0 ^= abb_mask[from].p[0];\r
-\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];\r
- bb_chk.p[2] = 0;\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
- bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];\r
-\r
- while( bb_chk.p[0] | bb_chk.p[1] )\r
- {\r
- to = last_one01( bb_chk.p[0], bb_chk.p[1] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u1 = BB_BSILVER.p[1] & 0x7fc0000U;\r
- while( u1 )\r
- {\r
- from = last_one1( u1 );\r
- u1 ^= abb_mask[from].p[1];\r
- \r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = bb_chk.p[2] = 0;\r
- \r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
- while ( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- bb_piece = BB_BSILVER;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_w_silver_attacks[sq_wk];\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
- \r
-\r
- u0 = BB_BKNIGHT.p[0];\r
- u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;\r
- while( u0 | u1 )\r
- {\r
- from = last_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = bb_chk.p[2] = 0;\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];\r
-\r
- while( bb_chk.p[0] )\r
- {\r
- to = last_one0( bb_chk.p[0] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u2 = BB_BKNIGHT.p[2];\r
- u1 = BB_BKNIGHT.p[1] & 0x3ffffU;\r
- while( u2 | u1 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk = abb_w_knight_attacks[sq_wk];\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_BLANCE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- bb_chk.p[1] = bb_chk.p[2] = 0;\r
-\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u1 = BB_BLANCE.p[1];\r
- u2 = BB_BLANCE.p[2];\r
- while( u1| u2 )\r
- {\r
- from = last_one12( u1, u2 );\r
- u1 ^= abb_mask[from].p[1];\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- bb_chk = bb_file_chk;\r
- idirec = (int)adirec[sq_wk][from];\r
- if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
- }\r
- else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(-BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from - nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag1( from );\r
- if ( BBContract( bb_desti, BB_B_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
- if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = LastOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from - nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag2( from );\r
- if ( BBContract( bb_desti, BB_B_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
- if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBIni( bb_chk );\r
- bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
- if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );\r
- while ( BBToU(bb_chk) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
-\r
- from = to + nfile;\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
- if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
-\r
-\r
- if ( IsHandGold(HAND_B) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(gold);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandSilver(HAND_B) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(silver);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandKnight(HAND_B) && sq_wk < A2 )\r
- {\r
- to = sq_wk + 2*nfile - 1;\r
- if ( aifile[sq_wk] != file1 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
-\r
- to = sq_wk + 2*nfile + 1;\r
- if ( aifile[sq_wk] != file9 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandPawn(HAND_B)\r
- && sq_wk < A1\r
- && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )\r
- {\r
- to = sq_wk + nfile;\r
- if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(pawn);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandLance(HAND_B) )\r
- {\r
- unsigned int move;\r
- int dist, min_dist;\r
-\r
- if ( (int)aifile[sq_wk] == file1\r
- || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
- to += nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(lance);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandRook(HAND_B) )\r
- {\r
- unsigned int move;\r
- int file, dist, min_dist;\r
-\r
- if ( (int)aifile[sq_wk] == file1\r
- || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
- to += nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;\r
- file >= file1 && BOARD[to] == empty;\r
- file -= 1, to -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;\r
- file <= file9 && BOARD[to] == empty;\r
- file += 1, to += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
- to -= nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandBishop(HAND_B) )\r
- {\r
- unsigned int move;\r
- int file, rank, dist;\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
- file >= 0 && rank >= 0 && BOARD[to] == empty;\r
- to -= 10, file -= 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
- file <= file9 && rank >= 0 && BOARD[to] == empty;\r
- to -= 8, file += 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to += 8, file -= 1, rank += 1, dist = 1;\r
- file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
- to += 8, file -= 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_wk;\r
- file = (int)aifile[sq_wk];\r
- rank = (int)airank[sq_wk];\r
- for ( to += 10, file += 1, rank += 1, dist = 1;\r
- file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
- to += 10, file += 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- return pmove;\r
-}\r
-\r
-\r
-unsigned int *\r
-w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
-{\r
- bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
- bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
- const tree_t * restrict ptree = __ptree__;\r
- unsigned int u0, u1, u2;\r
- int from, to, sq_bk, idirec;\r
-\r
- sq_bk = SQ_BKING;\r
- bb_rook_chk = bb_file_chk = AttackFile( sq_bk );\r
- bb_rook_chk.p[aslide[sq_bk].ir0] |= AttackRank( sq_bk );\r
- bb_diag1_chk = AttackDiag1( sq_bk );\r
- bb_diag2_chk = AttackDiag2( sq_bk );\r
- AttackBishop( bb_bishop_chk, sq_bk );\r
- BBNot( bb_move_to, BB_WOCCUPY );\r
- BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
- BBNot( bb_drop_to, bb_drop_to );\r
-\r
-\r
- from = SQ_WKING;\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBIni( bb_chk );\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WDRAGON;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- AttackDragon( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = LastOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WHORSE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- AttackHorse( bb_desti, from );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- u0 = BB_WROOK.p[0];\r
- u1 = BB_WROOK.p[1];\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_rook_chk;\r
- bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[0] | bb_chk.p[1] )\r
- {\r
- to = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- u2 = BB_WROOK.p[2];\r
- while( u2 )\r
- {\r
- from = first_one2( u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- \r
- AttackRook( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
- u0 = BB_WBISHOP.p[0];\r
- u1 = BB_WBISHOP.p[1];\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- bb_chk = bb_bishop_chk;\r
- bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while ( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
-\r
- while( bb_chk.p[0] | bb_chk.p[1] )\r
- {\r
- to = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
- bb_chk.p[0] ^= abb_mask[to].p[0];\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- u2 = BB_WBISHOP.p[2];\r
- while( u2 )\r
- {\r
- from = first_one2( u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- \r
- AttackBishop( bb_desti, from );\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- BBAnd( bb_chk, bb_desti, bb_move_to );\r
- }\r
- else {\r
- BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
- BBAnd( bb_chk, bb_chk, bb_desti );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- }\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WTGOLD;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_b_gold_attacks[sq_bk];\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = ( To2Move(to) | From2Move(from)\r
- | Piece2Move(-BOARD[from])\r
- | Cap2Move(BOARD[to]) );\r
- }\r
- }\r
-\r
- \r
- u2 = BB_WSILVER.p[2];\r
- while( u2 )\r
- {\r
- from = first_one2( u2 );\r
- u2 ^= abb_mask[from].p[2];\r
-\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];\r
- bb_chk.p[0] = 0;\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
- bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];\r
-\r
- while( bb_chk.p[2] | bb_chk.p[1] )\r
- {\r
- to = first_one12( bb_chk.p[1], bb_chk.p[2] );\r
- bb_chk.p[1] ^= abb_mask[to].p[1];\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u1 = BB_WSILVER.p[1] & 0x1ffU;\r
- while( u1 )\r
- {\r
- from = first_one1( u1 );\r
- u1 ^= abb_mask[from].p[1];\r
- \r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = bb_chk.p[0] = 0;\r
- \r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
- while ( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- bb_piece = BB_WSILVER;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk = abb_b_silver_attacks[sq_bk];\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
- \r
- u2 = BB_WKNIGHT.p[2];\r
- u1 = BB_WKNIGHT.p[1] & 0x3ffffU;\r
- while( u2 | u1 )\r
- {\r
- from = first_one12( u1, u2 );\r
- u2 ^= abb_mask[from].p[2];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = bb_chk.p[0] = 0;\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];\r
-\r
- while( bb_chk.p[2] )\r
- {\r
- to = first_one2( bb_chk.p[2] );\r
- bb_chk.p[2] ^= abb_mask[to].p[2];\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u0 = BB_WKNIGHT.p[0];\r
- u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk = abb_b_knight_attacks[sq_bk];\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- bb_piece = BB_WLANCE;\r
- while( BBToU( bb_piece ) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
-\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- bb_chk.p[1] = bb_chk.p[0] = 0;\r
-\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- }\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
- }\r
- }\r
- \r
-\r
- u0 = BB_WLANCE.p[0];\r
- u1 = BB_WLANCE.p[1];\r
- while( u0 | u1 )\r
- {\r
- from = first_one01( u0, u1 );\r
- u0 ^= abb_mask[from].p[0];\r
- u1 ^= abb_mask[from].p[1];\r
-\r
- bb_chk = bb_file_chk;\r
- idirec = (int)adirec[sq_bk][from];\r
- if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
- {\r
- bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
- BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
- }\r
- else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }\r
-\r
- BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;\r
-\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
- | Cap2Move(BOARD[to]);\r
- }\r
- }\r
-\r
-\r
- BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from + nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag1( from );\r
- if ( BBContract( bb_desti, BB_W_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
- if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );\r
- while ( BBToU(bb_piece) )\r
- {\r
- from = FirstOne( bb_piece );\r
- Xor( from, bb_piece );\r
- \r
- to = from + nfile;\r
- if ( BOARD[to] != empty ) { continue; }\r
-\r
- bb_desti = AttackDiag2( from );\r
- if ( BBContract( bb_desti, BB_W_BH ) )\r
- {\r
- *pmove = To2Move(to) | From2Move(from)\r
- | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
- if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
- }\r
-\r
- BBIni( bb_chk );\r
- bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
- if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };\r
- BBAnd( bb_chk, bb_chk, bb_move_to );\r
- BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );\r
- while ( BBToU(bb_chk) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
-\r
- from = to - nfile;\r
- *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)\r
- | Cap2Move(BOARD[to]);\r
- if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
- pmove += 1;\r
- }\r
-\r
-\r
- if ( IsHandGold(HAND_W) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(gold);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandSilver(HAND_W) )\r
- {\r
- BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );\r
- while( BBToU( bb_chk ) )\r
- {\r
- to = FirstOne( bb_chk );\r
- Xor( to, bb_chk );\r
- *pmove++ = To2Move(to) | Drop2Move(silver);\r
- }\r
- }\r
- \r
-\r
- if ( IsHandKnight(HAND_W) && sq_bk > I8 )\r
- {\r
- to = sq_bk - 2*nfile - 1;\r
- if ( aifile[sq_bk] != file1 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
-\r
- to = sq_bk - 2*nfile + 1;\r
- if ( aifile[sq_bk] != file9 && BOARD[to] == empty )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(knight);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandPawn(HAND_W)\r
- && sq_bk > I9\r
- && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )\r
- {\r
- to = sq_bk - nfile;\r
- if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )\r
- {\r
- *pmove++ = To2Move(to) | Drop2Move(pawn);\r
- }\r
- }\r
-\r
-\r
- if ( IsHandLance(HAND_W) )\r
- {\r
- unsigned int move;\r
- int dist, min_dist;\r
-\r
- if ( (int)aifile[sq_bk] == file1\r
- || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
- to -= nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(lance);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandRook(HAND_W) )\r
- {\r
- unsigned int move;\r
- int file, dist, min_dist;\r
-\r
- if ( (int)aifile[sq_bk] == file1\r
- || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
- to -= nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
- to += nfile, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
-\r
- if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }\r
- else { min_dist = 3; }\r
-\r
- for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;\r
- file <= file9 && BOARD[to] == empty;\r
- file += 1, to += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;\r
- file >= file1 && BOARD[to] == empty;\r
- file -= 1, to -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(rook);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- if ( IsHandBishop(HAND_W) )\r
- {\r
- unsigned int move;\r
- int file, rank, dist;\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to += 10, file += 1, rank += 1, dist = 1;\r
- file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
- to += 10, file += 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to += 8, file -= 1, rank += 1, dist = 1;\r
- file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
- to += 8, file -= 1, rank += 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
- file <= file9 && rank >= 0 && BOARD[to] == empty;\r
- to -= 8, file += 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
-\r
- to = sq_bk;\r
- file = (int)aifile[sq_bk];\r
- rank = (int)airank[sq_bk];\r
- for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
- file >= 0 && rank >= 0 && BOARD[to] == empty;\r
- to -= 10, file -= 1, rank -= 1, dist += 1 )\r
- {\r
- move = To2Move(to) | Drop2Move(bishop);\r
- if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
- else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
- *pmove++ = move;\r
- }\r
- }\r
-\r
-\r
- return pmove;\r
-}\r
-\r
-\r
-static bitboard_t\r
-add_behind_attacks( int idirec, int ik, bitboard_t bb )\r
-{\r
- bitboard_t bb_tmp;\r
-\r
- if ( idirec == direc_diag1 )\r
- {\r
- bb_tmp = abb_bishop_attacks_rr45[ik][0];\r
- }\r
- else if ( idirec == direc_diag2 )\r
- {\r
- bb_tmp = abb_bishop_attacks_rl45[ik][0];\r
- }\r
- else if ( idirec == direc_file )\r
- {\r
- bb_tmp = abb_file_attacks[ik][0];\r
- }\r
- else {\r
- assert( idirec == direc_rank );\r
- BBIni( bb_tmp );\r
- bb_tmp.p[aslide[ik].ir0] = ai_rook_attacks_r0[ik][0];\r
- }\r
- BBNot( bb_tmp, bb_tmp );\r
- BBOr( bb, bb, bb_tmp );\r
-\r
- return bb;\r
-}\r
+#include <assert.h>
+#include "shogi.h"
+
+
+static void CONV add_behind_attacks( bitboard_t * restrict pbb, int idirec,
+ int ik );
+
+unsigned int * CONV
+b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_wk, idirec;
+
+ sq_wk = SQ_WKING;
+ bb_file_chk = AttackFile( sq_wk );
+ bb_rank_chk = AttackRank( sq_wk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_wk );
+ bb_diag2_chk = AttackDiag2( sq_wk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_BOCCUPY );
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+ from = SQ_BKING;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_BDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ bb_piece = BB_BHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ u1 = BB_BROOK.p[1];
+ u2 = BB_BROOK.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[1] | bb_chk.p[2] )
+ {
+ to = last_one12( bb_chk.p[1], bb_chk.p[2] );
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ u0 = BB_BROOK.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+ u1 = BB_BBISHOP.p[1];
+ u2 = BB_BBISHOP.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[1] | bb_chk.p[2] )
+ {
+ to = last_one12( bb_chk.p[1], bb_chk.p[2] );
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ u0 = BB_BBISHOP.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_BTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_gold_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = ( To2Move(to) | From2Move(from)
+ | Piece2Move(BOARD[from])
+ | Cap2Move(-BOARD[to]) );
+ }
+ }
+
+
+ u0 = BB_BSILVER.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
+ bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
+
+ while( bb_chk.p[0] | bb_chk.p[1] )
+ {
+ to = last_one01( bb_chk.p[0], bb_chk.p[1] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u1 = BB_BSILVER.p[1] & 0x7fc0000U;
+ while( u1 )
+ {
+ from = last_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+ while ( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_BSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_silver_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+
+ u0 = BB_BKNIGHT.p[0];
+ u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = last_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
+
+ while( bb_chk.p[0] )
+ {
+ to = last_one0( bb_chk.p[0] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u2 = BB_BKNIGHT.p[2];
+ u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = last_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_w_knight_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_BLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(-BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u1 = BB_BLANCE.p[1];
+ u2 = BB_BLANCE.p[2];
+ while( u1| u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(-BOARD[to]);
+ }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); }
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+ if ( BBContract( bb_desti, BB_B_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+ if ( BBContract( bb_desti, BB_B_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_B_RD ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ while ( BBTest(bb_chk) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+
+ from = to + nfile;
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(-BOARD[to]);
+ if ( from < A5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+
+
+ if ( IsHandGold(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(gold);
+ }
+ }
+
+
+ if ( IsHandSilver(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(silver);
+ }
+ }
+
+
+ if ( IsHandKnight(HAND_B) && sq_wk < A2 )
+ {
+ to = sq_wk + 2*nfile - 1;
+ if ( aifile[sq_wk] != file1 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+
+ to = sq_wk + 2*nfile + 1;
+ if ( aifile[sq_wk] != file9 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+ }
+
+
+ if ( IsHandPawn(HAND_B)
+ && sq_wk < A1
+ && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )
+ {
+ to = sq_wk + nfile;
+ if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(pawn);
+ }
+ }
+
+
+ if ( IsHandLance(HAND_B) )
+ {
+ unsigned int move;
+ int dist, min_dist;
+
+ if ( (int)aifile[sq_wk] == file1
+ || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+ to += nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(lance);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandRook(HAND_B) )
+ {
+ unsigned int move;
+ int file, dist, min_dist;
+
+ if ( (int)aifile[sq_wk] == file1
+ || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+ to += nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;
+ file >= file1 && BOARD[to] == empty;
+ file -= 1, to -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;
+ file <= file9 && BOARD[to] == empty;
+ file += 1, to += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+ to -= nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandBishop(HAND_B) )
+ {
+ unsigned int move;
+ int file, rank, dist;
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to -= 10, file -= 1, rank -= 1, dist = 1;
+ file >= 0 && rank >= 0 && BOARD[to] == empty;
+ to -= 10, file -= 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to -= 8, file += 1, rank -= 1, dist = 1;
+ file <= file9 && rank >= 0 && BOARD[to] == empty;
+ to -= 8, file += 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to += 8, file -= 1, rank += 1, dist = 1;
+ file >= 0 && rank <= rank9 && BOARD[to] == empty;
+ to += 8, file -= 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_wk;
+ file = (int)aifile[sq_wk];
+ rank = (int)airank[sq_wk];
+ for ( to += 10, file += 1, rank += 1, dist = 1;
+ file <= file9 && rank <= rank9 && BOARD[to] == empty;
+ to += 10, file += 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ return pmove;
+}
+
+
+unsigned int * CONV
+w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_bk, idirec;
+
+ sq_bk = SQ_BKING;
+ bb_file_chk = AttackFile( sq_bk );
+ bb_rank_chk = AttackRank( sq_bk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_bk );
+ bb_diag2_chk = AttackDiag2( sq_bk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_WOCCUPY );
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+
+ from = SQ_WKING;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_WDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = LastOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_WHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ u0 = BB_WROOK.p[0];
+ u1 = BB_WROOK.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[0] | bb_chk.p[1] )
+ {
+ to = first_one01( bb_chk.p[0], bb_chk.p[1] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ u2 = BB_WROOK.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+ u0 = BB_WBISHOP.p[0];
+ u1 = BB_WBISHOP.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while ( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+
+ while( bb_chk.p[0] | bb_chk.p[1] )
+ {
+ to = first_one01( bb_chk.p[0], bb_chk.p[1] );
+ bb_chk.p[0] ^= abb_mask[to].p[0];
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ u2 = BB_WBISHOP.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_WTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_gold_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = ( To2Move(to) | From2Move(from)
+ | Piece2Move(-BOARD[from])
+ | Cap2Move(BOARD[to]) );
+ }
+ }
+
+
+ u2 = BB_WSILVER.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
+ bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
+
+ while( bb_chk.p[2] | bb_chk.p[1] )
+ {
+ to = first_one12( bb_chk.p[1], bb_chk.p[2] );
+ bb_chk.p[1] ^= abb_mask[to].p[1];
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u1 = BB_WSILVER.p[1] & 0x1ffU;
+ while( u1 )
+ {
+ from = first_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+ while ( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ bb_piece = BB_WSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_silver_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ u2 = BB_WKNIGHT.p[2];
+ u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = first_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
+
+ while( bb_chk.p[2] )
+ {
+ to = first_one2( bb_chk.p[2] );
+ bb_chk.p[2] ^= abb_mask[to].p[2];
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u0 = BB_WKNIGHT.p[0];
+ u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_b_knight_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+
+ bb_piece = BB_WLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(BOARD[to]) | FLAG_PROMO;
+ }
+ }
+
+
+ u0 = BB_WLANCE.p[0];
+ u1 = BB_WLANCE.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
+
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)
+ | Cap2Move(BOARD[to]);
+ }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); }
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+ if ( BBContract( bb_desti, BB_W_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+ if ( BBContract( bb_desti, BB_W_BH ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_W_RD ) )
+ {
+ BBNotAnd( bb_chk, bb_chk, abb_mask[to] );
+
+ *pmove = To2Move(to) | From2Move(from)
+ | Piece2Move(pawn) | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+ }
+
+ while ( BBTest(bb_chk) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+
+ from = to - nfile;
+ *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)
+ | Cap2Move(BOARD[to]);
+ if ( from > I5 ) { *pmove |= FLAG_PROMO; }
+ pmove += 1;
+ }
+
+
+ if ( IsHandGold(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(gold);
+ }
+ }
+
+
+ if ( IsHandSilver(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
+ while( BBTest( bb_chk ) )
+ {
+ to = FirstOne( bb_chk );
+ Xor( to, bb_chk );
+ *pmove++ = To2Move(to) | Drop2Move(silver);
+ }
+ }
+
+
+ if ( IsHandKnight(HAND_W) && sq_bk > I8 )
+ {
+ to = sq_bk - 2*nfile - 1;
+ if ( aifile[sq_bk] != file1 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+
+ to = sq_bk - 2*nfile + 1;
+ if ( aifile[sq_bk] != file9 && BOARD[to] == empty )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(knight);
+ }
+ }
+
+
+ if ( IsHandPawn(HAND_W)
+ && sq_bk > I9
+ && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )
+ {
+ to = sq_bk - nfile;
+ if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )
+ {
+ *pmove++ = To2Move(to) | Drop2Move(pawn);
+ }
+ }
+
+
+ if ( IsHandLance(HAND_W) )
+ {
+ unsigned int move;
+ int dist, min_dist;
+
+ if ( (int)aifile[sq_bk] == file1
+ || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+ to -= nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(lance);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandRook(HAND_W) )
+ {
+ unsigned int move;
+ int file, dist, min_dist;
+
+ if ( (int)aifile[sq_bk] == file1
+ || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;
+ to -= nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;
+ to += nfile, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+
+ if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }
+ else { min_dist = 3; }
+
+ for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;
+ file <= file9 && BOARD[to] == empty;
+ file += 1, to += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;
+ file >= file1 && BOARD[to] == empty;
+ file -= 1, to -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(rook);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ if ( IsHandBishop(HAND_W) )
+ {
+ unsigned int move;
+ int file, rank, dist;
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to += 10, file += 1, rank += 1, dist = 1;
+ file <= file9 && rank <= rank9 && BOARD[to] == empty;
+ to += 10, file += 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to += 8, file -= 1, rank += 1, dist = 1;
+ file >= 0 && rank <= rank9 && BOARD[to] == empty;
+ to += 8, file -= 1, rank += 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to -= 8, file += 1, rank -= 1, dist = 1;
+ file <= file9 && rank >= 0 && BOARD[to] == empty;
+ to -= 8, file += 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+
+ to = sq_bk;
+ file = (int)aifile[sq_bk];
+ rank = (int)airank[sq_bk];
+ for ( to -= 10, file -= 1, rank -= 1, dist = 1;
+ file >= 0 && rank >= 0 && BOARD[to] == empty;
+ to -= 10, file -= 1, rank -= 1, dist += 1 )
+ {
+ move = To2Move(to) | Drop2Move(bishop);
+ if ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }
+ else if ( dist > 2 ) { move |= MOVE_CHK_SET; }
+ *pmove++ = move;
+ }
+ }
+
+
+ return pmove;
+}
+
+
+int CONV b_have_checks( tree_t * restrict __ptree__ )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_wk, idirec;
+
+ sq_wk = SQ_WKING;
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+ if ( IsHandGold(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandSilver(HAND_B) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandKnight(HAND_B) && sq_wk < A2 )
+ {
+ if ( aifile[sq_wk] != file1
+ && BOARD[sq_wk + 2*nfile - 1] == empty ) { return 1; }
+
+ if ( aifile[sq_wk] != file9
+ && BOARD[sq_wk + 2*nfile + 1] == empty ) { return 1; }
+ }
+
+ if ( IsHandLance(HAND_B)
+ && sq_wk + nfile < nsquare
+ && BOARD[sq_wk + nfile] == empty ) { return 1; }
+
+ if ( IsHandRook(HAND_B) )
+ {
+ if ( sq_wk + nfile < nsquare
+ && BOARD[sq_wk + nfile] == empty ) { return 1; }
+
+ if ( file1 < (int)aifile[sq_wk]
+ && BOARD[sq_wk - 1] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_wk] < file9
+ && BOARD[sq_wk + 1] == empty ) { return 1; }
+
+ if ( 0 <= sq_wk - nfile
+ && BOARD[sq_wk - nfile] == empty ) { return 1; }
+ }
+
+ if ( IsHandBishop(HAND_B) )
+ {
+ if ( 0 < (int)aifile[sq_wk]
+ && 0 < (int)airank[sq_wk]
+ && BOARD[sq_wk - 10] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_wk] < file9
+ && 0 < (int)airank[sq_wk]
+ && BOARD[sq_wk - 8] == empty ) { return 1; }
+
+ if ( 0 < (int)aifile[sq_wk]
+ && (int)airank[sq_wk] < rank9
+ && BOARD[sq_wk + 8] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_wk] < file9
+ && (int)airank[sq_wk] < rank9
+ && BOARD[sq_wk + 10] == empty ) { return 1; }
+ }
+
+ if ( IsHandPawn(HAND_B)
+ && sq_wk < A1
+ && BOARD[sq_wk+nfile] == empty
+ && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) )
+ && ! is_mate_b_pawn_drop( __ptree__, sq_wk+nfile ) )
+ {
+ return 1;
+ }
+
+
+ bb_file_chk = AttackFile( sq_wk );
+ bb_rank_chk = AttackRank( sq_wk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_wk );
+ bb_diag2_chk = AttackDiag2( sq_wk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_BOCCUPY );
+
+ from = SQ_BKING;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_BDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ bb_piece = BB_BHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u1 = BB_BROOK.p[1];
+ u2 = BB_BROOK.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_BROOK.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u1 = BB_BBISHOP.p[1];
+ u2 = BB_BBISHOP.p[2];
+ while( u1 | u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_BBISHOP.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_BTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_gold_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u0 = BB_BSILVER.p[0];
+ while( u0 )
+ {
+ from = last_one0( u0 );
+ u0 ^= abb_mask[from].p[0];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];
+ bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];
+
+ if ( bb_chk.p[0] | bb_chk.p[1] ) { return 1; }
+ }
+
+
+ u1 = BB_BSILVER.p[1] & 0x7fc0000U;
+ while( u1 )
+ {
+ from = last_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];
+
+ if ( bb_chk.p[0] ) { return 1; }
+ }
+
+
+ bb_piece = BB_BSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_w_silver_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u0 = BB_BKNIGHT.p[0];
+ u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = last_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];
+
+ if ( bb_chk.p[0] ) { return 1; }
+ }
+
+
+ u2 = BB_BKNIGHT.p[2];
+ u1 = BB_BKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = last_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_w_knight_attacks[sq_wk];
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_BLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ bb_chk.p[1] = bb_chk.p[2] = 0;
+
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u1 = BB_BLANCE.p[1];
+ u2 = BB_BLANCE.p[2];
+ while( u1| u2 )
+ {
+ from = last_one12( u1, u2 );
+ u1 ^= abb_mask[from].p[1];
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_wk][from];
+ if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_wk );
+ BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];
+ if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );
+ if ( BBTest(bb_chk) ) { return 1; }
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+
+ if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+
+ if ( BBContract( bb_desti, BB_B_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_BPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = LastOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from - nfile;
+ if ( BOARD[to] > 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_B_RD ) ) { return 1; }
+ }
+
+ return 0;
+}
+
+
+int CONV w_have_checks( tree_t * restrict __ptree__ )
+{
+ bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;
+ bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;
+ bitboard_t bb_rank_chk;
+ const tree_t * restrict ptree = __ptree__;
+ unsigned int u0, u1, u2;
+ int from, to, sq_bk, idirec;
+
+ sq_bk = SQ_BKING;
+ BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );
+ BBNot( bb_drop_to, bb_drop_to );
+
+ if ( IsHandGold(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandSilver(HAND_W) )
+ {
+ BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ if ( IsHandKnight(HAND_W) && sq_bk > I8 )
+ {
+ if ( aifile[sq_bk] != file1
+ && BOARD[sq_bk - 2*nfile - 1] == empty ) { return 1; }
+
+ if ( aifile[sq_bk] != file9
+ && BOARD[sq_bk - 2*nfile + 1] == empty ) { return 1; }
+ }
+
+ if ( IsHandLance(HAND_W)
+ && 0 <= sq_bk - nfile
+ && BOARD[sq_bk - nfile] == empty ) { return 1; }
+
+ if ( IsHandRook(HAND_W) )
+ {
+ if ( sq_bk + nfile < nsquare
+ && BOARD[sq_bk + nfile] == empty ) { return 1; }
+
+ if ( file1 < (int)aifile[sq_bk]
+ && BOARD[sq_bk - 1] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_bk] < file9
+ && BOARD[sq_bk + 1] == empty ) { return 1; }
+
+ if ( 0 <= sq_bk - nfile
+ && BOARD[sq_bk - nfile] == empty ) { return 1; }
+ }
+
+ if ( IsHandBishop(HAND_W) )
+ {
+ if ( 0 < (int)aifile[sq_bk]
+ && 0 < (int)airank[sq_bk]
+ && BOARD[sq_bk - 10] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_bk] < file9
+ && 0 < (int)airank[sq_bk]
+ && BOARD[sq_bk - 8] == empty ) { return 1; }
+
+ if ( 0 < (int)aifile[sq_bk]
+ && (int)airank[sq_bk] < rank9
+ && BOARD[sq_bk + 8] == empty ) { return 1; }
+
+ if ( (int)aifile[sq_bk] < file9
+ && (int)airank[sq_bk] < rank9
+ && BOARD[sq_bk + 10] == empty ) { return 1; }
+ }
+
+ if ( IsHandPawn(HAND_W)
+ && sq_bk > I9
+ && BOARD[sq_bk - nfile] == empty
+ && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) )
+ && ! is_mate_w_pawn_drop( __ptree__, sq_bk - nfile ) )
+ {
+ return 1;
+ }
+
+
+ bb_file_chk = AttackFile( sq_bk );
+ bb_rank_chk = AttackRank( sq_bk );
+ BBOr( bb_rook_chk, bb_file_chk, bb_rank_chk );
+
+ bb_diag1_chk = AttackDiag1( sq_bk );
+ bb_diag2_chk = AttackDiag2( sq_bk );
+ BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );
+ BBNot( bb_move_to, BB_WOCCUPY );
+
+
+ from = SQ_WKING;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBIni( bb_chk );
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WDRAGON;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackDragon( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WHORSE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ AttackHorse( bb_desti, from );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_WROOK.p[0];
+ u1 = BB_WROOK.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_rook_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u2 = BB_WROOK.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackRook( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u0 = BB_WBISHOP.p[0];
+ u1 = BB_WBISHOP.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ bb_chk = bb_bishop_chk;
+ bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ u2 = BB_WBISHOP.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ AttackBishop( bb_desti, from );
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ BBAnd( bb_chk, bb_desti, bb_move_to );
+ }
+ else {
+ BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );
+ BBAnd( bb_chk, bb_chk, bb_desti );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ }
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WTGOLD;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_gold_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u2 = BB_WSILVER.p[2];
+ while( u2 )
+ {
+ from = first_one2( u2 );
+ u2 ^= abb_mask[from].p[2];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];
+ bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+ bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];
+
+ if ( bb_chk.p[2] | bb_chk.p[1] ) { return 1; }
+ }
+
+
+ u1 = BB_WSILVER.p[1] & 0x1ffU;
+ while( u1 )
+ {
+ from = first_one1( u1 );
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];
+
+ if ( bb_chk.p[2] ) { return 1; }
+ }
+
+
+ bb_piece = BB_WSILVER;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk = abb_b_silver_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u2 = BB_WKNIGHT.p[2];
+ u1 = BB_WKNIGHT.p[1] & 0x3ffffU;
+ while( u2 | u1 )
+ {
+ from = first_one12( u1, u2 );
+ u2 ^= abb_mask[from].p[2];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];
+
+ if ( bb_chk.p[2] ) { return 1; }
+ }
+
+
+ u0 = BB_WKNIGHT.p[0];
+ u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = abb_b_knight_attacks[sq_bk];
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ bb_piece = BB_WLANCE;
+ while( BBTest( bb_piece ) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ bb_chk.p[1] = bb_chk.p[0] = 0;
+
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+
+ u0 = BB_WLANCE.p[0];
+ u1 = BB_WLANCE.p[1];
+ while( u0 | u1 )
+ {
+ from = first_one01( u0, u1 );
+ u0 ^= abb_mask[from].p[0];
+ u1 ^= abb_mask[from].p[1];
+
+ bb_chk = bb_file_chk;
+ idirec = (int)adirec[sq_bk][from];
+ if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )
+ {
+ add_behind_attacks( &bb_chk, idirec, sq_bk );
+ BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );
+ }
+ else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }
+
+ BBAnd( bb_chk, bb_chk, AttackFile( from ) );
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;
+
+ if ( BBTest( bb_chk ) ) { return 1; }
+ }
+
+ BBIni( bb_chk );
+ bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];
+ if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };
+ BBAnd( bb_chk, bb_chk, bb_move_to );
+ BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );
+ if ( BBTest( bb_chk ) ) { return 1; }
+
+ BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag1( from );
+
+ if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackDiag2( from );
+
+ if ( BBContract( bb_desti, BB_W_BH ) ) { return 1; }
+ }
+
+ BBAnd( bb_piece, bb_rank_chk, BB_WPAWN );
+ while ( BBTest(bb_piece) )
+ {
+ from = FirstOne( bb_piece );
+ Xor( from, bb_piece );
+
+ to = from + nfile;
+ if ( BOARD[to] < 0 ) { continue; }
+
+ bb_desti = AttackRank( from );
+ if ( BBContract( bb_desti, BB_W_RD ) ) { return 1; }
+ }
+
+ return 0;
+}
+
+
+static void CONV
+add_behind_attacks( bitboard_t * restrict pbb, int idirec, int ik )
+{
+ bitboard_t bb_tmp;
+
+ if ( idirec == direc_diag1 )
+ {
+ bb_tmp = abb_bishop_attacks_rr45[ik][0];
+ }
+ else if ( idirec == direc_diag2 )
+ {
+ bb_tmp = abb_bishop_attacks_rl45[ik][0];
+ }
+ else if ( idirec == direc_file )
+ {
+ bb_tmp = abb_file_attacks[ik][0];
+ }
+ else {
+ assert( idirec == direc_rank );
+ bb_tmp = abb_rank_attacks[ik][0];
+ }
+ BBNot( bb_tmp, bb_tmp );
+ BBOr( *pbb, *pbb, bb_tmp );
+}