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 
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)){
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);
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  {
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  {
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);
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,
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  {
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)){
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,
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  {
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());
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  {
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  {
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  {
858  if(allEmpty || state.pieceAt(pos).isEmpty())
859  action.dropMove(pos,BISHOP,P);
862  if(allEmpty || state.pieceAt(pos).isEmpty())
863  action.dropMove(pos,BISHOP,P);
866  if(allEmpty || state.pieceAt(pos).isEmpty())
867  action.dropMove(pos,BISHOP,P);
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  {
879  if(allEmpty || state.pieceAt(pos).isEmpty())
880  action.dropMove(pos,ROOK,P);
883  if(allEmpty || state.pieceAt(pos).isEmpty())
884  action.dropMove(pos,ROOK,P);
887  if(allEmpty || state.pieceAt(pos).isEmpty())
888  action.dropMove(pos,ROOK,P);
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 
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>
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>
1005  generate(Player player, const NumEffectState& state, Square target,
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: