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
00011 #ifdef MOVE_DEBUG
00012 # include <cassert>
00013 # define move_assert(x) assert(x)
00014 #else
00015 # define move_assert(x)
00016 #endif
00017
00018
00019
00020
00021 namespace osl
00022 {
00048 class Move
00049 {
00050 public:
00051 static const int BitOffsetPromote=Piece::BitOffsetMovePromote;
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
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 }
00350 }
00351 #endif
00352
00353
00354
00355