addEffectWithEffect.tcc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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