addEffect_.tcc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
4 #include "osl/move_generator/addEffect_.h"
5 #include "osl/move_action/safeFilter.h"
6 #include "osl/move_generator/open.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
29 ? Add_Effect_Table.getNearMaskWithPromote<P>(PtypeTraits<T>::moveType,from,target)
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 }
94 Offset o=Board_Table.getShortOffset(Offset32(to,from));
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 }
129 Direction longD=Board_Table.getLongDirection<BLACK>(from,target);
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 {
190 if (!PtypeTraits<T>::isBasic)
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>
326 class GoldKingAction
327 {
328 const NumEffectState& state;
329 Square target;
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 {}
339 void operator()(Piece p)
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>
350 class ShortPieceAction
351 {
352 const NumEffectState& state;
353 Square target;
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 {}
363 void operator()(Piece p)
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>
382 class LongPieceAction
383 {
384 const NumEffectState& state;
385 Square target;
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 {}
395 void operator()(Piece p)
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>
421 void osl::move_generator::AddEffectShort<P,T,isAttackToKing>::
422 generate(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
423 {
424 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
425 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
426 typedef without_effect::ShortPieceAction<P,T,Action> action_t;
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>
438 void osl::move_generator::AddEffectLong<P,T,isAttackToKing>::
439 generate(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
440 {
441 typedef without_effect::LongPieceAction<P,T,Action,isAttackToKing> action_t;
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>
453 void osl::move_generator::AddEffect<P,isAttackToKing>::
454 generateKing(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
455 {
456 typedef without_effect::GoldKingAction<P,KING,Action> action_t;
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>
463 void osl::move_generator::AddEffect<P,isAttackToKing>::
464 generateGold(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
465 {
466 typedef without_effect::GoldKingAction<P,GOLD,Action> action_t;
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>
478 void osl::move_generator::AddEffect<P,isAttackToKing>::
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>
496 void osl::move_generator::GenerateAddEffect<isAttackToKing>::
497 generate(Player player, const NumEffectState& state, Square target,
498 move_action::Store& store)
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: