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/open.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 {
00025 template <Player P,Ptype T,class Action>
00026 void generateShortDrop(NumEffectState const& state,Position target,Action& action)
00027 {
00028 Position targetForP=target.positionForBlack(P);
00029 for(int i=0;;i++){
00030 Position pos=Add_Effect8_Table.getDropPosition(T,targetForP,i);
00031 if(pos.isPieceStand()) break;
00032 pos=pos.positionForBlack<P>();
00033 if(state.getPieceAt(pos).isEmpty() &&
00034 (T!=PAWN || !state.isPawnMaskSet<P>(pos.x()))){
00035 if((T==BISHOP || T==ROOK) &&
00036 state.hasEffectBy<PlayerTraits<P>::opponent>(pos)) continue;
00037 action.dropMove(pos,T,P);
00038 }
00039 }
00040 }
00041
00052 template <Player P,Ptype T,class Action>
00053 void generateLongDropWithOffset(NumEffectState const& state,Position to,Position from, Offset offset,int countMax,Action& action){
00054 const Player altP=PlayerTraits<P>::opponent;
00055 int count=0;
00056 for(;;){
00057 Piece p;
00058 for(;(p=state.getPieceAt(from)).isEmpty();from+=offset){
00059 if(T==LANCE)
00060 action.dropMove(from,T,P);
00061 else if(!state.hasEffectBy<altP>(from)){
00062 action.dropMove(from,T,P);
00063 if(++count>=countMax) return;
00064 }
00065 }
00066 if(!p.isOnBoardByOwner<P>()) return;
00067 if(!Ptype_Table.getEffect(p.ptypeO(),from,to).hasEffect()) return;
00068 from+=offset;
00069 }
00070 }
00071
00081 template <Player P,Ptype T,class Action>
00082 void generateLongDrop(NumEffectState const& state,Position target,Action& action)
00083 {
00084 BOOST_STATIC_ASSERT(T==ROOK || T==BISHOP || T==LANCE);
00085
00086 generateShortDrop<P,T,Action>(state,target,action);
00087 Position targetForP=target.positionForBlack(P);
00088
00089 for(int i=0;;i++){
00090 Offset offset=Add_Effect8_Table.getLongDropDirect(T,targetForP,i);
00091 if(offset.zero()) break;
00092 offset=offset.blackOffset<P>();
00093 Position pos=target+offset;
00094 assert(pos.isOnBoard());
00095 Position from=pos+offset;
00096 if(state.getPieceAt(pos).isEmpty()){
00097 Piece p=state.getPieceAt(from);
00098
00099 if(!p.isOnBoardByOwner<P>() ||
00100 !state.hasEffectByPiece(p,pos)) continue;
00101 from+=offset;
00102 }
00103 generateLongDropWithOffset<P,T,Action>(state,pos,from,offset,2,action);
00104 }
00105 for(int i=0;;i++){
00106 PO po=Add_Effect8_Table.getLongDropPosition(T,targetForP,i);
00107 if(po.first.isPieceStand()) break;
00108 Position pos=po.first.positionForBlack<P>();
00109 Offset offset=po.second.blackOffset<P>();
00110 assert(!offset.zero());
00111 generateLongDropWithOffset<P,T,Action>(state,pos-offset,pos,offset,2,action);
00112 }
00113 if(T==BISHOP){
00114 for(int i=0;;i++){
00115 POO poo=Add_Effect8_Table.getLongDrop2Position(T,targetForP,i);
00116 if(poo.first.isPieceStand()) break;
00117 Position pos=poo.first.positionForBlack<P>();
00118 Offset offset1=poo.second.first.blackOffset<P>();
00119 assert(!offset1.zero());
00120 Offset offset2=poo.second.second.blackOffset<P>();
00121 assert(!offset2.zero());
00122 Piece p=state.getPieceAt(pos);
00123 if(p.isEmpty()){
00124 generateLongDropWithOffset<P,T,Action>(state,pos-offset1,
00125 pos,offset1,2,action);
00126 generateLongDropWithOffset<P,T,Action>(state,pos-offset2,
00127 pos+offset2,offset2,1,
00128 action);
00129 }
00130 else if(p.isOnBoardByOwner<P>()){
00131 if(state.hasEffectByPiece(p,pos-offset1)){
00132 generateLongDropWithOffset<P,T,Action>(state,pos-offset1,
00133 pos+offset1,offset1,
00134 2,action);
00135 }
00136 if(state.hasEffectByPiece(p,pos-offset2)){
00137 generateLongDropWithOffset<P,T,Action>(state,pos-offset2,
00138 pos+offset2,offset2,
00139 2,action);
00140 }
00141 }
00142 }
00143 }
00144 }
00145
00155 template <Player P,Ptype T,class Action,bool isPromote>
00156 void generateShortMove(NumEffectState const& state,Piece attacker,
00157 Position target, Action& action)
00158 {
00159 Position from=attacker.position();
00160 Offset32 o32=Offset32(from,target).blackOffset32<P>();
00161 for(int i=0;;i++){
00162 Offset o=Add_Effect8_Table.getShortMoveOffset(isPromote,T,o32,i);
00163 if(o.zero()) break;
00164 Position pos=target+o.blackOffset<P>();
00165 if(!pos.isOnBoard()) continue;
00166 if(isPromote &&
00167 !from.canPromote<P>() &&
00168 !pos.canPromote<P>()) continue;
00169 if(!isPromote &&
00170 (T==PAWN ? pos.canPromote<P>() :
00171 (PtypeTraits<T>::isBasic
00172 && !PtypePlayerTraits<T,P>::canDropTo(pos))))
00173 continue;
00174 Piece p=state.getPieceAt(pos);
00175 if(p.template canMoveOn<P>()){
00176 action.unknownMove(from,pos,p,
00177 (isPromote ? PtypeFuns<T>::promotePtype : T),
00178 isPromote,P);
00179 }
00180 }
00181 }
00182
00195 template<Player P,Ptype T>
00196 bool canAddLongEffect(NumEffectState const& state,Position from,Position to,Piece& blocker,Offset offset)
00197 {
00198 Piece p;
00199 for(Position pos=to+offset;pos!=from;pos+=offset){
00200 Piece p=state.getPieceAt(pos);
00201 if(!p.isEmpty()){
00202 if(!p.isOnBoardByOwner<P>() ||
00203 !Ptype_Table.getEffect(p.ptypeO(),pos,to).hasEffect()){
00204 blocker=p;
00205 assert(!blocker.isEdge());
00206 return false;
00207 }
00208 }
00209 }
00210 return true;
00211 }
00223 template<Player P,Ptype T>
00224 bool canAddLongEffect(NumEffectState const& state,Position from,Position to,Piece& blocker)
00225 {
00226 Offset offset=Board_Table.getShortOffset(Offset32(from,to));
00227 return canAddLongEffect<P,T>(state,from,to,blocker,offset);
00228 }
00239 template <Player P,Ptype T,class Action,bool canPromote>
00240 void generateLongMove(NumEffectState const& state,Piece attacker,
00241 Position target, Action& action)
00242 {
00243 Position from=attacker.position();
00244 Offset32 o32=Offset32(from,target).blackOffset32<P>();
00245
00246 OffsetPair op=Add_Effect8_Table.getBetweenOffset(T,o32);
00247 if(!op.first.zero()){
00248 Position pos=target+op.first.blackOffset<P>();
00249 Offset offset=op.second.blackOffset<P>();
00250 if(pos.isOnBoard()){
00251 Piece blocker=Piece::EMPTY();
00252 if(!canAddLongEffect<P,T>(state,from,pos,blocker,-offset) &&
00253 state.hasEffectByPiece(attacker,blocker.position())){
00254 assert(!blocker.isEmpty() && !blocker.isEdge());
00255 Position pos1=blocker.position();
00256 if(blocker.isOnBoardByOwner<P>()){
00257
00258 Open<P>::generate
00259 (state,blocker,action,pos,
00260 longToShort(Board_Table.getLongDirection<BLACK>(Offset32(pos,from).blackOffset32<P>())));
00261 }
00262 else{
00263 if(canPromote && T!=LANCE &&
00264 (from.canPromote<P>() || pos1.canPromote<P>())){
00265 action.unknownMove(from,pos1,state.getPieceAt(pos1),
00266 PtypeFuns<T>::promotePtype,true,P);
00267 }
00268 else if (T!=LANCE || PtypePlayerTraits<KNIGHT,P>::canDropTo(pos1))
00269 action.unknownMove(from,pos1,state.getPieceAt(pos1),T,false,P);
00270 }
00271 }
00272 }
00273 }
00274
00275
00276 for(int i=0;;i++){
00277 Offset o=Add_Effect8_Table.getShortMoveOffset(false,T,o32,i);
00278 if(o.zero()) break;
00279 Position pos=target+o.blackOffset<P>();
00280 if(pos.isOnBoard() &&
00281 (T==LANCE || !canPromote ||
00282 (!from.canPromote<P>() && (!pos.canPromote<P>()))) &&
00283 state.getPieceAt(pos).template canMoveOn<P>() &&
00284 state.hasEffectByPiece(attacker,pos) &&
00285
00286 (T!=LANCE || PtypePlayerTraits<KNIGHT,P>::canDropTo(pos))
00287 ){
00288 action.unknownMove(from,pos,state.getPieceAt(pos),
00289 T,false,P);
00290 }
00291 }
00292
00293 for(int i=0;;i++){
00294 Offset o=Add_Effect8_Table.getShortMoveOffset(true,T,o32,i);
00295 if(o.zero()) break;
00296 Position pos=target+o.blackOffset<P>();
00297 if(pos.isOnBoard() && state.getPieceAt(pos).template canMoveOn<P>() &&
00298 (from.canPromote<P>() || pos.canPromote<P>()) &&
00299 state.hasEffectByPiece(attacker,pos)
00300 ){
00301 action.unknownMove(from,pos,state.getPieceAt(pos),
00302 PtypeFuns<T>::promotePtype,true,P);
00303 }
00304 }
00305
00306 if(T!=LANCE){
00307 for(int i=0;;i++){
00308 OffsetPair op=Add_Effect8_Table.getLongMoveOffset(T,o32,i);
00309 if(op.first.zero()) break;
00310 Position pos1=target+op.first.blackOffset<P>();
00311 Position pos2=target+op.second.blackOffset<P>();
00312 Piece blocker=Piece::EMPTY();
00313 if(pos1.isOnBoard() && pos2.isOnBoard() &&
00314 state.getPieceAt(pos1).template canMoveOn<P>() &&
00315 state.hasEffectByPiece(attacker,pos1) &&
00316 canAddLongEffect<P,T>(state,pos1,pos2,blocker)){
00317 if(canPromote &&
00318 (from.canPromote<P>() || pos1.canPromote<P>())){
00319 action.unknownMove(from,pos1,state.getPieceAt(pos1),
00320 PtypeFuns<T>::promotePtype,true,P);
00321 }
00322 else action.unknownMove(from,pos1,state.getPieceAt(pos1),T,false,P);
00323 }
00324 }
00325 }
00326 }
00327
00331 template <Player P,Ptype T,class Action>
00332 class ShortPieceAction
00333 {
00334 NumEffectState const& state;
00335 Position target;
00336 Action& action;
00337 public:
00338 ShortPieceAction(NumEffectState const& s,Position p,Action& a)
00339 :state(s),target(p),action(a)
00340 {}
00344 void operator()(Piece p)
00345 {
00346 if (p.isPromotedNotKingGold())
00347 {
00348 generateShortMove<P,PtypeFuns<T>::promotePtype,Action,false>(state,p,target,action);
00349 }
00350 else
00351 {
00352 generateShortMove<P,T,Action,true>(state,p,target,action);
00353 generateShortMove<P,T,Action,false>(state,p,target,action);
00354 }
00355 }
00356 };
00357
00361 template <Player P,class Action>
00362 class GoldAction
00363 {
00364 NumEffectState const& state;
00365 Position target;
00366 Action& action;
00367 public:
00368 GoldAction(NumEffectState const& s,Position p,Action& a)
00369 :state(s),target(p),action(a)
00370 {}
00374 void operator()(Piece p)
00375 {
00376 generateShortMove<P,GOLD,Action,false>(state,p,target,action);
00377 }
00378 };
00379
00383 template <Player P,Ptype T,class Action>
00384 class LongPieceAction
00385 {
00386 NumEffectState const& state;
00387 Position target;
00388 Action& action;
00389 public:
00390 LongPieceAction(NumEffectState const& s,Position p,Action& a)
00391 :state(s),target(p),action(a)
00392 {}
00396 void operator()(Piece p)
00397 {
00398 Position from=p.position();
00399 if (p.isPromotedNotKingGold())
00400 {
00401 if (T==LANCE)
00402 generateShortMove<P,PtypeFuns<T>::promotePtype,Action,false>(state,p,target,action);
00403 else
00404 generateLongMove<P,PtypeFuns<T>::promotePtype,Action,false>(state,p,target,action);
00405 }
00406 else
00407 {
00408 generateLongMove<P,T,Action,true>(state,p,target,action);
00409 }
00410 }
00411 };
00412
00413 template<Player P,Ptype T,class Action>
00414 void generateShort(const NumEffectState& state,Position target,
00415 Action& action)
00416 {
00417 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00418 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00419 typedef ShortPieceAction<P,T,Action> action_t;
00420 action_t gkAction(state,target,action);
00421 state.template forEachOnBoard<P,T,action_t>(gkAction);
00423 if (state.template hasPieceOnStand<P,T>()){
00424 generateShortDrop<P,T,Action>(state,target,action);
00425 }
00426 }
00427
00428 template<Player P,Ptype T,class Action>
00429 void generateLong(const NumEffectState& state,Position target,
00430 Action& action)
00431 {
00432 BOOST_STATIC_ASSERT((PtypeTraits<T>::isBasic));
00433 BOOST_STATIC_ASSERT((PtypeTraits<T>::canPromote));
00434 typedef LongPieceAction<P,T,Action> action_t;
00435 action_t gkAction(state,target,action);
00436 state.template forEachOnBoard<P,T,action_t>(gkAction);
00437 }
00438
00439 template<Player P,class Action>
00440 void generateGold(const NumEffectState& state,Position target,
00441 Action& action)
00442 {
00443 typedef GoldAction<P,Action> action_t;
00444 action_t gkAction(state,target,action);
00445 state.template forEachOnBoard<P,GOLD,action_t>(gkAction);
00447 if (state.template hasPieceOnStand<P,GOLD>()){
00448 generateShortDrop<P,GOLD,Action>(state,target,action);
00449 }
00450 }
00451 }
00452
00453 template<Player P>
00454 template<class Action>
00455 void AddEffect8<P>::
00456 generateBigDrop(const NumEffectState& state,Action& action)
00457 {
00458 Position target=state.getKingPosition<PlayerTraits<P>::opponent>();
00459 if (state.template hasPieceOnStand<P,BISHOP>()){
00460 generateLongDrop<P,BISHOP,Action>(state,target,action);
00461 }
00462 if (state.template hasPieceOnStand<P,ROOK>()){
00463 generateLongDrop<P,ROOK,Action>(state,target,action);
00464 }
00465 }
00466
00467 template<Player P>
00468 template<class Action>
00469 void AddEffect8<P>::
00470 generateNotBigDrop(const NumEffectState& state,Action& action)
00471 {
00472 Position target=state.getKingPosition<PlayerTraits<P>::opponent>();
00473 generateShort<P,PAWN,Action>(state,target,action);
00474 generateLong<P,LANCE,Action>(state,target,action);
00475 if (state.template hasPieceOnStand<P,LANCE>()){
00476 generateLongDrop<P,LANCE,Action>(state,target,action);
00477 }
00478 generateShort<P,KNIGHT,Action>(state,target,action);
00479 generateShort<P,SILVER,Action>(state,target,action);
00480 generateGold<P,Action>(state,target,action);
00481
00482 generateLong<P,BISHOP,Action>(state,target,action);
00483 generateLong<P,ROOK,Action>(state,target,action);
00484 }
00485
00486 template<Player P>
00487 template<class Action>
00488 void AddEffect8<P>::
00489 generate(const NumEffectState& state,Action& action)
00490 {
00491 generateNotBigDrop(state,action);
00492 generateBigDrop(state,action);
00493 }
00494 }
00495 }
00496 #endif
00497
00498
00499
00500