00001 #ifndef OSL_BASIC_TYPE_H
00002 #define OSL_BASIC_TYPE_H
00003 #include "osl/config.h"
00004 #include <type_traits>
00005 #include <cassert>
00006 #include <iosfwd>
00007 namespace osl{
00008 enum Player{
00009 BLACK=0,
00010 WHITE= -1
00011 };
00012
00013 constexpr Player alt(Player player){
00014 return static_cast<Player>(-1-static_cast<int>(player));
00015 }
00016 constexpr int playerToIndex(Player player){
00017 return -static_cast<int>(player);
00018 }
00019 constexpr Player indexToPlayer(int n) {
00020
00021 return static_cast<Player>(-n);
00022 }
00023 constexpr int sign(Player player){
00024
00025
00026 return 1+(static_cast<int>(player)<<1);
00027 }
00028 constexpr int playerToMask(Player player){
00029 return static_cast<int>(player);
00030 }
00031
00032
00033
00034 int operator+(Player, int); int operator+(int, Player);
00035 int operator-(Player, int); int operator-(int, Player);
00036 int operator*(Player, int); int operator*(int, Player);
00037 int operator/(Player, int); int operator/(int, Player);
00038
00042 bool isValid(Player player);
00043 #if 0
00044 template<Player P>
00045 struct PlayerTraits;
00046
00047 template<>
00048 struct PlayerTraits<BLACK>{
00049 static const int offsetMul=1;
00050 static const int index=0;
00051 static const int mask=0;
00052 static const Player opponent=WHITE;
00053 };
00054
00055 template<>
00056 struct PlayerTraits<WHITE>{
00057 static const int offsetMul=-1;
00058 static const int index=1;
00059 static const int mask= -1;
00060 static const Player opponent=BLACK;
00061 };
00062 #endif
00063 std::ostream& operator<<(std::ostream& os,Player player);
00064
00065 namespace misc
00066 {
00067
00068 template<int v>
00069 struct Int2Type{ enum { value=v }; };
00070
00071 template<typename T>
00072 struct Type2Type{};
00073
00074 template<Player P>
00075 struct Player2Type{ enum { value=P }; };
00076
00077 struct EmptyType{};
00078 }
00079 using misc::Int2Type;
00080 using misc::Player2Type;
00081
00083 enum Ptype
00084 {
00085 PTYPE_EMPTY=0,
00086 PTYPE_EDGE=1,
00087 PPAWN=2,
00088 PLANCE=3,
00089 PKNIGHT=4,
00090 PSILVER=5,
00091 PBISHOP=6,
00092 PROOK=7,
00093 KING=8,
00094 GOLD=9,
00095 PAWN=10,
00096 LANCE=11,
00097 KNIGHT=12,
00098 SILVER=13,
00099 BISHOP=14,
00100 ROOK=15,
00101
00102 PTYPE_MIN=0,
00103 PTYPE_BASIC_MIN=KING,
00104 PTYPE_PIECE_MIN=2,
00105 PTYPE_MAX=15,
00106 };
00107 const int PTYPE_SIZE=PTYPE_MAX-PTYPE_MIN+1;
00108
00109 std::istream& operator>>(std::istream& is, Ptype& ptype);
00110 std::ostream& operator<<(std::ostream& os,const Ptype ptype);
00111
00115 bool isValid(Ptype ptype);
00116
00120 constexpr bool isPiece(Ptype ptype)
00121 {
00122
00123 return static_cast<int>(ptype)>=PTYPE_PIECE_MIN;
00124 }
00128 inline bool isBasic(Ptype ptype)
00129 {
00130 assert(isValid(ptype));
00131 return static_cast<int>(ptype)>PROOK;
00132 }
00133
00137 inline bool isPromoted(Ptype ptype)
00138 {
00139 assert(isPiece(ptype));
00140 return static_cast<int>(ptype)<KING;
00141 }
00142
00147 inline bool canPromote(Ptype ptype)
00148 {
00149 assert(isPiece(ptype));
00150 return static_cast<int>(ptype)>GOLD;
00151 }
00152
00157 inline Ptype unpromote(Ptype ptype)
00158 {
00159 assert(isPiece(ptype));
00160 Ptype ret=static_cast<Ptype>(static_cast<int>(ptype)|8);
00161 assert(isPiece(ret));
00162 return ret;
00163 }
00164 constexpr Ptype unpromoteSafe(Ptype ptype)
00165 {
00166 return (! isPiece(ptype)) ? ptype : unpromote(ptype);
00167 }
00168
00173 inline Ptype promote(Ptype ptype)
00174 {
00175 assert(canPromote(ptype));
00176 Ptype ret=static_cast<Ptype>(static_cast<int>(ptype)-8);
00177 assert(isPiece(ret));
00178 return ret;
00179 }
00180
00181 inline bool isMajorBasic(Ptype ptype)
00182 {
00183 return ptype >= 14;
00184 }
00185 inline bool isMajor(Ptype ptype)
00186 {
00187 assert(isPiece(ptype));
00188 return isMajorBasic(unpromote(ptype));
00189 }
00190 inline bool isMajorNonPieceOK(Ptype ptype)
00191 {
00192 return (static_cast<int>(ptype)|8)>=14;
00193 }
00194
00199 enum PtypeO {
00200 PTYPEO_MIN= PTYPE_EMPTY-16,
00201 PTYPEO_MAX= 15,
00202 };
00203
00204 #define NEW_PTYPEO(player,ptype) static_cast<PtypeO>(static_cast<int>(ptype)-(16&static_cast<int>(player)))
00205 inline unsigned int ptypeOIndex(PtypeO ptypeo)
00206 {
00207 const int result = ptypeo - PTYPEO_MIN;
00208 assert(result >= 0);
00209 return result;
00210 }
00211 inline PtypeO newPtypeO(Player player,Ptype ptype)
00212 {
00213 return static_cast<PtypeO>(static_cast<int>(ptype)-(16&static_cast<int>(player)));
00214 }
00215
00216
00217 inline Ptype getPtype(PtypeO ptypeO)
00218 {
00219 return static_cast<Ptype>(static_cast<int>(ptypeO)& 15);
00220 }
00221
00223 inline PtypeO promote(PtypeO ptypeO)
00224 {
00225 assert(canPromote(getPtype(ptypeO)));
00226 PtypeO ret=static_cast<PtypeO>(static_cast<int>(ptypeO)-8);
00227 assert(isPiece(getPtype(ret)));
00228 return ret;
00229 }
00230
00232 inline PtypeO promoteWithMask(PtypeO ptypeO,int promoteMask)
00233 {
00234 assert(promoteMask==0 || promoteMask==0x800000);
00235 PtypeO ret=static_cast<PtypeO>(static_cast<int>(ptypeO)-(promoteMask>>20));
00236 return ret;
00237 }
00238
00240 inline PtypeO unpromote(PtypeO ptypeO)
00241 {
00242 return static_cast<PtypeO>(static_cast<int>(ptypeO)|8);
00243 }
00244
00245 bool isValidPtypeO(int ptypeO);
00246
00250 inline bool isPiece(PtypeO ptypeO)
00251 {
00252 assert(isValidPtypeO(ptypeO));
00253 return isPiece(getPtype(ptypeO));
00254 }
00255
00256 inline Player getOwner(PtypeO ptypeO)
00257 {
00258 assert(isPiece(ptypeO));
00259 return static_cast<Player>(static_cast<int>(ptypeO)>>31);
00260 }
00261
00262
00264 inline PtypeO captured(PtypeO ptypeO)
00265 {
00266 assert(isPiece(ptypeO));
00267 return static_cast<PtypeO>((static_cast<int>(ptypeO)|8)^(~15));
00268 }
00269
00271 inline PtypeO alt(PtypeO ptypeO)
00272 {
00273 assert(isPiece(ptypeO));
00274 return static_cast<PtypeO>(static_cast<int>(ptypeO)^(~15));
00275 }
00276
00281 inline PtypeO altIfPiece(PtypeO ptypeO)
00282 {
00283 int v=static_cast<int>(ptypeO);
00284 return static_cast<PtypeO>(v^((1-(v&15))&~15));
00285 }
00286
00287 inline bool canPromote(PtypeO ptypeO)
00288 {
00289 return canPromote(getPtype(ptypeO));
00290 }
00291
00292
00296 inline bool isPromoted(PtypeO ptypeO)
00297 {
00298 assert(isValidPtypeO(ptypeO));
00299 return isPromoted(getPtype(ptypeO));
00300 }
00301
00302
00303 const PtypeO PTYPEO_EMPTY=newPtypeO(BLACK,PTYPE_EMPTY);
00304 const PtypeO PTYPEO_EDGE=newPtypeO(WHITE,PTYPE_EDGE);
00305
00306 std::ostream& operator<<(std::ostream& os,const PtypeO ptypeO);
00307
00308 const int PTYPEO_SIZE=PTYPEO_MAX-PTYPEO_MIN+1;
00309
00310 enum Direction{
00311 SHORT_DIRECTION_MIN=0,
00312 SHORT8_DIRECTION_MIN=0,
00313 UL=0,
00314 U=1,
00315 UR=2,
00316 L=3,
00317 R=4,
00318 DL=5,
00319 D=6,
00320 DR=7,
00321 SHORT8_DIRECTION_MAX=7,
00322 UUL=8,
00323 UUR=9,
00324 LONG_DIRECTION_MIN=10,
00325 LONG_UL=10,
00326 LONG_U=11,
00327 LONG_UR=12,
00328 LONG_L=13,
00329 LONG_R=14,
00330 LONG_DL=15,
00331 LONG_D=16,
00332 LONG_DR=17,
00333 LONG_DIRECTION_MAX=17,
00334 DIRECTION_MIN=0,
00335 SHORT_DIRECTION_MAX=9,
00336 SHORT_DIRECTION_SIZE=10,
00337 DIRECTION_MAX=17,
00338 DIRECTION_INVALID_VALUE=18,
00339 DIRECTION_SIZE=18
00340 };
00341
00342 constexpr bool isShort(Direction d){
00343 return d<=SHORT_DIRECTION_MAX;
00344 }
00345
00346 constexpr bool isShort8(Direction d){
00347 return d<=SHORT8_DIRECTION_MAX;
00348 }
00349
00350 constexpr bool isLong(Direction d){
00351 return d>=LONG_DIRECTION_MIN;
00352 }
00353
00354 constexpr Direction inverseUnsafe(Direction d){
00355 return static_cast<Direction>(7 - d);
00356 }
00357
00358 constexpr Direction inverse(Direction d){
00359
00360 return inverseUnsafe(d);
00361 }
00362
00366 constexpr Direction primDir(Direction d){
00367
00368 return (d<4) ? d : inverse(d);
00369 }
00374 constexpr Direction primDirUnsafe(Direction d){
00375 return (d<4) ? d : inverseUnsafe(d);
00376 }
00377
00378 bool isValid(Direction d);
00379
00380 constexpr Direction longToShort(Direction d){
00381
00382 return static_cast<Direction>(static_cast<int>(d)-LONG_UL);
00383 }
00384
00388 constexpr Direction shortToLong(Direction d){
00389
00390 return static_cast<Direction>(static_cast<int>(d)+LONG_UL);
00391 }
00392
00393 constexpr int dirToMask(Direction dir){
00394 return (1<<static_cast<int>(dir));
00395 }
00396
00397 std::ostream& operator<<(std::ostream& os,const Direction d);
00398
00424 class Square;
00425 bool operator==(Square l, Square r);
00429 class Offset
00430 {
00431 public:
00432 enum {
00433 OFFSET_MIN=-0x100,
00434 ONBOARD_OFFSET_MIN=-0x88,
00435 OFFSET_ZERO=0,
00436 ONBOARD_OFFSET_MAX=0x88,
00437 OFFSET_MAX=0x100,
00438 ONBOARD_OFFSET_SIZE=0x88*2+1
00439 };
00440 static const int BOARD_HEIGHT=16;
00441 private:
00442 int offset;
00443 explicit Offset(int o) : offset(o)
00444 {
00445 }
00446 public:
00447 static const Offset makeDirect(int value) { return Offset(value); }
00448 int intValue() const { return offset; }
00449 public:
00450 static int makeOffset(int dx,int dy) { return dx*BOARD_HEIGHT + dy; }
00451 Offset(int dx,int dy) : offset(makeOffset(dx,dy))
00452 {
00453 }
00454 Offset(Player, Direction);
00455 Offset() : offset(OFFSET_ZERO)
00456 {
00457 }
00458 template <Player, Direction>
00459 static Offset make();
00460 static const Offset ZERO() { return Offset(OFFSET_ZERO); }
00461 int
00462 #ifdef __GNUC__
00463 __attribute__ ((pure))
00464 #endif
00465 dx() const;
00466 int
00467 #ifdef __GNUC__
00468 __attribute__ ((pure))
00469 #endif
00470 dy() const;
00471 unsigned int index() const { return offset - OFFSET_MIN; }
00472
00473 Offset& operator+=(Offset other)
00474 {
00475 offset += other.offset;
00476 return *this;
00477 }
00478 Offset& operator-=(Offset other){
00479 offset -= other.offset;
00480 return *this;
00481 }
00482 const Offset operator+(Offset other) const
00483 {
00484 Offset result(*this);
00485 return result += other;
00486 }
00487 const Offset operator-(const Offset other) const
00488 {
00489 Offset result(*this);
00490 return result -= other;
00491 }
00492 const Offset operator*(const int mult) const {
00493 return static_cast<Offset>(static_cast<int>(offset)*mult);
00494 }
00495 const Offset operator-() const { return Offset(-offset); }
00499 template <Player P>
00500 const Offset blackOffset() const { return (P==BLACK) ? *this : -(*this); }
00501
00502 bool zero() const { return offset == OFFSET_ZERO; }
00503 };
00504
00508 inline Offset newOffset(int dx,int dy){
00509 return Offset(dx,dy);
00510 }
00511
00512 inline bool operator==(Offset l, Offset r)
00513 {
00514 return l.intValue() == r.intValue();
00515 }
00516 inline bool operator!=(Offset l, Offset r)
00517 {
00518 return ! (l == r);
00519 }
00520 inline bool operator<(Offset l, Offset r)
00521 {
00522 return l.intValue() < r.intValue();
00523 }
00524
00525
00526 std::ostream& operator<<(std::ostream&, Offset);
00527 }
00528 #include "bits/directionTraits.h"
00529 namespace osl
00530 {
00531 class Square
00532 {
00533 unsigned int square;
00534 explicit Square(int p) : square(p)
00535 {
00536 }
00537 public:
00538 static const Square makeDirect(int value) { return Square(value); }
00539 unsigned int uintValue() const { return square; }
00540 enum {
00541 PIECE_STAND=0,
00542 MIN=0,
00543 SIZE=0x100
00544 };
00545 Square() : square(PIECE_STAND)
00546 {
00547 }
00548 static const Square STAND() { return Square(PIECE_STAND); }
00549 Square(int x, int y) : square((x*Offset::BOARD_HEIGHT)+y+1)
00550 {
00551 assert(square < SIZE);
00552 }
00556 static const Square makeNoCheck(int x, int y) {
00557 return Square((x*Offset::BOARD_HEIGHT)+y+1);
00558 }
00559 static const Square nth(unsigned int i) { return Square(i+MIN); }
00563 int x() const { return square >> 4; }
00567 int y() const { return (square&0xf)-1; }
00571 int y1() const { return square&0xf; }
00572 unsigned int index() const { return square - MIN; }
00573 static unsigned int indexMax() { return SIZE - MIN; }
00574 int indexForOffset32() const { return square + (square&0xf0); }
00575
00576 bool isPieceStand() const { return square == PIECE_STAND; }
00577 bool isOnBoardSlow() const;
00583 bool isOnBoard() const {
00584 return (0xffffff88&(square-0x12)&
00585 ((unsigned int)((square&0x77)^0x12)+0xffffff77))==0;
00586 }
00591 bool isEdge() const {
00592 assert(!isPieceStand() && 0<=x() && x()<=10 && 0<=y() && y()<=10);
00593 return (0x88&(square-0x12)&((square&0x11)+0xf7))!=0;
00594 }
00595 bool isValid() const;
00596
00597
00598 const Square squareForBlack(Player player) const {
00599 return (player == BLACK)
00600 ? *this
00601 : makeDirect(Square(9,9).uintValue()+Square(1,1).uintValue()-uintValue());
00602 }
00603
00608 template<Player P>
00609 const Square squareForBlack() const{
00610 return squareForBlack(P);
00611 }
00612
00613 const Square rotate180() const
00614 {
00615 return squareForBlack<WHITE>();
00616 }
00617 const Square rotate180EdgeOK() const
00618 {
00619 Square ret=makeDirect(Square(9,9).uintValue()+Square(1,1).uintValue()-uintValue());
00620 return ret;
00621 }
00622 const Square rotate180Safe() const
00623 {
00624 if (isPieceStand())
00625 return *this;
00626 return squareForBlack<WHITE>();
00627 }
00628 const Square flipHorizontal() const
00629 {
00630 if (isPieceStand())
00631 return *this;
00632 return Square(10-x(), y());
00633 }
00634
00635 static const Square onBoardMax(){ return Square(9,9); }
00636 static const Square onBoardMin(){ return Square(1,1); }
00637
00641 bool isOnBoardRegion() const {
00642 return static_cast<unsigned int>(index()-onBoardMin().index())
00643 <= static_cast<unsigned int>(onBoardMax().index()-onBoardMin().index());
00644 }
00645
00646 Square& operator++() {
00647 square += 1;
00648 return *this;
00649 }
00650
00651 static int reverseX(int x) { return 10-x; }
00652 static int reverseY(int y) { return 10-y; }
00653 public:
00654 template <Player P>
00655 static bool canPromoteY(int y) {
00656 return P == BLACK ? y <= 3 : y >= 7;
00657 }
00658 template <Player P>
00659 bool canPromote() const{
00660 return canPromote(P);
00661 }
00662 bool canPromote(Player player) const
00663 {
00664 if (player==BLACK)
00665 return (uintValue()&0xf)<=4;
00666 else
00667 return (uintValue()&0x8)!=0;
00668 }
00673 bool isULRD(Square sq) const{
00674 assert(isOnBoard() && sq.isOnBoard());
00675 unsigned int v=uintValue() ^ sq.uintValue();
00676 return (((v+0xefull)^v)&0x110ull)!=0x110ull;
00677 }
00681 bool isUD(Square sq) const{
00682 assert(isOnBoard() && sq.isOnBoard());
00683 unsigned int v=uintValue() ^ sq.uintValue();
00684 return (v&0xf0)==0;
00685 }
00689 template<Player P>
00690 bool isU(Square sq) const{
00691 assert(isOnBoard() && sq.isOnBoard());
00692 unsigned int v=uintValue() ^ sq.uintValue();
00693 if(P==BLACK)
00694 return ((v|(uintValue()-sq.uintValue()))&0xf0)==0;
00695 else
00696 return ((v|(sq.uintValue()-uintValue()))&0xf0)==0;
00697 }
00701 bool isLR(Square sq) const{
00702 assert(isOnBoard() && sq.isOnBoard());
00703 unsigned int v=uintValue() ^ sq.uintValue();
00704 return (v&0xf)==0;
00705 }
00706 Square& operator+=(Offset offset) {
00707 square += offset.intValue();
00708 return *this;
00709 }
00710 Square& operator-=(Offset offset) {
00711 square -= offset.intValue();
00712 return *this;
00713 }
00714 const Square operator+(Offset offset) const {
00715 Square result(*this);
00716 return result+=offset;
00717 }
00718 const Square operator-(Offset offset) const {
00719 Square result(*this);
00720 return result-=offset;
00721 }
00722 const Offset operator-(Square other) const {
00723 return Offset::makeDirect(square - other.square);
00724 }
00725 template<int Y>
00726 bool yEq() {
00727 return (uintValue()&0xf)==(Y+1);
00728 }
00729 template<int Y>
00730 typename std::enable_if<Y!=2,bool>::type yLe() {
00731 return (uintValue()&0xf)<=(Y+1);
00732 }
00733 template<int Y>
00734 typename std::enable_if<Y==2,bool>::type yLe() {
00735 return (uintValue()&0xc)==0;
00736 }
00737 template<int Y>
00738 typename std::enable_if<Y!=7,bool>::type yGe() {
00739 return (uintValue()&0xf)>=(Y+1);
00740 }
00741 template<int Y>
00742 typename std::enable_if<Y==7,bool>::type yGe() {
00743 return (uintValue()&0x8)!=0;
00744 }
00745 template <Player P, Direction D>
00746 const Square neighbor() const {
00747 return *this + DirectionPlayerTraits<D,P>::offset();
00748 }
00749 template <Player P, Direction D>
00750 const Square back() const {
00751 return neighbor<alt(P),D>();
00752 }
00753 const Square neighbor(Player P, Direction D) const;
00754 const Square back(Player P, Direction D) const;
00755 bool isNeighboring8(Square to) const;
00756 };
00757
00758 inline bool operator==(Square l, Square r)
00759 {
00760 return l.uintValue() == r.uintValue();
00761 }
00762 inline bool operator!=(Square l, Square r)
00763 {
00764 return ! (l == r);
00765 }
00766 inline bool operator<(Square l, Square r)
00767 {
00768 return l.uintValue() < r.uintValue();
00769 }
00770 inline bool operator>(Square l, Square r)
00771 {
00772 return l.uintValue() > r.uintValue();
00773 }
00774 std::ostream& operator<<(std::ostream&, Square);
00775
00776 class Piece;
00777 inline bool operator==(Piece l, Piece r);
00778 const int EMPTY_NUM=0x80;
00779 const int EDGE_NUM=0x40;
00787 class Piece
00788 {
00789 int piece;
00790 Piece(int p) : piece(p)
00791 {
00792 }
00793 public:
00794 static const int SIZE=40;
00795 static const Piece makeDirect(int value) { return Piece(value); }
00796 int intValue() const { return piece; }
00797 static const Piece EMPTY() { return Piece(BLACK,PTYPE_EMPTY,EMPTY_NUM,Square::STAND()); }
00798 static const Piece EDGE() { return Piece(WHITE,PTYPE_EDGE,EDGE_NUM,Square::STAND()); }
00799 static const int BitOffsetPtype=16;
00800 static const int BitOffsetPromote=BitOffsetPtype+3;
00801 static const int BitOffsetMovePromote=BitOffsetPromote+4;
00802
00803 Piece(Player owner, Ptype ptype, int num, Square square)
00804 : piece((static_cast<int>(owner)<<20)
00805 +(static_cast<int>(ptype)<<BitOffsetPtype)
00806 +((num)<<8)+ square.uintValue())
00807 {
00808 }
00809 Piece() : piece(EMPTY().piece)
00810 {
00811 }
00815 static const Piece
00816 #ifdef __GNUC__
00817 __attribute__ ((pure))
00818 #endif
00819 makeKing(Player owner, Square square);
00820
00821 Ptype ptype() const {
00822 return static_cast<Ptype>((piece>>BitOffsetPtype)&0xf);
00823 }
00824 PtypeO ptypeO() const {
00825 return static_cast<PtypeO>(piece>>BitOffsetPtype);
00826 }
00827
00828 int number() const {
00829 return ((piece&0xff00)>>8);
00830 }
00831
00832 const Square square() const {
00833 return Square::makeDirect(piece&0xff);
00834 }
00835
00836 Piece& operator+=(Offset offset) {
00837 piece += offset.intValue();
00838 return *this;
00839 }
00840
00841 void setSquare(Square square) {
00842 piece = (piece&0xffffff00)+square.uintValue();
00843 }
00844 public:
00851 template<Player P>
00852 bool isOnBoardByOwner() const { return isOnBoardByOwner(P); }
00856 bool isOnBoardByOwner(Player owner) const
00857 {
00858 if(owner==BLACK)
00859 return static_cast<int>(static_cast<unsigned int>(piece)&0x800000ff)>0;
00860 else
00861 return static_cast<int>((-piece)&0x800000ff)>0;
00862 }
00863
00864
00865 const Piece promote() const {
00866 assert(canPromote(ptype()));
00867 return Piece(piece-0x80000);
00868 }
00869
00870
00871 const Piece unpromote() const {
00872 return Piece((int)piece|0x80000);
00873 }
00874
00879 const Piece captured() const {
00880
00881
00882 return Piece((piece&0xfff7ff00)^0xfff80000);
00883 }
00884
00885 const Piece promoteWithMask(int promote_mask) const {
00886 assert(! (isPromoted() && promote_mask));
00887 assert(promote_mask==0 || promote_mask==(1<<23));
00888 return Piece(piece - (promote_mask>>(BitOffsetMovePromote-BitOffsetPromote)));
00889 }
00890
00891 const Piece checkPromote(bool promotep) const {
00892 return Piece(piece - (promotep<<19));
00893 }
00894
00898 bool isPromoted() const { return (piece&(1<<19))==0; }
00899
00904 bool isOnBoardNotPromoted() const{
00905 int mask=piece&((1<<19)|0xff);
00906 return mask>(1<<19);
00907 }
00908 bool isPromotedNotKingGold() const {
00909 assert(ptype()!=KING && ptype()!=GOLD);
00910 return isPromoted();
00911 }
00912
00913 bool isEmpty() const {
00914 return (piece&0x8000)!=0;
00915 }
00916 static bool isEmptyNum(int num) {
00917 return (num&0x80)!=0;
00918 }
00919 bool isEdge() const {
00920 return (piece&0x4000)!=0;
00921 }
00922 static bool isEdgeNum(int num){
00923 assert(!isEmptyNum(num));
00924 return (num&0x40)!=0;
00925 }
00926 static bool isPieceNum(int num){
00927 return (num&0xc0)==0;
00928 }
00929 template<Ptype T>
00930 bool isPtype() const{
00931 return (piece&0xf0000)==((T)<<BitOffsetPtype);
00932 }
00937 bool isPlayerPtype(Player pl,Ptype ptype) const{
00938 assert(PTYPE_PIECE_MIN<=ptype && ptype<=PTYPE_MAX);
00939 return (piece&0x1f0000)==(((ptype)<<BitOffsetPtype)|(pl&0x100000));
00940 }
00945 bool isPlayerBasicPtype(Player pl,Ptype ptype) const{
00946 assert(PTYPE_PIECE_MIN<=ptype && ptype<=PTYPE_MAX);
00947 assert(isBasic(ptype));
00948 if(canPromote(ptype))
00949 return (piece&0x170000)==(((osl::promote(ptype))<<BitOffsetPtype)|(pl&0x100000));
00950 else
00951 return isPlayerPtype(pl,ptype);
00952 }
00953 bool isPiece() const {
00954 return (piece&0xc000)==0;
00955 }
00959 bool pieceIsBlack() const{
00960 assert(isPiece());
00961 return static_cast<int>(piece)>=0;
00962 }
00963 Player owner() const
00964 {
00965 assert(isPiece());
00966 return static_cast<Player>(piece>>20);
00967 }
00968
00969 private:
00970 public:
00979 template<Player P>
00980 bool canMoveOn() const { return canMoveOn(P); }
00981 bool canMoveOn(Player pl) const{
00982 return pl == BLACK ? ((piece+0xe0000)&0x104000)==0 : piece>=0;
00983 }
00984
00985 bool isOnBoard() const {
00986 assert(square().isValid());
00987 return ! square().isPieceStand();
00988 }
00989 };
00990
00991 inline bool operator<(Piece l, Piece r)
00992 {
00993 return l.intValue() < r.intValue();
00994 }
00995 inline bool operator==(Piece l, Piece r)
00996 {
00997 return l.intValue() == r.intValue();
00998 }
00999 inline bool operator!=(Piece l, Piece r)
01000 {
01001 return ! (l == r);
01002 }
01003
01004 std::ostream& operator<<(std::ostream& os,const Piece piece);
01005 }
01006
01008
01009 #ifdef MOVE_DEBUG
01010 # include <cassert>
01011 # define move_assert(x) assert(x)
01012 #else
01013 # define move_assert(x)
01014 #endif
01015
01016
01017
01018
01019 namespace osl
01020 {
01021 class SimpleState;
01023 enum Move16 {
01024 MOVE16_NONE = 0,
01025 };
01051 class Move
01052 {
01053 public:
01054 static const int BitOffsetPromote=Piece::BitOffsetMovePromote;
01055 private:
01056 int move;
01057 explicit Move(int value) : move(value)
01058 {
01059 }
01060 enum {
01061 INVALID_VALUE = (1<<8), DECLARE_WIN = (2<<8),
01062 BLACK_PASS = 0, WHITE_PASS = (-1)<<28,
01063 };
01064 public:
01065 int intValue() const { return move; }
01067 unsigned int hash() const;
01071 static const unsigned int MaxUniqMoves=600;
01072 private:
01073 void init(Square from, Square to, Ptype ptype,
01074 Ptype capture_ptype, bool is_promote, Player player)
01075 {
01076 move = (to.uintValue()
01077 + (from.uintValue()<<8)
01078 + (static_cast<unsigned int>(capture_ptype)<<16)
01079 + (static_cast<unsigned int>(is_promote)<<BitOffsetPromote)
01080 + (static_cast<unsigned int>(ptype)<<24)
01081 + (static_cast<int>(player)<<28));
01082 }
01083 public:
01084 Move() : move(INVALID_VALUE)
01085 {
01086 }
01088 bool isNormal() const {
01089
01090 return move & 0x00ff;
01091 }
01092 bool isPass() const { return (move & 0xffff) == 0; }
01093 static const Move makeDirect(int value) { return Move(value); }
01094 static const Move PASS(Player P) { return Move(P<<28); }
01095 static const Move INVALID() { return Move(INVALID_VALUE); }
01096 static const Move DeclareWin() { return Move(DECLARE_WIN); }
01100 Move(Square from, Square to, Ptype ptype,
01101 Ptype capture_ptype, bool is_promote, Player player)
01102 {
01103 move_assert(from.isValid());
01104 move_assert(to.isOnBoard());
01105 move_assert(isValid(ptype));
01106 move_assert(isValid(capture_ptype));
01107 move_assert(isValid(player));
01108 init(from, to, ptype, capture_ptype, is_promote, player);
01109 move_assert(isValid());
01110 }
01114 Move(Square to, Ptype ptype, Player player)
01115 {
01116 move_assert(to.isOnBoard());
01117 move_assert(isValid(ptype));
01118 move_assert(isValid(player));
01119 init(Square::STAND(), to, ptype, PTYPE_EMPTY, false, player);
01120 move_assert(isValid());
01121 }
01122 static const Move fromMove16(Move16, const SimpleState&);
01123 Move16 toMove16() const;
01124
01125 const Square from() const
01126 {
01127 assert(! isInvalid());
01128 move_assert(isValidOrPass());
01129 const Square result = Square::makeDirect((move>>8) & 0xff);
01130 return result;
01131 }
01132 const Square to() const {
01133 assert(! isInvalid());
01134 move_assert(isValidOrPass());
01135 const Square result = Square::makeDirect(move & 0xff);
01136 return result;
01137 }
01139 unsigned int fromTo() const { return move & 0xffff; }
01143 int promoteMask() const {
01144 assert(isNormal());
01145 return (static_cast<int>(move)&(1<<BitOffsetPromote));
01146 }
01147 bool isPromotion() const { assert(isNormal()); return (move & (1<<BitOffsetPromote))!=0; }
01148 bool isCapture() const { assert(isNormal()); return capturePtype() != PTYPE_EMPTY; }
01149 bool isCaptureOrPromotion() const { return isCapture() || isPromotion(); }
01150 bool isDrop() const { assert(isNormal()); return from().isPieceStand(); }
01151 bool isPawnDrop() const {
01152 return isDrop() && ptype() == PAWN;
01153 }
01154
01155 Ptype ptype() const {
01156 assert(! isInvalid());
01157 move_assert(isValidOrPass());
01158 const Ptype result = static_cast<Ptype>((move >> 24) & 0xf);
01159 return result;
01160 }
01162 PtypeO ptypeO() const {
01163 assert(! isInvalid());
01164 const PtypeO result = static_cast<PtypeO>(move >> 24);
01165 return result;
01166 }
01168 PtypeO oldPtypeO() const {
01169 assert(! isInvalid());
01170 const PtypeO result = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
01171 return result;
01172 }
01174 Ptype oldPtype() const {
01175 assert(! isInvalid());
01176 move_assert(isValidOrPass());
01177 const PtypeO old_ptypeo = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
01178 return getPtype(old_ptypeo);
01179 }
01180 Ptype capturePtype() const {
01181 assert(isNormal());
01182 const Ptype result = static_cast<Ptype>((move>>16)&0xf);
01183 return result;
01184 }
01185 PtypeO capturePtypeO() const {
01186 assert(isCapture());
01187 return newPtypeO(alt(player()), capturePtype());
01188 }
01189 PtypeO capturePtypeOSafe() const {
01190 if (! isCapture())
01191 return PTYPEO_EMPTY;
01192 return capturePtypeO();
01193 }
01194
01195 Player player() const {
01196 assert(! isInvalid());
01197 const Player result = static_cast<Player>(move>>28);
01198 return result;
01199 }
01200 bool isValid() const;
01202 bool isInvalid() const {
01203 return static_cast<unsigned int>(move-1) < DECLARE_WIN;
01204 }
01205 bool isValidOrPass() const { return isPass() || isValid(); }
01206
01207 Move newFrom(Square new_from) const
01208 {
01209 assert(isNormal());
01210 int result = static_cast<int>(intValue());
01211 result &= ~(0xff00);
01212 result += (new_from.uintValue()<<8);
01213 return makeDirect(result);
01214 }
01215 Move newAddFrom(Square new_from) const
01216 {
01217 assert(isNormal());
01218 assert(from().uintValue()==0);
01219 int result = static_cast<int>(intValue());
01220 result += (new_from.uintValue()<<8);
01221 return makeDirect(result);
01222 }
01226 const Move newAddCapture(Piece capture) const
01227 {
01228 assert(! isCapture());
01229 return makeDirect(intValue()+(capture.intValue()&0xf0000));
01230 }
01231 const Move newCapture(Piece capture) const
01232 {
01233 return makeDirect((intValue()&0xfff0ffff)+(capture.intValue()&0xf0000));
01234 }
01235 const Move newCapture(Ptype capture) const
01236 {
01237 return makeDirect((intValue()&0xfff0ffff)
01238 +(static_cast<int>(capture)<<Piece::BitOffsetPtype));
01239 }
01243 const Move unpromote() const {
01244 assert(isNormal());
01245 move_assert(isPromotion() && isPromoted(ptype()));
01246 return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
01247 }
01251 const Move promote() const {
01252 assert(isNormal());
01253 move_assert(!isPromotion() && canPromote(ptype()));
01254 return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
01255 }
01260 inline Move newAddTo(Offset o) const{
01261 return makeDirect(intValue()+o.intValue());
01262 }
01267 inline Move newAddTo(Square sq) const{
01268 assert((intValue()&0xff)==0);
01269 return Move::makeDirect(intValue()+sq.uintValue());
01270 }
01274 inline Move newAddPtype(Ptype newPtype) const{
01275 assert(ptype()==PTYPE_EMPTY);
01276 return Move::makeDirect(intValue()
01277 + (static_cast<unsigned int>(newPtype)<<24));
01278 }
01279 template<Player P>
01280 static bool ignoreUnpromote(Ptype ptype,Square from,Square to){
01281 switch(ptype){
01282 case PAWN:
01283 return to.canPromote<P>();
01284 case BISHOP: case ROOK:
01285 return to.canPromote<P>() || from.canPromote<P>();
01286 case LANCE:
01287 return (P==BLACK ? to.y()==2 : to.y()==8);
01288 default: return false;
01289 }
01290 }
01295 template<Player P>
01296 bool ignoreUnpromote() const{
01297 assert(player()==P);
01298 if(isDrop()) return false;
01299 return ignoreUnpromote<P>(ptype(),from(),to());
01300 }
01301 bool ignoreUnpromote() const{
01302 if(player()==BLACK) return ignoreUnpromote<BLACK>();
01303 else return ignoreUnpromote<WHITE>();
01304 }
01308 template<Player P>
01309 bool hasIgnoredUnpromote() const{
01310 assert(player()==P);
01311 if(!isPromotion()) return false;
01312 switch(ptype()){
01313 case PPAWN:
01314 return (P==BLACK ? to().y()!=1 : to().y()!=9);
01315 case PLANCE:
01316 return (P==BLACK ? to().y()==2 : to().y()==8);
01317 case PBISHOP: case PROOK:
01318 return true;
01319 default: return false;
01320 }
01321 }
01322 bool hasIgnoredUnpromote() const{
01323 if(player()==BLACK) return hasIgnoredUnpromote<BLACK>();
01324 else return hasIgnoredUnpromote<WHITE>();
01325 }
01326 const Move rotate180() const;
01327 };
01328 inline bool operator<(Move lhs, Move rhs)
01329 {
01330 #ifdef PRESERVE_MOVE_ORDER
01331 int l=lhs.intValue();
01332 l=(l&0xffff0000)+((l>>8)&0xff)+((l<<8)&0xff00);
01333 int r=rhs.intValue();
01334 r=(r&0xffff0000)+((r>>8)&0xff)+((r<<8)&0xff00);
01335 return l<r;
01336 #else
01337 return lhs.intValue() < rhs.intValue();
01338 #endif
01339 }
01340 inline bool operator==(Move lhs, Move rhs)
01341 {
01342 return lhs.intValue() == rhs.intValue();
01343 }
01344 inline bool operator!=(Move lhs, Move rhs)
01345 {
01346 return ! (lhs == rhs);
01347 }
01348
01349 std::ostream& operator<<(std::ostream& os, Move move);
01350 }
01351
01352 namespace std
01353 {
01354 template <typename T> struct hash;
01355 template <> struct hash<osl::Move>
01356 {
01357 unsigned long operator()(osl::Move m) const { return m.intValue(); }
01358 };
01359 }
01360 #endif
01361
01362
01363
01364
01365