addEffect_.tcc
Go to the documentation of this file.
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         // static assert?
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     } // namespace without_effect
00416   } // namespace move_generator
00417 } // namespace osl
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 //  BOOST_STATIC_ASSERT(!isAttackToKing);
00482   NearMask nearMask=NearMask::make<P>(state,target);
00483   /* 各種類によるmove */
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 /* _MOVE_GENERATOR_ADD_EFFECT_TCC */
00514 // ;;; Local Variables:
00515 // ;;; mode:c++
00516 // ;;; c-basic-offset:2
00517 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines