addEffect8.tcc
Go to the documentation of this file.
00001 #ifndef _MOVE_GENERATOR_ADD_EFFECT8_TCC
00002 #define _MOVE_GENERATOR_ADD_EFFECT8_TCC
00003 #include "osl/move_generator/addEffect8.h"
00004 #include "osl/move_generator/pieceOnBoard.h"
00005 #include "osl/move_generator/addEffect8Table.h"
00006 #include "osl/misc/loki.h"
00007 
00008 #include <boost/static_assert.hpp>
00009 
00010 using namespace osl;
00011 
00012 namespace osl
00013 {
00014   namespace move_generator
00015   {
00016     namespace addeffect8{
00027       template <Player P,Ptype T,class Action>
00028       void generateShortDrop(NumEffectState const& state,Square target,Action& action)
00029       {
00030         Square targetForP=target.squareForBlack(P);
00031         for(int i=0;;i++){
00032           Square pos=Add_Effect8_Table.getDropSquare(T,targetForP,i);
00033           if(pos.isPieceStand()) break;
00034           pos=pos.squareForBlack<P>();
00035           if(state.pieceAt(pos).isEmpty() &&
00036              (T!=PAWN || !state.isPawnMaskSet<P>(pos.x()))){
00037             if((T==BISHOP || T==ROOK) && 
00038                state.hasEffectByNotPinnedAndKing(alt(P),pos)) continue;
00039             action.dropMove(pos,T,P);
00040           }
00041         }
00042       }
00043 
00054       template <Player P,Ptype T,class Action>
00055       void generateLongDropWithOffset(NumEffectState const& state,Square to,Square from, Offset offset,int countMax,Action& action){
00056         const Player altP=PlayerTraits<P>::opponent;
00057         int count=0;
00058         for(;;){
00059           Piece p;
00060           for(;(p=state.pieceAt(from)).isEmpty();from+=offset){
00061             if(T==LANCE)
00062               action.dropMove(from,T,P);
00063             else if(!state.hasEffectAt<altP>(from)){
00064               action.dropMove(from,T,P);
00065               if(++count>=countMax) return;
00066             }
00067           }
00068           if(!p.isOnBoardByOwner<P>()) return;
00069           if(!Ptype_Table.getEffect(p.ptypeO(),from,to).hasEffect()) return;
00070           from+=offset;
00071         }
00072       }
00073       
00083       template <Player P,Ptype T,class Action>
00084       void generateLongDrop(NumEffectState const& state,Square target,Action& action)
00085       {
00086         BOOST_STATIC_ASSERT(T==ROOK || T==BISHOP || T==LANCE);
00087         // 8近傍以内へのdropはshort扱いで作る.
00088         generateShortDrop<P,T,Action>(state,target,action);
00089         Square targetForP=target.squareForBlack(P);
00090         // 8近傍に駒がある時(王手にならない)に直接方向の利き
00091         for(int i=0;;i++){
00092           Offset offset=Add_Effect8_Table.getLongDropDirect(T,targetForP,i);
00093           if(offset.zero()) break;
00094           offset=offset.blackOffset<P>();
00095           Square pos=target+offset;
00096           assert(pos.isOnBoard());
00097           Square from=pos+offset;
00098           if(state.pieceAt(pos).isEmpty()){
00099             Piece p=state.pieceAt(from);
00100             // 一つ置いて短い利きの時のみOK
00101             if(!p.isOnBoardByOwner<P>() ||
00102                !state.hasEffectByPiece(p,pos)) continue;
00103             from+=offset;
00104           }
00105           generateLongDropWithOffset<P,T,Action>(state,pos,from,offset,2,action);
00106         }
00107         for(int i=0;;i++){
00108           PO po=Add_Effect8_Table.getLongDropSquare(T,targetForP,i);
00109           if(po.first.isPieceStand()) break;
00110           Square pos=po.first.squareForBlack<P>();
00111           Offset offset=po.second.blackOffset<P>();
00112           assert(!offset.zero());
00113           generateLongDropWithOffset<P,T,Action>(state,pos-offset,pos,offset,2,action);
00114         }
00115         if(T==BISHOP){
00116           for(int i=0;;i++){
00117             POO poo=Add_Effect8_Table.getLongDrop2Square(T,targetForP,i);
00118             if(poo.first.isPieceStand()) break;
00119             Square pos=poo.first.squareForBlack<P>();
00120             Offset offset1=poo.second.first.blackOffset<P>();
00121             assert(!offset1.zero());
00122             Offset offset2=poo.second.second.blackOffset<P>();
00123             assert(!offset2.zero());
00124             Piece p=state.pieceAt(pos);
00125             if(p.isEmpty()){
00126               generateLongDropWithOffset<P,T,Action>(state,pos-offset1,
00127                                                      pos,offset1,2,action);
00128               generateLongDropWithOffset<P,T,Action>(state,pos-offset2,
00129                                                      pos+offset2,offset2,1,
00130                                                      action);
00131             }
00132             else if(p.isOnBoardByOwner<P>()){
00133               if(state.hasEffectByPiece(p,pos-offset1)){
00134                 generateLongDropWithOffset<P,T,Action>(state,pos-offset1,
00135                                                        pos+offset1,offset1,
00136                                                        2,action);
00137               }
00138               if(state.hasEffectByPiece(p,pos-offset2)){
00139                 generateLongDropWithOffset<P,T,Action>(state,pos-offset2,
00140                                                        pos+offset2,offset2,
00141                                                        2,action);
00142               }
00143             }
00144           }
00145         }
00146       }
00147       
00156       template <Player P,Ptype T,class Action>
00157       void generateShortMove(NumEffectState const& state,Piece attacker,
00158                              Square target, Action& action)
00159       {
00160         Square from=attacker.square();
00161         Offset32 o32=Offset32(from,target).blackOffset32<P>();
00162         for(int i=0;;i++){
00163           Offset o=Add_Effect8_Table.getShortMoveOffset(false,T,o32,i);
00164           if(o.zero()) break;
00165           Square pos=target+o.blackOffset<P>();
00166           if((T!=KNIGHT && pos.isEdge()) ||
00167              (T==KNIGHT && !pos.isOnBoard())) continue;
00168           if((T==PAWN ? pos.canPromote<P>() :
00169               (PtypeTraits<T>::isBasic 
00170                && !PtypePlayerTraits<T,P>::canDropTo(pos))))
00171             continue;
00172           Piece p=state.pieceAt(pos);
00173           if(p.isEmpty()){
00174             if(!state.pinOrOpen(P).test(attacker.number()) ||
00175                state.pinnedCanMoveTo<P>(attacker,pos))
00176               action.simpleMove(from,pos,T,false,P);
00177           }
00178         }
00179       }
00180 
00187       template<Player P>
00188       bool findBlocker(NumEffectState const& state,Piece attacker, Square target, Square from,Square& pos,Piece& blocker, Offset offset)
00189       {
00190         if(state.hasEffectByPiece(attacker,pos)){
00191           blocker=state.pieceAt(pos);
00192           if(!blocker.isEmpty()) return blocker.isOnBoardByOwner<P>();
00193           pos-=offset;
00194           if(abs(pos.x()-target.x())>1 || abs(pos.y()-target.y())>1)
00195             return false;
00196           blocker=state.pieceAt(pos);
00197           return blocker.isOnBoardByOwner<P>();
00198         }
00199         else{
00200           // TODO effectedNumTableを使える?
00201           for(Square pos1=from+offset;pos1!=pos;pos1+=offset){
00202             Piece p=state.pieceAt(pos1);
00203             if(!p.isEmpty()){
00204               if(!p.isOnBoardByOwner<P>()) return false;
00205               if(!Ptype_Table.getEffect(p.ptypeO(),pos1,pos).hasEffect()){
00206                 blocker=p;
00207                 for(pos1+=offset;pos1!=pos;pos1+=offset){
00208                   p=state.pieceAt(pos1);
00209                   if(!p.isEmpty()){
00210                     if(!p.isOnBoardByOwner<P>() ||
00211                        !Ptype_Table.getEffect(p.ptypeO(),pos1,pos).hasEffect()) return false;
00212                   }
00213                 }
00214                 pos=blocker.square();
00215                 return true;
00216               }
00217               if(pos1==pos-offset &&
00218                  (pos+offset).isOnBoard() &&
00219                  !Ptype_Table.getEffect(p.ptypeO(),pos1,pos+offset).hasEffect()){
00220                 blocker=p;
00221                 pos=blocker.square();
00222                 return true;
00223               }
00224               return false;
00225             }
00226           }
00227           return false;
00228         }
00229       }
00242       template<Player P,Ptype T>
00243       bool canAddLongEffect(NumEffectState const& state,Square from,Square to,Piece& blocker,Offset offset)
00244       {
00245         for(Square pos=to+offset;pos!=from;pos+=offset){
00246           Piece p=state.pieceAt(pos);
00247           if(!p.isEmpty()){
00248             if(!p.isOnBoardByOwner<P>() ||
00249                !Ptype_Table.getEffect(p.ptypeO(),pos,to).hasEffect()){
00250               blocker=p;
00251               assert(!blocker.isEdge());
00252               return false;
00253             }
00254           }
00255         }
00256         return true;
00257       }
00269       template<Player P,Ptype T>
00270       bool canAddLongEffect(NumEffectState const& state,Square from,Square to,Piece& blocker)
00271       {
00272         Offset offset=Board_Table.getShortOffset(Offset32(from,to));
00273         return canAddLongEffect<P,T>(state,from,to,blocker,offset);
00274       }
00285       template <Player P,Ptype T,class Action>
00286       void generateLongMove(NumEffectState const& state,Piece attacker,
00287                             Square target, Action& action)
00288       {
00289         Square from=attacker.square();
00290         // 飛車,角はpromoteできる時はpromoteする手を生成済み
00291         if((T==ROOK || T==BISHOP) && from.canPromote<P>())
00292           return;
00293         Offset32 o32=Offset32(from,target).blackOffset32<P>();
00294         // 間の味方の駒のopen
00295         OffsetPair op=Add_Effect8_Table.getBetweenOffset(T,o32);
00296         if(!op.first.zero()){
00297           Square pos=target+op.first.blackOffset<P>();
00298           Offset offset=op.second.blackOffset<P>();
00299           if(pos.isOnBoard()){
00300             Piece blocker=Piece::EMPTY();
00301             if(findBlocker<P>(state,attacker,target,from,pos,blocker,offset)){
00302               Direction d=longToShort(Board_Table.getLongDirection<BLACK>(Offset32(pos,from).blackOffset32<P>()));
00303 //              std::cerr << "blocker=" << blocker << ",d=" << d << std::endl;
00304               PieceOnBoard<Action,true>::template generate<P,true>(
00305                 state,blocker,action,1<<primDir(d));
00306             }
00307           }
00308         }
00309         if(T==LANCE) return;
00310         // 移動後に短い利きで迫る
00311         // promoteなし
00312         for(int i=0;;i++){
00313           Offset o=Add_Effect8_Table.getShortMoveOffset(false,T,o32,i);
00314           if(o.zero()) break;
00315           Square pos=target+o.blackOffset<P>();
00316           if(!pos.isOnBoard()) continue;
00317           if ((!canPromote(T) || !pos.canPromote<P>()) &&
00318               state.hasEffectByPiece(attacker,pos) &&
00319               state.pieceAt(pos).isEmpty()){
00320             if(!state.pinOrOpen(P).test(attacker.number()) ||
00321                state.pinnedCanMoveTo<P>(attacker,pos))
00322               action.simpleMove(from,pos,T,false,P);
00323           }
00324         }
00325         // 移動後に長い利きで迫る
00326         for(int i=0;;i++){
00327           OffsetPair op=Add_Effect8_Table.getLongMoveOffset(T,o32,i);
00328           if(op.first.zero()) break;
00329           Square pos1=target+op.first.blackOffset<P>();
00330           Square pos2=target+op.second.blackOffset<P>();
00331           Piece blocker=Piece::EMPTY();
00332           if(pos1.isOnBoard() && pos2.isOnBoard() &&
00333              state.pieceAt(pos1).isEmpty() &&
00334              (!canPromote(T) || !pos1.canPromote<P>()) &&
00335              state.hasEffectByPiece(attacker,pos1) &&
00336              canAddLongEffect<P,T>(state,pos1,pos2,blocker)){
00337             if(!state.pinOrOpen(P).test(attacker.number()) ||
00338                state.pinnedCanMoveTo<P>(attacker,pos1))
00339               action.simpleMove(from,pos1,T,false,P);
00340           }
00341         }
00342       }
00343 
00347       template <Player P,Ptype T,class Action>
00348       class ShortPieceAction
00349       {
00350         NumEffectState const& state;
00351         Square target;
00352         Action& action;
00353       public:
00354         ShortPieceAction(NumEffectState const& s,Square p,Action& a)
00355           :state(s),target(p),action(a)
00356         {}
00360         void operator()(Piece p)
00361         {
00362           if (p.isPromotedNotKingGold())
00363           {
00364             generateShortMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
00365           }
00366           else
00367           {
00368             generateShortMove<P,T,Action>(state,p,target,action);
00369           }  
00370         }
00371       };
00372 
00376       template <Player P,class Action>
00377       class GoldAction
00378       {
00379         NumEffectState const& state;
00380         Square target;
00381         Action& action;
00382       public:
00383         GoldAction(NumEffectState const& s,Square p,Action& a)
00384           :state(s),target(p),action(a)
00385         {}
00389         void operator()(Piece p)
00390         {
00391           generateShortMove<P,GOLD,Action>(state,p,target,action);
00392         }
00393       };
00394 
00398       template <Player P,Ptype T,class Action>
00399       class LongPieceAction
00400       {
00401         NumEffectState const& state;
00402         Square target;
00403         Action& action;
00404       public:
00405         LongPieceAction(NumEffectState const& s,Square p,Action& a)
00406           :state(s),target(p),action(a)
00407         {}
00411         void operator()(Piece p)
00412         {
00413           if (p.isPromotedNotKingGold())
00414           {
00415             if (T==LANCE)
00416               generateShortMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
00417             else
00418               generateLongMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
00419           }
00420           else
00421           {
00422             generateLongMove<P,T,Action>(state,p,target,action);
00423           }  
00424         }
00425       };
00426 
00427       template<Player P,Ptype T,class Action>
00428       void generateShort(const NumEffectState& state,Square target,
00429                          Action& action)
00430       {
00431         BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00432         BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00433         typedef ShortPieceAction<P,T,Action> action_t;
00434         action_t gkAction(state,target,action);
00435         state.template forEachOnBoard<P,T,action_t>(gkAction);
00437         if (state.template hasPieceOnStand<T>(P)){
00438           generateShortDrop<P,T,Action>(state,target,action);
00439         }
00440       }
00441 
00442       template<Player P,Ptype T,class Action>
00443       void generateLong(const NumEffectState& state,Square target,
00444                         Action& action)
00445       {
00446         BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00447         BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00448         typedef LongPieceAction<P,T,Action> action_t;
00449         action_t gkAction(state,target,action);
00450         state.template forEachOnBoard<P,T,action_t>(gkAction);
00451       }
00452 
00453       template<Player P,class Action>
00454       void generateGold(const NumEffectState& state,Square target,
00455                         Action& action)
00456       {
00457         typedef GoldAction<P,Action> action_t;
00458         action_t gkAction(state,target,action);
00459         state.template forEachOnBoard<P,GOLD,action_t>(gkAction);
00461         if (state.template hasPieceOnStand<GOLD>(P)){
00462           generateShortDrop<P,GOLD,Action>(state,target,action);
00463         }
00464       }
00465     }
00466 
00467     template<Player P>
00468     template<class Action>
00469     void AddEffect8<P>::
00470     generateBigDrop(const NumEffectState& state,Action& action)
00471     {
00472       using namespace addeffect8;
00473       Square target=state.kingSquare<PlayerTraits<P>::opponent>();
00474       if (state.template hasPieceOnStand<BISHOP>(P)){
00475         generateLongDrop<P,BISHOP,Action>(state,target,action);
00476       }
00477       if (state.template hasPieceOnStand<ROOK>(P)){
00478         generateLongDrop<P,ROOK,Action>(state,target,action);
00479       }
00480     }
00481 
00482     template<Player P>
00483     template<class Action>
00484     void AddEffect8<P>::
00485     generateNotBigDrop(const NumEffectState& state,Action& action)
00486     {
00487       using namespace addeffect8;
00488       Square target=state.kingSquare<PlayerTraits<P>::opponent>();
00489       generateShort<P,PAWN,Action>(state,target,action);
00490       generateLong<P,LANCE,Action>(state,target,action);
00491       if (state.template hasPieceOnStand<LANCE>(P)){
00492         generateLongDrop<P,LANCE,Action>(state,target,action);
00493       }
00494       generateShort<P,KNIGHT,Action>(state,target,action);
00495       generateShort<P,SILVER,Action>(state,target,action);
00496       generateGold<P,Action>(state,target,action);
00497       // no king move
00498       generateLong<P,BISHOP,Action>(state,target,action);
00499       generateLong<P,ROOK,Action>(state,target,action);
00500     }
00501 
00502     template<Player P>
00503     template<class Action>
00504     void AddEffect8<P>::
00505     generate(const NumEffectState& state,Action& action)
00506     {
00507       generateNotBigDrop(state,action);
00508       generateBigDrop(state,action);
00509     }
00510   }
00511 }
00512 #endif /* _MOVE_GENERATOR_ADD_EFFECT8_TCC */
00513 // ;;; Local Variables:
00514 // ;;; mode:c++
00515 // ;;; c-basic-offset:2
00516 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines