Force iteration to start at 1 in analyze mode
[bonanza.git] / genchk.c
1 #include <assert.h>\r
2 #include "shogi.h"\r
3 \r
4 \r
5 static bitboard_t add_behind_attacks( int idirec, int ik, bitboard_t bb );\r
6 \r
7 \r
8 unsigned int *\r
9 b_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
10 {\r
11   bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
12   bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
13   const tree_t * restrict ptree = __ptree__;\r
14   unsigned int u0, u1, u2;\r
15   int from, to, sq_wk, idirec;\r
16 \r
17   sq_wk = SQ_WKING;\r
18   bb_rook_chk  = bb_file_chk = AttackFile( sq_wk );\r
19   bb_rook_chk.p[aslide[sq_wk].ir0] |= AttackRank( sq_wk );\r
20   bb_diag1_chk = AttackDiag1( sq_wk );\r
21   bb_diag2_chk = AttackDiag2( sq_wk );\r
22   BBOr( bb_bishop_chk, bb_diag1_chk, bb_diag2_chk );\r
23   BBNot( bb_move_to, BB_BOCCUPY );\r
24   BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
25   BBNot( bb_drop_to, bb_drop_to );\r
26 \r
27   from  = SQ_BKING;\r
28   idirec = (int)adirec[sq_wk][from];\r
29   if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
30     {\r
31       BBIni( bb_chk );\r
32       bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
33       BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
34       BBAnd( bb_chk, bb_chk, bb_move_to );\r
35 \r
36       while( BBToU( bb_chk ) )\r
37         {\r
38           to = LastOne( bb_chk );\r
39           Xor( to, bb_chk );\r
40           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
41             | Cap2Move(-BOARD[to]);\r
42         }\r
43     }\r
44 \r
45 \r
46   bb_piece = BB_BDRAGON;\r
47   while( BBToU( bb_piece ) )\r
48     {\r
49       from = LastOne( bb_piece );\r
50       Xor( from, bb_piece );\r
51 \r
52       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
53       idirec = (int)adirec[sq_wk][from];\r
54       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
55         {\r
56           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
57         }\r
58 \r
59       AttackDragon( bb_desti, from );\r
60       BBAnd( bb_chk, bb_chk, bb_desti );\r
61       BBAnd( bb_chk, bb_chk, bb_move_to );\r
62 \r
63       while( BBToU( bb_chk ) )\r
64         {\r
65           to = LastOne( bb_chk );\r
66           Xor( to, bb_chk );\r
67           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
68             | Cap2Move(-BOARD[to]);\r
69         }\r
70     }\r
71 \r
72   bb_piece = BB_BHORSE;\r
73   while( BBToU( bb_piece ) )\r
74     {\r
75       from = LastOne( bb_piece );\r
76       Xor( from, bb_piece );\r
77 \r
78       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
79       idirec = (int)adirec[sq_wk][from];\r
80       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
81         {\r
82           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
83         }\r
84 \r
85       AttackHorse( bb_desti, from );\r
86       BBAnd( bb_chk, bb_chk, bb_desti );\r
87       BBAnd( bb_chk, bb_chk, bb_move_to );\r
88 \r
89       while( BBToU( bb_chk ) )\r
90         {\r
91           to = LastOne( bb_chk );\r
92           Xor( to, bb_chk );\r
93           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
94             | Cap2Move(-BOARD[to]);\r
95         }\r
96     }\r
97 \r
98   u1 = BB_BROOK.p[1];\r
99   u2 = BB_BROOK.p[2];\r
100   while( u1 | u2 )\r
101     {\r
102       from = last_one12( u1, u2 );\r
103       u1   ^= abb_mask[from].p[1];\r
104       u2   ^= abb_mask[from].p[2];\r
105 \r
106       AttackRook( bb_desti, from );\r
107 \r
108       idirec = (int)adirec[sq_wk][from];\r
109       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
110         {\r
111           BBAnd( bb_chk, bb_desti, bb_move_to );\r
112         }\r
113       else {\r
114         bb_chk       = bb_rook_chk;\r
115         bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
116         BBAnd( bb_chk, bb_chk, bb_desti );\r
117         BBAnd( bb_chk, bb_chk, bb_move_to );\r
118       }\r
119 \r
120       while ( bb_chk.p[0] )\r
121         {\r
122           to          = last_one0( bb_chk.p[0] );\r
123           bb_chk.p[0] ^= abb_mask[to].p[0];\r
124           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
125             | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
126         }\r
127 \r
128       while( bb_chk.p[1] | bb_chk.p[2] )\r
129         {\r
130           to          = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
131           bb_chk.p[1] ^= abb_mask[to].p[1];\r
132           bb_chk.p[2] ^= abb_mask[to].p[2];\r
133           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
134             | Cap2Move(-BOARD[to]);\r
135         }\r
136     }\r
137 \r
138   u0 = BB_BROOK.p[0];\r
139   while( u0 )\r
140     {\r
141       from = last_one0( u0 );\r
142       u0   ^= abb_mask[from].p[0];\r
143       \r
144       AttackRook( bb_desti, from );\r
145 \r
146       idirec = (int)adirec[sq_wk][from];\r
147       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
148         {\r
149           BBAnd( bb_chk, bb_desti, bb_move_to );\r
150         }\r
151       else {\r
152         BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_wk] );\r
153         BBAnd( bb_chk, bb_chk, bb_desti );\r
154         BBAnd( bb_chk, bb_chk, bb_move_to );\r
155       }\r
156 \r
157       while( BBToU( bb_chk ) )\r
158         {\r
159           to = LastOne( bb_chk );\r
160           Xor( to, bb_chk );\r
161           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
162             | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
163         }\r
164     }\r
165 \r
166   u1 = BB_BBISHOP.p[1];\r
167   u2 = BB_BBISHOP.p[2];\r
168   while( u1 | u2 )\r
169     {\r
170       from = last_one12( u1, u2 );\r
171       u1   ^= abb_mask[from].p[1];\r
172       u2   ^= abb_mask[from].p[2];\r
173 \r
174       AttackBishop( bb_desti, from );\r
175 \r
176       idirec = (int)adirec[sq_wk][from];\r
177       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
178         {\r
179           BBAnd( bb_chk, bb_desti, bb_move_to );\r
180         }\r
181       else {\r
182         bb_chk       = bb_bishop_chk;\r
183         bb_chk.p[0] |= abb_king_attacks[sq_wk].p[0];\r
184         BBAnd( bb_chk, bb_chk, bb_desti );\r
185         BBAnd( bb_chk, bb_chk, bb_move_to );\r
186       }\r
187 \r
188       while ( bb_chk.p[0] )\r
189         {\r
190           to          = last_one0( bb_chk.p[0] );\r
191           bb_chk.p[0] ^= abb_mask[to].p[0];\r
192           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
193             | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
194         }\r
195 \r
196       while( bb_chk.p[1] | bb_chk.p[2] )\r
197         {\r
198           to          = last_one12( bb_chk.p[1], bb_chk.p[2] );\r
199           bb_chk.p[1] ^= abb_mask[to].p[1];\r
200           bb_chk.p[2] ^= abb_mask[to].p[2];\r
201           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
202             | Cap2Move(-BOARD[to]);\r
203         }\r
204     }\r
205 \r
206   u0 = BB_BBISHOP.p[0];\r
207   while( u0 )\r
208     {\r
209       from = last_one0( u0 );\r
210       u0   ^= abb_mask[from].p[0];\r
211       \r
212       AttackBishop( bb_desti, from );\r
213 \r
214       idirec = (int)adirec[sq_wk][from];\r
215       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
216         {\r
217           BBAnd( bb_chk, bb_desti, bb_move_to );\r
218         }\r
219       else {\r
220         BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_wk] );\r
221         BBAnd( bb_chk, bb_chk, bb_desti );\r
222         BBAnd( bb_chk, bb_chk, bb_move_to );\r
223       }\r
224 \r
225       while( BBToU( bb_chk ) )\r
226         {\r
227           to = LastOne( bb_chk );\r
228           Xor( to, bb_chk );\r
229           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
230             | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
231         }\r
232     }\r
233 \r
234 \r
235   bb_piece = BB_BTGOLD;\r
236   while( BBToU( bb_piece ) )\r
237     {\r
238       from = LastOne( bb_piece );\r
239       Xor( from, bb_piece );\r
240 \r
241       bb_chk = abb_w_gold_attacks[sq_wk];\r
242 \r
243       idirec = (int)adirec[sq_wk][from];\r
244       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
245         {\r
246           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
247         }\r
248 \r
249       BBAnd( bb_chk, bb_chk, abb_b_gold_attacks[from] );\r
250       BBAnd( bb_chk, bb_chk, bb_move_to );\r
251 \r
252       while( BBToU( bb_chk ) )\r
253         {\r
254           to = LastOne( bb_chk );\r
255           Xor( to, bb_chk );\r
256           *pmove++ = ( To2Move(to) | From2Move(from)\r
257                        | Piece2Move(BOARD[from])\r
258                        | Cap2Move(-BOARD[to]) );\r
259         }\r
260     }\r
261   \r
262 \r
263   u0 = BB_BSILVER.p[0];\r
264   while( u0 )\r
265     {\r
266       from = last_one0( u0 );\r
267       u0   ^= abb_mask[from].p[0];\r
268 \r
269       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
270       bb_chk.p[1] = abb_w_gold_attacks[sq_wk].p[1];\r
271       bb_chk.p[2] = 0;\r
272 \r
273       idirec = (int)adirec[sq_wk][from];\r
274       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
275         {\r
276           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
277         }\r
278 \r
279       bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
280       bb_chk.p[1] &= bb_move_to.p[1] & abb_b_silver_attacks[from].p[1];\r
281 \r
282       while( bb_chk.p[0] | bb_chk.p[1] )\r
283         {\r
284           to          = last_one01( bb_chk.p[0], bb_chk.p[1] );\r
285           bb_chk.p[0] ^= abb_mask[to].p[0];\r
286           bb_chk.p[1] ^= abb_mask[to].p[1];\r
287           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
288             | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
289         }\r
290     }\r
291   \r
292 \r
293   u1 = BB_BSILVER.p[1] & 0x7fc0000U;\r
294   while( u1 )\r
295     {\r
296       from = last_one1( u1 );\r
297       u1   ^= abb_mask[from].p[1];\r
298       \r
299       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
300       bb_chk.p[1] = bb_chk.p[2] = 0;\r
301       \r
302       idirec = (int)adirec[sq_wk][from];\r
303       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
304         {\r
305           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
306         }\r
307 \r
308       bb_chk.p[0] &= bb_move_to.p[0] & abb_b_silver_attacks[from].p[0];\r
309       while ( bb_chk.p[0] )\r
310         {\r
311           to          = last_one0( bb_chk.p[0] );\r
312           bb_chk.p[0] ^= abb_mask[to].p[0];\r
313           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
314             | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
315         }\r
316     }\r
317   \r
318 \r
319   bb_piece = BB_BSILVER;\r
320   while( BBToU( bb_piece ) )\r
321     {\r
322       from = LastOne( bb_piece );\r
323       Xor( from, bb_piece );\r
324 \r
325       bb_chk = abb_w_silver_attacks[sq_wk];\r
326 \r
327       idirec = (int)adirec[sq_wk][from];\r
328       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
329         {\r
330           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
331         }\r
332 \r
333       BBAnd( bb_chk, bb_chk, abb_b_silver_attacks[from] );\r
334       BBAnd( bb_chk, bb_chk, bb_move_to );\r
335 \r
336       while( BBToU( bb_chk ) )\r
337         {\r
338           to = LastOne( bb_chk );\r
339           Xor( to, bb_chk );\r
340           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
341             | Cap2Move(-BOARD[to]);\r
342         }\r
343     }\r
344   \r
345 \r
346   u0 = BB_BKNIGHT.p[0];\r
347   u1 = BB_BKNIGHT.p[1] & 0x7fffe00U;\r
348   while( u0 | u1 )\r
349     {\r
350       from = last_one01( u0, u1 );\r
351       u0   ^= abb_mask[from].p[0];\r
352       u1   ^= abb_mask[from].p[1];\r
353 \r
354       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
355       bb_chk.p[1] = bb_chk.p[2] = 0;\r
356 \r
357       idirec = (int)adirec[sq_wk][from];\r
358       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
359         {\r
360           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
361         }\r
362 \r
363       bb_chk.p[0] &= abb_b_knight_attacks[from].p[0] & bb_move_to.p[0];\r
364 \r
365       while( bb_chk.p[0] )\r
366         {\r
367           to          = last_one0( bb_chk.p[0] );\r
368           bb_chk.p[0] ^= abb_mask[to].p[0];\r
369           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
370                        | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
371         }\r
372     }\r
373   \r
374 \r
375   u2 = BB_BKNIGHT.p[2];\r
376   u1 = BB_BKNIGHT.p[1] & 0x3ffffU;\r
377   while( u2 | u1 )\r
378     {\r
379       from = last_one12( u1, u2 );\r
380       u2   ^= abb_mask[from].p[2];\r
381       u1   ^= abb_mask[from].p[1];\r
382 \r
383       bb_chk = abb_w_knight_attacks[sq_wk];\r
384 \r
385       idirec = (int)adirec[sq_wk][from];\r
386       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
387         {\r
388           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
389         }\r
390 \r
391       BBAnd( bb_chk, bb_chk, abb_b_knight_attacks[from] );\r
392       BBAnd( bb_chk, bb_chk, bb_move_to );\r
393 \r
394       while( BBToU( bb_chk ) )\r
395         {\r
396           to = LastOne( bb_chk );\r
397           Xor( to, bb_chk );\r
398           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
399             | Cap2Move(-BOARD[to]);\r
400         }\r
401     }\r
402 \r
403 \r
404   bb_piece = BB_BLANCE;\r
405   while( BBToU( bb_piece ) )\r
406     {\r
407       from = LastOne( bb_piece );\r
408       Xor( from, bb_piece );\r
409 \r
410       bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
411       bb_chk.p[1] = bb_chk.p[2] = 0;\r
412 \r
413       idirec = (int)adirec[sq_wk][from];\r
414       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
415         {\r
416           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
417         }\r
418 \r
419       BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
420       BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
421       BBAnd( bb_chk, bb_chk, bb_move_to );\r
422 \r
423       while( BBToU( bb_chk ) )\r
424         {\r
425           to = LastOne( bb_chk );\r
426           Xor( to, bb_chk );\r
427           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
428             | Cap2Move(-BOARD[to]) | FLAG_PROMO;\r
429         }\r
430     }\r
431   \r
432 \r
433   u1 = BB_BLANCE.p[1];\r
434   u2 = BB_BLANCE.p[2];\r
435   while( u1| u2 )\r
436     {\r
437       from = last_one12( u1, u2 );\r
438       u1   ^= abb_mask[from].p[1];\r
439       u2   ^= abb_mask[from].p[2];\r
440 \r
441       bb_chk = bb_file_chk;\r
442       idirec = (int)adirec[sq_wk][from];\r
443       if ( idirec && is_pinned_on_white_king( ptree, from, idirec ) )\r
444         {\r
445           bb_chk = add_behind_attacks( idirec, sq_wk, bb_chk );\r
446           BBAnd( bb_chk, bb_chk, abb_minus_rays[from] );\r
447         }\r
448       else { BBAnd( bb_chk, bb_file_chk, abb_plus_rays[sq_wk] );}\r
449 \r
450       BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
451       BBAnd( bb_chk, bb_chk, bb_move_to );\r
452       bb_chk.p[0] = bb_chk.p[0] & 0x1ffU;\r
453 \r
454       while( BBToU( bb_chk ) )\r
455         {\r
456           to = LastOne( bb_chk );\r
457           Xor( to, bb_chk );\r
458           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
459             | Cap2Move(-BOARD[to]);\r
460         }\r
461     }\r
462 \r
463 \r
464   BBAnd( bb_piece, bb_diag1_chk, BB_BPAWN );\r
465   while ( BBToU(bb_piece) )\r
466     {\r
467       from = LastOne( bb_piece );\r
468       Xor( from, bb_piece );\r
469       \r
470       to = from - nfile;\r
471       if ( BOARD[to] != empty ) { continue; }\r
472 \r
473       bb_desti = AttackDiag1( from );\r
474       if ( BBContract( bb_desti, BB_B_BH ) )\r
475         {\r
476           *pmove = To2Move(to) | From2Move(from)\r
477             | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
478           if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
479           pmove += 1;\r
480         }\r
481     }\r
482 \r
483   BBAnd( bb_piece, bb_diag2_chk, BB_BPAWN );\r
484   while ( BBToU(bb_piece) )\r
485     {\r
486       from = LastOne( bb_piece );\r
487       Xor( from, bb_piece );\r
488       \r
489       to = from - nfile;\r
490       if ( BOARD[to] != empty ) { continue; }\r
491 \r
492       bb_desti = AttackDiag2( from );\r
493       if ( BBContract( bb_desti, BB_B_BH ) )\r
494         {\r
495           *pmove = To2Move(to) | From2Move(from)\r
496             | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
497           if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
498           pmove += 1;\r
499         }\r
500     }\r
501 \r
502   BBIni( bb_chk );\r
503   bb_chk.p[0] = abb_w_gold_attacks[sq_wk].p[0];\r
504   if ( sq_wk < A2 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_wk+nfile] ); };\r
505   BBAnd( bb_chk, bb_chk, bb_move_to );\r
506   BBAnd( bb_chk, bb_chk, BB_BPAWN_ATK );\r
507   while ( BBToU(bb_chk) )\r
508     {\r
509       to = LastOne( bb_chk );\r
510       Xor( to, bb_chk );\r
511 \r
512       from = to + nfile;\r
513       *pmove = To2Move(to) | From2Move(from)\r
514         | Piece2Move(pawn) | Cap2Move(-BOARD[to]);\r
515       if ( from < A5 ) { *pmove |= FLAG_PROMO; }\r
516       pmove += 1;\r
517     }\r
518 \r
519 \r
520   if ( IsHandGold(HAND_B) )\r
521     {\r
522       BBAnd( bb_chk, bb_drop_to, abb_w_gold_attacks[sq_wk] );\r
523       while( BBToU( bb_chk ) )\r
524         {\r
525           to = LastOne( bb_chk );\r
526           Xor( to, bb_chk );\r
527           *pmove++ = To2Move(to) | Drop2Move(gold);\r
528         }\r
529     }\r
530   \r
531 \r
532   if ( IsHandSilver(HAND_B) )\r
533     {\r
534       BBAnd( bb_chk, bb_drop_to, abb_w_silver_attacks[sq_wk] );\r
535       while( BBToU( bb_chk ) )\r
536         {\r
537           to = LastOne( bb_chk );\r
538           Xor( to, bb_chk );\r
539           *pmove++ = To2Move(to) | Drop2Move(silver);\r
540         }\r
541     }\r
542   \r
543 \r
544   if ( IsHandKnight(HAND_B) && sq_wk < A2 )\r
545     {\r
546       to = sq_wk + 2*nfile - 1;\r
547       if ( aifile[sq_wk] != file1 && BOARD[to] == empty )\r
548         {\r
549           *pmove++ = To2Move(to) | Drop2Move(knight);\r
550         }\r
551 \r
552       to = sq_wk + 2*nfile + 1;\r
553       if ( aifile[sq_wk] != file9 && BOARD[to] == empty )\r
554         {\r
555           *pmove++ = To2Move(to) | Drop2Move(knight);\r
556         }\r
557     }\r
558 \r
559 \r
560   if ( IsHandPawn(HAND_B)\r
561        && sq_wk < A1\r
562        && ! ( BBToU(BB_BPAWN) & ( mask_file1 >> aifile[sq_wk] ) ) )\r
563     {\r
564       to = sq_wk + nfile;\r
565       if ( BOARD[to] == empty && ! is_mate_b_pawn_drop( __ptree__, to ) )\r
566         {\r
567           *pmove++ = To2Move(to) | Drop2Move(pawn);\r
568         }\r
569     }\r
570 \r
571 \r
572   if ( IsHandLance(HAND_B) )\r
573     {\r
574       unsigned int move;\r
575       int dist, min_dist;\r
576 \r
577       if ( (int)aifile[sq_wk] == file1\r
578            || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
579       else                                  { min_dist = 3; }\r
580 \r
581       for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
582             to += nfile, dist += 1 )\r
583         {\r
584           move = To2Move(to) | Drop2Move(lance);\r
585           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
586           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
587           *pmove++ = move;\r
588         }\r
589     }\r
590 \r
591 \r
592   if ( IsHandRook(HAND_B) )\r
593     {\r
594       unsigned int move;\r
595       int file, dist, min_dist;\r
596 \r
597       if ( (int)aifile[sq_wk] == file1\r
598            || (int)aifile[sq_wk] == file9 ) { min_dist = 2; }\r
599       else                                  { min_dist = 3; }\r
600 \r
601       for ( to = sq_wk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
602             to += nfile, dist += 1 )\r
603         {\r
604           move = To2Move(to) | Drop2Move(rook);\r
605           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
606           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
607           *pmove++ = move;\r
608         }\r
609 \r
610       for ( file = (int)aifile[sq_wk]-1, to = sq_wk-1, dist = 1;\r
611             file >= file1 && BOARD[to] == empty;\r
612             file -= 1, to -= 1, dist += 1 )\r
613         {\r
614           move = To2Move(to) | Drop2Move(rook);\r
615           if      ( dist == 1 ) { move |= MOVE_CHK_CLEAR; }\r
616           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
617           *pmove++ = move;\r
618         }\r
619 \r
620       if ( sq_wk < A8 || I2 < sq_wk ) { min_dist = 2; }\r
621       else                            { min_dist = 3; }\r
622 \r
623       for ( file = (int)aifile[sq_wk]+1, to = sq_wk+1, dist = 1;\r
624             file <= file9 && BOARD[to] == empty;\r
625             file += 1, to += 1, dist += 1 )\r
626         {\r
627           move = To2Move(to) | Drop2Move(rook);\r
628           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
629           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
630           *pmove++ = move;\r
631         }\r
632 \r
633       for ( to = sq_wk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
634             to -= nfile, dist += 1 )\r
635         {\r
636           move = To2Move(to) | Drop2Move(rook);\r
637           if ( (int)airank[to] == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
638           if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }\r
639           else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }\r
640           *pmove++ = move;\r
641         }\r
642     }\r
643 \r
644 \r
645   if ( IsHandBishop(HAND_B) )\r
646     {\r
647       unsigned int move;\r
648       int file, rank, dist;\r
649 \r
650       to   = sq_wk;\r
651       file = (int)aifile[sq_wk];\r
652       rank = (int)airank[sq_wk];\r
653       for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
654             file >= 0 && rank >= 0 && BOARD[to] == empty;\r
655             to -= 10, file -= 1, rank -= 1, dist += 1 )\r
656         {\r
657           move = To2Move(to) | Drop2Move(bishop);\r
658           if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
659           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
660           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
661           *pmove++ = move;\r
662         }\r
663 \r
664       to   = sq_wk;\r
665       file = (int)aifile[sq_wk];\r
666       rank = (int)airank[sq_wk];\r
667       for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
668             file <= file9 && rank >= 0 && BOARD[to] == empty;\r
669             to -= 8, file += 1, rank -= 1, dist += 1 )\r
670         {\r
671           move = To2Move(to) | Drop2Move(bishop);\r
672           if ( rank == rank3 ) { move |= MOVE_CHK_CLEAR; }\r
673           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
674           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
675           *pmove++ = move;\r
676         }\r
677 \r
678       to   = sq_wk;\r
679       file = (int)aifile[sq_wk];\r
680       rank = (int)airank[sq_wk];\r
681       for ( to += 8, file -= 1, rank += 1, dist = 1;\r
682             file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
683             to += 8, file -= 1, rank += 1, dist += 1 )\r
684         {\r
685           move = To2Move(to) | Drop2Move(bishop);\r
686           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
687           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
688           *pmove++ = move;\r
689         }\r
690 \r
691       to   = sq_wk;\r
692       file = (int)aifile[sq_wk];\r
693       rank = (int)airank[sq_wk];\r
694       for ( to += 10, file += 1, rank += 1, dist = 1;\r
695             file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
696             to += 10, file += 1, rank += 1, dist += 1 )\r
697         {\r
698           move = To2Move(to) | Drop2Move(bishop);\r
699           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
700           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
701           *pmove++ = move;\r
702         }\r
703     }\r
704 \r
705 \r
706   return pmove;\r
707 }\r
708 \r
709 \r
710 unsigned int *\r
711 w_gen_checks( tree_t * restrict __ptree__, unsigned int * restrict pmove )\r
712 {\r
713   bitboard_t bb_piece, bb_rook_chk, bb_bishop_chk, bb_chk, bb_move_to;\r
714   bitboard_t bb_diag1_chk, bb_diag2_chk, bb_file_chk, bb_drop_to, bb_desti;\r
715   const tree_t * restrict ptree = __ptree__;\r
716   unsigned int u0, u1, u2;\r
717   int from, to, sq_bk, idirec;\r
718 \r
719   sq_bk = SQ_BKING;\r
720   bb_rook_chk = bb_file_chk = AttackFile( sq_bk );\r
721   bb_rook_chk.p[aslide[sq_bk].ir0] |= AttackRank( sq_bk );\r
722   bb_diag1_chk = AttackDiag1( sq_bk );\r
723   bb_diag2_chk = AttackDiag2( sq_bk );\r
724   AttackBishop( bb_bishop_chk, sq_bk );\r
725   BBNot( bb_move_to, BB_WOCCUPY );\r
726   BBOr( bb_drop_to, BB_BOCCUPY, BB_WOCCUPY );\r
727   BBNot( bb_drop_to, bb_drop_to );\r
728 \r
729 \r
730   from  = SQ_WKING;\r
731   idirec = (int)adirec[sq_bk][from];\r
732   if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
733     {\r
734       BBIni( bb_chk );\r
735       bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
736       BBAnd( bb_chk, bb_chk, abb_king_attacks[from] );\r
737       BBAnd( bb_chk, bb_chk, bb_move_to );\r
738 \r
739       while( BBToU( bb_chk ) )\r
740         {\r
741           to = FirstOne( bb_chk );\r
742           Xor( to, bb_chk );\r
743           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(king)\r
744             | Cap2Move(BOARD[to]);\r
745         }\r
746     }\r
747 \r
748 \r
749   bb_piece = BB_WDRAGON;\r
750   while( BBToU( bb_piece ) )\r
751     {\r
752       from = FirstOne( bb_piece );\r
753       Xor( from, bb_piece );\r
754 \r
755       BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
756       idirec = (int)adirec[sq_bk][from];\r
757       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
758         {\r
759           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
760         }\r
761 \r
762       AttackDragon( bb_desti, from );\r
763       BBAnd( bb_chk, bb_chk, bb_desti );\r
764       BBAnd( bb_chk, bb_chk, bb_move_to );\r
765 \r
766       while( BBToU( bb_chk ) )\r
767         {\r
768           to = LastOne( bb_chk );\r
769           Xor( to, bb_chk );\r
770           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(dragon)\r
771             | Cap2Move(BOARD[to]);\r
772         }\r
773     }\r
774 \r
775 \r
776   bb_piece = BB_WHORSE;\r
777   while( BBToU( bb_piece ) )\r
778     {\r
779       from = FirstOne( bb_piece );\r
780       Xor( from, bb_piece );\r
781 \r
782       BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
783       idirec = (int)adirec[sq_bk][from];\r
784       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
785         {\r
786           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
787         }\r
788 \r
789       AttackHorse( bb_desti, from );\r
790       BBAnd( bb_chk, bb_chk, bb_desti );\r
791       BBAnd( bb_chk, bb_chk, bb_move_to );\r
792 \r
793       while( BBToU( bb_chk ) )\r
794         {\r
795           to = FirstOne( bb_chk );\r
796           Xor( to, bb_chk );\r
797           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(horse)\r
798             | Cap2Move(BOARD[to]);\r
799         }\r
800     }\r
801 \r
802   u0 = BB_WROOK.p[0];\r
803   u1 = BB_WROOK.p[1];\r
804   while( u0 | u1 )\r
805     {\r
806       from = first_one01( u0, u1 );\r
807       u0   ^= abb_mask[from].p[0];\r
808       u1   ^= abb_mask[from].p[1];\r
809 \r
810       AttackRook( bb_desti, from );\r
811 \r
812       idirec = (int)adirec[sq_bk][from];\r
813       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
814         {\r
815           BBAnd( bb_chk, bb_desti, bb_move_to );\r
816         }\r
817       else {\r
818         bb_chk       = bb_rook_chk;\r
819         bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
820         BBAnd( bb_chk, bb_chk, bb_desti );\r
821         BBAnd( bb_chk, bb_chk, bb_move_to );\r
822       }\r
823 \r
824       while ( bb_chk.p[2] )\r
825         {\r
826           to          = first_one2( bb_chk.p[2] );\r
827           bb_chk.p[2] ^= abb_mask[to].p[2];\r
828           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
829             | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
830         }\r
831 \r
832       while( bb_chk.p[0] | bb_chk.p[1] )\r
833         {\r
834           to          = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
835           bb_chk.p[0] ^= abb_mask[to].p[0];\r
836           bb_chk.p[1] ^= abb_mask[to].p[1];\r
837           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
838             | Cap2Move(BOARD[to]);\r
839         }\r
840     }\r
841 \r
842   u2 = BB_WROOK.p[2];\r
843   while( u2 )\r
844     {\r
845       from = first_one2( u2 );\r
846       u2   ^= abb_mask[from].p[2];\r
847       \r
848       AttackRook( bb_desti, from );\r
849 \r
850       idirec = (int)adirec[sq_bk][from];\r
851       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
852         {\r
853           BBAnd( bb_chk, bb_desti, bb_move_to );\r
854         }\r
855       else {\r
856         BBOr( bb_chk, bb_rook_chk, abb_king_attacks[sq_bk] );\r
857         BBAnd( bb_chk, bb_chk, bb_desti );\r
858         BBAnd( bb_chk, bb_chk, bb_move_to );\r
859       }\r
860 \r
861       while( BBToU( bb_chk ) )\r
862         {\r
863           to = FirstOne( bb_chk );\r
864           Xor( to, bb_chk );\r
865           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(rook)\r
866             | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
867         }\r
868     }\r
869 \r
870   u0 = BB_WBISHOP.p[0];\r
871   u1 = BB_WBISHOP.p[1];\r
872   while( u0 | u1 )\r
873     {\r
874       from = first_one01( u0, u1 );\r
875       u0   ^= abb_mask[from].p[0];\r
876       u1   ^= abb_mask[from].p[1];\r
877 \r
878       AttackBishop( bb_desti, from );\r
879 \r
880       idirec = (int)adirec[sq_bk][from];\r
881       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
882         {\r
883           BBAnd( bb_chk, bb_desti, bb_move_to );\r
884         }\r
885       else {\r
886         bb_chk       = bb_bishop_chk;\r
887         bb_chk.p[2] |= abb_king_attacks[sq_bk].p[2];\r
888         BBAnd( bb_chk, bb_chk, bb_desti );\r
889         BBAnd( bb_chk, bb_chk, bb_move_to );\r
890       }\r
891 \r
892       while ( bb_chk.p[2] )\r
893         {\r
894           to          = first_one2( bb_chk.p[2] );\r
895           bb_chk.p[2] ^= abb_mask[to].p[2];\r
896           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
897             | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
898         }\r
899 \r
900       while( bb_chk.p[0] | bb_chk.p[1] )\r
901         {\r
902           to          = first_one01( bb_chk.p[0], bb_chk.p[1] );\r
903           bb_chk.p[0] ^= abb_mask[to].p[0];\r
904           bb_chk.p[1] ^= abb_mask[to].p[1];\r
905           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
906             | Cap2Move(BOARD[to]);\r
907         }\r
908     }\r
909 \r
910   u2 = BB_WBISHOP.p[2];\r
911   while( u2 )\r
912     {\r
913       from = first_one2( u2 );\r
914       u2   ^= abb_mask[from].p[2];\r
915       \r
916       AttackBishop( bb_desti, from );\r
917 \r
918       idirec = (int)adirec[sq_bk][from];\r
919       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
920         {\r
921           BBAnd( bb_chk, bb_desti, bb_move_to );\r
922         }\r
923       else {\r
924         BBOr( bb_chk, bb_bishop_chk, abb_king_attacks[sq_bk] );\r
925         BBAnd( bb_chk, bb_chk, bb_desti );\r
926         BBAnd( bb_chk, bb_chk, bb_move_to );\r
927       }\r
928 \r
929       while( BBToU( bb_chk ) )\r
930         {\r
931           to = FirstOne( bb_chk );\r
932           Xor( to, bb_chk );\r
933           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(bishop)\r
934             | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
935         }\r
936     }\r
937 \r
938 \r
939   bb_piece = BB_WTGOLD;\r
940   while( BBToU( bb_piece ) )\r
941     {\r
942       from = FirstOne( bb_piece );\r
943       Xor( from, bb_piece );\r
944 \r
945       bb_chk = abb_b_gold_attacks[sq_bk];\r
946 \r
947       idirec = (int)adirec[sq_bk][from];\r
948       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
949         {\r
950           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
951         }\r
952 \r
953       BBAnd( bb_chk, bb_chk, abb_w_gold_attacks[from] );\r
954       BBAnd( bb_chk, bb_chk, bb_move_to );\r
955 \r
956       while( BBToU( bb_chk ) )\r
957         {\r
958           to = FirstOne( bb_chk );\r
959           Xor( to, bb_chk );\r
960           *pmove++ = ( To2Move(to) | From2Move(from)\r
961                        | Piece2Move(-BOARD[from])\r
962                        | Cap2Move(BOARD[to]) );\r
963         }\r
964     }\r
965 \r
966   \r
967   u2 = BB_WSILVER.p[2];\r
968   while( u2 )\r
969     {\r
970       from = first_one2( u2 );\r
971       u2   ^= abb_mask[from].p[2];\r
972 \r
973       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
974       bb_chk.p[1] = abb_b_gold_attacks[sq_bk].p[1];\r
975       bb_chk.p[0] = 0;\r
976 \r
977       idirec = (int)adirec[sq_bk][from];\r
978       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
979         {\r
980           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
981         }\r
982 \r
983       bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
984       bb_chk.p[1] &= bb_move_to.p[1] & abb_w_silver_attacks[from].p[1];\r
985 \r
986       while( bb_chk.p[2] | bb_chk.p[1] )\r
987         {\r
988           to          = first_one12( bb_chk.p[1], bb_chk.p[2] );\r
989           bb_chk.p[1] ^= abb_mask[to].p[1];\r
990           bb_chk.p[2] ^= abb_mask[to].p[2];\r
991           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
992             | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
993         }\r
994     }\r
995   \r
996 \r
997   u1 = BB_WSILVER.p[1] & 0x1ffU;\r
998   while( u1 )\r
999     {\r
1000       from = first_one1( u1 );\r
1001       u1   ^= abb_mask[from].p[1];\r
1002       \r
1003       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
1004       bb_chk.p[1] = bb_chk.p[0] = 0;\r
1005       \r
1006       idirec = (int)adirec[sq_bk][from];\r
1007       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
1008         {\r
1009           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
1010         }\r
1011 \r
1012       bb_chk.p[2] &= bb_move_to.p[2] & abb_w_silver_attacks[from].p[2];\r
1013       while ( bb_chk.p[2] )\r
1014         {\r
1015           to          = first_one2( bb_chk.p[2] );\r
1016           bb_chk.p[2] ^= abb_mask[to].p[2];\r
1017           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
1018             | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
1019         }\r
1020     }\r
1021   \r
1022 \r
1023   bb_piece = BB_WSILVER;\r
1024   while( BBToU( bb_piece ) )\r
1025     {\r
1026       from = FirstOne( bb_piece );\r
1027       Xor( from, bb_piece );\r
1028 \r
1029       bb_chk = abb_b_silver_attacks[sq_bk];\r
1030 \r
1031       idirec = (int)adirec[sq_bk][from];\r
1032       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
1033         {\r
1034           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
1035         }\r
1036 \r
1037       BBAnd( bb_chk, bb_chk, abb_w_silver_attacks[from] );\r
1038       BBAnd( bb_chk, bb_chk, bb_move_to );\r
1039 \r
1040       while( BBToU( bb_chk ) )\r
1041         {\r
1042           to = FirstOne( bb_chk );\r
1043           Xor( to, bb_chk );\r
1044           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(silver)\r
1045             | Cap2Move(BOARD[to]);\r
1046         }\r
1047     }\r
1048 \r
1049   \r
1050   u2 = BB_WKNIGHT.p[2];\r
1051   u1 = BB_WKNIGHT.p[1] & 0x3ffffU;\r
1052   while( u2 | u1 )\r
1053     {\r
1054       from = first_one12( u1, u2 );\r
1055       u2   ^= abb_mask[from].p[2];\r
1056       u1   ^= abb_mask[from].p[1];\r
1057 \r
1058       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
1059       bb_chk.p[1] = bb_chk.p[0] = 0;\r
1060 \r
1061       idirec = (int)adirec[sq_bk][from];\r
1062       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
1063         {\r
1064           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
1065         }\r
1066 \r
1067       bb_chk.p[2] &= abb_w_knight_attacks[from].p[2] & bb_move_to.p[2];\r
1068 \r
1069       while( bb_chk.p[2] )\r
1070         {\r
1071           to          = first_one2( bb_chk.p[2] );\r
1072           bb_chk.p[2] ^= abb_mask[to].p[2];\r
1073           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
1074                        | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
1075         }\r
1076     }\r
1077   \r
1078 \r
1079   u0 = BB_WKNIGHT.p[0];\r
1080   u1 = BB_WKNIGHT.p[1] & 0x7fffe00U;\r
1081   while( u0 | u1 )\r
1082     {\r
1083       from = first_one01( u0, u1 );\r
1084       u0   ^= abb_mask[from].p[0];\r
1085       u1   ^= abb_mask[from].p[1];\r
1086 \r
1087       bb_chk = abb_b_knight_attacks[sq_bk];\r
1088 \r
1089       idirec = (int)adirec[sq_bk][from];\r
1090       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
1091         {\r
1092           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
1093         }\r
1094 \r
1095       BBAnd( bb_chk, bb_chk, abb_w_knight_attacks[from] );\r
1096       BBAnd( bb_chk, bb_chk, bb_move_to );\r
1097 \r
1098       while( BBToU( bb_chk ) )\r
1099         {\r
1100           to = FirstOne( bb_chk );\r
1101           Xor( to, bb_chk );\r
1102           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(knight)\r
1103             | Cap2Move(BOARD[to]);\r
1104         }\r
1105     }\r
1106 \r
1107 \r
1108   bb_piece = BB_WLANCE;\r
1109   while( BBToU( bb_piece ) )\r
1110     {\r
1111       from = FirstOne( bb_piece );\r
1112       Xor( from, bb_piece );\r
1113 \r
1114       bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
1115       bb_chk.p[1] = bb_chk.p[0] = 0;\r
1116 \r
1117       idirec = (int)adirec[sq_bk][from];\r
1118       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
1119         {\r
1120           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
1121         }\r
1122 \r
1123       BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
1124       BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
1125       BBAnd( bb_chk, bb_chk, bb_move_to );\r
1126 \r
1127       while( BBToU( bb_chk ) )\r
1128         {\r
1129           to = FirstOne( bb_chk );\r
1130           Xor( to, bb_chk );\r
1131           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
1132             | Cap2Move(BOARD[to]) | FLAG_PROMO;\r
1133         }\r
1134     }\r
1135   \r
1136 \r
1137   u0 = BB_WLANCE.p[0];\r
1138   u1 = BB_WLANCE.p[1];\r
1139   while( u0 | u1 )\r
1140     {\r
1141       from = first_one01( u0, u1 );\r
1142       u0   ^= abb_mask[from].p[0];\r
1143       u1   ^= abb_mask[from].p[1];\r
1144 \r
1145       bb_chk = bb_file_chk;\r
1146       idirec = (int)adirec[sq_bk][from];\r
1147       if ( idirec && is_pinned_on_black_king( ptree, from, idirec ) )\r
1148         {\r
1149           bb_chk = add_behind_attacks( idirec, sq_bk, bb_chk );\r
1150           BBAnd( bb_chk, bb_chk, abb_plus_rays[from] );\r
1151         }\r
1152       else { BBAnd( bb_chk, bb_file_chk, abb_minus_rays[sq_bk] ); }\r
1153 \r
1154       BBAnd( bb_chk, bb_chk, AttackFile( from ) );\r
1155       BBAnd( bb_chk, bb_chk, bb_move_to );\r
1156       bb_chk.p[2] = bb_chk.p[2] & 0x7fc0000U;\r
1157 \r
1158       while( BBToU( bb_chk ) )\r
1159         {\r
1160           to = FirstOne( bb_chk );\r
1161           Xor( to, bb_chk );\r
1162           *pmove++ = To2Move(to) | From2Move(from) | Piece2Move(lance)\r
1163             | Cap2Move(BOARD[to]);\r
1164         }\r
1165     }\r
1166 \r
1167 \r
1168   BBAnd( bb_piece, bb_diag1_chk, BB_WPAWN );\r
1169   while ( BBToU(bb_piece) )\r
1170     {\r
1171       from = FirstOne( bb_piece );\r
1172       Xor( from, bb_piece );\r
1173       \r
1174       to = from + nfile;\r
1175       if ( BOARD[to] != empty ) { continue; }\r
1176 \r
1177       bb_desti = AttackDiag1( from );\r
1178       if ( BBContract( bb_desti, BB_W_BH ) )\r
1179         {\r
1180           *pmove = To2Move(to) | From2Move(from)\r
1181             | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
1182           if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
1183           pmove += 1;\r
1184         }\r
1185     }\r
1186 \r
1187   BBAnd( bb_piece, bb_diag2_chk, BB_WPAWN );\r
1188   while ( BBToU(bb_piece) )\r
1189     {\r
1190       from = FirstOne( bb_piece );\r
1191       Xor( from, bb_piece );\r
1192       \r
1193       to = from + nfile;\r
1194       if ( BOARD[to] != empty ) { continue; }\r
1195 \r
1196       bb_desti = AttackDiag2( from );\r
1197       if ( BBContract( bb_desti, BB_W_BH ) )\r
1198         {\r
1199           *pmove = To2Move(to) | From2Move(from)\r
1200             | Piece2Move(pawn) | Cap2Move(BOARD[to]);\r
1201           if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
1202           pmove += 1;\r
1203         }\r
1204     }\r
1205 \r
1206   BBIni( bb_chk );\r
1207   bb_chk.p[2] = abb_b_gold_attacks[sq_bk].p[2];\r
1208   if ( sq_bk > I8 ) { BBOr( bb_chk, bb_chk, abb_mask[sq_bk-nfile] ); };\r
1209   BBAnd( bb_chk, bb_chk, bb_move_to );\r
1210   BBAnd( bb_chk, bb_chk, BB_WPAWN_ATK );\r
1211   while ( BBToU(bb_chk) )\r
1212     {\r
1213       to = FirstOne( bb_chk );\r
1214       Xor( to, bb_chk );\r
1215 \r
1216       from = to - nfile;\r
1217       *pmove = To2Move(to) | From2Move(from) | Piece2Move(pawn)\r
1218         | Cap2Move(BOARD[to]);\r
1219       if ( from > I5 ) { *pmove |= FLAG_PROMO; }\r
1220       pmove += 1;\r
1221     }\r
1222 \r
1223 \r
1224   if ( IsHandGold(HAND_W) )\r
1225     {\r
1226       BBAnd( bb_chk, bb_drop_to, abb_b_gold_attacks[sq_bk] );\r
1227       while( BBToU( bb_chk ) )\r
1228         {\r
1229           to = FirstOne( bb_chk );\r
1230           Xor( to, bb_chk );\r
1231           *pmove++ = To2Move(to) | Drop2Move(gold);\r
1232         }\r
1233     }\r
1234   \r
1235 \r
1236   if ( IsHandSilver(HAND_W) )\r
1237     {\r
1238       BBAnd( bb_chk, bb_drop_to, abb_b_silver_attacks[sq_bk] );\r
1239       while( BBToU( bb_chk ) )\r
1240         {\r
1241           to = FirstOne( bb_chk );\r
1242           Xor( to, bb_chk );\r
1243           *pmove++ = To2Move(to) | Drop2Move(silver);\r
1244         }\r
1245     }\r
1246   \r
1247 \r
1248   if ( IsHandKnight(HAND_W) && sq_bk > I8 )\r
1249     {\r
1250       to = sq_bk - 2*nfile - 1;\r
1251       if ( aifile[sq_bk] != file1 && BOARD[to] == empty )\r
1252         {\r
1253           *pmove++ = To2Move(to) | Drop2Move(knight);\r
1254         }\r
1255 \r
1256       to = sq_bk - 2*nfile + 1;\r
1257       if ( aifile[sq_bk] != file9 && BOARD[to] == empty )\r
1258         {\r
1259           *pmove++ = To2Move(to) | Drop2Move(knight);\r
1260         }\r
1261     }\r
1262 \r
1263 \r
1264   if ( IsHandPawn(HAND_W)\r
1265        && sq_bk > I9\r
1266        && ! ( BBToU(BB_WPAWN) & ( mask_file1 >> aifile[sq_bk] ) ) )\r
1267     {\r
1268       to = sq_bk - nfile;\r
1269       if ( BOARD[to] == empty && ! is_mate_w_pawn_drop( __ptree__, to ) )\r
1270         {\r
1271           *pmove++ = To2Move(to) | Drop2Move(pawn);\r
1272         }\r
1273     }\r
1274 \r
1275 \r
1276   if ( IsHandLance(HAND_W) )\r
1277     {\r
1278       unsigned int move;\r
1279       int dist, min_dist;\r
1280 \r
1281       if ( (int)aifile[sq_bk] == file1\r
1282            || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
1283       else                                  { min_dist = 3; }\r
1284 \r
1285       for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
1286             to -= nfile, dist += 1 )\r
1287         {\r
1288           move = To2Move(to) | Drop2Move(lance);\r
1289           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
1290           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
1291           *pmove++ = move;\r
1292         }\r
1293     }\r
1294 \r
1295 \r
1296   if ( IsHandRook(HAND_W) )\r
1297     {\r
1298       unsigned int move;\r
1299       int file, dist, min_dist;\r
1300 \r
1301       if ( (int)aifile[sq_bk] == file1\r
1302            || (int)aifile[sq_bk] == file9 ) { min_dist = 2; }\r
1303       else                                  { min_dist = 3; }\r
1304 \r
1305       for ( to = sq_bk-nfile, dist = 1; to >= 0 && BOARD[to] == empty;\r
1306             to -= nfile, dist += 1 )\r
1307         {\r
1308           move = To2Move(to) | Drop2Move(rook);\r
1309           if      ( dist == 1 )        { move |= MOVE_CHK_CLEAR; }\r
1310           else if ( dist > min_dist )  { move |= MOVE_CHK_SET; }\r
1311           *pmove++ = move;\r
1312         }\r
1313 \r
1314       for ( to = sq_bk+nfile, dist = 1; to < nsquare && BOARD[to] == empty;\r
1315             to += nfile, dist += 1 )\r
1316         {\r
1317           move = To2Move(to) | Drop2Move(rook);\r
1318           if ( (int)airank[to] == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
1319           if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }\r
1320           else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }\r
1321           *pmove++ = move;\r
1322         }\r
1323 \r
1324 \r
1325       if ( sq_bk < A8 || I2 < sq_bk ) { min_dist = 2; }\r
1326       else                            { min_dist = 3; }\r
1327 \r
1328       for ( file = (int)aifile[sq_bk]+1, to = sq_bk+1, dist = 1;\r
1329             file <= file9 && BOARD[to] == empty;\r
1330             file += 1, to += 1, dist += 1 )\r
1331         {\r
1332           move = To2Move(to) | Drop2Move(rook);\r
1333           if      ( dist == 1 )       { move |= MOVE_CHK_CLEAR; }\r
1334           else if ( dist > min_dist ) { move |= MOVE_CHK_SET; }\r
1335           *pmove++ = move;\r
1336         }\r
1337 \r
1338       for ( file = (int)aifile[sq_bk]-1, to = sq_bk-1, dist = 1;\r
1339             file >= file1 && BOARD[to] == empty;\r
1340             file -= 1, to -= 1, dist += 1 )\r
1341         {\r
1342           move = To2Move(to) | Drop2Move(rook);\r
1343           if      ( dist == 1 )           { move |= MOVE_CHK_CLEAR; }\r
1344           else if ( dist > min_dist )     { move |= MOVE_CHK_SET; }\r
1345           *pmove++ = move;\r
1346         }\r
1347     }\r
1348 \r
1349 \r
1350   if ( IsHandBishop(HAND_W) )\r
1351     {\r
1352       unsigned int move;\r
1353       int file, rank, dist;\r
1354 \r
1355       to   = sq_bk;\r
1356       file = (int)aifile[sq_bk];\r
1357       rank = (int)airank[sq_bk];\r
1358       for ( to += 10, file += 1, rank += 1, dist = 1;\r
1359             file <= file9 && rank <= rank9 && BOARD[to] == empty;\r
1360             to += 10, file += 1, rank += 1, dist += 1 )\r
1361         {\r
1362           move = To2Move(to) | Drop2Move(bishop);\r
1363           if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
1364           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
1365           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
1366           *pmove++ = move;\r
1367         }\r
1368 \r
1369       to   = sq_bk;\r
1370       file = (int)aifile[sq_bk];\r
1371       rank = (int)airank[sq_bk];\r
1372       for ( to += 8, file -= 1, rank += 1, dist = 1;\r
1373             file >= 0 && rank <= rank9 && BOARD[to] == empty;\r
1374             to += 8, file -= 1, rank += 1, dist += 1 )\r
1375         {\r
1376           move = To2Move(to) | Drop2Move(bishop);\r
1377           if ( rank == rank7 ) { move |= MOVE_CHK_CLEAR; }\r
1378           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
1379           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
1380           *pmove++ = move;\r
1381         }\r
1382 \r
1383       to   = sq_bk;\r
1384       file = (int)aifile[sq_bk];\r
1385       rank = (int)airank[sq_bk];\r
1386       for ( to -= 8, file += 1, rank -= 1, dist = 1;\r
1387             file <= file9 && rank >= 0 && BOARD[to] == empty;\r
1388             to -= 8, file += 1, rank -= 1, dist += 1 )\r
1389         {\r
1390           move = To2Move(to) | Drop2Move(bishop);\r
1391           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
1392           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
1393           *pmove++ = move;\r
1394         }\r
1395 \r
1396       to   = sq_bk;\r
1397       file = (int)aifile[sq_bk];\r
1398       rank = (int)airank[sq_bk];\r
1399       for ( to -= 10, file -= 1, rank -= 1, dist = 1;\r
1400             file >= 0 && rank >= 0 && BOARD[to] == empty;\r
1401             to -= 10, file -= 1, rank -= 1, dist += 1 )\r
1402         {\r
1403           move = To2Move(to) | Drop2Move(bishop);\r
1404           if ( dist == 1 )     { move |= MOVE_CHK_CLEAR; }\r
1405           else if ( dist > 2 ) { move |= MOVE_CHK_SET; }\r
1406           *pmove++ = move;\r
1407         }\r
1408     }\r
1409 \r
1410 \r
1411   return pmove;\r
1412 }\r
1413 \r
1414 \r
1415 static bitboard_t\r
1416 add_behind_attacks( int idirec, int ik, bitboard_t bb )\r
1417 {\r
1418   bitboard_t bb_tmp;\r
1419 \r
1420   if ( idirec == direc_diag1 )\r
1421     {\r
1422       bb_tmp = abb_bishop_attacks_rr45[ik][0];\r
1423     }\r
1424   else if ( idirec == direc_diag2 )\r
1425     {\r
1426       bb_tmp = abb_bishop_attacks_rl45[ik][0];\r
1427     }\r
1428   else if ( idirec == direc_file )\r
1429     {\r
1430       bb_tmp = abb_file_attacks[ik][0];\r
1431     }\r
1432   else {\r
1433     assert( idirec == direc_rank );\r
1434     BBIni( bb_tmp );\r
1435     bb_tmp.p[aslide[ik].ir0] = ai_rook_attacks_r0[ik][0];\r
1436   }\r
1437   BBNot( bb_tmp, bb_tmp );\r
1438   BBOr( bb, bb, bb_tmp );\r
1439 \r
1440   return bb;\r
1441 }\r