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,Position target,Action& action)
00029 {
00030 Position targetForP=target.positionForBlack(P);
00031 for(int i=0;;i++){
00032 Position pos=Add_Effect8_Table.getDropPosition(T,targetForP,i);
00033 if(pos.isPieceStand()) break;
00034 pos=pos.positionForBlack<P>();
00035 if(state.getPieceAt(pos).isEmpty() &&
00036 (T!=PAWN || !state.isPawnMaskSet<P>(pos.x()))){
00037 if((T==BISHOP || T==ROOK) &&
00038 state.hasEffectByNotPinned<PlayerTraits<P>::opponent>(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,Position to,Position 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.getPieceAt(from)).isEmpty();from+=offset){
00061 if(T==LANCE)
00062 action.dropMove(from,T,P);
00063 else if(!state.hasEffectBy<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,Position target,Action& action)
00085 {
00086 BOOST_STATIC_ASSERT(T==ROOK || T==BISHOP || T==LANCE);
00087
00088 generateShortDrop<P,T,Action>(state,target,action);
00089 Position targetForP=target.positionForBlack(P);
00090
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 Position pos=target+offset;
00096 assert(pos.isOnBoard());
00097 Position from=pos+offset;
00098 if(state.getPieceAt(pos).isEmpty()){
00099 Piece p=state.getPieceAt(from);
00100
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.getLongDropPosition(T,targetForP,i);
00109 if(po.first.isPieceStand()) break;
00110 Position pos=po.first.positionForBlack<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.getLongDrop2Position(T,targetForP,i);
00118 if(poo.first.isPieceStand()) break;
00119 Position pos=poo.first.positionForBlack<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.getPieceAt(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 Position target, Action& action)
00159 {
00160 Position from=attacker.position();
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 Position 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.getPieceAt(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
00193 template<Player P,Ptype T>
00194 bool canAddLongEffect(NumEffectState const& state,Position from,Position to,Piece& blocker,Offset offset)
00195 {
00196 Piece p;
00197 for(Position pos=to+offset;pos!=from;pos+=offset){
00198 Piece p=state.getPieceAt(pos);
00199 if(!p.isEmpty()){
00200 if(!p.isOnBoardByOwner<P>() ||
00201 !Ptype_Table.getEffect(p.ptypeO(),pos,to).hasEffect()){
00202 blocker=p;
00203 assert(!blocker.isEdge());
00204 return false;
00205 }
00206 }
00207 }
00208 return true;
00209 }
00221 template<Player P,Ptype T>
00222 bool canAddLongEffect(NumEffectState const& state,Position from,Position to,Piece& blocker)
00223 {
00224 Offset offset=Board_Table.getShortOffset(Offset32(from,to));
00225 return canAddLongEffect<P,T>(state,from,to,blocker,offset);
00226 }
00237 template <Player P,Ptype T,class Action>
00238 void generateLongMove(NumEffectState const& state,Piece attacker,
00239 Position target, Action& action)
00240 {
00241 Position from=attacker.position();
00242
00243 if((T==ROOK || T==BISHOP) && from.canPromote<P>())
00244 return;
00245 Offset32 o32=Offset32(from,target).blackOffset32<P>();
00246
00247 OffsetPair op=Add_Effect8_Table.getBetweenOffset(T,o32);
00248 if(!op.first.zero()){
00249 Position pos=target+op.first.blackOffset<P>();
00250 Offset offset=op.second.blackOffset<P>();
00251 if(pos.isOnBoard()){
00252 Piece blocker=Piece::EMPTY();
00253 if(!canAddLongEffect<P,T>(state,from,pos,blocker,-offset) &&
00254 state.hasEffectByPiece(attacker,blocker.position())){
00255 assert(!blocker.isEmpty() && !blocker.isEdge());
00256 Position pos1=blocker.position();
00257 if(blocker.isOnBoardByOwner<P>()){
00258 Direction d=longToShort(Board_Table.getLongDirection<BLACK>(Offset32(pos,from).blackOffset32<P>()));
00259
00260 PieceOnBoard<Action,true>::template generate<P,true>(
00261 state,blocker,action,1<<primDir(d));
00262 }
00263 }
00264 }
00265 }
00266 if(T==LANCE) return;
00267
00268
00269 for(int i=0;;i++){
00270 Offset o=Add_Effect8_Table.getShortMoveOffset(false,T,o32,i);
00271 if(o.zero()) break;
00272 Position pos=target+o.blackOffset<P>();
00273 if(!pos.isOnBoard()) continue;
00274 if ((!canPromote(T) || !pos.canPromote<P>()) &&
00275 state.hasEffectByPiece(attacker,pos) &&
00276 state.getPieceAt(pos).isEmpty()){
00277 if(!state.pinOrOpen(P).test(attacker.number()) ||
00278 state.pinnedCanMoveTo<P>(attacker,pos))
00279 action.simpleMove(from,pos,T,false,P);
00280 }
00281 }
00282
00283 for(int i=0;;i++){
00284 OffsetPair op=Add_Effect8_Table.getLongMoveOffset(T,o32,i);
00285 if(op.first.zero()) break;
00286 Position pos1=target+op.first.blackOffset<P>();
00287 Position pos2=target+op.second.blackOffset<P>();
00288 Piece blocker=Piece::EMPTY();
00289 if(pos1.isOnBoard() && pos2.isOnBoard() &&
00290 state.getPieceAt(pos1).isEmpty() &&
00291 (!canPromote(T) || !pos1.canPromote<P>()) &&
00292 state.hasEffectByPiece(attacker,pos1) &&
00293 canAddLongEffect<P,T>(state,pos1,pos2,blocker)){
00294 if(!state.pinOrOpen(P).test(attacker.number()) ||
00295 state.pinnedCanMoveTo<P>(attacker,pos1))
00296 action.simpleMove(from,pos1,T,false,P);
00297 }
00298 }
00299 }
00300
00304 template <Player P,Ptype T,class Action>
00305 class ShortPieceAction
00306 {
00307 NumEffectState const& state;
00308 Position target;
00309 Action& action;
00310 public:
00311 ShortPieceAction(NumEffectState const& s,Position p,Action& a)
00312 :state(s),target(p),action(a)
00313 {}
00317 void operator()(Piece p)
00318 {
00319 if (p.isPromotedNotKingGold())
00320 {
00321 generateShortMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
00322 }
00323 else
00324 {
00325 generateShortMove<P,T,Action>(state,p,target,action);
00326 }
00327 }
00328 };
00329
00333 template <Player P,class Action>
00334 class GoldAction
00335 {
00336 NumEffectState const& state;
00337 Position target;
00338 Action& action;
00339 public:
00340 GoldAction(NumEffectState const& s,Position p,Action& a)
00341 :state(s),target(p),action(a)
00342 {}
00346 void operator()(Piece p)
00347 {
00348 generateShortMove<P,GOLD,Action>(state,p,target,action);
00349 }
00350 };
00351
00355 template <Player P,Ptype T,class Action>
00356 class LongPieceAction
00357 {
00358 NumEffectState const& state;
00359 Position target;
00360 Action& action;
00361 public:
00362 LongPieceAction(NumEffectState const& s,Position p,Action& a)
00363 :state(s),target(p),action(a)
00364 {}
00368 void operator()(Piece p)
00369 {
00370 Position from=p.position();
00371 if (p.isPromotedNotKingGold())
00372 {
00373 if (T==LANCE)
00374 generateShortMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
00375 else
00376 generateLongMove<P,PtypeFuns<T>::promotePtype,Action>(state,p,target,action);
00377 }
00378 else
00379 {
00380 generateLongMove<P,T,Action>(state,p,target,action);
00381 }
00382 }
00383 };
00384
00385 template<Player P,Ptype T,class Action>
00386 void generateShort(const NumEffectState& state,Position target,
00387 Action& action)
00388 {
00389 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00390 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00391 typedef ShortPieceAction<P,T,Action> action_t;
00392 action_t gkAction(state,target,action);
00393 state.template forEachOnBoard<P,T,action_t>(gkAction);
00395 if (state.template hasPieceOnStand<T>(P)){
00396 generateShortDrop<P,T,Action>(state,target,action);
00397 }
00398 }
00399
00400 template<Player P,Ptype T,class Action>
00401 void generateLong(const NumEffectState& state,Position target,
00402 Action& action)
00403 {
00404 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00405 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00406 typedef LongPieceAction<P,T,Action> action_t;
00407 action_t gkAction(state,target,action);
00408 state.template forEachOnBoard<P,T,action_t>(gkAction);
00409 }
00410
00411 template<Player P,class Action>
00412 void generateGold(const NumEffectState& state,Position target,
00413 Action& action)
00414 {
00415 typedef GoldAction<P,Action> action_t;
00416 action_t gkAction(state,target,action);
00417 state.template forEachOnBoard<P,GOLD,action_t>(gkAction);
00419 if (state.template hasPieceOnStand<GOLD>(P)){
00420 generateShortDrop<P,GOLD,Action>(state,target,action);
00421 }
00422 }
00423 }
00424
00425 template<Player P>
00426 template<class Action>
00427 void AddEffect8<P>::
00428 generateBigDrop(const NumEffectState& state,Action& action)
00429 {
00430 using namespace addeffect8;
00431 Position target=state.getKingPosition<PlayerTraits<P>::opponent>();
00432 if (state.template hasPieceOnStand<BISHOP>(P)){
00433 generateLongDrop<P,BISHOP,Action>(state,target,action);
00434 }
00435 if (state.template hasPieceOnStand<ROOK>(P)){
00436 generateLongDrop<P,ROOK,Action>(state,target,action);
00437 }
00438 }
00439
00440 template<Player P>
00441 template<class Action>
00442 void AddEffect8<P>::
00443 generateNotBigDrop(const NumEffectState& state,Action& action)
00444 {
00445 using namespace addeffect8;
00446 Position target=state.getKingPosition<PlayerTraits<P>::opponent>();
00447 generateShort<P,PAWN,Action>(state,target,action);
00448 generateLong<P,LANCE,Action>(state,target,action);
00449 if (state.template hasPieceOnStand<LANCE>(P)){
00450 generateLongDrop<P,LANCE,Action>(state,target,action);
00451 }
00452 generateShort<P,KNIGHT,Action>(state,target,action);
00453 generateShort<P,SILVER,Action>(state,target,action);
00454 generateGold<P,Action>(state,target,action);
00455
00456 generateLong<P,BISHOP,Action>(state,target,action);
00457 generateLong<P,ROOK,Action>(state,target,action);
00458 }
00459
00460 template<Player P>
00461 template<class Action>
00462 void AddEffect8<P>::
00463 generate(const NumEffectState& state,Action& action)
00464 {
00465 generateNotBigDrop(state,action);
00466 generateBigDrop(state,action);
00467 }
00468 }
00469 }
00470 #endif
00471
00472
00473
00474