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