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
00087 generateShortDrop<P,T,Action>(state,target,action);
00088 Square targetForP=target.squareForBlack(P);
00089
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
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
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
00290 if((T==ROOK || T==BISHOP) && from.canPromote<P>())
00291 return;
00292 Offset32 o32=Offset32(from,target).blackOffset32<P>();
00293
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
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
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
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
00512
00513
00514
00515