00001 #ifndef OSL_MOVE_H
00002 #define OSL_MOVE_H
00003 #include "osl/player.h"
00004 #include "osl/ptype.h"
00005 #include "osl/position.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; }
00066 static const unsigned int MaxUniqMoves=600;
00067 private:
00068 void init(Position from, Position to, Ptype ptype,
00069 Ptype capture_ptype, bool is_promote, Player player)
00070 {
00071 move = (to.uintValue()
00072 + (from.uintValue()<<8)
00073 + (static_cast<unsigned int>(capture_ptype)<<16)
00074 + (static_cast<unsigned int>(is_promote)<<BitOffsetPromote)
00075 + (static_cast<unsigned int>(ptype)<<24)
00076 + (static_cast<int>(player)<<28));
00077 }
00078 public:
00079 Move() : move(INVALID_VALUE)
00080 {
00081 }
00083 bool isNormal() const {
00084
00085 return move & 0x00ff;
00086 }
00087 bool isPass() const { return (move & 0xffff) == 0; }
00088 static const Move makeDirect(int value) { return Move(value); }
00089 static const Move PASS(Player P) { return Move(P<<28); }
00090 static const Move INVALID() { return Move(INVALID_VALUE); }
00091 static const Move DeclareWin() { return Move(DECLARE_WIN); }
00095 Move(Position from, Position to, Ptype ptype,
00096 Ptype capture_ptype, bool is_promote, Player player)
00097 {
00098 move_assert(from.isValid());
00099 move_assert(to.isOnBoard());
00100 move_assert(isValid(ptype));
00101 move_assert(isValid(capture_ptype));
00102 move_assert(isValid(player));
00103 init(from, to, ptype, capture_ptype, is_promote, player);
00104 move_assert(isValid());
00105 }
00109 Move(Position to, Ptype ptype, Player player)
00110 {
00111 move_assert(to.isOnBoard());
00112 move_assert(isValid(ptype));
00113 move_assert(isValid(player));
00114 init(Position::STAND(), to, ptype, PTYPE_EMPTY, false, player);
00115 move_assert(isValid());
00116 }
00117
00118 const Position from() const
00119 {
00120 assert(! isInvalid());
00121 move_assert(isValidOrPass());
00122 const Position result = Position::makeDirect((move>>8) & 0xff);
00123 return result;
00124 }
00125 const Position to() const {
00126 assert(! isInvalid());
00127 move_assert(isValidOrPass());
00128 const Position result = Position::makeDirect(move & 0xff);
00129 return result;
00130 }
00132 unsigned int fromTo() const { return move & 0xffff; }
00136 int promoteMask() const {
00137 assert(isNormal());
00138 return (static_cast<int>(move)&(1<<BitOffsetPromote));
00139 }
00140 bool isPromote() const { assert(isNormal()); return (move & (1<<BitOffsetPromote))!=0; }
00141 bool isDrop() const { assert(isNormal()); return from().isPieceStand(); }
00142
00143 Ptype ptype() const {
00144 assert(! isInvalid());
00145 move_assert(isValidOrPass());
00146 const Ptype result = static_cast<Ptype>((move >> 24) & 0xf);
00147 return result;
00148 }
00150 PtypeO ptypeO() const {
00151 assert(! isInvalid());
00152 const PtypeO result = static_cast<PtypeO>(move >> 24);
00153 return result;
00154 }
00156 PtypeO oldPtypeO() const {
00157 assert(! isInvalid());
00158 const PtypeO result = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
00159 return result;
00160 }
00162 Ptype oldPtype() const {
00163 assert(! isInvalid());
00164 move_assert(isValidOrPass());
00165 const PtypeO old_ptypeo = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
00166 return getPtype(old_ptypeo);
00167 }
00168 Ptype capturePtype() const {
00169 assert(isNormal());
00170 const Ptype result = static_cast<Ptype>((move>>16)&0xf);
00171 return result;
00172 }
00173 PtypeO capturePtypeO() const {
00174 assert(capturePtype() != PTYPE_EMPTY);
00175 return newPtypeO(alt(player()), capturePtype());
00176 }
00177 PtypeO capturePtypeOSafe() const {
00178 if (capturePtype() == PTYPE_EMPTY)
00179 return PTYPEO_EMPTY;
00180 return capturePtypeO();
00181 }
00182
00183 Player player() const {
00184 assert(! isInvalid());
00185 const Player result = static_cast<Player>(move>>28);
00186 return result;
00187 }
00188 bool isValid() const;
00190 bool isInvalid() const {
00191 return static_cast<unsigned int>(move-1) < DECLARE_WIN;
00192 }
00193 bool isValidOrPass() const { return isPass() || isValid(); }
00194
00195 Move newFrom(Position new_from) const
00196 {
00197 assert(isNormal());
00198 int result = static_cast<int>(intValue());
00199 result &= ~(0xff00);
00200 result += (new_from.uintValue()<<8);
00201 return makeDirect(result);
00202 }
00203 Move newAddFrom(Position new_from) const
00204 {
00205 assert(isNormal());
00206 assert(from().uintValue()==0);
00207 int result = static_cast<int>(intValue());
00208 result += (new_from.uintValue()<<8);
00209 return makeDirect(result);
00210 }
00214 const Move newAddCapture(Piece capture) const
00215 {
00216 assert(capturePtype()==PTYPE_EMPTY);
00217 return makeDirect(intValue()+(capture.intValue()&0xf0000));
00218 }
00219 const Move newCapture(Piece capture) const
00220 {
00221 return makeDirect((intValue()&0xfff0ffff)+(capture.intValue()&0xf0000));
00222 }
00223 const Move newCapture(Ptype capture) const
00224 {
00225 return makeDirect((intValue()&0xfff0ffff)
00226 +(static_cast<int>(capture)<<Piece::BitOffsetPtype));
00227 }
00231 const Move unpromote() const {
00232 assert(isNormal());
00233 move_assert(isPromote() && isPromoted(ptype()));
00234 return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
00235 }
00239 const Move promote() const {
00240 assert(isNormal());
00241 move_assert(!isPromote() && canPromote(ptype()));
00242 return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
00243 }
00248 inline Move newAddTo(Offset o) const{
00249 return makeDirect(intValue()+o.intValue());
00250 }
00255 inline Move newAddTo(Position pos) const{
00256 assert((intValue()&0xff)==0);
00257 return Move::makeDirect(intValue()+pos.uintValue());
00258 }
00262 inline Move newAddPtype(Ptype newPtype) const{
00263 assert(ptype()==PTYPE_EMPTY);
00264 return Move::makeDirect(intValue()
00265 + (static_cast<unsigned int>(newPtype)<<24));
00266 }
00267 template<Player P>
00268 static bool ignoreUnpromote(Ptype ptype,Position from,Position to){
00269 switch(ptype){
00270 case PAWN:
00271 return to.canPromote<P>();
00272 case BISHOP: case ROOK:
00273 return to.canPromote<P>() || from.canPromote<P>();
00274 case LANCE:
00275 return (P==BLACK ? to.y()==2 : to.y()==8);
00276 default: return false;
00277 }
00278 }
00283 template<Player P>
00284 bool ignoreUnpromote() const{
00285 assert(player()==P);
00286 if(isDrop()) return false;
00287 return ignoreUnpromote<P>(ptype(),from(),to());
00288 }
00289 bool ignoreUnpromote(Player pl) const{
00290 if(pl==BLACK) return ignoreUnpromote<BLACK>();
00291 else return ignoreUnpromote<WHITE>();
00292 }
00296 template<Player P>
00297 bool hasIgnoredUnpromote() const{
00298 assert(player()==P);
00299 if(!isPromote()) return false;
00300 switch(ptype()){
00301 case PPAWN:
00302 return (P==BLACK ? to().y()!=1 : to().y()!=9);
00303 case PLANCE:
00304 return (P==BLACK ? to().y()==2 : to().y()==8);
00305 case PBISHOP: case PROOK:
00306 return true;
00307 default: return false;
00308 }
00309 }
00310 bool hasIgnoredUnpromote(Player pl) const{
00311 if(pl==BLACK) return hasIgnoredUnpromote<BLACK>();
00312 else return hasIgnoredUnpromote<WHITE>();
00313 }
00314 const Move rotate180() const;
00315 };
00316 inline bool operator<(Move lhs, Move rhs)
00317 {
00318 #ifdef PRESERVE_MOVE_ORDER
00319 int l=lhs.intValue();
00320 l=(l&0xffff0000)+((l>>8)&0xff)+((l<<8)&0xff00);
00321 int r=rhs.intValue();
00322 r=(r&0xffff0000)+((r>>8)&0xff)+((r<<8)&0xff00);
00323 return l<r;
00324 #else
00325 return lhs.intValue() < rhs.intValue();
00326 #endif
00327 }
00328 inline bool operator==(Move lhs, Move rhs)
00329 {
00330 return lhs.intValue() == rhs.intValue();
00331 }
00332 inline bool operator!=(Move lhs, Move rhs)
00333 {
00334 return ! (lhs == rhs);
00335 }
00336
00337 std::ostream& operator<<(std::ostream& os, Move move);
00338 }
00339 #endif
00340
00341
00342
00343