My Project
addEffectWithEffect.tcc
Go to the documentation of this file.
1#ifndef _GENERATER_ADD_EFFECT_WITH_EFFECT_TCC
2#define _GENERATER_ADD_EFFECT_WITH_EFFECT_TCC
3
4#include "osl/move_generator/addEffectWithEffect.h"
5#include "osl/move_generator/open.h"
6#include "osl/move_generator/open.tcc"
7#include "osl/move_generator/pieceOnBoard.tcc"
8
9//#define GENERATE_PAWNDROP_CHECKMATE
10
11namespace osl
12{
13 namespace move_generator
14 {
15 namespace detail
16 {
17 /**
18 * マスtoに移動可能な駒pを移動する手を生成する.
19 * ptypeMaskで指定されたptypeになる場合以外は手を生成しない.
20 * @param state - 盤面
21 * @param p - 利きを持つコマ
22 * @param to - 目的のマス
23 * @param toP - 目的のマスに現在ある駒(又は空白)
24 * @param action - 手生成のaction(典型的にはstoreかfilterつきstore)
25 * @param ptypeMask - 移動後の駒のptypeに対応するbitが1なら手を生成する
26 * should promoteは?
27 * 呼び出す時はpinnedの場合のunsafeなdirectionは排除済み
28 */
29 template<osl::Player P,class Action>
30 void generateMovePiecePtypeMask(const NumEffectState& state,Piece p,Square to,Piece toP,Action& action,unsigned int ptypeMask)
31 {
32 assert(p.isOnBoardByOwner<P>());
33 assert(toP==state.pieceAt(to));
34 Ptype ptype=p.ptype();
35 Square from=p.square();
36 if(canPromote(ptype) &&
37 (to.canPromote<P>() || from.canPromote<P>())){
38 Ptype pptype=osl::promote(ptype);
39 if(((1<<pptype)&ptypeMask)!=0)
40 action.unknownMove(from,to,toP,pptype,true,P);
41 if(Move::ignoreUnpromote<P>(ptype,from,to)) return;
42 }
43 //
44 if(((1<<ptype)&ptypeMask)!=0)
45 action.unknownMove(p.square(),to,toP,ptype,false,P);
46 }
47 /**
48 * あるマスに利きを持つすべての駒の中で,
49 * ptypeMaskで指定されたptypeになる場合は移動する手を生成する
50 * @param state - 盤面
51 * @param to - 目的のマス
52 * @param toP - 目的のマスに現在ある駒(又は空白)
53 * @param action - 手生成のaction(典型的にはstoreかfilterつきstore)
54 * @param ptypeMask - 移動後の駒のptypeに対応するbitが1なら手を生成する
55 * pinnedの場合は移動する手が1手もない場合もある.
56 */
57 template<osl::Player P,class Action>
58 void generateMoveToPtypeMaskWithPieceMask(const NumEffectState& state,Square to,Piece toP,Action& action,unsigned int ptypeMask,PieceMask pieceMask)
59 {
60 if(pieceMask.test(KingTraits<P>::index)){
61 const Player altP=alt(P);
62 if(!state.hasEffectAt<altP>(to)){
63 action.unknownMove(state.kingSquare<P>(),to,toP,KING,false,P);
64 }
65 pieceMask.reset(KingTraits<P>::index);
66 }
67 while (pieceMask.any()){
68 const int num=pieceMask.takeOneBit();
69 Piece p=state.pieceOf(num);
70 if(state.pinOrOpen(P).test(num)){
71 Direction d=state.pinnedDir<P>(p);
72 Direction d1=Board_Table.template getShort8Unsafe<P>(p.square(),to);
73 if(primDir(d)!=primDirUnsafe(d1)) continue;
74 }
75 generateMovePiecePtypeMask<P,Action>(state,p,to,toP,action,ptypeMask);
76 }
77 }
78 template<osl::Player P,class Action>
79 void generateMoveToPtypeMask(const NumEffectState& state,Square to,Piece toP,Action& action,unsigned int ptypeMask)
80 {
81 PieceMask pieceMask=state.piecesOnBoard(P)&state.effectSetAt(to);
82 const Player altP=alt(P);
83 pieceMask.reset(KingTraits<P>::index); // 玉は除く
84 pieceMask &= ~state.pinOrOpen(altP); // open atackからのものを除く
85 generateMoveToPtypeMaskWithPieceMask<P,Action>(state,to,toP,action,ptypeMask,pieceMask);
86 }
87#ifndef GENERATE_PAWNDROP_CHECKMATE
88 /**
89 * 敵玉の前に歩を置いた場合に遮った利きで敵玉にlibertyが生まれるかどうか?
90 */
91 template<osl::Player P>
92 bool
93#ifdef __GNUC__
94 __attribute__ ((pure))
95#endif
96 blockingU(const NumEffectState& state,Square pos)
97 {
98 const osl::Player altP=alt(P);
99 NumBitmapEffect effect=state.effectSetAt(pos);
100 mask_t mask=(effect.getMask(1)& NumBitmapEffect::longEffectMask());
101 mask&=state.piecesOnBoard(P).getMask(1)<<8; // ROOK, BISHOPの利きのみのはず
102 while(mask.any()){
103 int num=mask.takeOneBit()+NumBitmapEffect::longToNumOffset;
104 Square from=state.pieceOf(num).square();
105 if( (P==BLACK ? from.y()>=pos.y() : pos.y()>=from.y()) ){
106 Square shadowPos=pos+Board_Table.getShortOffset(Offset32(pos,from));
107 assert((P==BLACK ? shadowPos.y()<=pos.y() : pos.y()<=shadowPos.y()) );
108 Piece p=state.pieceAt(shadowPos);
109 if(p.canMoveOn<altP>() && !state.hasMultipleEffectAt(P,shadowPos)){
110 return true;
111 }
112 }
113 }
114 return false;
115 }
116#endif
117 /**
118 * int DirType : 0 - U
119 * 1 - LRD
120 * 2 - UL,UR,DL,DR
121 * dirOffset = DirectionPlayerTraits<Dir,P>::offset()
122 */
123 template<osl::Player P,int DirType,class Action>
124 void generateDir(const NumEffectState& state,Square target,Action& action,bool& hasPawnCheckmate,Offset dirOffset,Direction Dir,Direction primDir,int ptypeMaskNotKing)
125 {
126 const Player altP=alt(P);
127 Square pos=target-dirOffset;
128 if(!pos.isOnBoard()) return;
129 Piece p=state.pieceAt(pos);
130 if(p.isOnBoardByOwner<P>()){
131 if(DirType==0 && state.hasLongEffectAt<LANCE>(P,pos)){
132 PieceOnBoard<Action>::template generate<P,true>(state,p,action,1<<primDir);
133 }
134 return;
135 }
136 if((state.Iking8Info(altP)&(1ull<<(40+Dir)))!=0){
137 // - posに利きがある
138 // TODO safe moveではない
139 generateMoveToPtypeMask<P,Action>(state,pos,p,action,
140 ptypeMaskNotKing);
141 }
142 if(DirType !=0) return;
143 if(p.isEmpty()){
144 Square pos1=state.kingMobilityOfPlayer(altP,Dir);
145 mask_t lance_mask=state.longEffectAt<LANCE>(pos1,P);
146 if(lance_mask.any()){
147 Piece p1=state.pieceAt(pos1);
148 if(p1.isOnBoardByOwner<P>()){
149 PieceOnBoard<Action>::template generate<P,true>(state,p1,action,1<<primDir);
150 //
151 if(state.hasEffectByPiece(p1,pos)){
152 PieceOnBoard<Action>::template generatePiece<P>(state,p1,pos,Piece::EMPTY(),action);
153 }
154 }
155 else if(p1.isOnBoardByOwner<altP>()){
156 assert(!lance_mask.hasMultipleBit());
157 int num=lance_mask.bsf()+PtypeFuns<LANCE>::indexNum*32;
158 Piece p2=state.pieceOf(num);
159 if(!state.pinOrOpen(P).test(num) ||
160 state.kingSquare<P>().isUD(p2.square())){
161 action.unknownMove(p2.square(),pos1,p1,LANCE,false,P);
162 }
163 }
164 }
165 // - PAWN, LANCEはここで調べる?
166 // + ただしPAWNはつみは禁止
167 if(! state.isPawnMaskSet<P>(target.x()) &&
168 state.hasPieceOnStand<PAWN>(P)){
169 // 利きをさえぎるパターンの検証
170#ifndef GENERATE_PAWNDROP_CHECKMATE
171 if(((state.Iking8Info(altP)&(0xff00ull|(1ull<<(U+24))))^(1ull<<(U+24)))!=0 || blockingU<P>(state,pos))
172 action.dropMove(pos,PAWN,P);
173 else
174 hasPawnCheckmate=true;
175#else
176 action.dropMove(pos,PAWN,P);
177#endif
178 }
179 if(state.hasPieceOnStand<LANCE>(P)){
180 action.dropMove(pos,LANCE,P);
181 for(pos-=DirectionPlayerTraits<U,P>::offset();
182 pos!=pos1;pos-=DirectionPlayerTraits<U,P>::offset()){
183 action.dropMove(pos,LANCE,P);
184 }
185 }
186 }
187 }
188
189 template<osl::Player P,int DirType,class Action,Direction Dir>
190 void generateDir(const NumEffectState& state,Square target,Action& action,bool& hasPawnCheckmate)
191 {
192 generateDir<P,DirType,Action>(state,target,action,hasPawnCheckmate,
193 DirectionPlayerTraits<Dir,P>::offset(),Dir,DirectionTraits<Dir>::primDir,DirectionTraits<Dir>::ptypeMaskNotKing);
194 }
195 /**
196 * int DirType : 0 - U
197 * 1 - LRD
198 * 2 - UL,UR,DL,DR
199 * dirOffset = DirectionPlayerTraits<Dir,P>::offset()
200 */
201 template<osl::Player P,int DirType,class Action>
202 void generateDirNotKing(const NumEffectState& state,Square target,Action& action,CArray<unsigned char,8>& pieceMobility, int& spaces, PieceMask const& notPieceMask,Offset dirOffset,Direction Dir,Direction primDir,int ptypeMask,Direction dirByBlack
203 )
204 {
205 const Player altP=alt(P);
206 Square pos=target-dirOffset;
207 if(!pos.isOnBoard()){
208 pieceMobility[dirByBlack]=pos.uintValue();
209 return;
210 }
211 Piece p=state.pieceAt(pos);
212 if(p.canMoveOn<P>()){
213 // - posに利きがある
214 const PieceMask pieceMask=state.piecesOnBoard(P)&state.effectSetAt(pos)&notPieceMask & ~state.effectSetAt(target);
215 if(pieceMask.any())
216 detail:: template generateMoveToPtypeMaskWithPieceMask<P,Action>(state,pos,p,action,
217 ptypeMask,pieceMask);
218 }
219 Square nextSquare=pos;
220 if(p.isEmpty()){
221 spaces|=(1u<<Dir);
222 if(DirType==0 && ! state.isPawnMaskSet<P>(target.x()) &&
223 state.hasPieceOnStand<PAWN>(P))
224 action.dropMove(pos,PAWN,P);
225 do{
226 pos-=dirOffset;
227 p=state.pieceAt(pos);
228 } while(p.isEmpty());
229 }
230 if(p.isOnBoardByOwner<P>() && state.hasEffectByPiece(p,target)){
231 for(;;){
232 Piece p1=state.findLongAttackAt(P,p,inverse(Dir));
233 if(!p1.isOnBoardByOwner<P>()){
234 break;
235 }
236 p=p1;
237 }
238 pos=p.square()-dirOffset;
239 while((p=state.pieceAt(pos)).isEmpty())
240 pos-=dirOffset;
241 }
242 else if (p.isOnBoardByOwner<altP>() && state.hasEffectByPiece(p,target)){
243 // shadowは1つだけ見る
244 Piece p1=state.findLongAttackAt(altP,p,Dir);
245 if(p1.isOnBoardByOwner<P>()){
246 if(pos!=nextSquare){
247 if(p1.ptype()==LANCE){
248 int num=p1.number();
249 if(!state.pinOrOpen(P).test(num) ||
250 p1.square().isUD(state.kingSquare<P>())){
251 action.unknownMove(p1.square(),pos,p,LANCE,false,P);
252 }
253 }
254 else
255 PieceOnBoard<Action>::template generatePiece<P>(state,p1,pos,p,action);
256 }
257 pos=p1.square();
258 p=p1;
259 }
260 else{
261 pos=p.square()-dirOffset;
262 while((p=state.pieceAt(pos)).isEmpty())
263 pos-=dirOffset;
264 }
265 }
266 pieceMobility[dirByBlack]=pos.uintValue();
267 if(p.isOnBoardByOwner<P>()){
268 Piece p1=state.findLongAttackAt(P,p,inverse(Dir));
269 if(p1.isOnBoardByOwner<P>()){
270 Open<Action>::template generate<P>(state,p,action,target,primDir);
271 }
272 }
273 else if(p.isOnBoardByOwner<altP>() && pos!=nextSquare){
274 if(DirType==0){
275 mask_t lance_mask=state.longEffectAt<LANCE>(pos,P);
276 if(lance_mask.any()){
277 assert(!lance_mask.hasMultipleBit());
278 int num=lance_mask.bsf()+PtypeFuns<LANCE>::indexNum*32;
279 Piece p2=state.pieceOf(num);
280 if(!state.pinOrOpen(P).test(num) ||
281 state.kingSquare<P>().isUD(p2.square())){
282 action.unknownMove(p2.square(),pos,p,LANCE,false,P);
283 }
284 }
285 }
286 if(DirType <= 1){
287 mask_t rook_mask=state.allEffectAt<ROOK>(P,pos);
288 while(rook_mask.any()){
289 int num=rook_mask.takeOneBit()+PtypeFuns<ROOK>::indexNum*32;
290 Piece p2=state.pieceOf(num);
291 if(p2.square()==target) continue;
292 PieceOnBoard<Action>::template generatePiece<P>(state,p2,pos,p,action);
293 }
294 }
295 if(DirType == 2){
296 mask_t bishop_mask=state.allEffectAt<BISHOP>(P,pos);
297 // 利きをチェックする必要あり
298 while(bishop_mask.any()){
299 int num=bishop_mask.takeOneBit()+PtypeFuns<BISHOP>::indexNum*32;
300 Piece p2=state.pieceOf(num);
301 if(p2.square()==target) continue;
302 PieceOnBoard<Action>::template generatePiece<P>(state,p2,pos,p,action);
303 }
304 }
305 }
306
307 // - PAWN, LANCEはここで調べる?
308 // + ただしPAWNはつみは禁止
309 if(DirType == 0){
310 if(state.hasPieceOnStand<LANCE>(P)){
311 for(pos+=DirectionPlayerTraits<U,P>::offset();
312 pos!=target;pos+=DirectionPlayerTraits<U,P>::offset()){
313 if(state.pieceAt(pos).isEmpty())
314 action.dropMove(pos,LANCE,P);
315 }
316 }
317 }
318 }
319
320 template<osl::Player P,int DirType,class Action,Direction Dir>
321 void generateDirNotKing(const NumEffectState& state,Square target,Action& action,CArray<unsigned char,8>& pieceMobility, int& spaces, PieceMask const& notPieceMask)
322 {
323 generateDirNotKing<P,DirType,Action>(state,target,action,pieceMobility,spaces,notPieceMask,
324 DirectionPlayerTraits<Dir,P>::offset(),Dir,DirectionTraits<Dir>::primDir,DirectionTraits<Dir>::ptypeMask,DirectionPlayerTraits<Dir,P>::directionByBlack);
325
326 }
327 template<osl::Player P,osl::Direction Dir,class Action,bool hasKnight>
328 void generateKnightDir(const NumEffectState& state,Square target,Action& action)
329 {
330 Square pos=target-DirectionPlayerTraits<Dir,P>::offset();
331 if(!pos.isOnBoard()) return;
332 Piece p=state.pieceAt(pos);
333 if(!p.canMoveOn<P>()) return;
334 mask_t mask=state.allEffectAt<KNIGHT>(P, pos);
335 mask &= ~state.promotedPieces().getMask<KNIGHT>();
336 // pinnedなknightは動けない
337 mask &= ~state.pinOrOpen(P).getMask(PtypeFuns<KNIGHT>::indexNum);
338 while(mask.any()){
339 const int num = mask.takeOneBit()+PtypeFuns<KNIGHT>::indexNum*32;
340 Piece p1=state.pieceOf(num);
341 action.unknownMove(p1.square(),pos,p,KNIGHT,false,P);
342 }
343 if(hasKnight && p.isEmpty()){
344 action.dropMove(pos,KNIGHT,P);
345 }
346 }
347 template<osl::Player P,class Action>
348 void generateKnightAll(const NumEffectState& state,Square target,Action& action)
349 {
350 if(state.hasPieceOnStand<KNIGHT>(P)){
351 detail::generateKnightDir<P,UUL,Action,true>(state,target,action);
352 detail::generateKnightDir<P,UUR,Action,true>(state,target,action);
353 }
354 else{
355 detail::generateKnightDir<P,UUL,Action,false>(state,target,action);
356 detail::generateKnightDir<P,UUR,Action,false>(state,target,action);
357 }
358 }
359 template <osl::Player P,class Action>
360 void generateDrop(Square target,Action& action,int spaceMask,osl::Ptype T,int dirMask,Offset offset)
361 {
362 if((spaceMask&dirMask)!=0){
363 Square pos=target-offset;
364 action.dropMove(pos,T,P);
365 }
366 }
367 template <osl::Player P,class Action,Direction Dir>
368 void generateDropDir(Square target,Action& action,int spaceMask,osl::Ptype T)
369 {
370 generateDrop<P,Action>(target,action,spaceMask,T,(1<<Dir),DirectionPlayerTraits<Dir,P>::offset());
371 }
372 template<Player P,class Action,bool mustCareSilver>
373 void generateOpenOrCapture(const NumEffectState& state,Square target,Piece p,int num,Action& action)
374 {
375 // TODO: pin, captureを作る
376 Direction d=Board_Table.template getShort8<P>(p.square(),target);
377 Square mid=state.mobilityOf((P==BLACK ? d : inverse(d)),num);
378 assert(mid.isOnBoard());
379 const Player altP=alt(P);
380 Square mid1=state.kingMobilityOfPlayer(altP,d);
381 if(mid==mid1){
382 Piece p1=state.pieceAt(mid);
383 assert(p1.isPiece());
384 Square target_next=target-Board_Table.getShort8OffsetUnsafe(p.square(),target);
385 if((P==BLACK ? p1.pieceIsBlack() : !p1.pieceIsBlack())){
386 // open attack
387 PieceOnBoard<Action>::template generate<P,true>(state,p1,action,(1<<primDir(d)));
388 // p1がtarget_nextに利きを持つ
389 if(state.hasEffectByPiece(p1,target_next)){
390 // silverが斜め下に利きを持つ場合は「成らず」しか生成しない
391 if(mustCareSilver && p1.ptype()==SILVER &&
392 (P==BLACK ? target.y()>mid.y() : target.y()<mid.y())){
393 // pinの場合は動ける可能性はない
394 if(!state.pinOrOpen(P).test(p1.number())){
395 action.unknownMove(mid,target_next,Piece::EMPTY(),SILVER,false,P);
396 }
397 }
398 else
399 PieceOnBoard<Action>::template generatePiece<P>(state,p1,target_next,Piece::EMPTY(),action);
400 }
401 }
402 else{
403 // 隣の場合はすでに作っている
404 if(mid==target_next)
405 return;
406 PieceOnBoard<Action>::template generatePiece<P>(state,p,mid,p1,action);
407 }
408 }
409 }
410
411 template<osl::Player P,class Action>
412 void generateRookLongMove(const NumEffectState& state,Square target,Action& action)
413 {
414 const Player altP=alt(P);
415 for(int num=PtypeTraits<ROOK>::indexMin;num<PtypeTraits<ROOK>::indexLimit;num++){
416 // pinの場合はすでに作っている
417 if(state.pinOrOpen(altP).test(num)) continue;
418 Piece p=state.pieceOf(num);
419 if(!p.isOnBoardByOwner<P>()) continue;
420 if(target.isULRD(p.square())){
421 generateOpenOrCapture<P,Action,false>(state,target,p,num,action);
422 continue;
423 }
424 int target_x=target.x();
425 int target_y=target.y();
426 int rook_x=p.square().x();
427 int rook_y=p.square().y();
428 if(p.isPromoted()){
429 if((unsigned int)(target_x-rook_x+1)>2u){ // abs(target_x-rook_x)>1
430 if((unsigned int)(target_y-rook_y+1)>2u){ // abs(target_y-rook_y)>1
431 {
432 Square pos(rook_x,target_y);
433 Piece p1=state.pieceAt(pos);
434 if(state.effectSetAt(pos).test(num) &&
435 p1.canMoveOn<P>() &&
436 state.kingMobilityAbs(altP,R).uintValue() >= pos.uintValue() &&
437 pos.uintValue() >= state.kingMobilityAbs(altP,L).uintValue() &&
438 (!state.pinOrOpen(P).test(num) ||
439 p.square().isUD(state.kingSquare<P>()))
440 ){
441 action.unknownMove(p.square(),pos,p1,PROOK,false,P);
442 }
443 }
444 {
445 Square pos(target_x,rook_y);
446 Piece p1=state.pieceAt(pos);
447 if(state.effectSetAt(pos).test(num) &&
448 p1.canMoveOn<P>() &&
449 state.kingMobilityAbs(altP,U).uintValue() >= pos.uintValue() &&
450 pos.uintValue() >= state.kingMobilityAbs(altP,D).uintValue() &&
451 (!state.pinOrOpen(P).test(num) ||
452 p.square().isLR(state.kingSquare<P>()))
453 ){
454 action.unknownMove(p.square(),pos,p1,PROOK,false,P);
455 }
456 }
457 }
458 else{ // (abs(target_x-rook_x)>1 && abs(target_y-rook_y)==1
459 int min_x=state.kingMobilityAbs(altP,L).x();
460 int max_x=state.kingMobilityAbs(altP,R).x();
461 if(target_x>rook_x) max_x=target_x-2;
462 else min_x=target_x+2;
463 min_x=std::max(min_x,rook_x-1);
464 max_x=std::min(max_x,rook_x+1);
465 for(int x=min_x;x<=max_x;x++){
466 Square pos=Square::makeNoCheck(x,target_y);
467 Piece p1=state.pieceAt(pos);
468 if(p1.canMoveOn<P>())
469 PieceOnBoard<Action>::template generatePiecePtype<P,PROOK>(state,p,pos,p1,action);
470 }
471 }
472 }
473 else if((unsigned int)(target_y-rook_y+1)>2u){ // abs(target_y-rook_y)>1, abs(target_x-rook_x)==1
474 int min_y=state.kingMobilityAbs(altP,D).y();
475 int max_y=state.kingMobilityAbs(altP,U).y();
476 if(target_y>rook_y) max_y=target_y-2;
477 else min_y=target_y+2;
478 min_y=std::max(min_y,rook_y-1);
479 max_y=std::min(max_y,rook_y+1);
480 for(int y=min_y;y<=max_y;y++){
481 Square pos=Square::makeNoCheck(target_x,y);
482 Piece p1=state.pieceAt(pos);
483 if(p1.canMoveOn<P>())
484 PieceOnBoard<Action>::template generatePiecePtype<P,PROOK>(state,p,pos,p1,action);
485 }
486 }
487 }
488 else{ // ROOK
489 // vertical move
490 if((unsigned int)(target_x-rook_x+1)>2u){ // abs(target_x-rook_x)>1
491 Square pos(rook_x,target_y);
492 Piece p1=state.pieceAt(pos);
493 if(state.effectSetAt(pos).test(num) &&
494 p1.canMoveOn<P>() &&
495 state.kingMobilityAbs(altP,R).uintValue() >= pos.uintValue() &&
496 pos.uintValue() >= state.kingMobilityAbs(altP,L).uintValue() &&
497 (!state.pinOrOpen(P).test(num) ||
498 p.square().isUD(state.kingSquare<P>()))
499 ){
500 if(Square::canPromoteY<P>(rook_y) || Square::canPromoteY<P>(target_y)){
501 action.unknownMove(p.square(),pos,p1,PROOK,true,P);
502 }
503 else action.unknownMove(p.square(),pos,p1,ROOK,false,P);
504 }
505 }
506 // horizontal move
507 if((unsigned int)(target_y-rook_y+1)>2u){ // abs(target_y-rook_y)>1
508 Square pos(target_x,rook_y);
509 Piece p1=state.pieceAt(pos);
510 if(state.effectSetAt(pos).test(num) &&
511 p1.canMoveOn<P>() &&
512 state.kingMobilityAbs(altP,U).uintValue() >= pos.uintValue() &&
513 pos.uintValue() >= state.kingMobilityAbs(altP,D).uintValue() &&
514 (!state.pinOrOpen(P).test(num) ||
515 p.square().isLR(state.kingSquare<P>()))
516 ){
517 if(Square::canPromoteY<P>(rook_y)){
518 action.unknownMove(p.square(),pos,p1,PROOK,true,P);
519 }
520 else
521 action.unknownMove(p.square(),pos,p1,ROOK,false,P);
522 }
523 }
524 }
525 }
526 }
527 template<osl::Player P,class Action>
528 void generateRookLongMoveNotKing(const NumEffectState& state,Square target,Action& action,CArray<unsigned char,8> const& pieceMobility)
529 {
530 for(int num=PtypeTraits<ROOK>::indexMin;num<PtypeTraits<ROOK>::indexLimit;num++){
531 Piece p=state.pieceOf(num);
532 if(!p.isOnBoardByOwner<P>()) continue;
533 if(target.isULRD(p.square())){
534 continue;
535 }
536 int dirMask=0; // can move to all direction
537 if(state.pin(P).test(num)){
538 Direction d=state.pinnedDir<P>(p);
539 dirMask=(~(1<<primDir(d)));
540 }
541 int target_x=target.x();
542 int target_y=target.y();
543 int rook_x=p.square().x();
544 int rook_y=p.square().y();
545 if(p.isPromoted()){
546 if((unsigned int)(target_x-rook_x+1)>2u){ // abs(target_x-rook_x)>1
547 if((unsigned int)(target_y-rook_y+1)>2u){ // abs(target_y-rook_y)>1
548 {
549 Square pos(rook_x,target_y);
550 Piece p1=state.pieceAt(pos);
551 if(p1.canMoveOn<P>() &&
552 pieceMobility[R] > pos.uintValue() &&
553 pos.uintValue() > pieceMobility[L] &&
554 (dirMask&(1<<U))==0 &&
555 state.effectSetAt(pos).test(num)
556 ){
557 action.unknownMove(p.square(),pos,p1,PROOK,false,P);
558 }
559 }
560 {
561 Square pos(target_x,rook_y);
562 Piece p1=state.pieceAt(pos);
563 if(p1.canMoveOn<P>() &&
564 pieceMobility[U] > pos.uintValue() &&
565 pos.uintValue() > pieceMobility[D] &&
566 (dirMask&(1<<L))==0 &&
567 state.effectSetAt(pos).test(num)){
568 action.unknownMove(p.square(),pos,p1,PROOK,false,P);
569 }
570 }
571 }
572 else{ // (abs(target_x-rook_x)>1 && abs(target_y-rook_y)==1
573 int min_x=Square::makeDirect(pieceMobility[L]).x()+1;
574 int max_x=Square::makeDirect(pieceMobility[R]).x()-1;
575 if(target_x>rook_x) max_x=target_x-2;
576 else min_x=target_x+2;
577 min_x=std::max(min_x,rook_x-1);
578 max_x=std::min(max_x,rook_x+1);
579 for(int x=min_x;x<=max_x;x++){
580 Square pos=Square::makeNoCheck(x,target_y);
581 if(((1<<primDirUnsafe(Board_Table.getShort8Unsafe<P>(p.square(),pos)))&dirMask)!=0) continue;
582 Piece p1=state.pieceAt(pos);
583 if(p1.canMoveOn<P>())
584 action.unknownMove(p.square(),pos,p1,PROOK,false,P);
585 }
586 }
587 }
588 else if((unsigned int)(target_y-rook_y+1)>2u){ // abs(target_y-rook_y)>1, abs(target_x-rook_x)==1
589 int min_y=Square::makeDirect(pieceMobility[D]).y()+1;
590 int max_y=Square::makeDirect(pieceMobility[U]).y()-1;
591 if(target_y>rook_y) max_y=target_y-2;
592 else min_y=target_y+2;
593 min_y=std::max(min_y,rook_y-1);
594 max_y=std::min(max_y,rook_y+1);
595 for(int y=min_y;y<=max_y;y++){
596 Square pos=Square::makeNoCheck(target_x,y);
597 if(((1<<primDirUnsafe(Board_Table.getShort8Unsafe<P>(p.square(),pos)))&dirMask)!=0) continue;
598 Piece p1=state.pieceAt(pos);
599 if(p1.canMoveOn<P>())
600 action.unknownMove(p.square(),pos,p1,PROOK,false,P);
601 }
602 }
603 }
604 else{ // ROOK
605 // vertical move
606 if((unsigned int)(target_x-rook_x+1)>2u){ // abs(target_x-rook_x)>1
607 Square pos(rook_x,target_y);
608 Piece p1=state.pieceAt(pos);
609 if(p1.canMoveOn<P>() &&
610 pieceMobility[R] > pos.uintValue() &&
611 pos.uintValue() > pieceMobility[L] &&
612 (dirMask&(1<<U))==0 &&
613 state.effectSetAt(pos).test(num)
614 ){
615 if(Square::canPromoteY<P>(rook_y) || Square::canPromoteY<P>(target_y)){
616 action.unknownMove(p.square(),pos,p1,PROOK,true,P);
617 }
618 else
619 action.unknownMove(p.square(),pos,p1,ROOK,false,P);
620 }
621 }
622 // horizontal move
623 if((unsigned int)(target_y-rook_y+1)>2u){ // abs(target_y-rook_y)>1
624 Square pos(target_x,rook_y);
625 Piece p1=state.pieceAt(pos);
626 if(p1.template canMoveOn<P>() &&
627 pieceMobility[U] > pos.uintValue() &&
628 pos.uintValue() > pieceMobility[D] &&
629 (dirMask&(1<<L))==0 &&
630 state.effectSetAt(pos).test(num)
631 ){
632 if(Square::canPromoteY<P>(rook_y)){
633 action.unknownMove(p.square(),pos,p1,PROOK,true,P);
634 }
635 else
636 action.unknownMove(p.square(),pos,p1,ROOK,false,P);
637 }
638 }
639 }
640 }
641 }
642 template<Player P,Ptype T,class Action>
643 void generateBishopLongMove(const NumEffectState& state,Square target,Action& action,Piece p,int num)
644 {
645 const Player altP=alt(P);
646 int target_x=target.x();
647 int target_y=target.y();
648 int target_xPy=target_x+target_y;
649 int target_xMy=target_x-target_y;
650 int bishop_x=p.square().x();
651 int bishop_y=p.square().y();
652 int bishop_xPy=bishop_x+bishop_y;
653 int bishop_xMy=bishop_x-bishop_y;
654 if(((target_xPy^bishop_xPy)&1)!=0){
655 if(T==BISHOP) return;
656 // 市松模様のparityの違う場合も,隣ならOK?
657 if((unsigned int)(target_xPy-bishop_xPy+1)<=2u){ // abs(target_xPy-bishop_xPy)==1
658 Square ul=state.kingMobilityAbs(altP,UL);
659 Square dr=state.kingMobilityAbs(altP,DR);
660 int min_xMy=ul.x()-ul.y();
661 int max_xMy=dr.x()-dr.y();
662 if(target_xMy>bishop_xMy) max_xMy=target_xMy-4;
663 else min_xMy=target_xMy+4;
664 min_xMy=std::max(min_xMy,bishop_xMy-1);
665 max_xMy=std::min(max_xMy,bishop_xMy+1);
666 for(int xMy=min_xMy;xMy<=max_xMy;xMy+=2){
667 int pos_x=(target_xPy+xMy)>>1;
668 int pos_y=(target_xPy-xMy)>>1;
669 Square pos=Square::makeNoCheck(pos_x,pos_y);
670 Piece p1=state.pieceAt(pos);
671 if(p1.canMoveOn<P>())
672 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
673 }
674 }
675 else if((unsigned int)(target_xMy-bishop_xMy+1)<=2u){ // abs(target_xMy-bishop_xMy)==1
676 Square dl=state.kingMobilityAbs(altP,DL);
677 Square ur=state.kingMobilityAbs(altP,UR);
678 int min_xPy=dl.x()+dl.y();
679 int max_xPy=ur.x()+ur.y();
680 if(target_xPy>bishop_xPy) max_xPy=target_xPy-4;
681 else min_xPy=target_xPy+4;
682 min_xPy=std::max(min_xPy,bishop_xPy-1);
683 max_xPy=std::min(max_xPy,bishop_xPy+1);
684 for(int xPy=min_xPy;xPy<=max_xPy;xPy+=2){
685 int pos_x=(xPy+target_xMy)>>1;
686 int pos_y=(xPy-target_xMy)>>1;
687 Square pos=Square::makeNoCheck(pos_x,pos_y);
688 Piece p1=state.pieceAt(pos);
689 if(p1.canMoveOn<P>())
690 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
691 }
692 }
693 return;
694 }
695 // / 方向(dx==dy)から王手をかける
696 if((unsigned int)(target_xPy-bishop_xPy+2)>4u){ // abs(target_xPy-bishop_xPy)>2
697 int pos_x=(bishop_xPy+target_xMy)>>1;
698 int pos_y=(bishop_xPy-target_xMy)>>1;
699 Square pos=Square::makeNoCheck(pos_x,pos_y);
700 if(pos.isOnBoard()){
701 Piece p1=state.pieceAt(pos);
702 if(state.effectSetAt(pos).test(num) &&
703 p1.canMoveOn<P>() &&
704 state.kingMobilityAbs(altP,UR).uintValue() >= pos.uintValue() &&
705 pos.uintValue() >= state.kingMobilityAbs(altP,DL).uintValue()
706 ){
707 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
708 }
709 }
710 }
711 else if(target_xPy==bishop_xPy){
712 generateOpenOrCapture<P,Action,true>(state,target,p,num,action);
713 return;
714 }
715 // \ 方向(dx== -dy)から王手をかける
716 if((unsigned int)(target_xMy-bishop_xMy+2)>4u){ // abs(target_xMy-bishop_xMy)>2
717 int pos_x=(target_xPy+bishop_xMy)>>1;
718 int pos_y=(target_xPy-bishop_xMy)>>1;
719 Square pos=Square::makeNoCheck(pos_x,pos_y);
720 if(pos.isOnBoard()){
721 Piece p1=state.pieceAt(pos);
722 if(state.effectSetAt(pos).test(num) &&
723 p1.canMoveOn<P>() &&
724 state.kingMobilityAbs(altP,DR).uintValue() >= pos.uintValue() &&
725 pos.uintValue() >= state.kingMobilityAbs(altP,UL).uintValue()
726 ){
727 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
728 }
729 }
730 }
731 else if(target_xMy==bishop_xMy){
732 generateOpenOrCapture<P,Action,true>(state,target,p,num,action);
733 return;
734 }
735
736 }
737 template<osl::Player P,Ptype T,class Action>
738 void generateBishopLongMoveNotKing(const NumEffectState& state,Square target,Action& action,CArray<unsigned char,8> const& pieceMobility,Piece p,int num)
739 {
740 int target_x=target.x();
741 int target_y=target.y();
742 int target_xPy=target_x+target_y;
743 int target_xMy=target_x-target_y;
744 int bishop_x=p.square().x();
745 int bishop_y=p.square().y();
746 int bishop_xPy=bishop_x+bishop_y;
747 int bishop_xMy=bishop_x-bishop_y;
748 if(((target_xPy^bishop_xPy)&1)!=0){
749 if(T!=PBISHOP) return;
750 // 市松模様のparityの違う場合も,隣ならOK?
751 if((unsigned int)(target_xPy-bishop_xPy+1)<=2u){ // abs(target_xPy-bishop_xPy)==1
752 Square ul=Square::makeDirect(pieceMobility[UL]);
753 Square dr=Square::makeDirect(pieceMobility[DR]);
754 int min_xMy=ul.x()-ul.y()+2;
755 int max_xMy=dr.x()-dr.y()-2;
756 if(target_xMy>bishop_xMy) max_xMy=target_xMy-4;
757 else min_xMy=target_xMy+4;
758 min_xMy=std::max(min_xMy,bishop_xMy-1);
759 max_xMy=std::min(max_xMy,bishop_xMy+1);
760 for(int xMy=min_xMy;xMy<=max_xMy;xMy+=2){
761 int pos_x=(target_xPy+xMy)>>1;
762 int pos_y=(target_xPy-xMy)>>1;
763 Square pos=Square::makeNoCheck(pos_x,pos_y);
764 Piece p1=state.pieceAt(pos);
765 if(p1.canMoveOn<P>())
766 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
767 }
768 return;
769 }
770 else if((unsigned int)(target_xMy-bishop_xMy+1)<=2u){ // abs(target_xMy-bishop_xMy)==1
771 Square dl=Square::makeDirect(pieceMobility[DL]);
772 Square ur=Square::makeDirect(pieceMobility[UR]);
773 int min_xPy=dl.x()+dl.y()+2;
774 int max_xPy=ur.x()+ur.y()-2;
775 if(target_xPy>bishop_xPy) max_xPy=target_xPy-4;
776 else min_xPy=target_xPy+4;
777 min_xPy=std::max(min_xPy,bishop_xPy-1);
778 max_xPy=std::min(max_xPy,bishop_xPy+1);
779 for(int xPy=min_xPy;xPy<=max_xPy;xPy+=2){
780 int pos_x=(xPy+target_xMy)>>1;
781 int pos_y=(xPy-target_xMy)>>1;
782 Square pos=Square::makeNoCheck(pos_x,pos_y);
783 Piece p1=state.pieceAt(pos);
784 if(p1.canMoveOn<P>())
785 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
786 }
787 }
788 return;
789 }
790 // / 方向(dx==dy)から王手をかける
791 if((unsigned int)(target_xPy-bishop_xPy+2)>4u){ // abs(target_xPy-bishop_xPy)>2
792 int pos_x=(bishop_xPy+target_xMy)>>1;
793 int pos_y=(bishop_xPy-target_xMy)>>1;
794 Square pos=Square::makeNoCheck(pos_x,pos_y);
795 if(pos.isOnBoard()){
796 if(pieceMobility[UR] > pos.uintValue() &&
797 pos.uintValue() > pieceMobility[DL] &&
798 state.effectSetAt(pos).test(num)){
799 Piece p1=state.pieceAt(pos);
800 if(p1.canMoveOn<P>())
801 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
802 }
803 }
804 }
805 // \ 方向(dx== -dy)から王手をかける
806 if((unsigned int)(target_xMy-bishop_xMy+2)>4u){ // abs(target_xMy-bishop_xMy)>2
807 int pos_x=(target_xPy+bishop_xMy)>>1;
808 int pos_y=(target_xPy-bishop_xMy)>>1;
809 Square pos=Square::makeNoCheck(pos_x,pos_y);
810 if(pos.isOnBoard()){
811 if(pieceMobility[DR] > pos.uintValue() &&
812 pos.uintValue() > pieceMobility[UL] &&
813 state.effectSetAt(pos).test(num)
814 ){
815 Piece p1=state.pieceAt(pos);
816 if(p1.canMoveOn<P>())
817 PieceOnBoard<Action>::template generatePiecePtype<P,T>(state,p,pos,p1,action);
818 }
819 }
820 }
821 }
822
823 template<Player P,class Action>
824 void generateDropGold(const NumEffectState& state,Square target,Action& action,int spaces)
825 {
826 if(!state.hasPieceOnStand<GOLD>(P)) return;
827 unsigned int gold_mask=spaces&((1<<U)|(1<<UR)|(1<<UL)|(1<<L)|(1<<R)|(1<<D));
828 if(gold_mask==0) return;
829 generateDropDir<P,Action,U>(target,action,gold_mask,GOLD);
830 generateDropDir<P,Action,UL>(target,action,gold_mask,GOLD);
831 generateDropDir<P,Action,UR>(target,action,gold_mask,GOLD);
832 generateDropDir<P,Action,L>(target,action,gold_mask,GOLD);
833 generateDropDir<P,Action,R>(target,action,gold_mask,GOLD);
834 generateDropDir<P,Action,D>(target,action,gold_mask,GOLD);
835 }
836 template<Player P,class Action>
837 void generateDropSilver(const NumEffectState& state,Square target,Action& action,int spaces)
838 {
839 if(!state.hasPieceOnStand<SILVER>(P)) return;
840 unsigned int silver_mask=spaces&((1<<U)|(1<<UR)|(1<<UL)|(1<<DL)|(1<<DR));
841 if(silver_mask ==0) return;
842
843 generateDropDir<P,Action,DL>(target,action,silver_mask,SILVER);
844 generateDropDir<P,Action,DR>(target,action,silver_mask,SILVER);
845 generateDropDir<P,Action,U>(target,action,silver_mask,SILVER);
846 generateDropDir<P,Action,UL>(target,action,silver_mask,SILVER);
847 generateDropDir<P,Action,UR>(target,action,silver_mask,SILVER);
848 }
849 /**
850 * allEmpty - shadow attackを生成する場合は,posがemptyでないこともある.
851 */
852 template<Player P,class Action,bool allEmpty>
853 void generateDropBishop(const NumEffectState& state,Square target,Action& action,Square ul,Square dr,Square ur,Square dl)
854 {
855 for(Square pos=dl+DirectionPlayerTraits<DL,P>::offset();
856 pos!=target;pos+=DirectionPlayerTraits<DL,P>::offset())
857 if(allEmpty || state.pieceAt(pos).isEmpty())
858 action.dropMove(pos,BISHOP,P);
859 for(Square pos=dr-DirectionPlayerTraits<UL,P>::offset();
860 pos!=target;pos-=DirectionPlayerTraits<UL,P>::offset())
861 if(allEmpty || state.pieceAt(pos).isEmpty())
862 action.dropMove(pos,BISHOP,P);
863 for(Square pos=ul+DirectionPlayerTraits<UL,P>::offset();
864 pos!=target;pos+=DirectionPlayerTraits<UL,P>::offset())
865 if(allEmpty || state.pieceAt(pos).isEmpty())
866 action.dropMove(pos,BISHOP,P);
867 for(Square pos=ur-DirectionPlayerTraits<DL,P>::offset();
868 pos!=target;pos-=DirectionPlayerTraits<DL,P>::offset())
869 if(allEmpty || state.pieceAt(pos).isEmpty())
870 action.dropMove(pos,BISHOP,P);
871 }
872
873 template<Player P,class Action,bool allEmpty>
874 void generateDropRook(const NumEffectState& state,Square target,Action& action,Square l,Square r,Square d,Square u)
875 {
876 for(Square pos=u-DirectionPlayerTraits<D,P>::offset();
877 pos!=target;pos-=DirectionPlayerTraits<D,P>::offset())
878 if(allEmpty || state.pieceAt(pos).isEmpty())
879 action.dropMove(pos,ROOK,P);
880 for(Square pos=l+DirectionPlayerTraits<L,P>::offset();
881 pos!=target;pos+=DirectionPlayerTraits<L,P>::offset())
882 if(allEmpty || state.pieceAt(pos).isEmpty())
883 action.dropMove(pos,ROOK,P);
884 for(Square pos=r-DirectionPlayerTraits<L,P>::offset();
885 pos!=target;pos-=DirectionPlayerTraits<L,P>::offset())
886 if(allEmpty || state.pieceAt(pos).isEmpty())
887 action.dropMove(pos,ROOK,P);
888 for(Square pos=d+DirectionPlayerTraits<D,P>::offset();
889 pos!=target;pos+=DirectionPlayerTraits<D,P>::offset())
890 if(allEmpty || state.pieceAt(pos).isEmpty())
891 action.dropMove(pos,ROOK,P);
892 }
893 template<osl::Player P,class Action>
894 void generateKing(const NumEffectState& state,Square target,Action& action,bool &hasPawnCheckmate)
895 {
896
897 const Player altP=alt(P);
898 assert(target==state.kingSquare(altP));
899 generateDir<P,0,Action,U>(state,target,action,hasPawnCheckmate);
900 generateKnightAll<P,Action>(state,target,action);
901 generateDir<P,2,Action,UL>(state,target,action,hasPawnCheckmate);
902 generateDir<P,2,Action,UR>(state,target,action,hasPawnCheckmate);
903 generateDir<P,1,Action,L>(state,target,action,hasPawnCheckmate);
904 generateDir<P,1,Action,R>(state,target,action,hasPawnCheckmate);
905 generateDir<P,1,Action,D>(state,target,action,hasPawnCheckmate);
906 generateDir<P,2,Action,DL>(state,target,action,hasPawnCheckmate);
907 generateDir<P,2,Action,DR>(state,target,action,hasPawnCheckmate);
908 detail::generateRookLongMove<P,Action>(state,target,action);
909 for(int num=PtypeTraits<BISHOP>::indexMin;num<PtypeTraits<BISHOP>::indexLimit;num++){
910 // pinの場合はすでに作っている
911 if(state.pinOrOpen(altP).test(num)) continue;
912 Piece p=state.pieceOf(num);
913 if(!p.isOnBoardByOwner<P>()) continue;
914 if(p.isPromoted())
915 generateBishopLongMove<P,PBISHOP,Action>(state,target,action,p,num);
916 else
917 generateBishopLongMove<P,BISHOP,Action>(state,target,action,p,num);
918 }
919 int spaces=King8Info(state.Iking8Info(altP)).spaces();
920 generateDropGold<P,Action>(state,target,action,spaces);
921 generateDropSilver<P,Action>(state,target,action,spaces);
922 // bishop
923 if(state.hasPieceOnStand<BISHOP>(P)){
924 generateDropBishop<P,Action,true>(state,target,action,
925 state.kingMobilityOfPlayer(altP,UL),
926 state.kingMobilityOfPlayer(altP,DR),
927 state.kingMobilityOfPlayer(altP,UR),
928 state.kingMobilityOfPlayer(altP,DL));
929 }
930 if(state.hasPieceOnStand<ROOK>(P)){
931 Square l,r,d,u;
932 l=state.kingMobilityOfPlayer(altP,L);
933 r=state.kingMobilityOfPlayer(altP,R);
934 d=state.kingMobilityOfPlayer(altP,D);
935 u=state.kingMobilityOfPlayer(altP,U);
936 generateDropRook<P,Action,true>(state,target,action,l,r,d,u);
937 }
938 }
939 template<osl::Player P,class Action>
940 void generateNotKing(const NumEffectState& state,Square target,Action& action)
941 {
942 int spaces=0;
943 CArray<unsigned char,8> pieceMobility;
944 PieceMask notPieceMask;
945 notPieceMask.setAll();
946 int num=state.pieceAt(target).number();
947 if(num != EMPTY_NUM){
948 notPieceMask.reset(num);
949 }
950 generateDirNotKing<P,0,Action,U>(state,target,action,pieceMobility,spaces,notPieceMask);
951 generateKnightAll<P,Action>(state,target,action);
952 generateDirNotKing<P,2,Action,UL>(state,target,action,pieceMobility,spaces,notPieceMask);
953 generateDirNotKing<P,2,Action,UR>(state,target,action,pieceMobility,spaces,notPieceMask);
954 generateDirNotKing<P,1,Action,L>(state,target,action,pieceMobility,spaces,notPieceMask);
955 generateDirNotKing<P,1,Action,R>(state,target,action,pieceMobility,spaces,notPieceMask);
956 generateDirNotKing<P,1,Action,D>(state,target,action,pieceMobility,spaces,notPieceMask);
957 generateDirNotKing<P,2,Action,DL>(state,target,action,pieceMobility,spaces,notPieceMask);
958 generateDirNotKing<P,2,Action,DR>(state,target,action,pieceMobility,spaces,notPieceMask);
959 // rookが移動する手
960 generateRookLongMoveNotKing<P,Action>(state,target,action,pieceMobility);
961 // bishopが移動する手
962 for(int num=PtypeTraits<BISHOP>::indexMin;num<PtypeTraits<BISHOP>::indexLimit;num++){
963 Piece p=state.pieceOf(num);
964 if(!p.isOnBoardByOwner<P>()) continue;
965 if(p.isPromoted())
966 generateBishopLongMoveNotKing<P,PBISHOP,Action>(state,target,action,pieceMobility,p,num);
967 else
968 generateBishopLongMoveNotKing<P,BISHOP,Action>(state,target,action,pieceMobility,p,num);
969 }
970 generateDropGold<P,Action>(state,target,action,spaces);
971 generateDropSilver<P,Action>(state,target,action,spaces);
972 if(state.hasPieceOnStand<BISHOP>(P)){
973 Square ul,dr,dl,ur;
974 ul=Square::makeDirect(pieceMobility[P==BLACK ? UL : DR]);
975 dr=Square::makeDirect(pieceMobility[P==BLACK ? DR : UL]);
976 ur=Square::makeDirect(pieceMobility[P==BLACK ? UR : DL]);
977 dl=Square::makeDirect(pieceMobility[P==BLACK ? DL : UR]);
978 generateDropBishop<P,Action,false>(state,target,action,ul,dr,ur,dl);
979 }
980 if(state.hasPieceOnStand<ROOK>(P)){
981 Square l,r,d,u;
982 l=Square::makeDirect(pieceMobility[P==BLACK ? L : R]);
983 r=Square::makeDirect(pieceMobility[P==BLACK ? R : L]);
984 d=Square::makeDirect(pieceMobility[P==BLACK ? D : U]);
985 u=Square::makeDirect(pieceMobility[P==BLACK ? U : D]);
986 generateDropRook<P,Action,false>(state,target,action,l,r,d,u);
987 }
988 }
989 } // namespace detail
990 template <class Action>
991 template <osl::Player P,bool isAttackToKing>
992 void osl::move_generator::AddEffectWithEffect<Action>::
993 generate(const NumEffectState& state,Square target,Action& action,bool &hasPawnCheckmate)
994 {
995 if(!isAttackToKing){
996 detail::template generateNotKing<P,Action>(state,target,action);
997 }
998 else{
999 detail::template generateKing<P,Action>(state,target,action,hasPawnCheckmate);
1000 }
1001 }
1002 template<bool isAttackToKing>
1003 void osl::move_generator::GenerateAddEffectWithEffect::
1004 generate(Player player, const NumEffectState& state, Square target,
1005 move_action::Store& store)
1006 {
1007 using namespace osl::move_action;
1008 bool dummy;
1009 if(player==BLACK){
1010 AddEffectWithEffect<Store>::generate<BLACK,isAttackToKing>(state,target,store,dummy);
1011 }
1012 else{
1013 AddEffectWithEffect<Store>::generate<WHITE,isAttackToKing>(state,target,store,dummy);
1014 }
1015 }
1016
1017 } // namespace move_generator
1018} // namespace osl
1019#endif /* _GENERATER_ADD_EFFECT_WITH_EFFECT_TCC */
1020// ;;; Local Variables:
1021// ;;; mode:c++
1022// ;;; c-basic-offset:2
1023// ;;; End: