All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
addEffect_.tcc
Go to the documentation of this file.
1 #ifndef _MOVE_GENERATOR_ADD_EFFECT_TCC
2 #define _MOVE_GENERATOR_ADD_EFFECT_TCC
3 
5 #include "osl/move_action/safeFilter.h"
7 #include <boost/type_traits.hpp>
8 
9 namespace osl
10 {
11  namespace move_generator
12  {
13  namespace without_effect
14  {
24  template <Player P,Ptype T,class Action,bool isPromote>
25  void generateMove(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action)
26  {
27  NearMask target_mask =
28  (isPromote
30  : Add_Effect_Table.getNearMask<P>(PtypeTraits<T>::moveType,from,target));
31  target_mask &= nearMask;
32  while (target_mask.any())
33  {
34  const int n =target_mask.takeOneBit();
35  Direction dir=static_cast<Direction>(n);
36  Square to=target-Board_Table.template getOffset<P>(dir);
37  if (!isPromote ||
38  (from.canPromote<P>()||to.canPromote<P>()))
39  action.unknownMove(from,to,state.pieceAt(to),(isPromote ? PtypeFuns<T>::promotePtype : T) ,isPromote,P);
40  }
41  }
42 
43  template <Player P,Ptype T,class Action>
44  void generateLongMoveDirectNoPromote(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action)
45  {
46  assert(state.pieceAt(from).template isOnBoardByOwner<P>());
47  NearMask target_mask=Add_Effect_Table.getNearMask<P>(T,from,target) &nearMask;
48  while (target_mask.any())
49  {
50  const int n = target_mask.takeOneBit();
51  Direction dir=static_cast<Direction>(n);
52  Square to=target-Board_Table.template getOffset<P>(dir);
56  if (state.hasEffectByPiece(state.pieceAt(from),to))
57  action.unknownMove(from,to,state.pieceAt(to),T,false,P);
58  }
59  }
60 
61  template <Player P,Ptype T,class Action>
62  void generateLongMoveDirectCanPromote(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action)
63  {
64  assert(state.pieceAt(from).template isOnBoardByOwner<P>());
65  NearMask target_mask=Add_Effect_Table.getNearMaskWithPromote<P>(T,from,target) &nearMask;
66  NearMask target_mask_no_promote=Add_Effect_Table.getNearMask<P>(T,from,target) &nearMask;
67  while (target_mask.any())
68  {
69  const int n = target_mask.takeOneBit();
70  Direction dir=static_cast<Direction>(n);
71  Square to=target-Board_Table.template getOffset<P>(dir);
75  if (state.hasEffectByPiece(state.pieceAt(from),to))
76  {
77  if (to.canPromote<P>()||from.canPromote<P>())
78  action.unknownMove(from,to,state.pieceAt(to),PtypeFuns<T>::promotePtype,true,P);
79  if ((target_mask_no_promote.isSet(n))!=0)
80  action.unknownMove(from,to,state.pieceAt(to),T,false,P);
81  }
82  }
83  }
87  template<bool isAttackToKing>
88  bool isEmptyOrAdditional(const NumEffectState& state,Square from,Square to,int& count)
89  {
90  count=0;
91  if(isAttackToKing){
92  return state.isEmptyBetween(from,to);
93  }
95  assert(!o.zero());
96  Piece p;
97  Square pos;
98  for(pos=from+o;pos!=to && (p=state.pieceAt(pos)).isEmpty();pos+=o)
99  ;
100  if(pos==to) return true;
101  assert(!p.isEdge());
102  count=1;
103  return state.hasEffectByPiece(p,to);
104  }
105  template <Player P,Ptype T,class Action,bool canPromote,bool isAttackToKing>
106  void generateLongMove(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action,int piece_num)
107  {
108  assert(state.pieceAt(from).template isOnBoardByOwner<P>());
109  // static assert?
110  assert(T==LANCE || T==BISHOP || T==PBISHOP || T==ROOK || T==PROOK);
112  const EffectContent effect_content=
113  Ptype_Table.getEffect(newPtypeO(BLACK,unpromote(T)),Offset32(target,from).blackOffset32<P>());
114  if (isAttackToKing)
115  {
116  assert(! effect_content.hasUnblockableEffect());
117  }
118  else if (effect_content.hasUnblockableEffect())
119  return;
120  if (effect_content.hasEffect())
121  {
125  if (T==PROOK)
126  {
127  generateMove<P,T,Action,false>(state,from,target,nearMask,action);
128  }
130  Direction shortD=longToShort(longD);
131  Piece p;
132  Square pos1;
133  if(isAttackToKing){
134  pos1=state.kingMobilityAbs(alt(P),shortD);
135  if(state.mobilityOf(shortD,piece_num)!=pos1) return;
136  p=state.pieceAt(pos1);
137  }
138  else{
139  Offset o1=effect_content.offset().template blackOffset<P>();
140  assert(!o1.zero());
141  pos1=target-o1;
142  for(;(p=state.pieceAt(pos1)).isEmpty();pos1-=o1) ;
143  if (pos1==from) return;
144  assert(!p.isEdge());
145  if(state.hasEffectByPiece(p,target)){
146  Piece p1;
147  Square pos3=pos1;
148  for(pos1-=o1;(p1=state.pieceAt(pos1)).isEmpty();pos1-=o1) ;
149  if(pos1==from){
150  if(p.isOnBoardByOwner<P>()) return;
151  pos1=pos3;
152  }
153  else{
154  p=p1;
155  if (! state.hasEffectByPiece(state.pieceAt(from), pos1))
156  return;
157  }
158  }
159  else{
160  if (! state.hasEffectByPiece(state.pieceAt(from), pos1))
161  return;
162  }
163  }
164  if (p.isOnBoardByOwner<P>())
165  {
166  Open<Action>::template generate<P>
167  (state,p,action,target,
168  longToShort(Board_Table.getLongDirection<BLACK>(Offset32(target,from).blackOffset32<P>())));
171  }
172  else
173  {
175  if (canPromote &&
176  (from.canPromote<P>()||pos1.canPromote<P>()) &&
178  (T!=LANCE ||
179  pos1==target-DirectionPlayerTraits<U,P>::offset()))
180  action.unknownMove(from,pos1,p,PtypeFuns<T>::promotePtype,true,P);
181  action.unknownMove(from,pos1,p,T,false,P);
182  }
183  }
184  else
185  {
191  {
192  generateLongMoveDirectNoPromote<P,T,Action>(state,from,target,nearMask,action);
193  }
194  else
195  {
196  generateLongMoveDirectCanPromote<P,T,Action>(state,from,target,nearMask,action);
197  }
198  if (T!=LANCE)
199  {
201  {
202  NearMask target_mask=Add_Effect_Table.getNearMaskLong<P>(T,from,target);
203  if(isAttackToKing) target_mask&=nearMask;
204  while (target_mask.any())
205  {
206  const int n = target_mask.takeOneBit();
207  Offset offset=Add_Effect_Table.getOffsetLong<P>(T,from,target,n&15);
208  Square mid=target+offset.blackOffset<P>();
210  if (! mid.isOnBoard())
211  continue;
212  Piece p=state.pieceAt(mid);
213  int count=0;
214  if (p.canMoveOn<P>()
215  && state.hasEffectByPiece(state.pieceAt(from),mid)
216  && isEmptyOrAdditional<isAttackToKing>(state,mid,target,count))
217  {
218  if (canPromote &&
219  (from.canPromote<P>()||mid.canPromote<P>()))
220  action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
221  action.unknownMove(from,mid,p,T,false,P);
222  }
223  }
224  }
226  if (T==PBISHOP)
227  {
228  NearMask target_mask=Add_Effect_Table.getNearMaskPBISHOP<P>(from,target);
229  if(isAttackToKing) target_mask&=nearMask;
230  while (target_mask.any())
231  {
232  const int n = target_mask.takeOneBit();
233  Offset offset=Add_Effect_Table.getOffsetPBISHOP<P>(from,target,n&15);
234  Square mid=target+offset.blackOffset<P>();
236  int count=0;
237  if (isEmptyOrAdditional<isAttackToKing>(state,mid,target,count))
238  {
239  for(int i=0;i<2;i++){
240  Piece p=state.pieceAt(mid);
241  if(p.canMoveOn<P>()){
242  if (canPromote &&
243  (from.canPromote<P>()||mid.canPromote<P>()))
244  action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
245  action.unknownMove(from,mid,p,T,false,P);
246  }
247  if (!p.isEmpty()){
248  if (isAttackToKing || count>0 || p.isEdge() || !state.hasEffectByPiece(p,target)) break;
249  count++;
250  }
251  mid=mid+Board_Table.getShortOffset(Offset32(mid,target));
252  }
253  }
254  }
255  }
257  if (T==PROOK)
258  {
259  NearMask target_mask=Add_Effect_Table.getNearMaskPROOK<P>(from,target);
260  if(isAttackToKing) target_mask&=nearMask;
261  while (target_mask.any())
262  {
263  const int n = target_mask.takeOneBit();
264  Offset offset=Add_Effect_Table.getOffsetPROOK<P>(from,target,n&15);
265  Square mid=target+offset.blackOffset<P>();
267  int count=0;
268  if (isEmptyOrAdditional<isAttackToKing>(state,mid,target,count))
269  {
270  for(int i=0;i<3;i++)
271  {
272  Piece p=state.pieceAt(mid);
273  if(p.canMoveOn<P>()){
274  if (canPromote &&
275  (from.canPromote<P>()||mid.canPromote<P>()))
276  action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
277  action.unknownMove(from,mid,p,T,false,P);
278  }
279  if (!p.isEmpty()){
280  if (isAttackToKing || count>0 || p.isEdge() || !state.hasEffectByPiece(p,target)) break;
281  count++;
282  }
283  mid=mid+Board_Table.getShortOffset(Offset32(mid,target));
284  }
285  }
286  }
287  }
288  }
289  }
290  }
291 
292  template <Player P,Ptype T,class Action,bool isLong,bool isAttackToKing>
293  void generateDrop(const NumEffectState& state,Square target, NearMask nearMask,Action& action)
294  {
295  NearMask target_mask
296  = (isLong ? NearMask::makeDirect(PtypeTraits<T>::moveMask>>10) :
297  NearMask::makeDirect(PtypeTraits<T>::moveMask<<16) & nearMask);
298  if(isAttackToKing && isLong) target_mask&=nearMask;
299  while (target_mask.any())
300  {
301  const int n = target_mask.takeOneBit();
302  Direction dir=static_cast<Direction>(n&15);
303  Offset offset=Board_Table.template getOffset<P>(dir);
304  Square to=target-offset;
305  if (isLong)
306  {
307  Piece p;
308  Square pos1;
309  for(pos1=to;(p=state.pieceAt(pos1)).isEmpty();pos1-=offset)
310  action.dropMove(pos1,T,P);
311  if(isAttackToKing || p.isEdge() || !state.hasEffectByPiece(p,target)) continue;
312  for(pos1-=offset;state.pieceAt(pos1).isEmpty();pos1-=offset)
313  action.dropMove(pos1,T,P);
314 
315  }
317  else if (T!=PAWN || !state.template isPawnMaskSet<P>(to.x()))
318  action.dropMove(to,T,P);
319  }
320  }
321 
325  template <Player P,Ptype T,class Action>
327  {
328  const NumEffectState& state;
330  Action& action;
331  NearMask nearMask;
332  public:
333  GoldKingAction(const NumEffectState& s,Square p,Action& a,NearMask n)
334  :state(s),target(p),action(a),nearMask(n)
335  {}
340  {
341  Square from=p.square();
342  generateMove<P,T,Action,false>(state,from,target,nearMask,action);
343  }
344  };
345 
349  template <Player P,Ptype T,class Action>
351  {
352  const NumEffectState& state;
354  Action& action;
355  NearMask nearMask;
356  public:
357  ShortPieceAction(const NumEffectState& s,Square p,Action& a,NearMask n)
358  :state(s),target(p),action(a),nearMask(n)
359  {}
364  {
365  Square from=p.square();
366  if (p.isPromotedNotKingGold())
367  {
368  generateMove<P,PtypeFuns<T>::promotePtype,Action,false>(state,from,target,nearMask,action);
369  }
370  else
371  {
372  generateMove<P,T,Action,true>(state,from,target,nearMask,action);
373  generateMove<P,T,Action,false>(state,from,target,nearMask,action);
374  }
375  }
376  };
377 
381  template <Player P,Ptype T,class Action,bool isAttackToKing>
383  {
384  const NumEffectState& state;
386  Action& action;
387  NearMask nearMask;
388  public:
389  LongPieceAction(const NumEffectState& s,Square p,Action& a,NearMask n)
390  :state(s),target(p),action(a),nearMask(n)
391  {}
396  {
397  Square from=p.square();
398  int num=p.number();
399  if (p.isPromotedNotKingGold())
400  {
401  if (T==LANCE)
402  generateMove<P,PtypeFuns<T>::promotePtype,Action,false>(state,from,target,nearMask,action);
403  else
404  {
405  generateLongMove<P,PtypeFuns<T>::promotePtype,Action,false,isAttackToKing>(state,from,target,nearMask,action,num);
406  }
407  }
408  else
409  {
410  generateLongMove<P,T,Action,true,isAttackToKing>(state,from,target,nearMask,action,num);
411  }
412  }
413  };
414 
415  } // namespace without_effect
416  } // namespace move_generator
417 } // namespace osl
418 
419 template <osl::Player P,osl::Ptype T,bool isAttackToKing>
420 template <class Action>
422 generate(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
423 {
427  action_t gkAction(state,target,action,nearMask);
428  state.template forEachOnBoard<P,T,action_t>(gkAction);
430  if (state.template hasPieceOnStand<T>(P))
431  {
432  without_effect::generateDrop<P,T,Action,false,isAttackToKing>(state,target,nearMask,action);
433  }
434 }
435 
436 template <osl::Player P,osl::Ptype T,bool isAttackToKing>
437 template <class Action>
439 generate(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
440 {
442  action_t gkAction(state,target,action,nearMask);
443  state.template forEachOnBoard<P,T,action_t>(gkAction);
445  if (state.template hasPieceOnStand<T>(P))
446  {
447  without_effect::generateDrop<P,T,Action,true,isAttackToKing>(state,target,nearMask,action);
448  }
449 }
450 
451 template <osl::Player P,bool isAttackToKing>
452 template <class Action>
454 generateKing(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
455 {
457  action_t gkAction(state,target,action,nearMask);
458  state.template forEachOnBoard<P,KING,action_t>(gkAction);
459 }
460 
461 template <osl::Player P,bool isAttackToKing>
462 template <class Action>
464 generateGold(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
465 {
467  action_t gkAction(state,target,action,nearMask);
468  state.template forEachOnBoard<P,GOLD,action_t>(gkAction);
470  if (state.template hasPieceOnStand<GOLD>(P))
471  {
472  without_effect::generateDrop<P,GOLD,Action,false,isAttackToKing>(state,target,nearMask,action);
473  }
474 }
475 
476 template <osl::Player P,bool isAttackToKing>
477 template <class Action>
479 generate(const NumEffectState& state,Square target,Action& action)
480 {
481 // BOOST_STATIC_ASSERT(!isAttackToKing);
482  NearMask nearMask=NearMask::make<P>(state,target);
483  /* 各種類によるmove */
484  AddEffectShort<P,PAWN,isAttackToKing>::generate(state,target,action,nearMask);
485  AddEffectLong<P,LANCE,isAttackToKing>::generate(state,target,action,nearMask);
486  AddEffectShort<P,KNIGHT,isAttackToKing>::generate(state,target,action,nearMask);
487  AddEffectShort<P,SILVER,isAttackToKing>::generate(state,target,action,nearMask);
488  generateGold(state,target,action,nearMask);
489  if (!isAttackToKing)
490  generateKing(state,target,action,nearMask);
491  AddEffectLong<P,BISHOP,isAttackToKing>::generate(state,target,action,nearMask);
492  AddEffectLong<P,ROOK,isAttackToKing>::generate(state,target,action,nearMask);
493 }
494 
495 template<bool isAttackToKing>
497 generate(Player player, const NumEffectState& state, Square target,
499 {
500  using namespace osl::move_action;
501  if(player==BLACK)
502  {
503  SafeFilter<BLACK,Store> filter(state, store);
504  AddEffect<BLACK,isAttackToKing>::generate(state,target,filter);
505  }
506  else
507  {
508  SafeFilter<WHITE,Store> filter(state, store);
509  AddEffect<WHITE,isAttackToKing>::generate(state,target,filter);
510  }
511 }
512 
513 #endif /* _MOVE_GENERATOR_ADD_EFFECT_TCC */
514 // ;;; Local Variables:
515 // ;;; mode:c++
516 // ;;; c-basic-offset:2
517 // ;;; End: