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 
11 namespace 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: