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 BBNot( bb_desti, BB_BOCCUPY );
25 BBAnd( bb_desti, bb_desti, abb_king_attacks[sq_bk] );
26 utemp = From2Move(sq_bk) | Piece2Move(king);
27 while ( BBToU( bb_desti ) )
29 to = LastOne( bb_desti );
30 if ( ! is_black_attacked( ptree, to ) )
32 *pmove++ = To2Move(to) | Cap2Move(-BOARD[to]) | utemp;
37 Xor( sq_bk, BB_BOCCUPY );
38 XorFile( sq_bk, OCCUPIED_FILE );
39 XorDiag2( sq_bk, OCCUPIED_DIAG2 );
40 XorDiag1( sq_bk, OCCUPIED_DIAG1 );
42 bb_checker = attacks_to_piece( ptree, sq_bk );
43 BBAnd( bb_checker, bb_checker, BB_WOCCUPY );
44 nchecker = PopuCount( bb_checker );
45 if ( nchecker == 2 ) { return pmove; }
47 sq_check = LastOne( bb_checker );
48 bb_inter = abb_obstacle[sq_bk][sq_check];
50 /* move other pieces */
51 BBOr( bb_target, bb_inter, bb_checker );
53 BBAnd( bb_desti, bb_target, BB_BPAWN_ATK );
54 while ( BBToU( bb_desti ) )
56 to = LastOne( bb_desti );
60 idirec = (int)adirec[sq_bk][from];
61 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
63 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(pawn)
64 | Cap2Move(-BOARD[to]) );
65 if ( to < A6 ) { utemp |= FLAG_PROMO; }
71 while ( BBToU( bb_piece ) )
73 from = LastOne( bb_piece );
74 Xor( from, bb_piece );
76 bb_desti = AttackFile( from );
77 BBAnd( bb_desti, bb_desti, abb_minus_rays[from] );
78 BBAnd( bb_desti, bb_desti, bb_target );
79 if ( ! BBToU( bb_desti ) ) { continue; }
81 idirec = (int)adirec[sq_bk][from];
82 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
84 to = LastOne( bb_desti );
86 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(lance)
87 | Cap2Move(-BOARD[to]) );
88 if ( to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
89 if ( to >= A7 ) { *pmove++ = utemp; }
93 bb_piece = BB_BKNIGHT;
94 while ( BBToU( bb_piece ) )
96 from = LastOne( bb_piece );
97 Xor( from, bb_piece );
99 BBAnd( bb_desti, bb_target, abb_b_knight_attacks[from] );
100 if ( ! BBToU( bb_desti ) ) { continue; }
102 idirec = (int)adirec[sq_bk][from];
103 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
105 to = LastOne( bb_desti );
108 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(knight)
109 | Cap2Move(-BOARD[to]) );
110 if ( to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
111 if ( to >= A7 ) { *pmove++ = utemp; }
113 } while ( BBToU( bb_desti ) );
116 bb_piece = BB_BSILVER;
117 while ( BBToU( bb_piece ) )
119 from = LastOne( bb_piece );
120 Xor( from, bb_piece );
122 BBAnd( bb_desti, bb_target, abb_b_silver_attacks[from] );
123 if ( ! BBToU( bb_desti ) ) { continue; }
125 idirec = (int)adirec[sq_bk][from];
126 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
128 to = LastOne( bb_desti );
130 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(silver)
131 | Cap2Move(-BOARD[to]) );
132 if ( from < A6 || to < A6 ) { *pmove++ = utemp | FLAG_PROMO; }
134 } while ( BBToU( bb_desti ) );
137 bb_piece = BB_BTGOLD;
138 while( BBToU( bb_piece ) )
140 from = LastOne( bb_piece );
141 Xor( from, bb_piece );
143 BBAnd( bb_desti, bb_target, abb_b_gold_attacks[from] );
144 if ( ! BBToU(bb_desti) ) { continue; }
146 idirec = (int)adirec[sq_bk][from];
147 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
149 to = LastOne( bb_desti );
151 *pmove++ = ( To2Move(to) | From2Move(from)
152 | Piece2Move(BOARD[from])
153 | Cap2Move(-BOARD[to]) );
154 } while( BBToU( bb_desti ) );
157 bb_piece = BB_BBISHOP;
158 while ( BBToU( bb_piece ) )
160 from = LastOne( bb_piece );
161 Xor( from, bb_piece );
163 AttackBishop( bb_desti, from );
164 BBAnd( bb_desti, bb_desti, bb_target );
165 if ( ! BBToU( bb_desti ) ) { continue; }
166 idirec = (int)adirec[sq_bk][from];
167 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
169 to = LastOne( bb_desti );
172 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(bishop)
173 | Cap2Move(-BOARD[to]) );
174 if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
176 } while ( BBToU( bb_desti ) );
180 while ( BBToU( bb_piece ) )
182 from = LastOne( bb_piece );
183 Xor( from, bb_piece );
185 AttackRook( bb_desti, from );
186 BBAnd( bb_desti, bb_desti, bb_target );
187 if ( ! BBToU( bb_desti ) ) { continue; }
188 idirec = (int)adirec[sq_bk][from];
189 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
191 to = LastOne( bb_desti );
194 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(rook)
195 | Cap2Move(-BOARD[to]) );
196 if ( from < A6 || to < A6 ) { utemp |= FLAG_PROMO; }
198 } while ( BBToU( bb_desti ) );
201 bb_piece = BB_BHORSE;
202 while( BBToU( bb_piece ) )
204 from = LastOne( bb_piece );
205 Xor( from, bb_piece );
207 AttackHorse( bb_desti, from );
208 BBAnd( bb_desti, bb_desti, bb_target );
209 if ( ! BBToU(bb_desti) ) { continue; }
211 idirec = (int)adirec[sq_bk][from];
212 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
214 to = LastOne( bb_desti );
216 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
217 | Cap2Move(-BOARD[to]) );
218 } while ( BBToU( bb_desti ) );
221 bb_piece = BB_BDRAGON;
222 while( BBToU( bb_piece ) )
224 from = LastOne( bb_piece );
225 Xor( from, bb_piece );
227 AttackDragon( bb_desti, from );
228 BBAnd( bb_desti, bb_desti, bb_target );
229 if ( ! BBToU(bb_desti) ) { continue; }
231 idirec = (int)adirec[sq_bk][from];
232 if ( ! idirec || ! is_pinned_on_black_king( ptree, from, idirec ) )
234 to = LastOne( bb_desti );
236 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
237 | Cap2Move(-BOARD[to]) );
238 } while ( BBToU( bb_desti ) );
241 if ( ! HAND_B ) { return pmove; }
242 if ( ! BBToU(bb_inter) ) { return pmove; }
245 bb_target = bb_inter;
246 ubb_target0a = bb_target.p[0] & 0x7fc0000U;
247 ubb_target0b = bb_target.p[0] & 0x003fe00U;
248 bb_target.p[0] &= 0x00001ffU;
249 bb_target.p[1] &= 0x7ffffffU;
250 bb_target.p[2] &= 0x7ffffffU;
254 if ( IsHandKnight( hand ) ) { ahand[ nhand++ ] = Drop2Move(knight); }
256 if ( IsHandLance( hand ) ) { ahand[ nhand++ ] = Drop2Move(lance); }
258 if ( IsHandSilver( hand ) ) { ahand[ nhand++ ] = Drop2Move(silver); }
259 if ( IsHandGold( hand ) ) { ahand[ nhand++ ] = Drop2Move(gold); }
260 if ( IsHandBishop( hand ) ) { ahand[ nhand++ ] = Drop2Move(bishop); }
261 if ( IsHandRook( hand ) ) { ahand[ nhand++ ] = Drop2Move(rook); }
263 if ( IsHandPawn( hand ) )
265 ubb_pawn_cmp= BBToU( BB_BPAWN_ATK );
266 ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
267 ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
268 ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
269 ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
270 ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
271 ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
272 ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
273 ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
274 ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
276 while ( BBToU( bb_target ) )
278 to = LastOne( bb_target );
280 if ( ! ais_pawn[aifile[to]] && ! IsMateBPawnDrop( ptree, to ) )
282 *pmove++ = utemp | Drop2Move(pawn);
284 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
285 Xor( to, bb_target );
288 while ( ubb_target0b )
290 to = last_one0( ubb_target0b );
292 if ( ! ais_pawn[aifile[to]] && ! IsMateBPawnDrop( ptree, to ) )
294 *pmove++ = utemp | Drop2Move(pawn);
296 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
297 ubb_target0b ^= abb_mask[ to ].p[0];
301 while ( BBToU( bb_target ) )
303 to = LastOne( bb_target );
305 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
306 Xor( to, bb_target );
309 while ( ubb_target0b )
311 to = last_one0( ubb_target0b );
313 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
314 ubb_target0b ^= abb_mask[ to ].p[0];
318 while ( ubb_target0a )
320 to = last_one0( ubb_target0a );
322 for ( i = nolance; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
323 ubb_target0a ^= abb_mask[ to ].p[0];
331 w_gen_evasion( tree_t * restrict ptree, unsigned int * restrict pmove )
333 bitboard_t bb_desti, bb_checker, bb_inter, bb_target, bb_piece;
334 unsigned int hand, ubb_target2a, ubb_target2b, ubb_pawn_cmp, utemp;
335 unsigned int ais_pawn[nfile];
336 int nchecker, sq_wk, to, sq_check, idirec;
337 int nhand, i, nolance, noknight, from;
343 Xor( sq_wk, BB_WOCCUPY );
344 XorFile( sq_wk, OCCUPIED_FILE );
345 XorDiag2( sq_wk, OCCUPIED_DIAG2 );
346 XorDiag1( sq_wk, OCCUPIED_DIAG1 );
348 BBNot( bb_desti, BB_WOCCUPY );
349 BBAnd( bb_desti, bb_desti, abb_king_attacks[sq_wk] );
350 utemp = From2Move(sq_wk) | Piece2Move(king);
351 while ( BBToU( bb_desti ) )
353 to = FirstOne( bb_desti );
354 if ( ! is_white_attacked( ptree, to ) )
356 *pmove++ = To2Move(to) | Cap2Move(BOARD[to]) | utemp;
361 Xor( sq_wk, BB_WOCCUPY );
362 XorFile( sq_wk, OCCUPIED_FILE );
363 XorDiag2( sq_wk, OCCUPIED_DIAG2 );
364 XorDiag1( sq_wk, OCCUPIED_DIAG1 );
366 bb_checker = attacks_to_piece( ptree, sq_wk );
367 BBAnd( bb_checker, bb_checker, BB_BOCCUPY );
368 nchecker = PopuCount( bb_checker );
369 if ( nchecker == 2 ) { return pmove; }
371 sq_check = FirstOne( bb_checker );
372 bb_inter = abb_obstacle[sq_wk][sq_check];
374 /* move other pieces */
375 BBOr( bb_target, bb_inter, bb_checker );
377 BBAnd( bb_desti, bb_target, BB_WPAWN_ATK );
378 while ( BBToU( bb_desti ) )
380 to = FirstOne( bb_desti );
384 idirec = (int)adirec[sq_wk][from];
385 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
387 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(pawn)
388 | Cap2Move(BOARD[to]) );
389 if ( to > I4 ) { utemp |= FLAG_PROMO; }
394 bb_piece = BB_WLANCE;
395 while ( BBToU( bb_piece ) )
397 from = FirstOne( bb_piece );
398 Xor( from, bb_piece );
400 bb_desti = AttackFile( from );
401 BBAnd( bb_desti, bb_desti, abb_plus_rays[from] );
402 BBAnd( bb_desti, bb_desti, bb_target );
403 if ( ! BBToU( bb_desti ) ) { continue; }
405 idirec = (int)adirec[sq_wk][from];
406 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
408 to = FirstOne( bb_desti );
410 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(lance)
411 | Cap2Move(BOARD[to]) );
412 if ( to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
413 if ( to <= I3 ) { *pmove++ = utemp; }
417 bb_piece = BB_WKNIGHT;
418 while ( BBToU( bb_piece ) )
420 from = FirstOne( bb_piece );
421 Xor( from, bb_piece );
423 BBAnd( bb_desti, bb_target, abb_w_knight_attacks[from] );
424 if ( ! BBToU( bb_desti ) ) { continue; }
426 idirec = (int)adirec[sq_wk][from];
427 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
429 to = FirstOne( bb_desti );
432 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(knight)
433 | Cap2Move(BOARD[to]) );
434 if ( to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
435 if ( to <= I3 ) { *pmove++ = utemp; }
436 } while ( BBToU( bb_desti ) );
439 bb_piece = BB_WSILVER;
440 while ( BBToU( bb_piece ) )
442 from = FirstOne( bb_piece );
443 Xor( from, bb_piece );
445 BBAnd( bb_desti, bb_target, abb_w_silver_attacks[from] );
446 if ( ! BBToU( bb_desti ) ) { continue; }
448 idirec = (int)adirec[sq_wk][from];
449 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
451 to = FirstOne( bb_desti );
453 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(silver)
454 | Cap2Move(BOARD[to]) );
455 if ( from > I4 || to > I4 ) { *pmove++ = utemp | FLAG_PROMO; }
457 } while ( BBToU( bb_desti ) );
460 bb_piece = BB_WTGOLD;
461 while( BBToU( bb_piece ) )
463 from = FirstOne( bb_piece );
464 Xor( from, bb_piece );
466 BBAnd( bb_desti, bb_target, abb_w_gold_attacks[from] );
467 if ( ! BBToU(bb_desti) ) { continue; }
469 idirec = (int)adirec[sq_wk][from];
470 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
472 to = FirstOne( bb_desti );
474 *pmove++ = ( To2Move(to) | From2Move(from)
475 | Piece2Move(-BOARD[from])
476 | Cap2Move(BOARD[to]) );
477 } while( BBToU( bb_desti ) );
480 bb_piece = BB_WBISHOP;
481 while ( BBToU( bb_piece ) )
483 from = FirstOne( bb_piece );
484 Xor( from, bb_piece );
486 AttackBishop( bb_desti, from );
487 BBAnd( bb_desti, bb_desti, bb_target );
488 if ( ! BBToU( bb_desti ) ) { continue; }
490 idirec = (int)adirec[sq_wk][from];
491 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
493 to = FirstOne( bb_desti );
496 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(bishop)
497 | Cap2Move(BOARD[to]) );
498 if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
500 } while ( BBToU( bb_desti ) );
504 while ( BBToU( bb_piece ) )
506 from = FirstOne( bb_piece );
507 Xor( from, bb_piece );
509 AttackRook( bb_desti, from );
510 BBAnd( bb_desti, bb_desti, bb_target );
511 if ( ! BBToU( bb_desti ) ) { continue; }
512 idirec = (int)adirec[sq_wk][from];
513 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
515 to = FirstOne( bb_desti );
518 utemp = ( To2Move(to) | From2Move(from) | Piece2Move(rook)
519 | Cap2Move(BOARD[to]) );
520 if ( from > I4 || to > I4 ) { utemp |= FLAG_PROMO; }
522 } while ( BBToU( bb_desti ) );
525 bb_piece = BB_WHORSE;
526 while( BBToU( bb_piece ) )
528 from = FirstOne( bb_piece );
529 Xor( from, bb_piece );
531 AttackHorse( bb_desti, from );
532 BBAnd( bb_desti, bb_desti, bb_target );
533 if ( ! BBToU(bb_desti) ) { continue; }
535 idirec = (int)adirec[sq_wk][from];
536 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
538 to = FirstOne( bb_desti );
540 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(horse)
541 | Cap2Move(BOARD[to]) );
542 } while ( BBToU( bb_desti ) );
545 bb_piece = BB_WDRAGON;
546 while( BBToU( bb_piece ) )
548 from = FirstOne( bb_piece );
549 Xor( from, bb_piece );
551 AttackDragon( bb_desti, from );
552 BBAnd( bb_desti, bb_desti, bb_target );
553 if ( ! BBToU(bb_desti) ) { continue; }
555 idirec = (int)adirec[sq_wk][from];
556 if ( ! idirec || ! is_pinned_on_white_king( ptree, from, idirec ) )
558 to = FirstOne( bb_desti );
560 *pmove++ = ( To2Move(to) | From2Move(from) | Piece2Move(dragon)
561 | Cap2Move(BOARD[to]) );
562 } while ( BBToU( bb_desti ) );
565 if ( ! HAND_W ) { return pmove; }
566 if ( ! BBToU(bb_inter) ) { return pmove; }
569 bb_target = bb_inter;
570 ubb_target2a = bb_target.p[2] & 0x00001ffU;
571 ubb_target2b = bb_target.p[2] & 0x003fe00U;
572 bb_target.p[0] &= 0x7ffffffU;
573 bb_target.p[1] &= 0x7ffffffU;
574 bb_target.p[2] &= 0x7fc0000U;
578 if ( IsHandKnight( hand ) ) { ahand[ nhand++ ] = Drop2Move(knight); }
580 if ( IsHandLance( hand ) ) { ahand[ nhand++ ] = Drop2Move(lance); }
582 if ( IsHandSilver( hand ) ) { ahand[ nhand++ ] = Drop2Move(silver); }
583 if ( IsHandGold( hand ) ) { ahand[ nhand++ ] = Drop2Move(gold); }
584 if ( IsHandBishop( hand ) ) { ahand[ nhand++ ] = Drop2Move(bishop); }
585 if ( IsHandRook( hand ) ) { ahand[ nhand++ ] = Drop2Move(rook); }
587 if ( IsHandPawn( hand ) )
589 ubb_pawn_cmp= BBToU( BB_WPAWN_ATK );
590 ais_pawn[0] = ubb_pawn_cmp & ( mask_file1 >> 0 );
591 ais_pawn[1] = ubb_pawn_cmp & ( mask_file1 >> 1 );
592 ais_pawn[2] = ubb_pawn_cmp & ( mask_file1 >> 2 );
593 ais_pawn[3] = ubb_pawn_cmp & ( mask_file1 >> 3 );
594 ais_pawn[4] = ubb_pawn_cmp & ( mask_file1 >> 4 );
595 ais_pawn[5] = ubb_pawn_cmp & ( mask_file1 >> 5 );
596 ais_pawn[6] = ubb_pawn_cmp & ( mask_file1 >> 6 );
597 ais_pawn[7] = ubb_pawn_cmp & ( mask_file1 >> 7 );
598 ais_pawn[8] = ubb_pawn_cmp & ( mask_file1 >> 8 );
600 while ( BBToU( bb_target ) )
602 to = FirstOne( bb_target );
604 if ( ! ais_pawn[aifile[to]] && ! IsMateWPawnDrop( ptree, to ) )
606 *pmove++ = utemp | Drop2Move(pawn);
608 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
609 Xor( to, bb_target );
612 while ( ubb_target2b )
614 to = first_one2( ubb_target2b );
616 if ( ! ais_pawn[aifile[to]] && ! IsMateWPawnDrop( ptree, to ) )
618 *pmove++ = utemp | Drop2Move(pawn);
620 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
621 ubb_target2b ^= abb_mask[ to ].p[2];
625 while ( BBToU( bb_target ) )
627 to = FirstOne( bb_target );
629 for ( i = 0; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
630 Xor( to, bb_target );
633 while ( ubb_target2b )
635 to = first_one2( ubb_target2b );
637 for ( i = noknight; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
638 ubb_target2b ^= abb_mask[ to ].p[2];
642 while ( ubb_target2a )
644 to = first_one2( ubb_target2a );
646 for ( i = nolance; i < nhand; i++ ) { *pmove++ = utemp|ahand[i]; }
647 ubb_target2a ^= abb_mask[ to ].p[2];