7 b_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove )
9 bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
10 unsigned int hand, ubb_target0a, ubb_target0b, ubb_pawn_cmp, utemp;
11 unsigned ais_pawn[nfile];
12 int nchecker, sq_bk, to, sq_check, idirec;
13 int nhand, i, nolance, noknight, from;
19 Xor( sq_bk, BB_BOCCUPY );
20 XorFile( sq_bk, OCCUPIED_FILE );
21 XorDiag2( sq_bk, OCCUPIED_DIAG2 );
22 XorDiag1( sq_bk, OCCUPIED_DIAG1 );
24 BBNotAnd( bb_desti, abb_king_attacks[sq_bk], BB_BOCCUPY );
25 utemp = From2Move(sq_bk) | Piece2Move(king);
26 while ( BBTest( bb_desti ) )
28 to = LastOne( bb_desti );
29 if ( ! is_black_attacked( ptree, to ) )
31 *pmove++ = To2Move(to) | Cap2Move(-BOARD[to]) | utemp;
36 Xor( sq_bk, BB_BOCCUPY );
37 XorFile( sq_bk, OCCUPIED_FILE );
38 XorDiag2( sq_bk, OCCUPIED_DIAG2 );
39 XorDiag1( sq_bk, OCCUPIED_DIAG1 );
41 bb_checker = w_attacks_to_piece( ptree, sq_bk );
42 nchecker = PopuCount( bb_checker );
43 if ( nchecker == 2 ) { return pmove; }
45 sq_check = LastOne( bb_checker );
46 bb_inter = abb_obstacle[sq_bk][sq_check];
48 /* move other pieces */
49 BBOr( bb_target, bb_inter, bb_checker );
51 BBAnd( bb_desti, bb_target, BB_BPAWN_ATK );
52 while ( BBTest( bb_desti ) )
54 to = LastOne( bb_desti );
58 idirec = (int)adirec[sq_bk][from];
59 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
61 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(pawn)
62 | Cap2Move(-BOARD[to]) );
63 if ( to < A6 ) { utemp |= FLAG_PROMO; }
69 while ( BBTest( bb_piece ) )
71 from = LastOne( bb_piece );
72 Xor( from, bb_piece );
74 bb_desti = AttackFile( from );
75 BBAnd( bb_desti, bb_desti, abb_minus_rays[from] );
76 BBAnd( bb_desti, bb_desti, bb_target );
77 if ( ! BBTest( bb_desti ) ) { continue; }
79 idirec = (int)adirec[sq_bk][from];
80 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
82 to = LastOne( bb_desti );
84 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(lance)
85 | Cap2Move(-BOARD[to]) );
86 if ( to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
87 if ( to >= A7 ) { *pmove++ = utemp; }
91 bb_piece = BB_BKNIGHT;
92 while ( BBTest( bb_piece ) )
94 from = LastOne( bb_piece );
95 Xor( from, bb_piece );
97 BBAnd( bb_desti, bb_target, abb_b_knight_attacks[from] );
98 if ( ! BBTest( bb_desti ) ) { continue; }
100 idirec = (int)adirec[sq_bk][from];
101 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
103 to = LastOne( bb_desti );
106 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(knight)
107 | Cap2Move(-BOARD[to]) );
108 if ( to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
109 if ( to >= A7 ) { *pmove++ = utemp; }
111 } while ( BBTest( bb_desti ) );
114 bb_piece = BB_BSILVER;
115 while ( BBTest( bb_piece ) )
117 from = LastOne( bb_piece );
118 Xor( from, bb_piece );
120 BBAnd( bb_desti, bb_target, abb_b_silver_attacks[from] );
121 if ( ! BBTest( bb_desti ) ) { continue; }
123 idirec = (int)adirec[sq_bk][from];
124 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
126 to = LastOne( bb_desti );
128 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(silver)
129 | Cap2Move(-BOARD[to]) );
130 if ( from < A6 || to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
132 } while ( BBTest( bb_desti ) );
135 bb_piece = BB_BTGOLD;
136 while( BBTest( bb_piece ) )
138 from = LastOne( bb_piece );
139 Xor( from, bb_piece );
141 BBAnd( bb_desti, bb_target, abb_b_gold_attacks[from] );
142 if ( ! BBTest(bb_desti) ) { continue; }
144 idirec = (int)adirec[sq_bk][from];
145 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
147 to = LastOne( bb_desti );
149 *pmove++ = ( To2Move(to) | From2Move(from)
150 | Piece2Move(BOARD[from])
151 | Cap2Move(-BOARD[to]) );
152 } while( BBTest( bb_desti ) );
155 bb_piece = BB_BBISHOP;
156 while ( BBTest( bb_piece ) )
158 from = LastOne( bb_piece );
159 Xor( from, bb_piece );
161 AttackBishop( bb_desti, from );
162 BBAnd( bb_desti, bb_desti, bb_target );
163 if ( ! BBTest( bb_desti ) ) { continue; }
164 idirec = (int)adirec[sq_bk][from];
165 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
167 to = LastOne( bb_desti );
170 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(bishop)
171 | Cap2Move(-BOARD[to]) );
172 if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
174 } while ( BBTest( bb_desti ) );
178 while ( BBTest( bb_piece ) )
180 from = LastOne( bb_piece );
181 Xor( from, bb_piece );
183 AttackRook( bb_desti, from );
184 BBAnd( bb_desti, bb_desti, bb_target );
185 if ( ! BBTest( bb_desti ) ) { continue; }
186 idirec = (int)adirec[sq_bk][from];
187 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
189 to = LastOne( bb_desti );
192 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(rook)
193 | Cap2Move(-BOARD[to]) );
194 if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
196 } while ( BBTest( bb_desti ) );
199 bb_piece = BB_BHORSE;
200 while( BBTest( bb_piece ) )
202 from = LastOne( bb_piece );
203 Xor( from, bb_piece );
205 AttackHorse( bb_desti, from );
206 BBAnd( bb_desti, bb_desti, bb_target );
207 if ( ! BBTest(bb_desti) ) { continue; }
209 idirec = (int)adirec[sq_bk][from];
210 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
212 to = LastOne( bb_desti );
214 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
215 | Cap2Move(-BOARD[to]) );
216 } while ( BBTest( bb_desti ) );
219 bb_piece = BB_BDRAGON;
220 while( BBTest( bb_piece ) )
222 from = LastOne( bb_piece );
223 Xor( from, bb_piece );
225 AttackDragon( bb_desti, from );
226 BBAnd( bb_desti, bb_desti, bb_target );
227 if ( ! BBTest(bb_desti) ) { continue; }
229 idirec = (int)adirec[sq_bk][from];
230 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
232 to = LastOne( bb_desti );
234 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
235 | Cap2Move(-BOARD[to]) );
236 } while ( BBTest( bb_desti ) );
239 if ( ! HAND_B ) { return pmove; }
240 if ( ! BBTest(bb_inter) ) { return pmove; }
243 bb_target = bb_inter;
244 ubb_target0a = bb_target.p[0] & 0x7fc0000U;
245 ubb_target0b = bb_target.p[0] & 0x003fe00U;
246 bb_target.p[0] &= 0x00001ffU;
247 bb_target.p[1] &= 0x7ffffffU;
248 bb_target.p[2] &= 0x7ffffffU;
252 if ( IsHandKnight( hand ) ) { ahand[ nhand++ ] = Drop2Move(knight); }
254 if ( IsHandLance( hand ) ) { ahand[ nhand++ ] = Drop2Move(lance); }
256 if ( IsHandSilver( hand ) ) { ahand[ nhand++ ] = Drop2Move(silver); }
257 if ( IsHandGold( hand ) ) { ahand[ nhand++ ] = Drop2Move(gold); }
258 if ( IsHandBishop( hand ) ) { ahand[ nhand++ ] = Drop2Move(bishop); }
259 if ( IsHandRook( hand ) ) { ahand[ nhand++ ] = Drop2Move(rook); }
261 if ( IsHandPawn( hand ) )
263 ubb_pawn_cmp= BBToU( BB_BPAWN_ATK );
264 ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
265 ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
266 ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
267 ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
268 ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
269 ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
270 ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
271 ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
272 ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
274 while ( BBTest( bb_target ) )
276 to = LastOne( bb_target );
278 if ( ! ais_pawn[aifile[to]] && ! IsMateBPawnDrop( ptree, to ) )
280 *pmove++ = utemp | Drop2Move(pawn);
282 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
283 Xor( to, bb_target );
286 while ( ubb_target0b )
288 to = last_one0( ubb_target0b );
290 if ( ! ais_pawn[aifile[to]] && ! IsMateBPawnDrop( ptree, to ) )
292 *pmove++ = utemp | Drop2Move(pawn);
294 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
295 ubb_target0b ^= abb_mask[ to ].p[0];
299 while ( BBTest( bb_target ) )
301 to = LastOne( bb_target );
303 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
304 Xor( to, bb_target );
307 while ( ubb_target0b )
309 to = last_one0( ubb_target0b );
311 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
312 ubb_target0b ^= abb_mask[ to ].p[0];
316 while ( ubb_target0a )
318 to = last_one0( ubb_target0a );
320 for ( i = nolance; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
321 ubb_target0a ^= abb_mask[ to ].p[0];
329 w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove )
331 bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
332 unsigned int hand, ubb_target2a, ubb_target2b, ubb_pawn_cmp, utemp;
333 unsigned int ais_pawn[nfile];
334 int nchecker, sq_wk, to, sq_check, idirec;
335 int nhand, i, nolance, noknight, from;
341 Xor( sq_wk, BB_WOCCUPY );
342 XorFile( sq_wk, OCCUPIED_FILE );
343 XorDiag2( sq_wk, OCCUPIED_DIAG2 );
344 XorDiag1( sq_wk, OCCUPIED_DIAG1 );
346 BBNotAnd( bb_desti, abb_king_attacks[sq_wk], BB_WOCCUPY );
347 utemp = From2Move(sq_wk) | Piece2Move(king);
348 while ( BBTest( bb_desti ) )
350 to = FirstOne( bb_desti );
351 if ( ! is_white_attacked( ptree, to ) )
353 *pmove++ = To2Move(to) | Cap2Move(BOARD[to]) | utemp;
358 Xor( sq_wk, BB_WOCCUPY );
359 XorFile( sq_wk, OCCUPIED_FILE );
360 XorDiag2( sq_wk, OCCUPIED_DIAG2 );
361 XorDiag1( sq_wk, OCCUPIED_DIAG1 );
363 bb_checker = b_attacks_to_piece( ptree, sq_wk );
364 nchecker = PopuCount( bb_checker );
365 if ( nchecker == 2 ) { return pmove; }
367 sq_check = FirstOne( bb_checker );
368 bb_inter = abb_obstacle[sq_wk][sq_check];
370 /* move other pieces */
371 BBOr( bb_target, bb_inter, bb_checker );
373 BBAnd( bb_desti, bb_target, BB_WPAWN_ATK );
374 while ( BBTest( bb_desti ) )
376 to = FirstOne( bb_desti );
380 idirec = (int)adirec[sq_wk][from];
381 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
383 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(pawn)
384 | Cap2Move(BOARD[to]) );
385 if ( to > I4 ) { utemp |= FLAG_PROMO; }
390 bb_piece = BB_WLANCE;
391 while ( BBTest( bb_piece ) )
393 from = FirstOne( bb_piece );
394 Xor( from, bb_piece );
396 bb_desti = AttackFile( from );
397 BBAnd( bb_desti, bb_desti, abb_plus_rays[from] );
398 BBAnd( bb_desti, bb_desti, bb_target );
399 if ( ! BBTest( bb_desti ) ) { continue; }
401 idirec = (int)adirec[sq_wk][from];
402 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
404 to = FirstOne( bb_desti );
406 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(lance)
407 | Cap2Move(BOARD[to]) );
408 if ( to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
409 if ( to <= I3 ) { *pmove++ = utemp; }
413 bb_piece = BB_WKNIGHT;
414 while ( BBTest( bb_piece ) )
416 from = FirstOne( bb_piece );
417 Xor( from, bb_piece );
419 BBAnd( bb_desti, bb_target, abb_w_knight_attacks[from] );
420 if ( ! BBTest( bb_desti ) ) { continue; }
422 idirec = (int)adirec[sq_wk][from];
423 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
425 to = FirstOne( bb_desti );
428 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(knight)
429 | Cap2Move(BOARD[to]) );
430 if ( to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
431 if ( to <= I3 ) { *pmove++ = utemp; }
432 } while ( BBTest( bb_desti ) );
435 bb_piece = BB_WSILVER;
436 while ( BBTest( bb_piece ) )
438 from = FirstOne( bb_piece );
439 Xor( from, bb_piece );
441 BBAnd( bb_desti, bb_target, abb_w_silver_attacks[from] );
442 if ( ! BBTest( bb_desti ) ) { continue; }
444 idirec = (int)adirec[sq_wk][from];
445 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
447 to = FirstOne( bb_desti );
449 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(silver)
450 | Cap2Move(BOARD[to]) );
451 if ( from > I4 || to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
453 } while ( BBTest( bb_desti ) );
456 bb_piece = BB_WTGOLD;
457 while( BBTest( bb_piece ) )
459 from = FirstOne( bb_piece );
460 Xor( from, bb_piece );
462 BBAnd( bb_desti, bb_target, abb_w_gold_attacks[from] );
463 if ( ! BBTest(bb_desti) ) { continue; }
465 idirec = (int)adirec[sq_wk][from];
466 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
468 to = FirstOne( bb_desti );
470 *pmove++ = ( To2Move(to) | From2Move(from)
471 | Piece2Move(-BOARD[from])
472 | Cap2Move(BOARD[to]) );
473 } while( BBTest( bb_desti ) );
476 bb_piece = BB_WBISHOP;
477 while ( BBTest( bb_piece ) )
479 from = FirstOne( bb_piece );
480 Xor( from, bb_piece );
482 AttackBishop( bb_desti, from );
483 BBAnd( bb_desti, bb_desti, bb_target );
484 if ( ! BBTest( bb_desti ) ) { continue; }
486 idirec = (int)adirec[sq_wk][from];
487 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
489 to = FirstOne( bb_desti );
492 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(bishop)
493 | Cap2Move(BOARD[to]) );
494 if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
496 } while ( BBTest( bb_desti ) );
500 while ( BBTest( bb_piece ) )
502 from = FirstOne( bb_piece );
503 Xor( from, bb_piece );
505 AttackRook( bb_desti, from );
506 BBAnd( bb_desti, bb_desti, bb_target );
507 if ( ! BBTest( bb_desti ) ) { continue; }
508 idirec = (int)adirec[sq_wk][from];
509 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
511 to = FirstOne( bb_desti );
514 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(rook)
515 | Cap2Move(BOARD[to]) );
516 if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
518 } while ( BBTest( bb_desti ) );
521 bb_piece = BB_WHORSE;
522 while( BBTest( bb_piece ) )
524 from = FirstOne( bb_piece );
525 Xor( from, bb_piece );
527 AttackHorse( bb_desti, from );
528 BBAnd( bb_desti, bb_desti, bb_target );
529 if ( ! BBTest(bb_desti) ) { continue; }
531 idirec = (int)adirec[sq_wk][from];
532 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
534 to = FirstOne( bb_desti );
536 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
537 | Cap2Move(BOARD[to]) );
538 } while ( BBTest( bb_desti ) );
541 bb_piece = BB_WDRAGON;
542 while( BBTest( bb_piece ) )
544 from = FirstOne( bb_piece );
545 Xor( from, bb_piece );
547 AttackDragon( bb_desti, from );
548 BBAnd( bb_desti, bb_desti, bb_target );
549 if ( ! BBTest(bb_desti) ) { continue; }
551 idirec = (int)adirec[sq_wk][from];
552 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
554 to = FirstOne( bb_desti );
556 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
557 | Cap2Move(BOARD[to]) );
558 } while ( BBTest( bb_desti ) );
561 if ( ! HAND_W ) { return pmove; }
562 if ( ! BBTest(bb_inter) ) { return pmove; }
565 bb_target = bb_inter;
566 ubb_target2a = bb_target.p[2] & 0x00001ffU;
567 ubb_target2b = bb_target.p[2] & 0x003fe00U;
568 bb_target.p[0] &= 0x7ffffffU;
569 bb_target.p[1] &= 0x7ffffffU;
570 bb_target.p[2] &= 0x7fc0000U;
574 if ( IsHandKnight( hand ) ) { ahand[ nhand++ ] = Drop2Move(knight); }
576 if ( IsHandLance( hand ) ) { ahand[ nhand++ ] = Drop2Move(lance); }
578 if ( IsHandSilver( hand ) ) { ahand[ nhand++ ] = Drop2Move(silver); }
579 if ( IsHandGold( hand ) ) { ahand[ nhand++ ] = Drop2Move(gold); }
580 if ( IsHandBishop( hand ) ) { ahand[ nhand++ ] = Drop2Move(bishop); }
581 if ( IsHandRook( hand ) ) { ahand[ nhand++ ] = Drop2Move(rook); }
583 if ( IsHandPawn( hand ) )
585 ubb_pawn_cmp= BBToU( BB_WPAWN_ATK );
586 ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
587 ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
588 ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
589 ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
590 ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
591 ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
592 ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
593 ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
594 ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
596 while ( BBTest( bb_target ) )
598 to = FirstOne( bb_target );
600 if ( ! ais_pawn[aifile[to]] && ! IsMateWPawnDrop( ptree, to ) )
602 *pmove++ = utemp | Drop2Move(pawn);
604 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
605 Xor( to, bb_target );
608 while ( ubb_target2b )
610 to = first_one2( ubb_target2b );
612 if ( ! ais_pawn[aifile[to]] && ! IsMateWPawnDrop( ptree, to ) )
614 *pmove++ = utemp | Drop2Move(pawn);
616 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
617 ubb_target2b ^= abb_mask[ to ].p[2];
621 while ( BBTest( bb_target ) )
623 to = FirstOne( bb_target );
625 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
626 Xor( to, bb_target );
629 while ( ubb_target2b )
631 to = first_one2( ubb_target2b );
633 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
634 ubb_target2b ^= abb_mask[ to ].p[2];
638 while ( ubb_target2a )
640 to = first_one2( ubb_target2a );
642 for ( i = nolance; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
643 ubb_target2a ^= abb_mask[ to ].p[2];
650 int CONV b_have_evasion( tree_t * restrict ptree )
652 bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
653 unsigned int ubb_pawn_cmp;
654 unsigned int ais_pawn[nfile];
655 int nchecker, sq_bk, to, sq_check, idirec, flag, from;
661 Xor( sq_bk, BB_BOCCUPY );
662 XorFile( sq_bk, OCCUPIED_FILE );
663 XorDiag2( sq_bk, OCCUPIED_DIAG2 );
664 XorDiag1( sq_bk, OCCUPIED_DIAG1 );
666 BBNotAnd( bb_desti, abb_king_attacks[sq_bk], BB_BOCCUPY );
668 while ( BBTest( bb_desti ) )
670 to = LastOne( bb_desti );
673 if ( ! is_black_attacked( ptree, to ) )
680 Xor( sq_bk, BB_BOCCUPY );
681 XorFile( sq_bk, OCCUPIED_FILE );
682 XorDiag2( sq_bk, OCCUPIED_DIAG2 );
683 XorDiag1( sq_bk, OCCUPIED_DIAG1 );
685 if ( flag ) { return 1; }
688 bb_checker = w_attacks_to_piece( ptree, sq_bk );
689 nchecker = PopuCount( bb_checker );
690 if ( nchecker == 2 ) { return 0; }
692 sq_check = LastOne( bb_checker );
693 bb_inter = abb_obstacle[sq_bk][sq_check];
695 /* move other pieces */
696 BBOr( bb_target, bb_inter, bb_checker );
698 BBAnd( bb_desti, bb_target, BB_BPAWN_ATK );
699 while ( BBTest( bb_desti ) )
701 to = LastOne( bb_desti );
705 idirec = (int)adirec[sq_bk][from];
707 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
710 bb_piece = BB_BLANCE;
711 while ( BBTest( bb_piece ) )
713 from = LastOne( bb_piece );
714 Xor( from, bb_piece );
716 bb_desti = AttackFile( from );
717 BBAnd( bb_desti, bb_desti, abb_minus_rays[from] );
718 BBAnd( bb_desti, bb_desti, bb_target );
719 if ( ! BBTest( bb_desti ) ) { continue; }
721 idirec = (int)adirec[sq_bk][from];
723 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
726 bb_piece = BB_BKNIGHT;
727 while ( BBTest( bb_piece ) )
729 from = LastOne( bb_piece );
730 Xor( from, bb_piece );
732 BBAnd( bb_desti, bb_target, abb_b_knight_attacks[from] );
733 if ( ! BBTest( bb_desti ) ) { continue; }
735 idirec = (int)adirec[sq_bk][from];
737 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
740 bb_piece = BB_BSILVER;
741 while ( BBTest( bb_piece ) )
743 from = LastOne( bb_piece );
744 Xor( from, bb_piece );
746 BBAnd( bb_desti, bb_target, abb_b_silver_attacks[from] );
747 if ( ! BBTest( bb_desti ) ) { continue; }
749 idirec = (int)adirec[sq_bk][from];
751 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
754 bb_piece = BB_BTGOLD;
755 while( BBTest( bb_piece ) )
757 from = LastOne( bb_piece );
758 Xor( from, bb_piece );
760 BBAnd( bb_desti, bb_target, abb_b_gold_attacks[from] );
761 if ( ! BBTest(bb_desti) ) { continue; }
763 idirec = (int)adirec[sq_bk][from];
765 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
768 bb_piece = BB_BBISHOP;
769 while ( BBTest( bb_piece ) )
771 from = LastOne( bb_piece );
772 Xor( from, bb_piece );
774 AttackBishop( bb_desti, from );
775 BBAnd( bb_desti, bb_desti, bb_target );
776 if ( ! BBTest( bb_desti ) ) { continue; }
778 idirec = (int)adirec[sq_bk][from];
780 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
784 while ( BBTest( bb_piece ) )
786 from = LastOne( bb_piece );
787 Xor( from, bb_piece );
789 AttackRook( bb_desti, from );
790 BBAnd( bb_desti, bb_desti, bb_target );
791 if ( ! BBTest( bb_desti ) ) { continue; }
793 idirec = (int)adirec[sq_bk][from];
795 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
798 bb_piece = BB_BHORSE;
799 while( BBTest( bb_piece ) )
801 from = LastOne( bb_piece );
802 Xor( from, bb_piece );
804 AttackHorse( bb_desti, from );
805 BBAnd( bb_desti, bb_desti, bb_target );
806 if ( ! BBTest(bb_desti) ) { continue; }
808 idirec = (int)adirec[sq_bk][from];
810 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
813 bb_piece = BB_BDRAGON;
814 while( BBTest( bb_piece ) )
816 from = LastOne( bb_piece );
817 Xor( from, bb_piece );
819 AttackDragon( bb_desti, from );
820 BBAnd( bb_desti, bb_desti, bb_target );
821 if ( ! BBTest(bb_desti) ) { continue; }
823 idirec = (int)adirec[sq_bk][from];
825 || ! is_pinned_on_black_king( ptree, from, idirec ) ) { return 1; }
829 if ( ! BBTest(bb_inter) ) { return 0; }
831 if ( IsHandSGBR(HAND_B) ) { return 1; }
833 bb_inter.p[0] &= 0x003ffffU;
834 if ( ! BBTest(bb_inter) ) { return 0; }
836 if ( IsHandLance(HAND_B) ) { return 1; }
838 if ( IsHandKnight(HAND_B) )
840 bb_target = bb_inter;
841 bb_target.p[0] &= 0x00001ffU;
842 if ( BBTest(bb_target) ) { return 1; }
845 if ( IsHandPawn(HAND_B) )
847 bb_target = bb_inter;
848 ubb_pawn_cmp= BBToU( BB_BPAWN_ATK );
849 ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
850 ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
851 ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
852 ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
853 ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
854 ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
855 ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
856 ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
857 ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
859 while ( BBTest( bb_target ) )
861 to = LastOne( bb_target );
862 Xor( to, bb_target );
864 if ( ! ais_pawn[aifile[to]]
865 && ! IsMateBPawnDrop( ptree, to ) ) { return 1; }
873 int CONV w_have_evasion( tree_t * restrict ptree )
875 bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
876 unsigned int ubb_pawn_cmp;
877 unsigned int ais_pawn[nfile];
878 int nchecker, sq_wk, to, sq_check, idirec, flag, from;
884 Xor( sq_wk, BB_WOCCUPY );
885 XorFile( sq_wk, OCCUPIED_FILE );
886 XorDiag2( sq_wk, OCCUPIED_DIAG2 );
887 XorDiag1( sq_wk, OCCUPIED_DIAG1 );
889 BBNotAnd( bb_desti, abb_king_attacks[sq_wk], BB_WOCCUPY );
890 while ( BBTest( bb_desti ) )
892 to = FirstOne( bb_desti );
895 if ( ! is_white_attacked( ptree, to ) )
902 Xor( sq_wk, BB_WOCCUPY );
903 XorFile( sq_wk, OCCUPIED_FILE );
904 XorDiag2( sq_wk, OCCUPIED_DIAG2 );
905 XorDiag1( sq_wk, OCCUPIED_DIAG1 );
907 if ( flag ) { return 1; }
910 bb_checker = b_attacks_to_piece( ptree, sq_wk );
911 nchecker = PopuCount( bb_checker );
912 if ( nchecker == 2 ) { return 0; }
914 sq_check = FirstOne( bb_checker );
915 bb_inter = abb_obstacle[sq_wk][sq_check];
917 /* move other pieces */
918 BBOr( bb_target, bb_inter, bb_checker );
920 BBAnd( bb_desti, bb_target, BB_WPAWN_ATK );
921 while ( BBTest( bb_desti ) )
923 to = FirstOne( bb_desti );
927 idirec = (int)adirec[sq_wk][from];
929 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
932 bb_piece = BB_WLANCE;
933 while ( BBTest( bb_piece ) )
935 from = FirstOne( bb_piece );
936 Xor( from, bb_piece );
938 bb_desti = AttackFile( from );
939 BBAnd( bb_desti, bb_desti, abb_plus_rays[from] );
940 BBAnd( bb_desti, bb_desti, bb_target );
941 if ( ! BBTest( bb_desti ) ) { continue; }
943 idirec = (int)adirec[sq_wk][from];
945 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
948 bb_piece = BB_WKNIGHT;
949 while ( BBTest( bb_piece ) )
951 from = FirstOne( bb_piece );
952 Xor( from, bb_piece );
954 BBAnd( bb_desti, bb_target, abb_w_knight_attacks[from] );
955 if ( ! BBTest( bb_desti ) ) { continue; }
957 idirec = (int)adirec[sq_wk][from];
959 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
962 bb_piece = BB_WSILVER;
963 while ( BBTest( bb_piece ) )
965 from = FirstOne( bb_piece );
966 Xor( from, bb_piece );
968 BBAnd( bb_desti, bb_target, abb_w_silver_attacks[from] );
969 if ( ! BBTest( bb_desti ) ) { continue; }
971 idirec = (int)adirec[sq_wk][from];
973 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
976 bb_piece = BB_WTGOLD;
977 while( BBTest( bb_piece ) )
979 from = FirstOne( bb_piece );
980 Xor( from, bb_piece );
982 BBAnd( bb_desti, bb_target, abb_w_gold_attacks[from] );
983 if ( ! BBTest(bb_desti) ) { continue; }
985 idirec = (int)adirec[sq_wk][from];
987 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
990 bb_piece = BB_WBISHOP;
991 while ( BBTest( bb_piece ) )
993 from = FirstOne( bb_piece );
994 Xor( from, bb_piece );
996 AttackBishop( bb_desti, from );
997 BBAnd( bb_desti, bb_desti, bb_target );
998 if ( ! BBTest( bb_desti ) ) { continue; }
1000 idirec = (int)adirec[sq_wk][from];
1002 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1005 bb_piece = BB_WROOK;
1006 while ( BBTest( bb_piece ) )
1008 from = FirstOne( bb_piece );
1009 Xor( from, bb_piece );
1011 AttackRook( bb_desti, from );
1012 BBAnd( bb_desti, bb_desti, bb_target );
1013 if ( ! BBTest( bb_desti ) ) { continue; }
1015 idirec = (int)adirec[sq_wk][from];
1017 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1020 bb_piece = BB_WHORSE;
1021 while( BBTest( bb_piece ) )
1023 from = FirstOne( bb_piece );
1024 Xor( from, bb_piece );
1026 AttackHorse( bb_desti, from );
1027 BBAnd( bb_desti, bb_desti, bb_target );
1028 if ( ! BBTest(bb_desti) ) { continue; }
1030 idirec = (int)adirec[sq_wk][from];
1032 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1035 bb_piece = BB_WDRAGON;
1036 while( BBTest( bb_piece ) )
1038 from = FirstOne( bb_piece );
1039 Xor( from, bb_piece );
1041 AttackDragon( bb_desti, from );
1042 BBAnd( bb_desti, bb_desti, bb_target );
1043 if ( ! BBTest(bb_desti) ) { continue; }
1045 idirec = (int)adirec[sq_wk][from];
1047 || ! is_pinned_on_white_king( ptree, from, idirec ) ) { return 1; }
1051 if ( ! BBTest(bb_inter) ) { return 0; }
1053 if ( IsHandSGBR(HAND_W) ) { return 1; }
1055 bb_inter.p[2] &= 0x7fffe00U;
1056 if ( ! BBTest(bb_inter) ) { return 0; }
1058 if ( IsHandLance(HAND_W) ) { return 1; }
1060 if ( IsHandKnight(HAND_W) )
1062 bb_target = bb_inter;
1063 bb_target.p[2] &= 0x7fc0000U;
1064 if ( BBTest(bb_target) ) { return 1; }
1067 if ( IsHandPawn(HAND_W) )
1069 bb_target = bb_inter;
1070 ubb_pawn_cmp= BBToU( BB_WPAWN_ATK );
1071 ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
1072 ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
1073 ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
1074 ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
1075 ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
1076 ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
1077 ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
1078 ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
1079 ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
1081 while ( BBTest( bb_target ) )
1083 to = FirstOne( bb_target );
1084 Xor( to, bb_target );
1086 if ( ! ais_pawn[aifile[to]]
1087 && ! IsMateWPawnDrop( ptree, to ) ) { return 1; }