00001
00002
00003 #ifndef OSL_NUM_EFFECT_STATE_H
00004 #define OSL_NUM_EFFECT_STATE_H
00005
00006 #include "osl/bits/numSimpleEffect.h"
00007 #include "osl/mobility/kingMobility.h"
00008 #include "osl/bits/align16New.h"
00009
00010 namespace osl
00011 {
00012 namespace checkmate
00013 {
00014 class King8Info;
00015 }
00016 class MoveVector;
00017 class NumEffectState;
00023 bool operator==(const NumEffectState& st1, const NumEffectState& st2);
00024
00030 class NumEffectState : public SimpleState
00031 #if OSL_WORDSIZE == 32
00032 , public misc::Align16New
00033 #endif
00034 {
00035 effect::NumSimpleEffectTable effects;
00036 CArray<PieceMask,2> pieces_onboard;
00038 PieceMask promoted;
00039 CArray<PieceMask,2> pin_or_open;
00040 KingMobility king_mobility;
00041 CArray<uint64_t,2> king8infos;
00042
00043 friend bool operator==(const NumEffectState& st1,const NumEffectState& st2);
00044 typedef NumEffectState state_t;
00045 public:
00046
00047
00048
00049 explicit NumEffectState(const SimpleState& st=SimpleState(HIRATE));
00050 ~NumEffectState();
00052 void copyFrom(const NumEffectState& src);
00053 void copyFrom(const SimpleState& src);
00054 bool isConsistent(bool showError=true) const;
00056 bool isConsistent(const NumEffectState& prev, Move moved, bool show_error=true) const;
00057 void showEffect(std::ostream& os) const;
00058
00059
00060
00061
00062
00063 const PieceMask& piecesOnBoard(Player p) const { return pieces_onboard[p]; }
00064 const PieceMask promotedPieces() const { return promoted; }
00065 const PieceMask pin(Player king) const
00066 {
00067 return pin_or_open[king]&piecesOnBoard(king);
00068 }
00070 const PieceMask checkShadow(Player attack) const
00071 {
00072 return pin_or_open[alt(attack)]&piecesOnBoard(attack);
00073 }
00074 PieceMask pinOrOpen(Player king) const
00075 {
00076 return pin_or_open[king];
00077 }
00078 uint64_t Iking8Info(Player king) const
00079 {
00080 return king8infos[king];
00081 }
00082 const checkmate::King8Info
00083 #ifdef __GNUC__
00084 __attribute__ ((pure))
00085 #endif
00086 king8Info(Player king) const;
00088 bool inCheck(Player P) const
00089 {
00090 const Square king = kingSquare(P);
00091 #ifdef ALLOW_KING_ABSENCE
00092 if (king.isPieceStand())
00093 return false;
00094 #endif
00095 return hasEffectAt(alt(P), king);
00096 }
00098 bool inCheck() const { return inCheck(turn()); }
00107 bool inUnblockableCheck(Player target) const {
00108 const Square king_position = kingSquare(target);
00109 Piece attacker_piece;
00110 if (hasEffectAt(alt(target), king_position, attacker_piece)) {
00111 if (attacker_piece == Piece::EMPTY())
00112 return true;
00113
00114 const Square from = attacker_piece.square();
00115 const EffectContent effect
00116 = Ptype_Table.getEffect(attacker_piece.ptypeO(),
00117 from, king_position);
00118 return effect.hasUnblockableEffect();
00119 }
00120
00121 return false;
00122 }
00123
00124 const EffectedNumTable& longEffectNumTable() const
00125 {
00126 return effects.effectedNumTable;
00127 }
00128
00130 const PieceMask effectedMask(Player pl) const
00131 {
00132 return effects.effected_mask[pl];
00133 }
00137 const PieceMask effectedChanged(Player pl) const
00138 {
00139 return effects.effected_changed_mask[pl];
00140 }
00141 bool hasChangedEffects() const {
00142 return ! effects.changedEffects(BLACK).isInvalid();
00143 }
00144 const BoardMask changedEffects(Player pl) const{
00145 assert(hasChangedEffects());
00146 return effects.changedEffects(pl);
00147 }
00148 const BoardMask changedEffects() const{
00149 BoardMask ret = changedEffects(BLACK);
00150 return ret |= changedEffects(WHITE);
00151 }
00152 const NumBitmapEffect changedPieces() const{
00153 return effects.changedPieces();
00154 }
00155 template <Ptype PTYPE> bool longEffectChanged() const
00156 {
00157 return changedPieces().template hasLong<PTYPE>();
00158 }
00159 template <Ptype PTYPE> bool anyEffectChanged() const
00160 {
00161 return changedPieces().template hasAny<PTYPE>();
00162 }
00163
00165 const Piece findThreatenedPiece(Player P) const;
00166
00167
00168
00169
00170 bool isOnBoardNum(int num) const
00171 {
00172 return piecesOnBoard(BLACK).test(num) || piecesOnBoard(WHITE).test(num);
00173 }
00174
00175 Square mobilityOf(Direction d,int num) const
00176 {
00177 return effects.mobilityTable.get(d,num);
00178 }
00179 Square mobilityOf(Direction d, Piece p) const
00180 {
00181 return mobilityOf(d, p.number());
00182 }
00183 Square kingMobilityAbs(Player p, Direction d) const
00184 {
00185 return Square::makeDirect(king_mobility[p][d]);
00186 }
00192 Square kingMobilityOfPlayer(Player p, Direction d) const
00193 {
00194 if (p == BLACK)
00195 d = inverse(d);
00196 return kingMobilityAbs(p, d);
00197 }
00202 template<Player P>
00203 Direction pinnedDir(Piece p) const
00204 {
00205 assert(p.owner() == P);
00206 assert(pinOrOpen(P).test(p.number()));
00207 Square king=kingSquare<P>();
00208 return Board_Table.getShort8<P>(p.square(),king);
00209 }
00210 Direction pinnedDir(Piece p) const
00211 {
00212 if (p.owner() == BLACK)
00213 return pinnedDir<BLACK>(p);
00214 else
00215 return pinnedDir<WHITE>(p);
00216 }
00221 template<Player P>
00222 bool pinnedCanMoveTo(Piece p,Square to) const
00223 {
00224 assert(p.owner() == P);
00225 Direction d=pinnedDir<P>(p);
00226 Square from=p.square();
00227 return primDir(d)==primDirUnsafe(Board_Table.getShort8Unsafe<P>(from,to));
00228 }
00229 bool pinnedCanMoveTo(Piece p,Square to) const
00230 {
00231 if (p.owner() == BLACK)
00232 return pinnedCanMoveTo<BLACK>(p, to);
00233 else
00234 return pinnedCanMoveTo<WHITE>(p, to);
00235 }
00239 template<Player P>
00240 Piece pinAttacker(Piece pinned) const
00241 {
00242 assert(pinned.owner() == P);
00243 assert(pinOrOpen(P).test(pinned.number()));
00244 Direction d=pinnedDir<P>(pinned);
00245 int attacker_num=longEffectNumTable()[pinned.number()][(P==BLACK ? d : inverseUnsafe(d))];
00246 return pieceOf(attacker_num);
00247 }
00248 Piece pinAttacker(Piece pinned) const
00249 {
00250 if (pinned.owner() == BLACK)
00251 return pinAttacker<BLACK>(pinned);
00252 else
00253 return pinAttacker<WHITE>(pinned);
00254 }
00255
00256
00257
00258 const NumBitmapEffect effectSetAt(Square sq) const
00259 {
00260 return effects.effectSetAt(sq);
00261 }
00266 int countEffect(Player player,Square target) const
00267 {
00268 assert(target.isOnBoard());
00269 return effectSetAt(target).countEffect(player);
00270 }
00276 int
00277 #ifdef __GNUC__
00278 __attribute__ ((pure))
00279 #endif
00280 countEffect(Player player,Square target, PieceMask pins) const
00281 {
00282 assert(target.isOnBoard());
00283 const NumBitmapEffect effect = effectSetAt(target);
00284 const int all = effect.countEffect(player);
00285 pins &= effect;
00286 return all - pins.countBit();
00287 }
00288
00289
00290
00291
00292 template <Ptype PTYPE>
00293 const mask_t allEffectAt(Player P, Square target) const
00294 {
00295 return effectSetAt(target).template selectBit<PTYPE>() & piecesOnBoard(P).template getMask<PTYPE>();
00296 }
00297 const mask_t allEffectAt(Player P, Ptype ptype, Square target) const;
00298 template <Ptype PTYPE> const mask_t longEffectAt(Square target) const
00299 {
00300 return effectSetAt(target).selectLong<PTYPE>() >> 8;
00301 }
00302 template <Ptype PTYPE> const mask_t longEffectAt(Square target, Player owner) const
00303 {
00304 return longEffectAt<PTYPE>(target) & piecesOnBoard(owner).getMask(1);
00305 }
00306 const mask_t longEffectAt(Square target) const
00307 {
00308 return effectSetAt(target).selectLong() >> 8;
00309 }
00310 const mask_t longEffectAt(Square target, Player owner) const
00311 {
00312 return longEffectAt(target) & piecesOnBoard(owner).getMask(1);
00313 }
00314
00315
00316
00317
00323 template<Player P>
00324 bool hasEffectAt(Square target) const {
00325 assert(target.isOnBoard());
00326 mask_t mask=effectSetAt(target).getMask(1);
00327 mask&=NumBitmapEffect::playerEffectMask<P>();
00328 return !mask.none();
00329 }
00335 bool hasEffectAt(Player player,Square target) const {
00336 assert(target.isOnBoard());
00337 mask_t mask=effectSetAt(target).getMask(1);
00338 mask&=NumBitmapEffect::playerEffectMask(player);
00339 return !mask.none();
00340 }
00341
00345 template <Ptype PTYPE>
00346 bool hasLongEffectAt(Player P, Square to) const {
00347 static_assert((PTYPE == LANCE || PTYPE == BISHOP || PTYPE == ROOK), "ptype");
00348 return longEffectAt<PTYPE>(to, P).any();
00349 }
00350
00354 template <Ptype PTYPE>
00355 bool hasEffectByPtype(Player attack, Square target) const
00356 {
00357 return allEffectAt<PTYPE>(attack, target).any();
00358 }
00362 template <Ptype PTYPE>
00363 bool hasEffectByPtypeStrict(Player attack, Square target) const
00364 {
00365 mask_t mask=allEffectAt<PTYPE>(attack, target);
00366 if (isPromoted(PTYPE))
00367 mask &= promoted.getMask<PTYPE>();
00368 else
00369 mask &= ~(promoted.getMask<PTYPE>());
00370 return mask.any();
00371 }
00376 template<Direction Dir,Player P>
00377 bool hasEffectInDirection(Square to) const {
00378 static_assert((DirectionTraits<Dir>::isLong), "Dir");
00379 const PieceMask& pieces_onboard=piecesOnBoard(P);
00380 mask_t mask1=pieces_onboard.getMask(1);
00381 mask1 &= ((PtypeDirectionTraits<LANCE,Dir>::canMove
00382 ? mask_t::makeDirect(PtypeFuns<LANCE>::indexMask)
00383 : mask_t::makeDirect(0))
00384 | (PtypeDirectionTraits<BISHOP,Dir>::canMove
00385 ? mask_t::makeDirect(PtypeFuns<BISHOP>::indexMask)
00386 : mask_t::makeDirect(0))
00387 | (PtypeDirectionTraits<ROOK,Dir>::canMove
00388 ? mask_t::makeDirect(PtypeFuns<ROOK>::indexMask)
00389 : mask_t::makeDirect(0)));
00390 mask1 <<= 8;
00391
00392 mask1&=effectSetAt(to).getMask(1)& NumBitmapEffect::longEffectMask();
00393 while (mask1.any())
00394 {
00395 int num=mask1.takeOneBit()+NumBitmapEffect::longToNumOffset;
00396 Square from = pieceOf(num).square();
00397 Direction dir=Board_Table.getLongDirection<BLACK>(Offset32(to,from));
00398 if (dir==DirectionPlayerTraits<Dir,P>::directionByBlack)
00399 return true;
00400 }
00401 return false;
00402 }
00409 bool hasEffectNotBy(Player player,Piece piece,Square target) const {
00410 assert(piece.owner()==player);
00411 PieceMask pieces_onboard=piecesOnBoard(player);
00412 int num=piece.number();
00413 pieces_onboard.reset(num);
00414 return (pieces_onboard&effectSetAt(target)).any();
00415 }
00419 bool hasEffectByNotPinnedAndKing(Player pl,Square target) const{
00420 assert(target.isOnBoard());
00421 PieceMask m=piecesOnBoard(pl)& ~pinOrOpen(pl) & effectSetAt(target);
00422 m.clearBit<KING>();
00423 return m.any();
00424 }
00428 bool hasEffectByNotPinned(Player pl,Square target) const{
00429 assert(target.isOnBoard());
00430 PieceMask m=piecesOnBoard(pl)& ~pinOrOpen(pl) & effectSetAt(target);
00431 return m.any();
00432 }
00439 bool hasMultipleEffectAt(Player player,Square target) const
00440 {
00441 mask_t mask=effectSetAt(target).getMask(1);
00442 mask&=NumBitmapEffect::playerEffectMask(player);
00443 return NumBitmapEffect::playerEffect(player).getMask(1) < mask;
00444 }
00445
00450 bool hasEffectByPiece(Piece attack, Square target) const
00451 {
00452 assert(attack.isPiece());
00453 assert(target.isOnBoard());
00454 return effectSetAt(target).test(attack.number());
00455 }
00456
00457
00465 bool hasEffectIf(PtypeO ptypeo,Square attacker,
00466 Square target) const
00467 #ifdef __GNUC__
00468 __attribute__ ((pure))
00469 #endif
00470 {
00471 Offset32 offset32=Offset32(target,attacker);
00472 EffectContent effect=Ptype_Table.getEffect(ptypeo,offset32);
00473 if (! effect.hasEffect())
00474 return false;
00475 if (effect.hasUnblockableEffect())
00476 return true;
00477 assert(Board_Table.getShortOffset(offset32) == effect.offset());
00478 return this->isEmptyBetween(attacker,target,effect.offset());
00479 }
00483 template<Player P>
00484 bool
00485 #ifdef __GNUC__
00486 __attribute__ ((pure))
00487 #endif
00488 hasEffectByWithRemove(Square target,Square removed) const;
00489
00490 bool hasEffectByWithRemove(Player player, Square target,Square removed) const{
00491 if (player==BLACK)
00492 return hasEffectByWithRemove<BLACK>(target,removed);
00493 else
00494 return hasEffectByWithRemove<WHITE>(target,removed);
00495 }
00496
00497
00498
00499
00500
00502 template <Ptype PTYPE>
00503 const Piece findAttackAt(Player attack, Square target) const
00504 {
00505 mask_t mask=allEffectAt<PTYPE>(attack, target);
00506 if (mask.none())
00507 return Piece::EMPTY();
00508 return pieceOf(mask.takeOneBit()+PtypeFuns<PTYPE>::indexNum*32);
00509 }
00510 template <Ptype PTYPE>
00511 const Piece findAttackAtStrict(Player attack, Square target) const
00512 {
00513 mask_t mask=allEffectAt<PTYPE>(attack, target);
00514 if (isPromoted(PTYPE))
00515 mask &= promoted.getMask<PTYPE>();
00516 else
00517 mask &= ~(promoted.getMask<PTYPE>());
00518 if (mask.none())
00519 return Piece::EMPTY();
00520 return pieceOf(mask.takeOneBit()+PtypeFuns<PTYPE>::indexNum*32);
00521 }
00526 const Piece findLongAttackAt(Player owner, int piece, Direction d) const
00527 {
00528 assert(pieceOf(piece).isOnBoardByOwner(owner));
00529 if (owner == BLACK)
00530 d = inverse(d);
00531 const int num = effects.effectedNumTable[piece][d];
00532 if (num == EMPTY_NUM)
00533 return Piece::EMPTY();
00534 return pieceOf(num);
00535 }
00536 const Piece findLongAttackAt(Player owner, Piece piece, Direction d) const
00537 {
00538 assert(piece.isPiece());
00539 assert(piece.owner() == owner);
00540 return findLongAttackAt(owner, piece.number(), d);
00541 }
00542 const Piece findLongAttackAt(Piece piece, Direction d) const
00543 {
00544 assert(piece.isPiece());
00545 return findLongAttackAt(piece.owner(), piece, d);
00546 }
00547 const Piece findLongAttackAt(Square square, Direction d) const
00548 {
00549 return findLongAttackAt(pieceOnBoard(square), d);
00550 }
00554 const Piece selectCheapPiece(PieceMask effect) const;
00560 const Piece findCheapAttack(Player P, Square square) const
00561 {
00562 return selectCheapPiece(piecesOnBoard(P) & effectSetAt(square));
00563 }
00569 const Piece findCheapAttackNotBy(Player P, Square square, const PieceMask& ignore) const
00570 {
00571 PieceMask pieces = piecesOnBoard(P);
00572 pieces &= ~ignore;
00573 return selectCheapPiece(pieces & effectSetAt(square));
00574 }
00575 const Piece findAttackNotBy(Player P, Square square, const PieceMask& ignore) const
00576 {
00577 PieceMask pieces = piecesOnBoard(P);
00578 pieces &= ~ignore;
00579 pieces &= effectSetAt(square);
00580 if (pieces.none())
00581 return Piece::EMPTY();
00582 return pieceOf(pieces.takeOneBit());
00583 }
00592 template<Player P>
00593 bool findCheckPiece(Piece& attack_piece) const
00594 {
00595 return hasEffectAt<alt(P)>(kingSquare(P),attack_piece);
00596 }
00597 bool hasEffectAt(Player P, Square target,Piece& attackerPiece) const
00598 {
00599 if (P == BLACK)
00600 return hasEffectAt<BLACK>(target, attackerPiece);
00601 else
00602 return hasEffectAt<WHITE>(target, attackerPiece);
00603 }
00610 template<Player P>
00611 bool hasEffectAt(Square target,Piece& attackerPiece) const {
00612 attackerPiece=Piece::EMPTY();
00613 const PieceMask& pieceMask=piecesOnBoard(P)&effectSetAt(target);
00614 mask_t mask=pieceMask.getMask(0);
00615 if (mask.none()) return false;
00620 if (mask.hasMultipleBit())
00621 return true;
00622 int num=mask.bsf();
00623 attackerPiece=pieceOf(num);
00624 return true;
00625 }
00626
00627
00628
00629
00630
00631 bool isSafeMove(Move move) const;
00632 bool isCheck(Move move) const;
00633 bool isPawnDropCheckmate(Move move) const;
00634 bool isDirectCheck(Move move) const;
00635 bool isOpenCheck(Move move) const;
00636
00637
00648 template <bool show_error>
00649 bool isAlmostValidMove(Move move) const;
00650 bool isAlmostValidMove(Move move,bool show_error=true) const;
00651
00657 void generateLegal(MoveVector&) const;
00663 void generateWithFullUnpromotions(MoveVector&) const;
00665 void generateAllUnsafe(MoveVector&) const;
00666
00667 void makeMove(Move move);
00668 void makeMovePass()
00669 {
00670 changeTurn();
00671 effects.clearChangedEffects();
00672 effects.clearEffectedChanged();
00673 }
00674
00675 template <class Function>
00676 void makeUnmakePass(Function &f)
00677 {
00678 changeTurn();
00679 f(Square::STAND());
00680 changeTurn();
00681 }
00682 template <class Function>
00683 void makeUnmakeMove(Move move, Function &f)
00684 {
00685 if (move.player() == BLACK)
00686 makeUnmakeMove(Player2Type<BLACK>(), move, f);
00687 else
00688 makeUnmakeMove(Player2Type<WHITE>(), move, f);
00689 }
00690 template <Player P, class Function>
00691 void makeUnmakeMove(Player2Type<P> player, Move move, Function &f)
00692 {
00693 if (move.isPass())
00694 return makeUnmakePass(f);
00695 assert(move.isValid());
00696 assert(isAlmostValidMove(move));
00697 assert(P == move.player());
00698 assert(P == turn());
00699 Square from=move.from();
00700 Square to=move.to();
00701 if (from.isPieceStand())
00702 {
00703 assert(pieceAt(to) == Piece::EMPTY());
00704 doUndoDropMove(player,to,move.ptype(),f);
00705 }
00706 else
00707 {
00708 assert(pieceAt(from) != Piece::EMPTY());
00709 Piece captured=pieceAt(to);
00710 if (captured != Piece::EMPTY())
00711 {
00712 doUndoCaptureMove(player,from,to,captured,move.promoteMask(),f);
00713 }
00714 else
00715 {
00716 doUndoSimpleMove(player,from,to,move.promoteMask(),f);
00717 }
00718 }
00719 }
00720 bool wasCheckEvasion(Move last_move) const;
00721
00722
00723
00726 template<Player P,Ptype T,typename F>
00727 void forEachOnBoard(F& func) const {
00728 mask_t onMask=piecesOnBoard(P).template selectBit<T>() ;
00729 while (onMask.any())
00730 {
00731 int num=onMask.takeOneBit()+((PtypeFuns<T>::indexNum)<<5);
00732 Piece p = pieceOf(num);
00733 func(p);
00734 }
00735 }
00738 template<Player P,Ptype T,typename F>
00739 void forEachOnBoardPtypeStrict(F& func) const
00740 {
00741 mask_t mask=piecesOnBoard(P).template selectBit<T>() ;
00742 if (isPromoted(T))
00743 mask &= promoted.getMask<T>();
00744 else
00745 mask &= ~(promoted.getMask<T>());
00746 while (mask.any())
00747 {
00748 int num=mask.takeOneBit()+((PtypeFuns<T>::indexNum)<<5);
00749 func(pieceOf(num));
00750 }
00751 }
00752 private:
00753 template<Player P,class Action>
00754 void forEachEffect(const PieceMask& pieces, Square sq,Action & action) const
00755 {
00756 #if OSL_WORDSIZE == 64
00757 mask_t mask=pieces.getMask(0);
00758 while (mask.any())
00759 {
00760 const int num=mask.takeOneBit();
00761 action.template doAction<P>(pieceOf(num),sq);
00762 }
00763 #elif OSL_WORDSIZE == 32
00764 mask_t mask0=pieces.getMask(0);
00765 while (mask0.any())
00766 {
00767 const int num=mask0.takeOneBit();
00768 action.template doAction<P>(pieceOf(num),sq);
00769 }
00770 mask_t mask1=pieces.getMask(1);
00771 while (mask1.any())
00772 {
00773 const int num=mask1.takeOneBit()+32;
00774 action.template doAction<P>(pieceOf(num),sq);
00775 }
00776 #endif
00777 }
00778 public:
00783 template<Player P,class Action>
00784 void forEachEffect(Square sq,Action & action) const
00785 {
00786 const PieceMask pieceMask=piecesOnBoard(P)&effectSetAt(sq);
00787 forEachEffect<P,Action>(pieceMask, sq, action);
00788 }
00794 template<Player P,class Action>
00795 void forEachEffect(Square sq,Action & action,const PieceMask& pin) const
00796 {
00797 PieceMask pieceMask=piecesOnBoard(P)&effectSetAt(sq);
00798 pieceMask &= ~pin;
00799 forEachEffect<P,Action>(pieceMask, sq, action);
00800 }
00801
00807 template<Player P,class Action>
00808 void forEachEffectNotBy(Square sq,Piece piece,Action & action) const {
00809 PieceMask pieces=piecesOnBoard(P)&effectSetAt(sq);
00810 pieces.reset(piece.number());
00811 forEachEffect<P,Action>(pieces, sq, action);
00812 }
00813
00814 private:
00815 template<Player P,Ptype Type,class Action,Direction Dir>
00816 void forEachEffectOfPieceDir(Square, Action&, Int2Type<false>) const {}
00817 template<Player P,Ptype Type,class Action,Direction Dir>
00818 void forEachEffectOfPieceDir(Square pieceSquare,Action & action,Int2Type<true>) const {
00819 const Offset offset=DirectionPlayerTraits<Dir,P>::offset();
00820 action.template doAction<P>(this->pieceAt(pieceSquare),pieceSquare+offset);
00821 }
00822
00823 template<Player P,Ptype Type,class Action,Direction Dir>
00824 void forEachEffectOfPieceDir(Square pieceSquare,Action & action) const {
00825 forEachEffectOfPieceDir<P,Type,Action,Dir>(pieceSquare,action,Int2Type<(PtypeTraits<Type>::moveMask & DirectionTraits<Dir>::mask)!=0>());
00826 }
00827 template<Player P,Ptype Type,class Action,Direction Dir>
00828 void forEachEffectOfPieceLongDir(Square, Action&, Int2Type<false>) const {}
00829 template<Player P,Ptype Type,class Action,Direction Dir>
00830 void forEachEffectOfPieceLongDir(Square pieceSquare,Action & action,Int2Type<true>) const {
00831 Piece piece=this->pieceAt(pieceSquare);
00832 const Offset offset=DirectionPlayerTraits<Dir,P>::offset();
00833 assert(offset.intValue() != 35);
00834 Square sq=pieceSquare+offset;
00835 for (;this->pieceAt(sq).isEmpty();sq+=offset)
00836 action.template doAction<P>(piece,sq);
00837 action.template doAction<P>(piece,sq);
00838 }
00839
00840 template<Player P,Ptype Type,class Action,Direction Dir>
00841 void forEachEffectOfPieceLongDir(Square pieceSquare,Action & action) const {
00842 forEachEffectOfPieceLongDir<P,Type,Action,Dir>(pieceSquare,action,Int2Type<(PtypeTraits<Type>::moveMask & DirectionTraits<Dir>::mask)!=0>());
00843 }
00844 public:
00852 template<Player P,Ptype Type,class Action>
00853 void forEachEffectOfPiece(Square pieceSquare,Action & action) const;
00854 template<class Action>
00855 void forEachEffectOfPiece(Piece piece,Action & action) const;
00856
00862 template <class Function, bool InterestEmpty>
00863 void forEachEffectOfPtypeO(Square, PtypeO, Function& f) const;
00864 template <Player P, class Function, bool InterestEmpty>
00865 void forEachEffectOfPtypeO(Square, Ptype, Function& f) const;
00866
00873 template <Player P>
00874 Piece safeCaptureNotByKing(Square target, Piece king) const;
00875 Piece safeCaptureNotByKing(Player P, Square target) const {
00876 const Piece king = kingPiece(P);
00877 if (P == BLACK)
00878 return this->safeCaptureNotByKing<BLACK>(target, king);
00879 else
00880 return this->safeCaptureNotByKing<WHITE>(target, king);
00881 }
00887 template <class Action>
00888 void forEachEffect(Player P, Square pos, Action& a) const {
00889 if (P == BLACK)
00890 this->template forEachEffect<BLACK>(pos,a);
00891 else
00892 this->template forEachEffect<WHITE>(pos,a);
00893 }
00897 void findEffect(Player P, Square target, PieceVector& out) const;
00898
00899 private:
00900 void doSimpleMove(Square from, Square to, int promoteMask);
00901 void doDropMove(Square to,Ptype ptype);
00902 void doCaptureMove(Square from, Square to, Piece target,int promoteMask);
00903
00904 template <Player P, class Function>
00905 void doUndoSimpleMove(Player2Type<P> player,
00906 Square from, Square to, int promoteMask,Function& func);
00907 template <Player P>
00908 void prologueSimple(Player2Type<P>, Square from, Square to, int promoteMask,
00909 Piece& oldPiece, int& num,
00910 PtypeO& oldPtypeO, PtypeO& new_ptypeo,
00911 CArray<PieceMask,2>& pin_or_open_backup,
00912 KingMobility& king_mobility_backup,
00913 PieceMask& promoted_backup,
00914 CArray<PieceMask,2>& effected_mask_backup,
00915 CArray<PieceMask,2>& effected_changed_mask_backup,
00916 CArray<uint64_t,2>& king8infos_backup,
00917 MobilityTable &mobility_backup
00918 );
00919 void epilogueSimple(Square from, Square to, Piece oldPiece,
00920 int num, PtypeO oldPtypeO, PtypeO newPtypeO,
00921 const CArray<PieceMask,2>& pin_or_open_backup,
00922 const KingMobility& king_mobility_backup,
00923 const PieceMask& promoted_backup,
00924 const CArray<PieceMask,2>& effected_mask_backup,
00925 const CArray<PieceMask,2>& effected_changed_mask_backup,
00926 const CArray<uint64_t,2>& king8infos_backup,
00927 const MobilityTable &mobility_backup
00928 );
00929 template <Player P, class Function>
00930 void doUndoDropMove(Player2Type<P> player,
00931 Square to, Ptype ptype, Function& func);
00932 template <Player P>
00933 void prologueDrop(Player2Type<P>, Square to, Ptype ptype,
00934 Piece& oldPiece, int& num, PtypeO& ptypeO,
00935 int& numIndex, mask_t& numMask,
00936 CArray<PieceMask,2>& pin_or_open_backup,
00937 KingMobility& king_mobility_backup,
00938 CArray<PieceMask,2>& effected_mask_backup,
00939 CArray<PieceMask,2>& effected_changed_mask_backup,
00940 CArray<uint64_t,2>& king8infos_backup,
00941 MobilityTable &mobility_backup);
00942 template<Player P>
00943 void epilogueDrop(Player2Type<P>, Square to, Ptype ptype, Piece oldPiece,
00944 int num, PtypeO ptypeO, int numIndex, mask_t numMask,
00945 const CArray<PieceMask,2>& pin_or_open_backup,
00946 const KingMobility& king_mobility_backup,
00947 const CArray<PieceMask,2>& effected_mask_backup,
00948 const CArray<PieceMask,2>& effected_changed_mask_backup,
00949 const CArray<uint64_t,2>& king8infos_backup,
00950 const MobilityTable &mobility_backup);
00951 template <Player P, class Function>
00952 void doUndoCaptureMove(Player2Type<P> player, Square from,Square to,
00953 Piece target, int promoteMask,Function& func);
00954
00955 template<Player P>
00956 void prologueCapture(Player2Type<P>, Square from, Square to, Piece target,
00957 int promoteMask,
00958 Piece& oldPiece, PtypeO& oldPtypeO, PtypeO& capturePtypeO,
00959 PtypeO& new_ptypeo, int& num0, int& num1,
00960 int& num1Index, mask_t& num1Mask,
00961 CArray<PieceMask,2>& pin_or_open_backup,
00962 KingMobility& king_mobility_backup,
00963 PieceMask& promoted_backup,
00964 CArray<PieceMask,2>& effected_mask_backup,
00965 CArray<PieceMask,2>& effected_changed_mask_backup,
00966 CArray<uint64_t,2>& king8infos_backup,
00967 MobilityTable &mobility_backup);
00968
00969 template<Player P>
00970 void epilogueCapture(Player2Type<P>, Square from, Square to, Piece target,
00971 Piece oldPiece, PtypeO oldPtypeO, PtypeO capturePtypeO,
00972 PtypeO newPtypeO, int num0, int num1,
00973 int num1Index, mask_t num1Mask,
00974 const CArray<PieceMask,2>& pin_or_open_backup,
00975 const KingMobility& king_mobility_backup,
00976 const PieceMask& promoted_backup,
00977 const CArray<PieceMask,2>& effected_mask_backup,
00978 const CArray<PieceMask,2>& effected_changed_mask_backup,
00979 const CArray<uint64_t,2>& king8infos_backup,
00980 const MobilityTable &mobility_backup);
00981
00982 template<Direction DIR>
00983 void makePinOpenDir(Square target,
00984 PieceMask& pins, PieceMask const& onBoard,Player defense)
00985 {
00986 const Offset offset = DirectionTraits<DIR>::blackOffset();
00987 Square sq=target-offset;
00988 int num;
00989 while(Piece::isEmptyNum(num=pieceAt(sq).number()))
00990 sq-=offset;
00991 king_mobility[defense][DIR]=static_cast<unsigned char>(sq.uintValue());
00992 if(Piece::isEdgeNum(num)) return;
00993 int num1=longEffectNumTable()[num][DIR];
00994 if(Piece::isPieceNum(num1) && onBoard.test(num1)){
00995 pins.set(num);
00996 }
00997 }
00998 void recalcPinOpen(Square changed, Direction &lastDir, Player defense)
00999 {
01000 Square target=kingSquare(defense);
01001 #ifdef ALLOW_KING_ABSENCE
01002 if (target.isPieceStand())
01003 return;
01004 #endif
01005 const Direction longD=Board_Table.getLongDirection<BLACK>(changed,target);
01006 if(!isLong(longD) || (lastDir!=UL && longD==lastDir)) return;
01007 lastDir=longD;
01008 Direction shortD=longToShort(longD);
01009 {
01010
01011 Square oldPos=Square::makeDirect(king_mobility[defense][shortD]);
01012 int oldNum=pieceAt(oldPos).number();
01013 if(Piece::isPieceNum(oldNum))
01014 pin_or_open[defense].reset(oldNum);
01015 }
01016 const Offset offset = Board_Table.getOffsetForBlack(longD);
01017 Square sq=target-offset;
01018 int num;
01019 while(Piece::isEmptyNum(num=pieceAt(sq).number()))
01020 sq-=offset;
01021 king_mobility[defense][shortD]=static_cast<unsigned char>(sq.uintValue());
01022 if(Piece::isEdgeNum(num)) return;
01023 int num1=longEffectNumTable()[num][shortD];
01024 if(Piece::isPieceNum(num1) && piecesOnBoard(alt(defense)).test(num1)){
01025 pin_or_open[defense].set(num);
01026 }
01027 }
01028 PieceMask makePinOpen(Square target,Player defense);
01029 void makePinOpen(Player defense);
01030 template<Player P>
01031 void makeKing8Info();
01032 };
01033
01034 inline bool operator!=(const NumEffectState& s1, const NumEffectState& s2)
01035 {
01036 return !(s1==s2);
01037 }
01038 }
01039
01040 template <osl::Player P, typename Function>
01041 void osl::NumEffectState::
01042 doUndoSimpleMove(Player2Type<P> player,
01043 Square from, Square to, int promoteMask, Function& func)
01044 {
01045 Piece oldPiece;
01046 int num;
01047 PtypeO oldPtypeO, newPtypeO;
01048 CArray<PieceMask,2> pin_or_open_backup;
01049 KingMobility king_mobility_backup;
01050 PieceMask promoted_backup;
01051 CArray<PieceMask,2> effected_mask_backup;
01052 CArray<PieceMask,2> effected_changed_mask_backup;
01053 CArray<uint64_t,2> king8infos_backup;
01054 MobilityTable mobility_backup;
01055 prologueSimple(player, from, to, promoteMask, oldPiece, num, oldPtypeO, newPtypeO,
01056 pin_or_open_backup,
01057 king_mobility_backup,
01058 promoted_backup,
01059 effected_mask_backup, effected_changed_mask_backup,
01060 king8infos_backup,
01061 mobility_backup);
01062 if (promoteMask!=0 && num < PtypeTraits<PAWN>::indexLimit)
01063 {
01064 clearPawn(P,from);
01065 changeTurn();
01066 func(to);
01067 changeTurn();
01068 setPawn(P,from);
01069 }
01070 else
01071 {
01072 changeTurn();
01073 func(to);
01074 changeTurn();
01075 }
01076 epilogueSimple(from, to, oldPiece, num, oldPtypeO, newPtypeO,
01077 pin_or_open_backup,
01078 king_mobility_backup,
01079 promoted_backup, effected_mask_backup, effected_changed_mask_backup,
01080 king8infos_backup,
01081 mobility_backup);
01082 }
01083
01084 template <osl::Player P, typename Function>
01085 void osl::NumEffectState::doUndoDropMove(Player2Type<P> player,
01086 Square to, Ptype ptype, Function& func)
01087 {
01088 Piece oldPiece;
01089 PtypeO ptypeO;
01090 int num, numIndex;
01091 mask_t numMask;
01092 CArray<PieceMask,2> pin_or_open_backup;
01093 KingMobility king_mobility_backup;
01094 CArray<PieceMask,2> effected_mask_backup;
01095 CArray<PieceMask,2> effected_changed_mask_backup;
01096 CArray<uint64_t,2> king8infos_backup;
01097 MobilityTable mobility_backup;
01098 prologueDrop(player, to, ptype, oldPiece, num, ptypeO, numIndex, numMask,
01099 pin_or_open_backup, king_mobility_backup,
01100 effected_mask_backup,effected_changed_mask_backup,
01101 king8infos_backup,
01102 mobility_backup);
01103 if (ptype==PAWN)
01104 {
01105 setPawn(P,to);
01106 changeTurn();
01107 func(to);
01108 changeTurn();
01109 clearPawn(P,to);
01110 }
01111 else
01112 {
01113 changeTurn();
01114 func(to);
01115 changeTurn();
01116 }
01117 epilogueDrop(player, to, ptype, oldPiece, num, ptypeO, numIndex, numMask,
01118 pin_or_open_backup, king_mobility_backup,
01119 effected_mask_backup,effected_changed_mask_backup,
01120 king8infos_backup,
01121 mobility_backup);
01122 }
01123
01124 template <osl::Player P, typename Function>
01125 void osl::NumEffectState::doUndoCaptureMove(Player2Type<P> player,
01126 Square from,Square to, Piece target,
01127 int promoteMask,Function& func)
01128 {
01129 Piece oldPiece;
01130 PtypeO oldPtypeO, capturePtypeO, newPtypeO;
01131 int num0, num1, num1Index;
01132 mask_t num1Mask;
01133 CArray<PieceMask,2> pin_or_open_backup;
01134 KingMobility king_mobility_backup;
01135 PieceMask promoted_backup;
01136 CArray<PieceMask,2> effected_mask_backup;
01137 CArray<PieceMask,2> effected_changed_mask_backup;
01138 CArray<uint64_t,2> king8infos_backup;
01139 MobilityTable mobility_backup;
01140 prologueCapture(player, from, to, target, promoteMask, oldPiece, oldPtypeO,
01141 capturePtypeO, newPtypeO, num0, num1, num1Index,num1Mask,
01142 pin_or_open_backup, king_mobility_backup,
01143 promoted_backup,
01144 effected_mask_backup, effected_changed_mask_backup,
01145 king8infos_backup,
01146 mobility_backup);
01147
01148 changeTurn();
01149 const Ptype capturePtype=target.ptype();
01150 if (capturePtype==PAWN)
01151 {
01152 clearPawn(alt(P),to);
01153 if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
01154 {
01155 clearPawn(P,from);
01156 func(to);
01157 setPawn(P,from);
01158 }
01159 else
01160 {
01161 func(to);
01162 }
01163 setPawn(alt(P),to);
01164 }
01165 else if (promoteMask!=0 && num0<PtypeTraits<PAWN>::indexLimit)
01166 {
01167 clearPawn(P,from);
01168 func(to);
01169 setPawn(P,from);
01170 }
01171 else
01172 {
01173 func(to);
01174 }
01175 changeTurn();
01176
01177 epilogueCapture(player, from, to, target, oldPiece, oldPtypeO, capturePtypeO, newPtypeO,
01178 num0, num1, num1Index,num1Mask,
01179 pin_or_open_backup, king_mobility_backup,
01180 promoted_backup,effected_mask_backup, effected_changed_mask_backup,
01181 king8infos_backup,
01182 mobility_backup);
01183 }
01184
01185 template <class Action>
01186 void osl::NumEffectState::
01187 forEachEffectOfPiece(Piece piece,Action & action) const
01188 {
01189 Square pieceSquare = piece.square();
01190 switch ((int)piece.ptypeO()) {
01191 case NEW_PTYPEO(WHITE,PAWN): forEachEffectOfPiece<WHITE,PAWN,Action>(pieceSquare,action); break;
01192 case NEW_PTYPEO(WHITE,LANCE): forEachEffectOfPiece<WHITE,LANCE,Action>(pieceSquare,action); break;
01193 case NEW_PTYPEO(WHITE,KNIGHT): forEachEffectOfPiece<WHITE,KNIGHT,Action>(pieceSquare,action); break;
01194 case NEW_PTYPEO(WHITE,SILVER): forEachEffectOfPiece<WHITE,SILVER,Action>(pieceSquare,action); break;
01195 case NEW_PTYPEO(WHITE,PPAWN): forEachEffectOfPiece<WHITE,PPAWN,Action>(pieceSquare,action); break;
01196 case NEW_PTYPEO(WHITE,PLANCE): forEachEffectOfPiece<WHITE,PLANCE,Action>(pieceSquare,action); break;
01197 case NEW_PTYPEO(WHITE,PKNIGHT): forEachEffectOfPiece<WHITE,PKNIGHT,Action>(pieceSquare,action); break;
01198 case NEW_PTYPEO(WHITE,PSILVER): forEachEffectOfPiece<WHITE,PSILVER,Action>(pieceSquare,action); break;
01199 case NEW_PTYPEO(WHITE,GOLD): forEachEffectOfPiece<WHITE,GOLD,Action>(pieceSquare,action); break;
01200 case NEW_PTYPEO(WHITE,BISHOP): forEachEffectOfPiece<WHITE,BISHOP,Action>(pieceSquare,action); break;
01201 case NEW_PTYPEO(WHITE,PBISHOP): forEachEffectOfPiece<WHITE,PBISHOP,Action>(pieceSquare,action); break;
01202 case NEW_PTYPEO(WHITE,ROOK): forEachEffectOfPiece<WHITE,ROOK,Action>(pieceSquare,action); break;
01203 case NEW_PTYPEO(WHITE,PROOK): forEachEffectOfPiece<WHITE,PROOK,Action>(pieceSquare,action); break;
01204 case NEW_PTYPEO(WHITE,KING): forEachEffectOfPiece<WHITE,KING,Action>(pieceSquare,action); break;
01205 case NEW_PTYPEO(BLACK,PAWN): forEachEffectOfPiece<BLACK,PAWN,Action>(pieceSquare,action); break;
01206 case NEW_PTYPEO(BLACK,LANCE): forEachEffectOfPiece<BLACK,LANCE,Action>(pieceSquare,action); break;
01207 case NEW_PTYPEO(BLACK,KNIGHT): forEachEffectOfPiece<BLACK,KNIGHT,Action>(pieceSquare,action); break;
01208 case NEW_PTYPEO(BLACK,SILVER): forEachEffectOfPiece<BLACK,SILVER,Action>(pieceSquare,action); break;
01209 case NEW_PTYPEO(BLACK,PPAWN): forEachEffectOfPiece<BLACK,PPAWN,Action>(pieceSquare,action); break;
01210 case NEW_PTYPEO(BLACK,PLANCE): forEachEffectOfPiece<BLACK,PLANCE,Action>(pieceSquare,action); break;
01211 case NEW_PTYPEO(BLACK,PKNIGHT): forEachEffectOfPiece<BLACK,PKNIGHT,Action>(pieceSquare,action); break;
01212 case NEW_PTYPEO(BLACK,PSILVER): forEachEffectOfPiece<BLACK,PSILVER,Action>(pieceSquare,action); break;
01213 case NEW_PTYPEO(BLACK,GOLD): forEachEffectOfPiece<BLACK,GOLD,Action>(pieceSquare,action); break;
01214 case NEW_PTYPEO(BLACK,BISHOP): forEachEffectOfPiece<BLACK,BISHOP,Action>(pieceSquare,action); break;
01215 case NEW_PTYPEO(BLACK,PBISHOP): forEachEffectOfPiece<BLACK,PBISHOP,Action>(pieceSquare,action); break;
01216 case NEW_PTYPEO(BLACK,ROOK): forEachEffectOfPiece<BLACK,ROOK,Action>(pieceSquare,action); break;
01217 case NEW_PTYPEO(BLACK,PROOK): forEachEffectOfPiece<BLACK,PROOK,Action>(pieceSquare,action); break;
01218 case NEW_PTYPEO(BLACK,KING): forEachEffectOfPiece<BLACK,KING,Action>(pieceSquare,action); break;
01219 default: assert(0);
01220 }
01221 }
01222
01223 template <osl::Player P, osl::Ptype Type, class Action>
01224 void osl::NumEffectState::
01225 forEachEffectOfPiece(Square pieceSquare,Action & action) const
01226 {
01227 forEachEffectOfPieceDir<P,Type,Action,UL>(pieceSquare,action);
01228 forEachEffectOfPieceDir<P,Type,Action,U>(pieceSquare,action);
01229 forEachEffectOfPieceDir<P,Type,Action,UR>(pieceSquare,action);
01230 forEachEffectOfPieceDir<P,Type,Action,L>(pieceSquare,action);
01231 forEachEffectOfPieceDir<P,Type,Action,R>(pieceSquare,action);
01232 forEachEffectOfPieceDir<P,Type,Action,DL>(pieceSquare,action);
01233 forEachEffectOfPieceDir<P,Type,Action,D>(pieceSquare,action);
01234 forEachEffectOfPieceDir<P,Type,Action,DR>(pieceSquare,action);
01235 forEachEffectOfPieceDir<P,Type,Action,UUL>(pieceSquare,action);
01236 forEachEffectOfPieceDir<P,Type,Action,UUR>(pieceSquare,action);
01237 forEachEffectOfPieceLongDir<P,Type,Action,LONG_UL>(pieceSquare,action);
01238 forEachEffectOfPieceLongDir<P,Type,Action,LONG_U>(pieceSquare,action);
01239 forEachEffectOfPieceLongDir<P,Type,Action,LONG_UR>(pieceSquare,action);
01240 forEachEffectOfPieceLongDir<P,Type,Action,LONG_L>(pieceSquare,action);
01241 forEachEffectOfPieceLongDir<P,Type,Action,LONG_R>(pieceSquare,action);
01242 forEachEffectOfPieceLongDir<P,Type,Action,LONG_DL>(pieceSquare,action);
01243 forEachEffectOfPieceLongDir<P,Type,Action,LONG_D>(pieceSquare,action);
01244 forEachEffectOfPieceLongDir<P,Type,Action,LONG_DR>(pieceSquare,action);
01245 }
01246
01247 #include "osl/bits/pieceStand.h"
01248 #endif
01249
01250
01251
01252