move.h
Go to the documentation of this file.
00001 #ifndef OSL_MOVE_H
00002 #define OSL_MOVE_H
00003 #include "osl/player.h"
00004 #include "osl/ptype.h"
00005 #include "osl/square.h"
00006 #include "osl/piece.h"
00007 #include <iosfwd>
00008 
00010 // #define MOVE_DEBUG
00011 #ifdef MOVE_DEBUG
00012 #  include <cassert>
00013 #  define move_assert(x) assert(x)
00014 #else
00015 #  define move_assert(x) 
00016 #endif
00017 // 2009/12/10 以前のfromが下位にあるパターンと
00018 // operator< を同じにしたい時に定義する.
00019 // #define PRESERVE_MOVE_ORDER
00020 
00021 namespace osl
00022 {
00048   class Move
00049   {
00050   public:
00051     static const int BitOffsetPromote=Piece::BitOffsetMovePromote;  // 23
00052   private:
00053     int move;
00054     explicit Move(int value) : move(value)
00055     {
00056     }
00057     enum { 
00058       INVALID_VALUE = (1<<8), DECLARE_WIN = (2<<8),
00059       BLACK_PASS = 0, WHITE_PASS = (-1)<<28, 
00060     };
00061   public:
00062     int intValue() const { return move; }
00064     unsigned int hash() const;
00068     static const unsigned int MaxUniqMoves=600;
00069   private:
00070     void init(Square from, Square to, Ptype ptype,
00071               Ptype capture_ptype, bool is_promote, Player player)
00072     {
00073       move =  (to.uintValue()
00074                + (from.uintValue()<<8)
00075                + (static_cast<unsigned int>(capture_ptype)<<16)
00076                + (static_cast<unsigned int>(is_promote)<<BitOffsetPromote)
00077                + (static_cast<unsigned int>(ptype)<<24)
00078                + (static_cast<int>(player)<<28));
00079     }
00080   public:
00081     Move() : move(INVALID_VALUE)
00082     {
00083     }
00085     bool isNormal() const { 
00086       // PASS や INVALID は to() が 00
00087       return move & 0x00ff; 
00088     }
00089     bool isPass() const { return (move & 0xffff) == 0; }
00090     static const Move makeDirect(int value) { return Move(value); }
00091     static const Move PASS(Player P) { return Move(P<<28); }
00092     static const Move INVALID() { return Move(INVALID_VALUE); }
00093     static const Move DeclareWin() { return Move(DECLARE_WIN); }
00097     Move(Square from, Square to, Ptype ptype,
00098          Ptype capture_ptype, bool is_promote, Player player)
00099     {
00100       move_assert(from.isValid());
00101       move_assert(to.isOnBoard());
00102       move_assert(isValid(ptype));
00103       move_assert(isValid(capture_ptype));
00104       move_assert(isValid(player));
00105       init(from, to, ptype, capture_ptype, is_promote, player);
00106       move_assert(isValid());
00107     }
00111     Move(Square to, Ptype ptype, Player player)
00112     {
00113       move_assert(to.isOnBoard());
00114       move_assert(isValid(ptype));
00115       move_assert(isValid(player));
00116       init(Square::STAND(), to, ptype, PTYPE_EMPTY, false, player);
00117       move_assert(isValid());
00118     }
00119 
00120     const Square from() const 
00121     {
00122       assert(! isInvalid());
00123       move_assert(isValidOrPass());
00124       const Square result = Square::makeDirect((move>>8) & 0xff);
00125       return result;
00126     }
00127     const Square to() const {
00128       assert(! isInvalid());
00129       move_assert(isValidOrPass());
00130       const Square result = Square::makeDirect(move & 0xff);
00131       return result;
00132     }
00134     unsigned int fromTo() const { return move & 0xffff; }
00138     int promoteMask() const {
00139       assert(isNormal());
00140       return (static_cast<int>(move)&(1<<BitOffsetPromote));
00141     }
00142     bool isPromotion() const { assert(isNormal()); return (move & (1<<BitOffsetPromote))!=0; }
00143     bool isCapture() const { assert(isNormal()); return capturePtype() != PTYPE_EMPTY; }
00144     bool isCaptureOrPromotion() const { return isCapture() || isPromotion(); }
00145     bool isDrop() const { assert(isNormal()); return from().isPieceStand(); }
00146       
00147     Ptype ptype() const {
00148       assert(! isInvalid());
00149       move_assert(isValidOrPass());
00150       const Ptype result = static_cast<Ptype>((move >> 24) & 0xf);
00151       return result;
00152     }
00154     PtypeO ptypeO() const {
00155       assert(! isInvalid());
00156       const PtypeO result = static_cast<PtypeO>(move >> 24);
00157       return result;
00158     }
00160     PtypeO oldPtypeO() const {
00161       assert(! isInvalid());
00162       const PtypeO result = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
00163       return result;
00164     }
00166     Ptype oldPtype() const { 
00167       assert(! isInvalid());
00168       move_assert(isValidOrPass());
00169       const PtypeO old_ptypeo = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
00170       return getPtype(old_ptypeo); 
00171     }
00172     Ptype capturePtype() const {
00173       assert(isNormal());
00174       const Ptype result = static_cast<Ptype>((move>>16)&0xf);
00175       return result;
00176     }
00177     PtypeO capturePtypeO() const {
00178       assert(isCapture());
00179       return newPtypeO(alt(player()), capturePtype());
00180     }
00181     PtypeO capturePtypeOSafe() const {
00182       if (! isCapture())
00183         return PTYPEO_EMPTY;
00184       return capturePtypeO();
00185     }
00186 
00187     Player player() const {
00188       assert(! isInvalid());
00189       const Player result = static_cast<Player>(move>>28);
00190       return result;
00191     }
00192     bool isValid() const;
00194     bool isInvalid() const { 
00195       return static_cast<unsigned int>(move-1) < DECLARE_WIN; 
00196     }
00197     bool isValidOrPass() const { return isPass() || isValid(); }
00198 
00199     Move newFrom(Square new_from) const
00200     {
00201       assert(isNormal());
00202       int result = static_cast<int>(intValue());
00203       result &= ~(0xff00);
00204       result += (new_from.uintValue()<<8);
00205       return makeDirect(result);
00206     }
00207     Move newAddFrom(Square new_from) const
00208     {
00209       assert(isNormal());
00210       assert(from().uintValue()==0);
00211       int result = static_cast<int>(intValue());
00212       result += (new_from.uintValue()<<8);
00213       return makeDirect(result);
00214     }
00218     const Move newAddCapture(Piece capture) const
00219     {
00220       assert(! isCapture());
00221       return makeDirect(intValue()+(capture.intValue()&0xf0000));
00222     }
00223     const Move newCapture(Piece capture) const
00224     {
00225       return makeDirect((intValue()&0xfff0ffff)+(capture.intValue()&0xf0000));
00226     }
00227     const Move newCapture(Ptype capture) const
00228     {
00229       return makeDirect((intValue()&0xfff0ffff)
00230                         +(static_cast<int>(capture)<<Piece::BitOffsetPtype));
00231     }
00235     const Move unpromote() const {
00236       assert(isNormal());
00237       move_assert(isPromotion() && isPromoted(ptype()));
00238       return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
00239     }
00243     const Move promote() const {
00244       assert(isNormal());
00245       move_assert(!isPromotion() && canPromote(ptype()));
00246       return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
00247     }
00252     inline Move newAddTo(Offset o) const{
00253       return makeDirect(intValue()+o.intValue());
00254     }
00259     inline Move newAddTo(Square sq) const{
00260       assert((intValue()&0xff)==0);
00261       return Move::makeDirect(intValue()+sq.uintValue());
00262     }
00266     inline Move newAddPtype(Ptype newPtype) const{
00267       assert(ptype()==PTYPE_EMPTY);
00268       return Move::makeDirect(intValue()
00269                               + (static_cast<unsigned int>(newPtype)<<24));
00270     }
00271     template<Player P>
00272     static bool ignoreUnpromote(Ptype ptype,Square from,Square to){
00273       switch(ptype){
00274       case PAWN: 
00275         return to.canPromote<P>();
00276       case BISHOP: case ROOK: 
00277         return to.canPromote<P>() || from.canPromote<P>();
00278       case LANCE:
00279         return (P==BLACK ? to.y()==2 : to.y()==8);
00280       default: return false;
00281       }
00282     }
00287     template<Player P>
00288     bool ignoreUnpromote() const{
00289       assert(player()==P);
00290       if(isDrop()) return false;
00291       return ignoreUnpromote<P>(ptype(),from(),to());
00292     }
00293     bool ignoreUnpromote() const{
00294       if(player()==BLACK) return ignoreUnpromote<BLACK>();
00295       else return ignoreUnpromote<WHITE>();
00296     }
00300     template<Player P>
00301     bool hasIgnoredUnpromote() const{
00302       assert(player()==P);
00303       if(!isPromotion()) return false;
00304       switch(ptype()){
00305       case PPAWN: 
00306         return (P==BLACK ? to().y()!=1 : to().y()!=9);
00307       case PLANCE:
00308         return (P==BLACK ? to().y()==2 : to().y()==8);
00309       case PBISHOP: case PROOK: 
00310         return true;
00311       default: return false;
00312       }
00313     }
00314     bool hasIgnoredUnpromote() const{
00315       if(player()==BLACK) return hasIgnoredUnpromote<BLACK>();
00316       else return hasIgnoredUnpromote<WHITE>();
00317     }
00318     const Move rotate180() const;
00319   };
00320   inline bool operator<(Move lhs, Move rhs)
00321   {
00322 #ifdef PRESERVE_MOVE_ORDER
00323     int l=lhs.intValue();
00324     l=(l&0xffff0000)+((l>>8)&0xff)+((l<<8)&0xff00);
00325     int r=rhs.intValue();
00326     r=(r&0xffff0000)+((r>>8)&0xff)+((r<<8)&0xff00);
00327     return l<r;
00328 #else
00329     return lhs.intValue() < rhs.intValue();
00330 #endif
00331   }
00332   inline bool operator==(Move lhs, Move rhs)
00333   {
00334     return lhs.intValue() == rhs.intValue();
00335   }
00336   inline bool operator!=(Move lhs, Move rhs)
00337   {
00338     return ! (lhs == rhs);
00339   }
00340 
00341   std::ostream& operator<<(std::ostream& os, Move move);
00342   namespace stl
00343   {
00344     template <typename T> struct hash;
00345     template <> struct hash<Move>
00346     {
00347       unsigned long operator()(Move m) const { return m.intValue(); }
00348     };
00349   } // namespace stl
00350 }
00351 #endif /* OSL_MOVE_H */
00352 // ;;; Local Variables:
00353 // ;;; mode:c++
00354 // ;;; c-basic-offset:2
00355 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines