bits/pieceStand.h
Go to the documentation of this file.
1 /* pieceStand.h
2  */
3 #ifndef OSL_PIECESTAND_H
4 #define OSL_PIECESTAND_H
5 #include "osl/basic_type.h"
6 #include "osl/container.h"
7 #include <iosfwd>
8 #include <cassert>
9 namespace osl
10 {
11  class SimpleState;
37  class PieceStand
38  {
39  public:
41  static const CArray<Ptype,7> order;
42  static const unsigned int carryMask = 0x48822224;
43  private:
46  mutable unsigned int flags;
47  public:
48  explicit PieceStand(unsigned int value=0) : flags(value)
49  {
50  }
51  explicit PieceStand(Player, const SimpleState&);
52  PieceStand(int pawnCount, int lanceCount,
53  int knightCount, int silverCount,
54  int goldCount, int bishopCount,
55  int rookCount, int kingCount)
56  : flags(0)
57  {
58  add(PAWN, pawnCount);
59  add(LANCE, lanceCount);
60  add(KNIGHT, knightCount);
61  add(SILVER, silverCount);
62  add(GOLD, goldCount);
63  add(BISHOP, bishopCount);
64  add(ROOK, rookCount);
65  add(KING, kingCount);
66  }
67 
68  void add(Ptype type, unsigned int num=1)
69  {
70  assert(isBasic(type));
71  assert(num == (num & mask[type]));
72  flags += (num << (shift[type]));
73  assert(testCarries() == 0); // overflow 検出
74  }
75  void sub(Ptype type, unsigned int num=1)
76  {
77  assert(isBasic(type));
78  assert(num == (num & mask[type]));
79  assert(get(type) >= num);
80  flags -= (num << (shift[type]));
81  }
82 
87  void tryAdd(Ptype type);
88  bool canAdd(Ptype type) const;
92  void trySub(Ptype type)
93  {
94  if (get(type))
95  sub(type);
96  }
97 
101  bool atMostOneKind() const;
102 
108  void addAtmostOnePiece(PieceStand const& ps){
109 #ifndef NDEBUG
110  const PieceStand copy(*this);
111 #endif
112  assert(! ps.testCarries());
113  assert(ps.atMostOneKind());
114  flags += ps.getFlags();
115  assert(carryUnchangedAfterAdd(copy, ps));
116  }
117 
118  void subAtmostOnePiece(PieceStand const& ps){
119 #ifndef NDEBUG
120  const PieceStand copy(*this);
121 #endif
122  assert(! ps.testCarries());
123  assert(ps.atMostOneKind());
124  flags -= ps.getFlags();
125  assert(carryUnchangedAfterSub(copy, ps));
126  }
127  private:
128  bool carryUnchangedAfterAdd(const PieceStand& original, const PieceStand& other) const;
129  bool carryUnchangedAfterSub(const PieceStand& original, const PieceStand& other) const;
130  public:
131  unsigned int get(Ptype type) const
132  {
133  return (flags >> (shift[type])) & mask[type];
134  }
135  void carriesOff() const { flags &= (~carryMask); }
136  void carriesOn() const { flags |= carryMask; }
137  unsigned int testCarries() const { return (flags & carryMask); }
138  bool isSuperiorOrEqualTo(PieceStand other) const
139  {
140  carriesOn();
141  other.carriesOff();
142  const bool result = (((flags - other.flags) & carryMask) == carryMask);
143  carriesOff();
144  return result;
145  }
150  template <Player P>
151  bool hasMoreThan(PieceStand other) const
152  {
153  if (P == BLACK)
154  return isSuperiorOrEqualTo(other);
155  else
156  return other.isSuperiorOrEqualTo(*this);
157  }
158  bool hasMoreThan(Player P, PieceStand other) const
159  {
160  if (P == BLACK)
161  return hasMoreThan<BLACK>(other);
162  else
163  return hasMoreThan<WHITE>(other);
164  }
165  unsigned int getFlags() const { return flags; }
167  bool any() const { return flags; }
171  const PieceStand max(PieceStand other) const
172  {
173  // other以上の数持っているptypeに対応するcarryが1になる.
174  const unsigned int mask0 = ((flags|carryMask)-other.flags) & carryMask;
175  // ROOK BISHOP KING用のMASKを作る
176  unsigned int my_mask = mask0-((mask0&0x40000024)>>2);
177  // GOLD SILVER KNIGHT LANCE用のMASKを作る
178  my_mask -= (mask0&0x08022200)>>3;
179  // PAWN用のMASKのみ残す
180  my_mask -= (mask0&0x00800000)>>5;
181  // my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
182  return PieceStand((flags&my_mask)|(other.flags&~my_mask));
183  }
187  const PieceStand max2(PieceStand other) const
188  {
189  // other以上の数持っているptypeに対応するcarryが1になる.
190  const unsigned int diff0=((flags|carryMask)-other.flags);
191  const unsigned int mask0=diff0&carryMask;
192 
193  // ROOK BISHOP KING GOLD SILVER KNIGHT LANCE用のMASKを作る
194  const unsigned int mask02=(mask0&0x40000024u)+(mask0&0x48022224u);
195  unsigned int my_mask=mask0-(mask02>>3);
196 
197  // PAWN用のMASKのみ残す
198  my_mask -= (mask0&0x00800000)>>5;
199  // my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
200  return PieceStand((other.flags+(diff0&my_mask))&~carryMask);
201  }
202 
203  const PieceStand nextStand(Player pl, Move move) const
204  {
205  assert(move.isNormal());
206  PieceStand result = *this;
207  if (move.player() == pl)
208  {
209  if (const Ptype ptype = move.capturePtype())
210  {
211  result.add(unpromote(ptype));
212  }
213  else if (move.isDrop())
214  {
215  const Ptype ptype = move.ptype();
216  assert(get(ptype));
217  result.sub(ptype);
218  }
219  }
220  return result;
221  }
222  const PieceStand nextStand(Move move) const
223  {
224  return nextStand(move.player(), move);
225  }
226  const PieceStand previousStand(Player pl, Move move) const
227  {
228  assert(move.isNormal());
229  PieceStand result = *this;
230  if (move.player() == pl)
231  {
232  if (const Ptype ptype = move.capturePtype())
233  {
234  const Ptype before = unpromote(ptype);
235  assert(get(before));
236  result.sub(before);
237  }
238  else if (move.isDrop())
239  {
240  const Ptype ptype = move.ptype();
241  result.add(ptype);
242  }
243  }
244  return result;
245  }
246  const PieceStand previousStand(Move move) const
247  {
248  return previousStand(move.player(), move);
249  }
250  };
251 
252  inline bool operator==(PieceStand l, PieceStand r)
253  {
254  assert(! l.testCarries());
255  assert(! r.testCarries());
256  return l.getFlags() == r.getFlags();
257  }
258  inline bool operator!=(PieceStand l, PieceStand r)
259  {
260  return ! (l == r);
261  }
262  inline bool operator<(PieceStand l, PieceStand r)
263  {
264  assert(! l.testCarries());
265  assert(! r.testCarries());
266  return l.getFlags() < r.getFlags();
267  }
268  std::ostream& operator<<(std::ostream&, PieceStand l);
269 
271  {
275  static std::ostream& writeNumbers(std::ostream&, const PieceStand& stand);
276  static std::istream& readNumbers(std::istream&, PieceStand& stand);
277  };
278 } // namespace osl
279 
280 #endif /* OSL_PIECESTAND_H */
281 // ;;; Local Variables:
282 // ;;; mode:c++
283 // ;;; c-basic-offset:2
284 // ;;; End:
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に,promote前の型を返す. promoteしていない型の時はそのまま返す ...
Definition: basic_type.h:157
bool isSuperiorOrEqualTo(PieceStand other) const
void add(Ptype type, unsigned int num=1)
PieceStand(int pawnCount, int lanceCount, int knightCount, int silverCount, int goldCount, int bishopCount, int rookCount, int kingCount)
static const CArray< unsigned char, PTYPE_MAX+1 > shift
bool isNormal() const
INVALID でも PASS でもない.
Definition: basic_type.h:1088
std::ostream & operator<<(std::ostream &os, Player player)
Definition: basic_type.cc:14
const PieceStand nextStand(Player pl, Move move) const
bool atMostOneKind() const
一種類の駒しかない
Definition: pieceStand.cc:53
unsigned int testCarries() const
Ptype
駒の種類を4ビットでコード化する
Definition: basic_type.h:83
static const CArray< unsigned char, PTYPE_MAX+1 > mask
Ptype ptype() const
Definition: basic_type.h:1155
void subAtmostOnePiece(PieceStand const &ps)
圧縮していない moveの表現 .
Definition: basic_type.h:1051
bool isBasic(Ptype ptype)
ptypeが基本型(promoteしていない)かのチェック
Definition: basic_type.h:128
const PieceStand previousStand(Move move) const
const PieceStand previousStand(Player pl, Move move) const
bool hasMoreThan(Player P, PieceStand other) const
Player player() const
Definition: basic_type.h:1195
bool operator<(Offset l, Offset r)
Definition: basic_type.h:520
bool canAdd(Ptype type) const
Definition: pieceStand.cc:39
bool carryUnchangedAfterSub(const PieceStand &original, const PieceStand &other) const
Definition: pieceStand.cc:69
void carriesOff() const
unsigned int getFlags() const
void tryAdd(Ptype type)
加算可能なら加える.
Definition: pieceStand.cc:47
bool hasMoreThan(PieceStand other) const
this と other が BLACK の持駒と考えた時に, this の方が同じか沢山持っていれば真.
Ptype capturePtype() const
Definition: basic_type.h:1180
bool isDrop() const
Definition: basic_type.h:1150
unsigned int flags
bool any() const
どれかの駒を一枚でも持っている
static const unsigned int carryMask
void trySub(Ptype type)
1枚以上持っていれば減らす
const PieceStand max2(PieceStand other) const
種類毎に this と other の持駒の多い方を取る (max のalternative)
static const CArray< Ptype, 7 > order
持駒の表示で良く使われる順番.
Player
Definition: basic_type.h:8
bool carryUnchangedAfterAdd(const PieceStand &original, const PieceStand &other) const
Definition: pieceStand.cc:60
void sub(Ptype type, unsigned int num=1)
const PieceStand max(PieceStand other) const
種類毎に this と other の持駒の多い方を取る
bool operator==(Square l, Square r)
Definition: basic_type.h:758
void carriesOn() const
片方の手番の持駒の枚数を記録するクラス.
bool operator!=(Offset l, Offset r)
Definition: basic_type.h:516
void addAtmostOnePiece(PieceStand const &ps)
pieceStand同士の加算,減算.
const PieceStand nextStand(Move move) const
PieceStand(unsigned int value=0)