All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
move.h
Go to the documentation of this file.
1 #ifndef OSL_MOVE_H
2 #define OSL_MOVE_H
3 #include "osl/player.h"
4 #include "osl/ptype.h"
5 #include "osl/square.h"
6 #include "osl/piece.h"
7 #include <iosfwd>
8 
10 // #define MOVE_DEBUG
11 #ifdef MOVE_DEBUG
12 # include <cassert>
13 # define move_assert(x) assert(x)
14 #else
15 # define move_assert(x)
16 #endif
17 // 2009/12/10 以前のfromが下位にあるパターンと
18 // operator< を同じにしたい時に定義する.
19 // #define PRESERVE_MOVE_ORDER
20 
21 namespace osl
22 {
23  namespace state {
24  class SimpleState;
25  }
27  enum Move16 {
29  };
55  class Move
56  {
57  public:
59  private:
60  int move;
61  explicit Move(int value) : move(value)
62  {
63  }
64  enum {
65  INVALID_VALUE = (1<<8), DECLARE_WIN = (2<<8),
66  BLACK_PASS = 0, WHITE_PASS = (-1)<<28,
67  };
68  public:
69  int intValue() const { return move; }
71  unsigned int hash() const;
75  static const unsigned int MaxUniqMoves=600;
76  private:
78  Ptype capture_ptype, bool is_promote, Player player)
79  {
80  move = (to.uintValue()
81  + (from.uintValue()<<8)
82  + (static_cast<unsigned int>(capture_ptype)<<16)
83  + (static_cast<unsigned int>(is_promote)<<BitOffsetPromote)
84  + (static_cast<unsigned int>(ptype)<<24)
85  + (static_cast<int>(player)<<28));
86  }
87  public:
89  {
90  }
92  bool isNormal() const {
93  // PASS や INVALID は to() が 00
94  return move & 0x00ff;
95  }
96  bool isPass() const { return (move & 0xffff) == 0; }
97  static const Move makeDirect(int value) { return Move(value); }
98  static const Move PASS(Player P) { return Move(P<<28); }
99  static const Move INVALID() { return Move(INVALID_VALUE); }
100  static const Move DeclareWin() { return Move(DECLARE_WIN); }
105  Ptype capture_ptype, bool is_promote, Player player)
106  {
107  move_assert(from.isValid());
108  move_assert(to.isOnBoard());
109  move_assert(isValid(ptype));
110  move_assert(isValid(capture_ptype));
111  move_assert(isValid(player));
112  init(from, to, ptype, capture_ptype, is_promote, player);
113  move_assert(isValid());
114  }
119  {
120  move_assert(to.isOnBoard());
121  move_assert(isValid(ptype));
122  move_assert(isValid(player));
123  init(Square::STAND(), to, ptype, PTYPE_EMPTY, false, player);
124  move_assert(isValid());
125  }
126  static const Move fromMove16(Move16, const state::SimpleState&);
127  Move16 toMove16() const;
128 
129  const Square from() const
130  {
131  assert(! isInvalid());
133  const Square result = Square::makeDirect((move>>8) & 0xff);
134  return result;
135  }
136  const Square to() const {
137  assert(! isInvalid());
139  const Square result = Square::makeDirect(move & 0xff);
140  return result;
141  }
143  unsigned int fromTo() const { return move & 0xffff; }
147  int promoteMask() const {
148  assert(isNormal());
149  return (static_cast<int>(move)&(1<<BitOffsetPromote));
150  }
151  bool isPromotion() const { assert(isNormal()); return (move & (1<<BitOffsetPromote))!=0; }
152  bool isCapture() const { assert(isNormal()); return capturePtype() != PTYPE_EMPTY; }
153  bool isCaptureOrPromotion() const { return isCapture() || isPromotion(); }
154  bool isDrop() const { assert(isNormal()); return from().isPieceStand(); }
155  bool isPawnDrop() const {
156  return isDrop() && ptype() == PAWN;
157  }
158 
159  Ptype ptype() const {
160  assert(! isInvalid());
162  const Ptype result = static_cast<Ptype>((move >> 24) & 0xf);
163  return result;
164  }
166  PtypeO ptypeO() const {
167  assert(! isInvalid());
168  const PtypeO result = static_cast<PtypeO>(move >> 24);
169  return result;
170  }
172  PtypeO oldPtypeO() const {
173  assert(! isInvalid());
174  const PtypeO result = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
175  return result;
176  }
178  Ptype oldPtype() const {
179  assert(! isInvalid());
181  const PtypeO old_ptypeo = static_cast<PtypeO>((move>>24)+((move >> (BitOffsetPromote-3))&8));
182  return getPtype(old_ptypeo);
183  }
184  Ptype capturePtype() const {
185  assert(isNormal());
186  const Ptype result = static_cast<Ptype>((move>>16)&0xf);
187  return result;
188  }
190  assert(isCapture());
191  return newPtypeO(alt(player()), capturePtype());
192  }
194  if (! isCapture())
195  return PTYPEO_EMPTY;
196  return capturePtypeO();
197  }
198 
199  Player player() const {
200  assert(! isInvalid());
201  const Player result = static_cast<Player>(move>>28);
202  return result;
203  }
204  bool isValid() const;
206  bool isInvalid() const {
207  return static_cast<unsigned int>(move-1) < DECLARE_WIN;
208  }
209  bool isValidOrPass() const { return isPass() || isValid(); }
210 
211  Move newFrom(Square new_from) const
212  {
213  assert(isNormal());
214  int result = static_cast<int>(intValue());
215  result &= ~(0xff00);
216  result += (new_from.uintValue()<<8);
217  return makeDirect(result);
218  }
219  Move newAddFrom(Square new_from) const
220  {
221  assert(isNormal());
222  assert(from().uintValue()==0);
223  int result = static_cast<int>(intValue());
224  result += (new_from.uintValue()<<8);
225  return makeDirect(result);
226  }
231  {
232  assert(! isCapture());
233  return makeDirect(intValue()+(capture.intValue()&0xf0000));
234  }
236  {
237  return makeDirect((intValue()&0xfff0ffff)+(capture.intValue()&0xf0000));
238  }
240  {
241  return makeDirect((intValue()&0xfff0ffff)
242  +(static_cast<int>(capture)<<Piece::BitOffsetPtype));
243  }
247  const Move unpromote() const {
248  assert(isNormal());
250  return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
251  }
255  const Move promote() const {
256  assert(isNormal());
258  return makeDirect(intValue()^((1<<BitOffsetPromote)^(1<<27)));
259  }
264  inline Move newAddTo(Offset o) const{
265  return makeDirect(intValue()+o.intValue());
266  }
271  inline Move newAddTo(Square sq) const{
272  assert((intValue()&0xff)==0);
273  return Move::makeDirect(intValue()+sq.uintValue());
274  }
278  inline Move newAddPtype(Ptype newPtype) const{
279  assert(ptype()==PTYPE_EMPTY);
280  return Move::makeDirect(intValue()
281  + (static_cast<unsigned int>(newPtype)<<24));
282  }
283  template<Player P>
285  switch(ptype){
286  case PAWN:
287  return to.canPromote<P>();
288  case BISHOP: case ROOK:
289  return to.canPromote<P>() || from.canPromote<P>();
290  case LANCE:
291  return (P==BLACK ? to.y()==2 : to.y()==8);
292  default: return false;
293  }
294  }
299  template<Player P>
300  bool ignoreUnpromote() const{
301  assert(player()==P);
302  if(isDrop()) return false;
303  return ignoreUnpromote<P>(ptype(),from(),to());
304  }
305  bool ignoreUnpromote() const{
306  if(player()==BLACK) return ignoreUnpromote<BLACK>();
307  else return ignoreUnpromote<WHITE>();
308  }
312  template<Player P>
313  bool hasIgnoredUnpromote() const{
314  assert(player()==P);
315  if(!isPromotion()) return false;
316  switch(ptype()){
317  case PPAWN:
318  return (P==BLACK ? to().y()!=1 : to().y()!=9);
319  case PLANCE:
320  return (P==BLACK ? to().y()==2 : to().y()==8);
321  case PBISHOP: case PROOK:
322  return true;
323  default: return false;
324  }
325  }
326  bool hasIgnoredUnpromote() const{
327  if(player()==BLACK) return hasIgnoredUnpromote<BLACK>();
328  else return hasIgnoredUnpromote<WHITE>();
329  }
330  const Move rotate180() const;
331  };
332  inline bool operator<(Move lhs, Move rhs)
333  {
334 #ifdef PRESERVE_MOVE_ORDER
335  int l=lhs.intValue();
336  l=(l&0xffff0000)+((l>>8)&0xff)+((l<<8)&0xff00);
337  int r=rhs.intValue();
338  r=(r&0xffff0000)+((r>>8)&0xff)+((r<<8)&0xff00);
339  return l<r;
340 #else
341  return lhs.intValue() < rhs.intValue();
342 #endif
343  }
344  inline bool operator==(Move lhs, Move rhs)
345  {
346  return lhs.intValue() == rhs.intValue();
347  }
348  inline bool operator!=(Move lhs, Move rhs)
349  {
350  return ! (lhs == rhs);
351  }
352 
353  std::ostream& operator<<(std::ostream& os, Move move);
354  namespace stl
355  {
356  template <typename T> struct hash;
357  template <> struct hash<Move>
358  {
359  unsigned long operator()(Move m) const { return m.intValue(); }
360  };
361  } // namespace stl
362 }
363 #endif /* OSL_MOVE_H */
364 // ;;; Local Variables:
365 // ;;; mode:c++
366 // ;;; c-basic-offset:2
367 // ;;; End: