00001 #ifndef _MOVE_GENERATOR_ADD_EFFECT_TCC
00002 #define _MOVE_GENERATOR_ADD_EFFECT_TCC
00003
00004 #include "osl/move_generator/addEffect_.h"
00005 #include "osl/move_action/safeFilter.h"
00006 #include "osl/move_generator/open.h"
00007 #include <boost/type_traits.hpp>
00008
00009 namespace osl
00010 {
00011 namespace move_generator
00012 {
00013 namespace without_effect
00014 {
00024 template <Player P,Ptype T,class Action,bool isPromote>
00025 void generateMove(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action)
00026 {
00027 NearMask target_mask =
00028 (isPromote
00029 ? Add_Effect_Table.getNearMaskWithPromote<P>(PtypeTraits<T>::moveType,from,target)
00030 : Add_Effect_Table.getNearMask<P>(PtypeTraits<T>::moveType,from,target));
00031 target_mask &= nearMask;
00032 while (target_mask.any())
00033 {
00034 const int n =target_mask.takeOneBit();
00035 Direction dir=static_cast<Direction>(n);
00036 Square to=target-Board_Table.template getOffset<P>(dir);
00037 if (!isPromote ||
00038 (from.canPromote<P>()||to.canPromote<P>()))
00039 action.unknownMove(from,to,state.pieceAt(to),(isPromote ? PtypeFuns<T>::promotePtype : T) ,isPromote,P);
00040 }
00041 }
00042
00043 template <Player P,Ptype T,class Action>
00044 void generateLongMoveDirectNoPromote(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action)
00045 {
00046 assert(state.pieceAt(from).template isOnBoardByOwner<P>());
00047 NearMask target_mask=Add_Effect_Table.getNearMask<P>(T,from,target) &nearMask;
00048 while (target_mask.any())
00049 {
00050 const int n = target_mask.takeOneBit();
00051 Direction dir=static_cast<Direction>(n);
00052 Square to=target-Board_Table.template getOffset<P>(dir);
00056 if (state.hasEffectByPiece(state.pieceAt(from),to))
00057 action.unknownMove(from,to,state.pieceAt(to),T,false,P);
00058 }
00059 }
00060
00061 template <Player P,Ptype T,class Action>
00062 void generateLongMoveDirectCanPromote(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action)
00063 {
00064 assert(state.pieceAt(from).template isOnBoardByOwner<P>());
00065 NearMask target_mask=Add_Effect_Table.getNearMaskWithPromote<P>(T,from,target) &nearMask;
00066 NearMask target_mask_no_promote=Add_Effect_Table.getNearMask<P>(T,from,target) &nearMask;
00067 while (target_mask.any())
00068 {
00069 const int n = target_mask.takeOneBit();
00070 Direction dir=static_cast<Direction>(n);
00071 Square to=target-Board_Table.template getOffset<P>(dir);
00075 if (state.hasEffectByPiece(state.pieceAt(from),to))
00076 {
00077 if (to.canPromote<P>()||from.canPromote<P>())
00078 action.unknownMove(from,to,state.pieceAt(to),PtypeFuns<T>::promotePtype,true,P);
00079 if ((target_mask_no_promote.isSet(n))!=0)
00080 action.unknownMove(from,to,state.pieceAt(to),T,false,P);
00081 }
00082 }
00083 }
00087 template<bool isAttackToKing>
00088 bool isEmptyOrAdditional(const NumEffectState& state,Square from,Square to,int& count)
00089 {
00090 count=0;
00091 if(isAttackToKing){
00092 return state.isEmptyBetween(from,to);
00093 }
00094 Offset o=Board_Table.getShortOffset(Offset32(to,from));
00095 assert(!o.zero());
00096 Piece p;
00097 Square pos;
00098 for(pos=from+o;pos!=to && (p=state.pieceAt(pos)).isEmpty();pos+=o)
00099 ;
00100 if(pos==to) return true;
00101 assert(!p.isEdge());
00102 count=1;
00103 return state.hasEffectByPiece(p,to);
00104 }
00105 template <Player P,Ptype T,class Action,bool canPromote,bool isAttackToKing>
00106 void generateLongMove(const NumEffectState& state,Square from,Square target, NearMask nearMask,Action& action,int piece_num)
00107 {
00108 assert(state.pieceAt(from).template isOnBoardByOwner<P>());
00109
00110 assert(T==LANCE || T==BISHOP || T==PBISHOP || T==ROOK || T==PROOK);
00112 const EffectContent effect_content=
00113 Ptype_Table.getEffect(newPtypeO(BLACK,unpromote(T)),Offset32(target,from).blackOffset32<P>());
00114 if (isAttackToKing)
00115 {
00116 assert(! effect_content.hasUnblockableEffect());
00117 }
00118 else if (effect_content.hasUnblockableEffect())
00119 return;
00120 if (effect_content.hasEffect())
00121 {
00125 if (T==PROOK)
00126 {
00127 generateMove<P,T,Action,false>(state,from,target,nearMask,action);
00128 }
00129 Direction longD=Board_Table.getLongDirection<BLACK>(from,target);
00130 Direction shortD=longToShort(longD);
00131 Piece p;
00132 Square pos1;
00133 if(isAttackToKing){
00134 pos1=state.kingMobilityAbs(alt(P),shortD);
00135 if(state.mobilityOf(shortD,piece_num)!=pos1) return;
00136 p=state.pieceAt(pos1);
00137 }
00138 else{
00139 Offset o1=effect_content.offset().template blackOffset<P>();
00140 assert(!o1.zero());
00141 pos1=target-o1;
00142 for(;(p=state.pieceAt(pos1)).isEmpty();pos1-=o1) ;
00143 if (pos1==from) return;
00144 assert(!p.isEdge());
00145 if(state.hasEffectByPiece(p,target)){
00146 Piece p1;
00147 Square pos3=pos1;
00148 for(pos1-=o1;(p1=state.pieceAt(pos1)).isEmpty();pos1-=o1) ;
00149 if(pos1==from){
00150 if(p.isOnBoardByOwner<P>()) return;
00151 pos1=pos3;
00152 }
00153 else{
00154 p=p1;
00155 if (! state.hasEffectByPiece(state.pieceAt(from), pos1))
00156 return;
00157 }
00158 }
00159 else{
00160 if (! state.hasEffectByPiece(state.pieceAt(from), pos1))
00161 return;
00162 }
00163 }
00164 if (p.isOnBoardByOwner<P>())
00165 {
00166 Open<Action>::template generate<P>
00167 (state,p,action,target,
00168 longToShort(Board_Table.getLongDirection<BLACK>(Offset32(target,from).blackOffset32<P>())));
00171 }
00172 else
00173 {
00175 if (canPromote &&
00176 (from.canPromote<P>()||pos1.canPromote<P>()) &&
00178 (T!=LANCE ||
00179 pos1==target-DirectionPlayerTraits<U,P>::offset()))
00180 action.unknownMove(from,pos1,p,PtypeFuns<T>::promotePtype,true,P);
00181 action.unknownMove(from,pos1,p,T,false,P);
00182 }
00183 }
00184 else
00185 {
00190 if (!PtypeTraits<T>::isBasic)
00191 {
00192 generateLongMoveDirectNoPromote<P,T,Action>(state,from,target,nearMask,action);
00193 }
00194 else
00195 {
00196 generateLongMoveDirectCanPromote<P,T,Action>(state,from,target,nearMask,action);
00197 }
00198 if (T!=LANCE)
00199 {
00201 {
00202 NearMask target_mask=Add_Effect_Table.getNearMaskLong<P>(T,from,target);
00203 if(isAttackToKing) target_mask&=nearMask;
00204 while (target_mask.any())
00205 {
00206 const int n = target_mask.takeOneBit();
00207 Offset offset=Add_Effect_Table.getOffsetLong<P>(T,from,target,n&15);
00208 Square mid=target+offset.blackOffset<P>();
00210 if (! mid.isOnBoard())
00211 continue;
00212 Piece p=state.pieceAt(mid);
00213 int count=0;
00214 if (p.canMoveOn<P>()
00215 && state.hasEffectByPiece(state.pieceAt(from),mid)
00216 && isEmptyOrAdditional<isAttackToKing>(state,mid,target,count))
00217 {
00218 if (canPromote &&
00219 (from.canPromote<P>()||mid.canPromote<P>()))
00220 action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
00221 action.unknownMove(from,mid,p,T,false,P);
00222 }
00223 }
00224 }
00226 if (T==PBISHOP)
00227 {
00228 NearMask target_mask=Add_Effect_Table.getNearMaskPBISHOP<P>(from,target);
00229 if(isAttackToKing) target_mask&=nearMask;
00230 while (target_mask.any())
00231 {
00232 const int n = target_mask.takeOneBit();
00233 Offset offset=Add_Effect_Table.getOffsetPBISHOP<P>(from,target,n&15);
00234 Square mid=target+offset.blackOffset<P>();
00236 int count=0;
00237 if (isEmptyOrAdditional<isAttackToKing>(state,mid,target,count))
00238 {
00239 for(int i=0;i<2;i++){
00240 Piece p=state.pieceAt(mid);
00241 if(p.canMoveOn<P>()){
00242 if (canPromote &&
00243 (from.canPromote<P>()||mid.canPromote<P>()))
00244 action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
00245 action.unknownMove(from,mid,p,T,false,P);
00246 }
00247 if (!p.isEmpty()){
00248 if (isAttackToKing || count>0 || p.isEdge() || !state.hasEffectByPiece(p,target)) break;
00249 count++;
00250 }
00251 mid=mid+Board_Table.getShortOffset(Offset32(mid,target));
00252 }
00253 }
00254 }
00255 }
00257 if (T==PROOK)
00258 {
00259 NearMask target_mask=Add_Effect_Table.getNearMaskPROOK<P>(from,target);
00260 if(isAttackToKing) target_mask&=nearMask;
00261 while (target_mask.any())
00262 {
00263 const int n = target_mask.takeOneBit();
00264 Offset offset=Add_Effect_Table.getOffsetPROOK<P>(from,target,n&15);
00265 Square mid=target+offset.blackOffset<P>();
00267 int count=0;
00268 if (isEmptyOrAdditional<isAttackToKing>(state,mid,target,count))
00269 {
00270 for(int i=0;i<3;i++)
00271 {
00272 Piece p=state.pieceAt(mid);
00273 if(p.canMoveOn<P>()){
00274 if (canPromote &&
00275 (from.canPromote<P>()||mid.canPromote<P>()))
00276 action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
00277 action.unknownMove(from,mid,p,T,false,P);
00278 }
00279 if (!p.isEmpty()){
00280 if (isAttackToKing || count>0 || p.isEdge() || !state.hasEffectByPiece(p,target)) break;
00281 count++;
00282 }
00283 mid=mid+Board_Table.getShortOffset(Offset32(mid,target));
00284 }
00285 }
00286 }
00287 }
00288 }
00289 }
00290 }
00291
00292 template <Player P,Ptype T,class Action,bool isLong,bool isAttackToKing>
00293 void generateDrop(const NumEffectState& state,Square target, NearMask nearMask,Action& action)
00294 {
00295 NearMask target_mask
00296 = (isLong ? NearMask::makeDirect(PtypeTraits<T>::moveMask>>10) :
00297 NearMask::makeDirect(PtypeTraits<T>::moveMask<<16) & nearMask);
00298 if(isAttackToKing && isLong) target_mask&=nearMask;
00299 while (target_mask.any())
00300 {
00301 const int n = target_mask.takeOneBit();
00302 Direction dir=static_cast<Direction>(n&15);
00303 Offset offset=Board_Table.template getOffset<P>(dir);
00304 Square to=target-offset;
00305 if (isLong)
00306 {
00307 Piece p;
00308 Square pos1;
00309 for(pos1=to;(p=state.pieceAt(pos1)).isEmpty();pos1-=offset)
00310 action.dropMove(pos1,T,P);
00311 if(isAttackToKing || p.isEdge() || !state.hasEffectByPiece(p,target)) continue;
00312 for(pos1-=offset;state.pieceAt(pos1).isEmpty();pos1-=offset)
00313 action.dropMove(pos1,T,P);
00314
00315 }
00317 else if (T!=PAWN || !state.template isPawnMaskSet<P>(to.x()))
00318 action.dropMove(to,T,P);
00319 }
00320 }
00321
00325 template <Player P,Ptype T,class Action>
00326 class GoldKingAction
00327 {
00328 const NumEffectState& state;
00329 Square target;
00330 Action& action;
00331 NearMask nearMask;
00332 public:
00333 GoldKingAction(const NumEffectState& s,Square p,Action& a,NearMask n)
00334 :state(s),target(p),action(a),nearMask(n)
00335 {}
00339 void operator()(Piece p)
00340 {
00341 Square from=p.square();
00342 generateMove<P,T,Action,false>(state,from,target,nearMask,action);
00343 }
00344 };
00345
00349 template <Player P,Ptype T,class Action>
00350 class ShortPieceAction
00351 {
00352 const NumEffectState& state;
00353 Square target;
00354 Action& action;
00355 NearMask nearMask;
00356 public:
00357 ShortPieceAction(const NumEffectState& s,Square p,Action& a,NearMask n)
00358 :state(s),target(p),action(a),nearMask(n)
00359 {}
00363 void operator()(Piece p)
00364 {
00365 Square from=p.square();
00366 if (p.isPromotedNotKingGold())
00367 {
00368 generateMove<P,PtypeFuns<T>::promotePtype,Action,false>(state,from,target,nearMask,action);
00369 }
00370 else
00371 {
00372 generateMove<P,T,Action,true>(state,from,target,nearMask,action);
00373 generateMove<P,T,Action,false>(state,from,target,nearMask,action);
00374 }
00375 }
00376 };
00377
00381 template <Player P,Ptype T,class Action,bool isAttackToKing>
00382 class LongPieceAction
00383 {
00384 const NumEffectState& state;
00385 Square target;
00386 Action& action;
00387 NearMask nearMask;
00388 public:
00389 LongPieceAction(const NumEffectState& s,Square p,Action& a,NearMask n)
00390 :state(s),target(p),action(a),nearMask(n)
00391 {}
00395 void operator()(Piece p)
00396 {
00397 Square from=p.square();
00398 int num=p.number();
00399 if (p.isPromotedNotKingGold())
00400 {
00401 if (T==LANCE)
00402 generateMove<P,PtypeFuns<T>::promotePtype,Action,false>(state,from,target,nearMask,action);
00403 else
00404 {
00405 generateLongMove<P,PtypeFuns<T>::promotePtype,Action,false,isAttackToKing>(state,from,target,nearMask,action,num);
00406 }
00407 }
00408 else
00409 {
00410 generateLongMove<P,T,Action,true,isAttackToKing>(state,from,target,nearMask,action,num);
00411 }
00412 }
00413 };
00414
00415 }
00416 }
00417 }
00418
00419 template <osl::Player P,osl::Ptype T,bool isAttackToKing>
00420 template <class Action>
00421 void osl::move_generator::AddEffectShort<P,T,isAttackToKing>::
00422 generate(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
00423 {
00424 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00425 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00426 typedef without_effect::ShortPieceAction<P,T,Action> action_t;
00427 action_t gkAction(state,target,action,nearMask);
00428 state.template forEachOnBoard<P,T,action_t>(gkAction);
00430 if (state.template hasPieceOnStand<T>(P))
00431 {
00432 without_effect::generateDrop<P,T,Action,false,isAttackToKing>(state,target,nearMask,action);
00433 }
00434 }
00435
00436 template <osl::Player P,osl::Ptype T,bool isAttackToKing>
00437 template <class Action>
00438 void osl::move_generator::AddEffectLong<P,T,isAttackToKing>::
00439 generate(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
00440 {
00441 typedef without_effect::LongPieceAction<P,T,Action,isAttackToKing> action_t;
00442 action_t gkAction(state,target,action,nearMask);
00443 state.template forEachOnBoard<P,T,action_t>(gkAction);
00445 if (state.template hasPieceOnStand<T>(P))
00446 {
00447 without_effect::generateDrop<P,T,Action,true,isAttackToKing>(state,target,nearMask,action);
00448 }
00449 }
00450
00451 template <osl::Player P,bool isAttackToKing>
00452 template <class Action>
00453 void osl::move_generator::AddEffect<P,isAttackToKing>::
00454 generateKing(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
00455 {
00456 typedef without_effect::GoldKingAction<P,KING,Action> action_t;
00457 action_t gkAction(state,target,action,nearMask);
00458 state.template forEachOnBoard<P,KING,action_t>(gkAction);
00459 }
00460
00461 template <osl::Player P,bool isAttackToKing>
00462 template <class Action>
00463 void osl::move_generator::AddEffect<P,isAttackToKing>::
00464 generateGold(const NumEffectState& state,Square target,Action& action,NearMask nearMask)
00465 {
00466 typedef without_effect::GoldKingAction<P,GOLD,Action> action_t;
00467 action_t gkAction(state,target,action,nearMask);
00468 state.template forEachOnBoard<P,GOLD,action_t>(gkAction);
00470 if (state.template hasPieceOnStand<GOLD>(P))
00471 {
00472 without_effect::generateDrop<P,GOLD,Action,false,isAttackToKing>(state,target,nearMask,action);
00473 }
00474 }
00475
00476 template <osl::Player P,bool isAttackToKing>
00477 template <class Action>
00478 void osl::move_generator::AddEffect<P,isAttackToKing>::
00479 generate(const NumEffectState& state,Square target,Action& action)
00480 {
00481
00482 NearMask nearMask=NearMask::make<P>(state,target);
00483
00484 AddEffectShort<P,PAWN,isAttackToKing>::generate(state,target,action,nearMask);
00485 AddEffectLong<P,LANCE,isAttackToKing>::generate(state,target,action,nearMask);
00486 AddEffectShort<P,KNIGHT,isAttackToKing>::generate(state,target,action,nearMask);
00487 AddEffectShort<P,SILVER,isAttackToKing>::generate(state,target,action,nearMask);
00488 generateGold(state,target,action,nearMask);
00489 if (!isAttackToKing)
00490 generateKing(state,target,action,nearMask);
00491 AddEffectLong<P,BISHOP,isAttackToKing>::generate(state,target,action,nearMask);
00492 AddEffectLong<P,ROOK,isAttackToKing>::generate(state,target,action,nearMask);
00493 }
00494
00495 template<bool isAttackToKing>
00496 void osl::move_generator::GenerateAddEffect<isAttackToKing>::
00497 generate(Player player, const NumEffectState& state, Square target,
00498 move_action::Store& store)
00499 {
00500 using namespace osl::move_action;
00501 if(player==BLACK)
00502 {
00503 SafeFilter<BLACK,Store> filter(state, store);
00504 AddEffect<BLACK,isAttackToKing>::generate(state,target,filter);
00505 }
00506 else
00507 {
00508 SafeFilter<WHITE,Store> filter(state, store);
00509 AddEffect<WHITE,isAttackToKing>::generate(state,target,filter);
00510 }
00511 }
00512
00513 #endif
00514
00515
00516
00517