00001 #ifndef _NUM_SIMPLE_EFFECT_H
00002 #define _NUM_SIMPLE_EFFECT_H
00003
00004 #include "osl/effect/numBitmapEffect.h"
00005 #include "osl/misc/carray.h"
00006 #include "osl/apply_move/doUndoMoveLockForward.h"
00007 #include "osl/apply_move/applyDoUndoXMove.h"
00008 #include "osl/ptype.h"
00009 #include "osl/piece.h"
00010
00011 #include <boost/static_assert.hpp>
00012
00013 namespace osl
00014 {
00015 namespace state
00016 {
00017 class SimpleState;
00018 }
00019 namespace effect
00020 {
00021 template<class State>
00022 class NumSimpleEffectTable;
00023 template<class State>
00024 bool operator==(const NumSimpleEffectTable<State>&,const NumSimpleEffectTable<State>&);
00025 template<class State>
00026 std::ostream& operator<<(std::ostream&, const NumSimpleEffectTable<State>&);
00027
00028
00029 struct NumSimpleEffectUtil
00030 {
00031 static const mask_t longEffectMask() {
00032 #if OSL_WORDSIZE == 64
00033 return mask_t::makeDirect(0xff0000000000uLL);
00034 #elif OSL_WORDSIZE == 32
00035 return mask_t::makeDirect(0xff00u);
00036 #endif
00037 }
00038 #if OSL_WORDSIZE == 64
00039 static const int longToNumOffset=-8;
00040 #elif OSL_WORDSIZE == 32
00041 static const int longToNumOffset=32-8;
00042 #endif
00043 static const mask_t makeLongMask(int num)
00044 {
00045 return mask_t::makeDirect(0x101) << PieceMask::numToOffset(num);
00046 }
00047 template<Player P>
00048 static NumBitmapEffect makeLongEffect(int num){
00049 assert(32<=num && num<=39);
00050 NumBitmapEffect effect=NumBitmapEffect::playerEffect<P>();
00051 effect.orMask(1,makeLongMask(num));
00052 return effect;
00053 }
00054 static NumBitmapEffect makeLongEffect(Player pl,int num){
00055 assert(32<=num && num<=39);
00056 NumBitmapEffect effect=NumBitmapEffect::playerEffect(pl);
00057 effect.orMask(1,makeLongMask(num));
00058 return effect;
00059 }
00060 };
00064 template<class State>
00065 class NumSimpleEffectTable
00066 {
00067 protected:
00068 CArray<NumBitmapEffect, Position::SIZE> effects;
00069 public:
00079 template<Player P,Ptype T,Direction Dir,NumBitmapEffect::Op OP>
00080 void doEffectShort(Position pos,int num)
00081 {
00082 if ((PtypeTraits<T>::moveMask & DirectionTraits<Dir>::mask)!=0)
00083 {
00084 const Position target = pos+DirectionPlayerTraits<Dir,P>::offset();
00085 effects[target.index()].template opEqual<OP>(NumBitmapEffect::makeEffect<P>(num));
00086 }
00087 }
00098 template<Player P,Ptype T,Direction Dir,NumBitmapEffect::Op OP>
00099 void doEffectLong(const State& state,Position pos,int num)
00100 {
00101 if ((PtypeTraits<T>::moveMask & DirectionTraits<DirectionPlayerTraits<Dir,P>::directionByBlack>::mask)!=0)
00102 {
00103
00104 Offset offset=DirectionPlayerTraits<Dir,BLACK>::offset();
00105 assert(!offset.zero());
00106 NumBitmapEffect effect=NumSimpleEffectUtil::makeLongEffect<P>(num);
00107
00108 for (;;)
00109 {
00110 pos=pos+offset;
00111 effects[pos.index()].template opEqual<OP>(effect);
00112
00113 if (! state.getPieceAt(pos).isEmpty()) break;
00114 }
00115 }
00116 }
00126 template<Player P,Ptype T,NumBitmapEffect::Op OP>
00127 void doEffectBy(const State& state,Position pos,int num);
00136 template<NumBitmapEffect::Op OP>
00137 void doEffect(const State& state,PtypeO ptypeo,Position pos,int num);
00138
00145 template<NumBitmapEffect::Op OP>
00146 void doEffect(const State& state,Piece p)
00147 {
00148 doEffect<OP>(state,p.ptypeO(),p.position(),p.number());
00149 }
00154 void init(const State& state);
00158 NumSimpleEffectTable(const State& state)
00159 {
00160 init(state);
00161 }
00166 const NumBitmapEffect getEffect(Position pos) const
00167 {
00168 return effects[pos.index()];
00169 }
00176 template<NumBitmapEffect::Op OP>
00177 void doBlockAt(const State& state,Position pos);
00178 friend bool operator== <>(const NumSimpleEffectTable& et1,const NumSimpleEffectTable& et2);
00179 };
00180
00181 template<class State>
00182 inline bool operator!=(const NumSimpleEffectTable<State>& et1,const NumSimpleEffectTable<State>& et2)
00183 {
00184 return !(et1==et2);
00185 }
00186
00187 template<class State>
00188 class NumSimpleEffect;
00189 template<class State>
00190 bool operator==(const NumSimpleEffect<State>& st1, const NumSimpleEffect<State>& st2);
00191
00197 template<class State>
00198 class NumSimpleEffect: public State
00199 {
00200 public:
00202 typedef NumSimpleEffect<State> effect_state_t;
00203 private:
00204 NumSimpleEffectTable<typename State::simple_state_t> effects;
00205 CArray<PieceMask,2> onBoardMask;
00206
00207 friend bool operator==<>(const NumSimpleEffect& st1,
00208 const NumSimpleEffect& st2);
00209 typedef NumSimpleEffect state_t;
00210 friend class apply_move::ApplyDoUndoSimpleMove<BLACK,NumSimpleEffect>;
00211 friend class apply_move::ApplyDoUndoCaptureMove<BLACK,NumSimpleEffect>;
00212 friend class apply_move::ApplyDoUndoDropMove<BLACK,NumSimpleEffect>;
00213 friend class apply_move::ApplyDoUndoSimpleMove<WHITE,NumSimpleEffect>;
00214 friend class apply_move::ApplyDoUndoCaptureMove<WHITE,NumSimpleEffect>;
00215 friend class apply_move::ApplyDoUndoDropMove<WHITE,NumSimpleEffect>;
00216 PieceMask& getOnBoardMask(Player p) {
00217 return onBoardMask[playerToIndex(p)];
00218 }
00219 public:
00220 const PieceMask& getOnBoardMask(Player p) const {
00221 return onBoardMask[playerToIndex(p)];
00222 }
00223 bool isOnBoardNum(int num) const
00224 {
00225 return getOnBoardMask(BLACK).test(num) ||
00226 getOnBoardMask(WHITE).test(num);
00227 }
00228
00229 Piece getPieceOf(int num) const
00230 {
00231 return State::getPieceOf(num);
00232 }
00236 template<Player P,Ptype T,typename F>
00237 void forEachOnBoard(F& func) const {
00238 mask_t onMask=getOnBoardMask(P).getMask(PtypeFuns<T>::indexNum)
00239 & mask_t::makeDirect(PtypeFuns<T>::indexMask);
00240
00241 while (onMask.any())
00242 {
00243 int num=onMask.takeOneBit()+((PtypeFuns<T>::indexNum)<<5);
00244 Piece p = getPieceOf(num);
00245 func(p);
00246 }
00247 }
00248
00249 explicit NumSimpleEffect(const state::SimpleState& st);
00250 ~NumSimpleEffect();
00251
00252 NumBitmapEffect getEffect(Position pos) const
00253 {
00254 return effects.getEffect(pos);
00255 }
00256 bool isConsistent(bool showError) const;
00257
00258 void doSimpleMove(Position from, Position to, int promoteMask);
00259 void doDropMove(Position to,Ptype ptype);
00260 void doCaptureMove(Position from, Position to, Piece target,int promoteMask);
00265 template<Direction Dir,Player P>
00266 bool hasEffectDir(Position to) const {
00267 BOOST_STATIC_ASSERT( (DirectionTraits<Dir>::isLong) );
00268 const PieceMask& onBoardMask=getOnBoardMask(P);
00269 mask_t mask1=onBoardMask.getMask(1);
00270 mask1 &= ((PtypeDirectionTraits<LANCE,Dir>::canMove
00271 ? mask_t::makeDirect(PtypeFuns<LANCE>::indexMask)
00272 : mask_t::makeDirect(0))
00273 | (PtypeDirectionTraits<BISHOP,Dir>::canMove
00274 ? mask_t::makeDirect(PtypeFuns<BISHOP>::indexMask)
00275 : mask_t::makeDirect(0))
00276 | (PtypeDirectionTraits<ROOK,Dir>::canMove
00277 ? mask_t::makeDirect(PtypeFuns<ROOK>::indexMask)
00278 : mask_t::makeDirect(0)));
00279 mask1 <<= 8;
00280
00281 mask1&=getEffect(to).getMask(1)& NumSimpleEffectUtil::longEffectMask();
00282 while (mask1.any())
00283 {
00284 int num=mask1.takeOneBit()+NumSimpleEffectUtil::longToNumOffset;
00285 Position from = getPieceOf(num).position();
00286 Direction dir=Board_Table.getLongDirection<BLACK>(Offset32(to,from));
00287 if (dir==DirectionPlayerTraits<Dir,P>::directionByBlack)
00288 return true;
00289 }
00290 return false;
00291 }
00295 template <Ptype PTYPE>
00296 bool hasEffectLong(Player P, Position to) const {
00297 BOOST_STATIC_ASSERT( (PTYPE == LANCE || PTYPE == BISHOP || PTYPE == ROOK) );
00298 const PieceMask& onBoardMask=getOnBoardMask(P);
00299 mask_t mask1=onBoardMask.getMask(1);
00300 mask1 &= mask_t::makeDirect(PtypeFuns<PTYPE>::indexMask);
00301 mask1 <<= 8;
00302
00303 mask1&=getEffect(to).getMask(1)& NumSimpleEffectUtil::longEffectMask();
00304 return mask1.any();
00305 }
00311 bool hasEffectBy(Player player,Position target) const {
00312 assert(target.isOnBoard());
00313 mask_t mask=getEffect(target).getMask(1);
00314 mask&=NumBitmapEffect::playerEffectMask(player);
00315 return !mask.none();
00316 }
00317
00318
00326 bool hasEffectNotBy(Player player,Piece piece,Position target) const {
00327 assert(piece.owner()==player);
00328 PieceMask onBoardMask=getOnBoardMask(player);
00329 int num=piece.number();
00330 onBoardMask.reset(num);
00331 return (onBoardMask&getEffect(target)).any();
00332 }
00339 bool hasMultipleEffectBy(Player player,Position target) const
00340 {
00341 mask_t mask=getEffect(target).getMask(1);
00342 mask&=NumBitmapEffect::playerEffectMask(player);
00343 return NumBitmapEffect::playerEffect(player).getMask(1) < mask;
00344 }
00345
00350 bool hasEffectByPiece(Piece attack, Position target) const
00351 {
00352 assert(target.isOnBoard());
00353 return getEffect(target).test(attack.number());
00354 }
00355
00359 template <Ptype PTYPE>
00360 bool hasEffectByPtype(Player attack, Position target) const
00361 {
00362 mask_t mask=getEffect(target).getMask(PtypeFuns<PTYPE>::indexNum);
00363 mask&=mask_t::makeDirect(PtypeFuns<PTYPE>::indexMask);
00364 const PieceMask& onBoardMask=getOnBoardMask(attack);
00365 mask&=onBoardMask.getMask(PtypeFuns<PTYPE>::indexNum);
00366 return mask.any();
00367 }
00369 template <Ptype PTYPE>
00370 const Piece effectPtype(Player attack, Position target) const
00371 {
00372 mask_t mask=getEffect(target).getMask(PtypeFuns<PTYPE>::indexNum);
00373 mask&=mask_t::makeDirect(PtypeFuns<PTYPE>::indexMask);
00374 const PieceMask& onBoardMask=getOnBoardMask(attack);
00375 mask&=onBoardMask.getMask(PtypeFuns<PTYPE>::indexNum);
00376 if (mask.none())
00377 return Piece::EMPTY();
00378 return getPieceOf(mask.takeOneBit()+PtypeFuns<PTYPE>::indexNum*32);
00379 }
00380
00385 int countEffect2(Player player,Position target) const
00386 {
00387 assert(target.isOnBoard());
00388 return std::min(2,countEffect(player,target));
00389 }
00394 int countEffect(Player player,Position target) const
00395 {
00396 assert(target.isOnBoard());
00397 return getEffect(target).countEffect(player);
00398 }
00404 int countEffect(Player player,Position target, PieceMask pins) const
00405 {
00406 assert(target.isOnBoard());
00407 const NumBitmapEffect effect = getEffect(target);
00408 const int all = effect.countEffect(player);
00409 pins &= effect;
00410 return all - pins.countBit();
00411 }
00412 private:
00413 int countKingEffect(Player P, PieceMask pieces) const
00414 {
00415 if (pieces.test(PtypeTable::getKingIndex(P)))
00416 return pieces.countBit2();
00417 return pieces.none() ? 0 : 2;
00418 }
00419 public:
00424 int countKingEffect(Player P, Position target) const
00425 {
00426 assert(target.isOnBoard());
00427 const PieceMask pieces
00428 = getOnBoardMask(P) & getEffect(target);
00429 return countKingEffect(P, pieces);
00430 }
00431 int countKingEffect(Player P, Position target, PieceMask dont_use) const
00432 {
00433 assert(target.isOnBoard());
00434 PieceMask pieces = getOnBoardMask(P);
00435 pieces ^= dont_use;
00436 return countKingEffect(P, pieces & getEffect(target));
00437 }
00444 template<Player P>
00445 Piece hasEffectPiece(Position p) const
00446 {
00447 assert(p.isOnBoard());
00448 #if OSL_WORDSIZE == 64
00449 const PieceMask pieceMask=getOnBoardMask(P)&getEffect(p);
00450 if (pieceMask.none()) return Piece::EMPTY();
00451 return getPieceOf(pieceMask.getMask(0).bsf());
00452 #elif OSL_WORDSIZE == 32
00453 const PieceMask& onBoardMask=getOnBoardMask(P);
00454 mask_t mask0=onBoardMask.getMask(0);
00455 NumBitmapEffect effect=getEffect(p);
00456 mask0&=effect.getMask(0);
00457 if (mask0.any())
00458 {
00459 return getPieceOf(mask0.bsf());
00460 }
00461 else{
00462 mask_t mask1=effect.getMask(1);
00463 mask1|=(mask1>>8);
00464 mask1&=onBoardMask.getMask(1);
00465 if (mask1.any())
00466 {
00467 int num=mask1.bsf()+32;
00468 assert(32<=num && num<=39);
00469 return getPieceOf(num);
00470 }
00471 else{
00472 return Piece::EMPTY();
00473 }
00474 }
00475 #endif
00476 }
00477 Piece hasEffectPiece(Player pl,Position pos) const
00478 {
00479 if (pl==BLACK) return hasEffectPiece<BLACK>(pos);
00480 else return hasEffectPiece<WHITE>(pos);
00481 }
00486 template<Player P,Ptype Type,class Action>
00487 void forEachEffectPtype(Position pos,Action & action) const {
00488 mask_t mask=getEffect(pos).getMask(PtypeFuns<Type>::indexNum);
00489 mask&=mask_t::makeDirect(PtypeFuns<Type>::indexMask);
00490 const PieceMask& onBoardMask=getOnBoardMask(P);
00491 mask&=onBoardMask.getMask(PtypeFuns<Type>::indexNum);
00492 while (mask.any())
00493 {
00494 int num=mask.takeOneBit()+(PtypeFuns<Type>::indexNum<<5);
00495 action.template doActionPtype<P,Type>(getPieceOf(num),pos);
00496 }
00497 }
00498
00503 template<Player P,class Action>
00504 void forEachEffect(Position pos,Action & action) const
00505 {
00506 const PieceMask pieceMask=getOnBoardMask(P)&getEffect(pos);
00507 #if OSL_WORDSIZE == 64
00508 mask_t mask=pieceMask.getMask(0);
00509 while (mask.any())
00510 {
00511 const int num=mask.takeOneBit();
00512 action.template doAction<P>(getPieceOf(num),pos);
00513 }
00514 #elif OSL_WORDSIZE == 32
00515 mask_t mask0=pieceMask.getMask(0);
00516 while (mask0.any())
00517 {
00518 const int num=mask0.takeOneBit();
00519 action.template doAction<P>(getPieceOf(num),pos);
00520 }
00521 mask_t mask1=pieceMask.getMask(1);
00522 while (mask1.any())
00523 {
00524 const int num=mask1.takeOneBit()+32;
00525 action.template doAction<P>(getPieceOf(num),pos);
00526 }
00527 #endif
00528 }
00534 template<Player P,class Action>
00535 void forEachEffect(Position pos,Action & action,const PieceMask& pin) const
00536 {
00537 PieceMask pieceMask=getOnBoardMask(P)&getEffect(pos);
00538 pieceMask &= ~pin;
00539 #if OSL_WORDSIZE == 64
00540 mask_t mask=pieceMask.getMask(0);
00541 while (mask.any())
00542 {
00543 const int num=mask.takeOneBit();
00544 action.template doAction<P>(getPieceOf(num),pos);
00545 }
00546 #elif OSL_WORDSIZE == 32
00547 mask_t mask0=pieceMask.getMask(0);
00548 while (mask0.any())
00549 {
00550 const int num=mask0.takeOneBit();
00551 action.template doAction<P>(getPieceOf(num),pos);
00552 }
00553 mask_t mask1=pieceMask.getMask(1);
00554 while (mask1.any())
00555 {
00556 const int num=mask1.takeOneBit()+32;
00557 action.template doAction<P>(getPieceOf(num),pos);
00558 }
00559 #endif
00560 }
00561
00567 template<Player P,class Action>
00568 void forEachEffectNotBy(Position pos,Piece piece,Action & action) const {
00569 PieceMask pieceMask=getOnBoardMask(P);
00570 pieceMask.reset(piece.number());
00571 PieceMask effectMask=(PieceMask)getEffect(pos);
00572 pieceMask=(pieceMask&effectMask);
00573 #if OSL_WORDSIZE == 64
00574 mask_t mask=pieceMask.getMask(0);
00575 while (mask.any())
00576 {
00577 int num=mask.takeOneBit();
00578 action.template doAction<P>(getPieceOf(num),pos);
00579 }
00580 #elif OSL_WORDSIZE == 32
00581 mask_t mask0=pieceMask.getMask(0);
00582 while (mask0.any())
00583 {
00584 int num=mask0.takeOneBit();
00585 action.template doAction<P>(getPieceOf(num),pos);
00586 }
00587 mask_t mask1=pieceMask.getMask(1);
00588 while (mask1.any())
00589 {
00590 int num=mask1.takeOneBit()+32;
00591 action.template doAction<P>(getPieceOf(num),pos);
00592 }
00593 #endif
00594 }
00595
00600 template<Player P,class Action>
00601 void forSortedEffect(Position pos,Action & action) const ;
00608 bool hasEffectTo(Piece attackerPiece,Position targetPosition) const
00609 {
00610 assert(attackerPiece.isPiece() && targetPosition.isOnBoard());
00611 return getEffect(targetPosition).test(attackerPiece.number());
00612 }
00613
00619 template<Player P>
00620 bool hasEffectBy(Position target) const {
00621 assert(target.isOnBoard());
00622 mask_t mask=getEffect(target).getMask(1);
00623 mask&=NumBitmapEffect::playerEffectMask<P>();
00624 return !mask.none();
00625 }
00626
00627 bool hasEffectBy(Player P, Position target,Piece& attackerPiece) const
00628 {
00629 if (P == BLACK)
00630 return hasEffectBy<BLACK>(target, attackerPiece);
00631 else
00632 return hasEffectBy<WHITE>(target, attackerPiece);
00633 }
00640 template<Player P>
00641 bool hasEffectBy(Position target,Piece& attackerPiece) const {
00642 attackerPiece=Piece::EMPTY();
00643 const PieceMask& pieceMask=getOnBoardMask(P)&getEffect(target);
00644 #if OSL_WORDSIZE == 64
00645 mask_t mask=pieceMask.getMask(0);
00646 if (mask.none()) return false;
00651 if (mask.hasMultipleBit())
00652 return true;
00653 int num=mask.bsf();
00654 attackerPiece=getPieceOf(num);
00655 return true;
00656 #elif OSL_WORDSIZE == 32
00657 mask_t mask0=pieceMask.getMask(0);
00658 mask_t mask1=pieceMask.getMask(1);
00659 if (mask0.any())
00660 {
00661 if (mask1.any())
00662 return true;
00663 int num=mask0.bsf();
00664 if (mask0 == PieceMask::numToMask(num))
00665 attackerPiece=getPieceOf(num);
00666 return true;
00667 }
00668 else if (mask1.any())
00669 {
00670 int num=mask1.bsf();
00671 if (mask1==PieceMask::numToMask(num))
00672 attackerPiece=getPieceOf(num+32);
00673 return true;
00674 }
00675 else
00676 return false;
00677 #endif
00678 }
00685 template<Player P>
00686 bool lastMoveIsCheck(Move , Piece& attack_piece) const
00687 {
00688 return hasEffectBy<PlayerTraits<P>::opponent>
00689 (getPieceOf(KingTraits<P>::index).position(),attack_piece);
00690 }
00691 Player getTurn() const{
00692 return State::getTurn();
00693 }
00694 Piece getPieceAt(Position pos) const{
00695 return State::getPieceAt(pos);
00696 }
00697 template<Player P,Ptype T>
00698 bool hasPieceOnStand() const {
00699 return State::template hasPieceOnStand<P,T>();
00700 }
00701 bool hasPieceOnStand(Player pl,Ptype ptype) const{
00702 return State::hasPieceOnStand(pl,ptype);
00703 }
00704 bool isValidMoveByRule(Move move,bool showError) const;
00715 template <bool show_error>
00716 bool isAlmostValidMove(Move move) const;
00717 bool isAlmostValidMove(Move move,bool show_error=true) const;
00718 };
00719
00720 template<class State>
00721 template<Player P,class Action>
00722 void NumSimpleEffect<State>::forSortedEffect(Position pos,Action & action) const {
00723 forEachEffectPtype<P,PAWN,Action>(pos,action);
00724 forEachEffectPtype<P,LANCE,Action>(pos,action);
00725 forEachEffectPtype<P,KNIGHT,Action>(pos,action);
00726 forEachEffectPtype<P,SILVER,Action>(pos,action);
00727 forEachEffectPtype<P,GOLD,Action>(pos,action);
00728 forEachEffectPtype<P,BISHOP,Action>(pos,action);
00729 forEachEffectPtype<P,ROOK,Action>(pos,action);
00730 forEachEffectPtype<P,KING,Action>(pos,action);
00731 }
00732
00733 template<class State>
00734 inline bool operator!=(const NumSimpleEffect<State>& s1,
00735 const NumSimpleEffect<State>& s2)
00736 {
00737 return !(s1==s2);
00738 }
00739 }
00740 using effect::NumSimpleEffect;
00741 using effect::NumBitmapEffect;
00742
00743 namespace apply_move
00744 {
00745 template<Player P,typename BaseState>
00746 struct ApplyDoUndoSimpleMove<P,NumSimpleEffect<BaseState> >
00747 {
00748 typedef NumSimpleEffect<BaseState> state_t;
00749 template <typename F>
00750 static void doUndoSimpleMove(state_t& s,
00751 Position from, Position to, int promoteMask,F& func);
00752
00753 static
00754 void prologue(state_t& s, Position from, Position to, int promoteMask,
00755 Piece& oldPiece, int& num,
00756 PtypeO& oldPtypeO, PtypeO& newPtypeO)
00757 {
00758 oldPiece=s.getPieceAt(from);
00759 Piece newPiece=oldPiece.promoteWithMask(promoteMask);
00760 newPiece+=(to-from);
00761 num=oldPiece.number();
00762
00763 oldPtypeO=oldPiece.ptypeO();
00764 newPtypeO=newPiece.ptypeO();
00765
00766 s.setPieceOf(num,newPiece);
00767 s.effects.template doEffect<NumBitmapEffect::Sub>(s,oldPtypeO,from,num);
00768
00769
00770 s.setBoard(to,newPiece);
00771 s.effects.template doBlockAt<NumBitmapEffect::Sub>(s,to);
00772 s.setBoard(from,Piece::EMPTY());
00773 s.effects.template doBlockAt<NumBitmapEffect::Add>(s,from);
00774 s.effects.template doEffect<NumBitmapEffect::Add>(s,newPtypeO,to,num);
00775 }
00776 static
00777 void epilogue(state_t& s, Position from, Position to, Piece oldPiece,
00778 int num, PtypeO oldPtypeO, PtypeO newPtypeO)
00779 {
00780 s.setPieceOf(num,oldPiece);
00781 s.effects.template doEffect<NumBitmapEffect::Sub>(s,newPtypeO,to,num);
00782 s.setBoard(from,oldPiece);
00783 s.effects.template doBlockAt<NumBitmapEffect::Sub>(s,from);
00784 s.setBoard(to,Piece::EMPTY());
00785 s.effects.template doBlockAt<NumBitmapEffect::Add>(s,to);
00786 s.effects.template doEffect<NumBitmapEffect::Add>(s,oldPtypeO,from,num);
00787 }
00788 };
00789
00790
00791 template<Player P,typename BaseState>
00792 template <typename F>
00793 void ApplyDoUndoSimpleMove<P,NumSimpleEffect<BaseState> >::
00794 doUndoSimpleMove(state_t& s,
00795 Position from, Position to, int promoteMask,F& func)
00796 {
00797 Piece oldPiece;
00798 int num;
00799 PtypeO oldPtypeO, newPtypeO;
00800 prologue(s, from, to, promoteMask, oldPiece, num, oldPtypeO, newPtypeO);
00801
00802 if (promoteMask!=0 && num < PtypeTraits<PAWN>::indexLimit)
00803 {
00804 s.clearPawn(P,from);
00805 s.changeTurn();
00806 func(to);
00807 s.changeTurn();
00808 s.setPawn(P,from);
00809 }
00810 else
00811 {
00812 s.changeTurn();
00813 func(to);
00814 s.changeTurn();
00815 }
00816
00817 epilogue(s, from, to, oldPiece, num, oldPtypeO, newPtypeO);
00818 }
00819
00820 template<Player P,typename BaseState>
00821 struct ApplyDoUndoDropMove<P,NumSimpleEffect<BaseState> >
00822 {
00823 typedef NumSimpleEffect<BaseState> state_t;
00824 template <typename F>
00825 static void doUndoDropMove(state_t& s,
00826 Position to, Ptype ptype,F& func);
00827 static
00828 void prologue(state_t& s, Position to, Ptype ptype,
00829 Piece& oldPiece, int& num, PtypeO& ptypeO,
00830 int& numIndex, mask_t& numMask)
00831 {
00832 #if OSL_WORDSIZE == 64
00833 numIndex=0;
00834 #elif OSL_WORDSIZE == 32
00835 numIndex=Ptype_Table.getIndex(ptype);
00836 #endif
00837 const mask_t ownMochigoma=
00838 s.standMask(P).getMask(numIndex) & Ptype_Table.getMaskLow(ptype);
00839 assert(ownMochigoma.any());
00840 numMask=ownMochigoma.lowestBit();
00841 int numLow = ownMochigoma.bsf();
00842 num = numLow|(numIndex<<5);
00843 oldPiece=s.getPieceOf(num);
00844 Piece newPiece=oldPiece;
00845 newPiece+=to-Position::STAND();
00846 ptypeO=newPiece.ptypeO();
00847 s.setPieceOf(num,newPiece);
00848 s.effects.template doEffect<NumBitmapEffect::Add>(s,ptypeO,to,num);
00849 s.setBoard(to,newPiece);
00850 s.effects.template doBlockAt<NumBitmapEffect::Sub>(s,to);
00851 s.standMask(P).xorMask(numIndex,numMask);
00852 s.getOnBoardMask(P).xorMask(numIndex,numMask);
00853 }
00854
00855 static
00856 void epilogue(state_t& s, Position to, Piece oldPiece,
00857 int num, PtypeO ptypeO, int numIndex, mask_t numMask)
00858 {
00859 s.standMask(P).xorMask(numIndex,numMask);
00860 s.getOnBoardMask(P).xorMask(numIndex,numMask);
00861 s.setBoard(to,Piece::EMPTY());
00862 s.effects.template doEffect<NumBitmapEffect::Sub>(s,ptypeO,to,num);
00863 s.effects.template doBlockAt<NumBitmapEffect::Add>(s,to);
00864 s.setPieceOf(num,oldPiece);
00865 }
00866 };
00867
00868 template<Player P,typename BaseState>
00869 template <typename F>
00870 void ApplyDoUndoDropMove<P,NumSimpleEffect<BaseState> >::
00871 doUndoDropMove(state_t& s,
00872 Position to, Ptype ptype,F& func)
00873 {
00874 Piece oldPiece;
00875 PtypeO ptypeO;
00876 int num, numIndex;
00877 mask_t numMask;
00878 prologue(s, to, ptype, oldPiece, num, ptypeO, numIndex, numMask);
00879
00880 if (ptype==PAWN)
00881 {
00882 s.setPawn(P,to);
00883 s.changeTurn();
00884 func(to);
00885 s.changeTurn();
00886 s.clearPawn(P,to);
00887 }
00888 else
00889 {
00890 s.changeTurn();
00891 func(to);
00892 s.changeTurn();
00893 }
00894 epilogue(s, to, oldPiece, num, ptypeO, numIndex, numMask);
00895
00896 }
00897
00898 template<Player P,typename BaseState>
00899 struct ApplyDoUndoCaptureMove<P,NumSimpleEffect<BaseState> >
00900 {
00901 typedef NumSimpleEffect<BaseState> state_t;
00902 template <typename F>
00903 static void doUndoCaptureMove(state_t& s, Position from,Position to,
00904 Piece target, int promoteMask,F& func);
00905 static
00906 void prologue(state_t& s, Position from, Position to, Piece target,
00907 int promoteMask,
00908 Piece& oldPiece, PtypeO& oldPtypeO, PtypeO& capturePtypeO,
00909 PtypeO& newPtypeO, int& num0, int& num1,
00910 int& num1Index, mask_t& num1Mask)
00911 {
00912 num1=target.number();
00913 num1Index=PieceMask::numToIndex(num1);
00914 num1Mask=PieceMask::numToMask(num1);
00915 s.getOnBoardMask(PlayerTraits<P>::opponent).xorMask(num1Index,num1Mask);
00916 s.standMask(P).xorMask(num1Index,num1Mask);
00917 oldPiece=s.getPieceAt(from);
00918 Piece newPiece=oldPiece.promoteWithMask(promoteMask);
00919 newPiece+=(to-from);
00920 num0=oldPiece.number();
00921 s.setPieceOf(num0,newPiece);
00922 s.setPieceOf(num1,target.captured());
00923
00924 oldPtypeO=oldPiece.ptypeO();
00925 newPtypeO=newPiece.ptypeO();
00926 capturePtypeO=target.ptypeO();
00927 s.effects.template doEffect<NumBitmapEffect::Sub>(s,capturePtypeO,to,num1);
00928 s.effects.template doEffect<NumBitmapEffect::Sub>(s,oldPtypeO,from,num0);
00929 s.setBoard(to,newPiece);
00930 s.setBoard(from,Piece::EMPTY());
00931 s.effects.template doBlockAt<NumBitmapEffect::Add>(s,from);
00932 s.effects.template doEffect<NumBitmapEffect::Add>(s,newPtypeO,to,num0);
00933 }
00934 static
00935 void epilogue(state_t& s, Position from, Position to, Piece target,
00936 Piece oldPiece, PtypeO oldPtypeO, PtypeO capturePtypeO,
00937 PtypeO newPtypeO, int num0, int num1,
00938 int num1Index, mask_t num1Mask)
00939 {
00940 s.standMask(P).xorMask(num1Index,num1Mask);
00941 s.getOnBoardMask(PlayerTraits<P>::opponent).xorMask(num1Index,num1Mask);
00942 s.setPieceOf(num0,oldPiece);
00943 s.setPieceOf(num1,target);
00944 s.effects.template doEffect<NumBitmapEffect::Sub>(s,newPtypeO,to,num0);
00945 s.effects.template doEffect<NumBitmapEffect::Add>(s,capturePtypeO,to,num1);
00946 s.setBoard(from,oldPiece);
00947 s.effects.template doBlockAt<NumBitmapEffect::Sub>(s,from);
00948 s.setBoard(to,target);
00949 s.effects.template doEffect<NumBitmapEffect::Add>(s,oldPtypeO,from,num0);
00950 }
00951
00952 };
00953
00954 template<Player P,typename BaseState>
00955 template <typename F>
00956 void ApplyDoUndoCaptureMove<P,NumSimpleEffect<BaseState> >::
00957 doUndoCaptureMove(state_t& s, Position from,Position to, Piece target,
00958 int promoteMask,F& func)
00959 {
00960 Piece oldPiece;
00961 PtypeO oldPtypeO, capturePtypeO, newPtypeO;
00962 int num0, num1, num1Index;
00963 mask_t num1Mask;
00964 prologue(s, from, to, target, promoteMask, oldPiece, oldPtypeO,
00965 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask);
00966
00967 s.changeTurn();
00968 const Ptype capturePtype=target.ptype();
00969 if (capturePtype==PAWN)
00970 {
00971 s.clearPawn(PlayerTraits<P>::opponent,to);
00972 if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
00973 {
00974 s.clearPawn(P,from);
00975 func(to);
00976 s.setPawn(P,from);
00977 }
00978 else
00979 {
00980 func(to);
00981 }
00982 s.setPawn(PlayerTraits<P>::opponent,to);
00983 }
00984 else if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
00985 {
00986 s.clearPawn(P,from);
00987 func(to);
00988 s.setPawn(P,from);
00989 }
00990 else
00991 {
00992 func(to);
00993 }
00994 s.changeTurn();
00995
00996 epilogue(s, from, to, target, oldPiece, oldPtypeO, capturePtypeO, newPtypeO,
00997 num0, num1, num1Index,num1Mask);
00998 }
00999
01000 template <class BaseState>
01001 class DoUndoMoveLockSimple<NumSimpleEffect<BaseState> >;
01002 template <class BaseState>
01003 class DoUndoMoveLockDrop<NumSimpleEffect<BaseState> >;
01004 template <class BaseState>
01005 class DoUndoMoveLockCapture<NumSimpleEffect<BaseState> >;
01006
01007 }
01008
01009 }
01010 #endif // _NUM_SIMPLE_EFFECT_H
01011
01012
01013
01014