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