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 <class State,Player P,Ptype T,class Action,bool isPromote>
00025 void generateMove(State const& state,Position from,Position 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 Position to=target-Board_Table.template getOffset<P>(dir);
00037 if (!isPromote ||
00038 (from.canPromote<P>()||to.canPromote<P>()))
00039 action.unknownMove(from,to,state.getPieceAt(to),(isPromote ? PtypeFuns<T>::promotePtype : T) ,isPromote,P);
00040 }
00041 }
00042
00043 template <class State,Player P,Ptype T,class Action>
00044 void generateLongMoveDirectNoPromote(State const& state,Position from,Position target, NearMask nearMask,Action& action)
00045 {
00046 NearMask target_mask=Add_Effect_Table.getNearMask<P>(T,from,target) &nearMask;
00047 while (target_mask.any())
00048 {
00049 const int n = target_mask.takeOneBit();
00050 Direction dir=static_cast<Direction>(n);
00051 Position to=target-Board_Table.template getOffset<P>(dir);
00055 if (state.isEmptyBetween(from,to))
00056 action.unknownMove(from,to,state.getPieceAt(to),T,false,P);
00057 }
00058 }
00059
00060 template <class State,Player P,Ptype T,class Action>
00061 void generateLongMoveDirectCanPromote(State const& state,Position from,Position target, NearMask nearMask,Action& action)
00062 {
00063 NearMask target_mask=Add_Effect_Table.getNearMaskWithPromote<P>(T,from,target) &nearMask;
00064 NearMask target_mask_no_promote=Add_Effect_Table.getNearMask<P>(T,from,target) &nearMask;
00065 while (target_mask.any())
00066 {
00067 const int n = target_mask.takeOneBit();
00068 Direction dir=static_cast<Direction>(n);
00069 Position to=target-Board_Table.template getOffset<P>(dir);
00073 if (state.isEmptyBetween(from,to))
00074 {
00075 if (to.canPromote<P>()||from.canPromote<P>())
00076 action.unknownMove(from,to,state.getPieceAt(to),PtypeFuns<T>::promotePtype,true,P);
00077 if ((target_mask_no_promote.isSet(n))!=0)
00078 action.unknownMove(from,to,state.getPieceAt(to),T,false,P);
00079 }
00080 }
00081 }
00085 template<class State,bool isAttackToKing>
00086 bool isEmptyOrAdditional(State const& state,Position from,Position to,int& count)
00087 {
00088 count=0;
00089 if(isAttackToKing){
00090 return state.isEmptyBetween(from,to);
00091 }
00092 Offset o=Board_Table.getShortOffset(Offset32(to,from));
00093 assert(!o.zero());
00094 Piece p;
00095 Position pos;
00096 for(pos=from+o;pos!=to && (p=state.getPieceAt(pos)).isEmpty();pos+=o)
00097 ;
00098 if(pos==to) return true;
00099 assert(!p.isEdge());
00100 count=1;
00101 return state.hasEffectTo(p,to);
00102 }
00103 template <class State,Player P,Ptype T,class Action,bool canPromote,bool isAttackToKing>
00104 void generateLongMove(State const& state,Position from,Position target, NearMask nearMask,Action& action)
00105 {
00106
00107 assert(T==LANCE || T==BISHOP || T==PBISHOP || T==ROOK || T==PROOK);
00109 const EffectContent effect_content=
00110 Ptype_Table.getEffect(newPtypeO(BLACK,unpromote(T)),Offset32(target,from).blackOffset32<P>());
00111 if (isAttackToKing)
00112 {
00113 assert(! effect_content.hasUnblockableEffect());
00114 }
00115 else if (effect_content.hasUnblockableEffect())
00116 return;
00117 if (effect_content.hasEffect())
00118 {
00122 if (T==PROOK)
00123 {
00124 generateMove<State,P,T,Action,false>(state,from,target,nearMask,action);
00125 }
00126 Offset o1=effect_content.offset().template blackOffset<P>();
00127 assert(!o1.zero());
00128 Piece p;
00129 Position pos1=target-o1;
00130 for(;(p=state.getPieceAt(pos1)).isEmpty();pos1-=o1) ;
00131
00132 if (isAttackToKing)
00133 {
00134 assert(pos1!=from);
00135 }
00136 else if (pos1==from) return;
00137 assert(!p.isEdge());
00138 if(!isAttackToKing && state.hasEffectTo(p,target)){
00139 Piece p1;
00140 Position pos3=pos1;
00141 for(pos1-=o1;(p1=state.getPieceAt(pos1)).isEmpty();pos1-=o1) ;
00142 if(pos1==from){
00143 if(p.isOnBoardByOwner<P>()) return;
00144 pos1=pos3;
00145 }
00146 else{
00147 p=p1;
00148 Position pos2=pos1-o1;
00149 for(;(p1=state.getPieceAt(pos2)).isEmpty();pos2-=o1) ;
00150 if (pos2!=from) return;
00151 }
00152 }
00153 else{
00154 Position pos2=pos1-o1;
00155 Piece p1;
00156 for(;(p1=state.getPieceAt(pos2)).isEmpty();pos2-=o1) ;
00157 if (pos2!=from) return;
00158 }
00159 if (p.isOnBoardByOwner<P>())
00160 {
00161 Open<P>::generate
00162 (state,p,action,target,
00163 longToShort(Board_Table.getLongDirection<BLACK>(Offset32(target,from).blackOffset32<P>())));
00166 }
00167 else
00168 {
00170 if (canPromote &&
00171 (from.canPromote<P>()||pos1.canPromote<P>()) &&
00173 (T!=LANCE || pos1==target-o1))
00174 action.unknownMove(from,pos1,p,PtypeFuns<T>::promotePtype,true,P);
00175 action.unknownMove(from,pos1,p,T,false,P);
00176 }
00177 }
00178 else
00179 {
00184 if (!PtypeTraits<T>::isBasic)
00185 {
00186 generateLongMoveDirectNoPromote<State,P,T,Action>(state,from,target,nearMask,action);
00187 }
00188 else
00189 {
00190 generateLongMoveDirectCanPromote<State,P,T,Action>(state,from,target,nearMask,action);
00191 }
00192 if (T!=LANCE)
00193 {
00195 {
00196 NearMask target_mask=Add_Effect_Table.getNearMaskLong<P>(T,from,target);
00197 if(isAttackToKing) target_mask&=nearMask;
00198 while (target_mask.any())
00199 {
00200 const int n = target_mask.takeOneBit();
00201 Offset offset=Add_Effect_Table.getOffsetLong<P>(T,from,target,n&15);
00202 Position mid=target+offset.blackOffset<P>();
00204 if (! mid.isOnBoardRegion())
00205 continue;
00206 Piece p=state.getPieceAt(mid);
00207 int count=0;
00208 if (p.canMoveOn<P>()
00209 && state.isEmptyBetween(from,mid)
00210 && isEmptyOrAdditional<State,isAttackToKing>(state,mid,target,count))
00211 {
00212 if (canPromote &&
00213 (from.canPromote<P>()||mid.canPromote<P>()))
00214 action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
00215 action.unknownMove(from,mid,p,T,false,P);
00216 }
00217 }
00218 }
00220 if (T==PBISHOP)
00221 {
00222 NearMask target_mask=Add_Effect_Table.getNearMaskPBISHOP<P>(from,target);
00223 if(isAttackToKing) target_mask&=nearMask;
00224 while (target_mask.any())
00225 {
00226 const int n = target_mask.takeOneBit();
00227 Offset offset=Add_Effect_Table.getOffsetPBISHOP<P>(from,target,n&15);
00228 Position mid=target+offset.blackOffset<P>();
00230 int count=0;
00231 if (isEmptyOrAdditional<State,isAttackToKing>(state,mid,target,count))
00232 {
00233 for(int i=0;i<2;i++){
00234 Piece p=state.getPieceAt(mid);
00235 if(p.canMoveOn<P>()){
00236 if (canPromote &&
00237 (from.canPromote<P>()||mid.canPromote<P>()))
00238 action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
00239 action.unknownMove(from,mid,p,T,false,P);
00240 }
00241 if (!p.isEmpty()){
00242 if (isAttackToKing || count>0 || p.isEdge() || !state.hasEffectTo(p,target)) break;
00243 count++;
00244 }
00245 mid=mid+Board_Table.getShortOffset(Offset32(mid,target));
00246 }
00247 }
00248 }
00249 }
00251 if (T==PROOK)
00252 {
00253 NearMask target_mask=Add_Effect_Table.getNearMaskPROOK<P>(from,target);
00254 if(isAttackToKing) target_mask&=nearMask;
00255 while (target_mask.any())
00256 {
00257 const int n = target_mask.takeOneBit();
00258 Offset offset=Add_Effect_Table.getOffsetPROOK<P>(from,target,n&15);
00259 Position mid=target+offset.blackOffset<P>();
00261 int count=0;
00262 if (isEmptyOrAdditional<State,isAttackToKing>(state,mid,target,count))
00263 {
00264 for(int i=0;i<3;i++)
00265 {
00266 Piece p=state.getPieceAt(mid);
00267 if(p.canMoveOn<P>()){
00268 if (canPromote &&
00269 (from.canPromote<P>()||mid.canPromote<P>()))
00270 action.unknownMove(from,mid,p,PtypeFuns<T>::promotePtype,true,P);
00271 action.unknownMove(from,mid,p,T,false,P);
00272 }
00273 if (!p.isEmpty()){
00274 if (isAttackToKing || count>0 || p.isEdge() || !state.hasEffectTo(p,target)) break;
00275 count++;
00276 }
00277 mid=mid+Board_Table.getShortOffset(Offset32(mid,target));
00278 }
00279 }
00280 }
00281 }
00282 }
00283 }
00284 }
00285
00286 template <class State,Player P,Ptype T,class Action,bool isLong,bool isAttackToKing>
00287 void generateDrop(State const& state,Position target, NearMask nearMask,Action& action)
00288 {
00289 NearMask target_mask
00290 = (isLong ? NearMask::makeDirect(PtypeTraits<T>::moveMask>>10) :
00291 NearMask::makeDirect(PtypeTraits<T>::moveMask<<16) & nearMask);
00292 if(isAttackToKing && isLong) target_mask&=nearMask;
00293 while (target_mask.any())
00294 {
00295 const int n = target_mask.takeOneBit();
00296 Direction dir=static_cast<Direction>(n&15);
00297 Offset offset=Board_Table.template getOffset<P>(dir);
00298 Position to=target-offset;
00299 if (isLong)
00300 {
00301 Piece p;
00302 Position pos1;
00303 for(pos1=to;(p=state.getPieceAt(pos1)).isEmpty();pos1-=offset)
00304 action.dropMove(pos1,T,P);
00305 if(isAttackToKing || p.isEdge() || !state.hasEffectTo(p,target)) continue;
00306 for(pos1-=offset;state.getPieceAt(pos1).isEmpty();pos1-=offset)
00307 action.dropMove(pos1,T,P);
00308
00309 }
00311 else if (T!=PAWN || !state.template isPawnMaskSet<P>(to.x()))
00312 action.dropMove(to,T,P);
00313 }
00314 }
00315
00319 template <class State,Player P,Ptype T,class Action>
00320 class GoldKingAction
00321 {
00322 State const& state;
00323 Position target;
00324 Action& action;
00325 NearMask nearMask;
00326 public:
00327 GoldKingAction(State const& s,Position p,Action& a,NearMask n)
00328 :state(s),target(p),action(a),nearMask(n)
00329 {}
00333 void operator()(Piece p)
00334 {
00335 Position from=p.position();
00336 generateMove<State,P,T,Action,false>(state,from,target,nearMask,action);
00337 }
00338 };
00339
00343 template <class State,Player P,Ptype T,class Action>
00344 class ShortPieceAction
00345 {
00346 State const& state;
00347 Position target;
00348 Action& action;
00349 NearMask nearMask;
00350 public:
00351 ShortPieceAction(State const& s,Position p,Action& a,NearMask n)
00352 :state(s),target(p),action(a),nearMask(n)
00353 {}
00357 void operator()(Piece p)
00358 {
00359 Position from=p.position();
00360 if (p.isPromotedNotKingGold())
00361 {
00362 generateMove<State,P,PtypeFuns<T>::promotePtype,Action,false>(state,from,target,nearMask,action);
00363 }
00364 else
00365 {
00366 generateMove<State,P,T,Action,true>(state,from,target,nearMask,action);
00367 generateMove<State,P,T,Action,false>(state,from,target,nearMask,action);
00368 }
00369 }
00370 };
00371
00375 template <class State,Player P,Ptype T,class Action,bool isAttackToKing>
00376 class LongPieceAction
00377 {
00378 State const& state;
00379 Position target;
00380 Action& action;
00381 NearMask nearMask;
00382 public:
00383 LongPieceAction(State const& s,Position p,Action& a,NearMask n)
00384 :state(s),target(p),action(a),nearMask(n)
00385 {}
00389 void operator()(Piece p)
00390 {
00391 Position from=p.position();
00392 if (p.isPromotedNotKingGold())
00393 {
00394 if (T==LANCE)
00395 generateMove<State,P,PtypeFuns<T>::promotePtype,Action,false>(state,from,target,nearMask,action);
00396 else
00397 {
00398 generateLongMove<State,P,PtypeFuns<T>::promotePtype,Action,false,isAttackToKing>(state,from,target,nearMask,action);
00399 }
00400 }
00401 else
00402 {
00403 generateLongMove<State,P,T,Action,true,isAttackToKing>(state,from,target,nearMask,action);
00404 }
00405 }
00406 };
00407
00408 }
00409 }
00410 }
00411
00412 template <osl::Player P,osl::Ptype T,bool isAttackToKing>
00413 template <class State,class Action>
00414 void osl::move_generator::AddEffectShort<P,T,isAttackToKing>::
00415 generate(const State& state,Position target,Action& action,NearMask nearMask)
00416 {
00417 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00418 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00419 typedef without_effect::ShortPieceAction<State,P,T,Action> action_t;
00420 action_t gkAction(state,target,action,nearMask);
00421 state.template forEachOnBoard<P,T,action_t>(gkAction);
00423 if (state.template hasPieceOnStand<P,T>())
00424 {
00425 without_effect::generateDrop<State,P,T,Action,false,isAttackToKing>(state,target,nearMask,action);
00426 }
00427 }
00428
00429 template <osl::Player P,osl::Ptype T,bool isAttackToKing>
00430 template <class State,class Action>
00431 void osl::move_generator::AddEffectLong<P,T,isAttackToKing>::
00432 generate(const State& state,Position target,Action& action,NearMask nearMask)
00433 {
00434 typedef without_effect::LongPieceAction<State,P,T,Action,isAttackToKing> action_t;
00435 action_t gkAction(state,target,action,nearMask);
00436 state.template forEachOnBoard<P,T,action_t>(gkAction);
00438 if (state.template hasPieceOnStand<P,T>())
00439 {
00440 without_effect::generateDrop<State,P,T,Action,true,isAttackToKing>(state,target,nearMask,action);
00441 }
00442 }
00443
00444 template <osl::Player P,bool isAttackToKing>
00445 template <class State,class Action>
00446 void osl::move_generator::AddEffect<P,isAttackToKing>::
00447 generateKing(const State& state,Position target,Action& action,NearMask nearMask)
00448 {
00449 typedef without_effect::GoldKingAction<State,P,KING,Action> action_t;
00450 action_t gkAction(state,target,action,nearMask);
00451 state.template forEachOnBoard<P,KING,action_t>(gkAction);
00452 }
00453
00454 template <osl::Player P,bool isAttackToKing>
00455 template <class State,class Action>
00456 void osl::move_generator::AddEffect<P,isAttackToKing>::
00457 generateGold(const State& state,Position target,Action& action,NearMask nearMask)
00458 {
00459 typedef without_effect::GoldKingAction<State,P,GOLD,Action> action_t;
00460 action_t gkAction(state,target,action,nearMask);
00461 state.template forEachOnBoard<P,GOLD,action_t>(gkAction);
00463 if (state.template hasPieceOnStand<P,GOLD>())
00464 {
00465 without_effect::generateDrop<State,P,GOLD,Action,false,isAttackToKing>(state,target,nearMask,action);
00466 }
00467 }
00468
00469 template <osl::Player P,bool isAttackToKing>
00470 template <class State,class Action>
00471 void osl::move_generator::AddEffect<P,isAttackToKing>::
00472 generate(const State& state,Position target,Action& action)
00473 {
00474 BOOST_STATIC_ASSERT(! boost::is_pointer<State>::value);
00475 NearMask nearMask=NearMask::make<State,P>(state,target);
00476
00477 AddEffectShort<P,PAWN,isAttackToKing>::generate(state,target,action,nearMask);
00478 AddEffectLong<P,LANCE,isAttackToKing>::generate(state,target,action,nearMask);
00479 AddEffectShort<P,KNIGHT,isAttackToKing>::generate(state,target,action,nearMask);
00480 AddEffectShort<P,SILVER,isAttackToKing>::generate(state,target,action,nearMask);
00481 generateGold(state,target,action,nearMask);
00482 if (!isAttackToKing)
00483 generateKing(state,target,action,nearMask);
00484 AddEffectLong<P,BISHOP,isAttackToKing>::generate(state,target,action,nearMask);
00485 AddEffectLong<P,ROOK,isAttackToKing>::generate(state,target,action,nearMask);
00486 }
00487
00488 template<bool isAttackToKing>
00489 template<class State>
00490 void osl::move_generator::GenerateAddEffect<isAttackToKing>::
00491 generate(Player player, const State& state, Position target,
00492 move_action::Store& store)
00493 {
00494 BOOST_STATIC_ASSERT(! boost::is_pointer<State>::value);
00495 using namespace osl::move_action;
00496 if(player==BLACK)
00497 {
00498 SafeFilter<BLACK,State,Store> filter(state, store);
00499 AddEffect<BLACK,isAttackToKing>::generate(state,target,filter);
00500 }
00501 else
00502 {
00503 SafeFilter<WHITE,State,Store> filter(state, store);
00504 AddEffect<WHITE,isAttackToKing>::generate(state,target,filter);
00505 }
00506 }
00507
00508 #endif
00509
00510
00511
00512