All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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/move.h"
6 #include "osl/misc/carray.h"
7 #include <iosfwd>
8 #include <cassert>
9 namespace osl
10 {
11  namespace state
12  {
13  class SimpleState;
14  }
40  class PieceStand
41  {
42  public:
44  static const CArray<Ptype,7> order;
45  static const unsigned int carryMask = 0x48822224;
46  private:
47  static const CArray<unsigned char,PTYPE_MAX+1> shift;
48  static const CArray<unsigned char,PTYPE_MAX+1> mask;
49  mutable unsigned int flags;
50  public:
51  explicit PieceStand(unsigned int value=0) : flags(value)
52  {
53  }
54  explicit PieceStand(Player, const state::SimpleState&);
55  PieceStand(int pawnCount, int lanceCount,
56  int knightCount, int silverCount,
57  int goldCount, int bishopCount,
58  int rookCount, int kingCount)
59  : flags(0)
60  {
61  add(PAWN, pawnCount);
62  add(LANCE, lanceCount);
63  add(KNIGHT, knightCount);
64  add(SILVER, silverCount);
65  add(GOLD, goldCount);
66  add(BISHOP, bishopCount);
67  add(ROOK, rookCount);
68  add(KING, kingCount);
69  }
70 
71  void add(Ptype type, unsigned int num=1)
72  {
73  assert(isBasic(type));
74  assert(num == (num & mask[type]));
75  flags += (num << (shift[type]));
76  assert(testCarries() == 0); // overflow 検出
77  }
78  void sub(Ptype type, unsigned int num=1)
79  {
80  assert(isBasic(type));
81  assert(num == (num & mask[type]));
82  assert(get(type) >= num);
83  flags -= (num << (shift[type]));
84  }
85 
90  void tryAdd(Ptype type);
91  bool canAdd(Ptype type) const;
95  void trySub(Ptype type)
96  {
97  if (get(type))
98  sub(type);
99  }
100 
104  bool atMostOneKind() const;
105 
111  void addAtmostOnePiece(PieceStand const& ps){
112 #ifndef NDEBUG
113  const PieceStand copy(*this);
114 #endif
115  assert(! ps.testCarries());
116  assert(ps.atMostOneKind());
117  flags += ps.getFlags();
118  assert(carryUnchangedAfterAdd(copy, ps));
119  }
120 
121  void subAtmostOnePiece(PieceStand const& ps){
122 #ifndef NDEBUG
123  const PieceStand copy(*this);
124 #endif
125  assert(! ps.testCarries());
126  assert(ps.atMostOneKind());
127  flags -= ps.getFlags();
128  assert(carryUnchangedAfterSub(copy, ps));
129  }
130  private:
131  bool carryUnchangedAfterAdd(const PieceStand& original, const PieceStand& other) const;
132  bool carryUnchangedAfterSub(const PieceStand& original, const PieceStand& other) const;
133  public:
134  unsigned int get(Ptype type) const
135  {
136  return (flags >> (shift[type])) & mask[type];
137  }
138  void carriesOff() const { flags &= (~carryMask); }
139  void carriesOn() const { flags |= carryMask; }
140  unsigned int testCarries() const { return (flags & carryMask); }
141  bool isSuperiorOrEqualTo(PieceStand other) const
142  {
143  carriesOn();
144  other.carriesOff();
145  const bool result = (((flags - other.flags) & carryMask) == carryMask);
146  carriesOff();
147  return result;
148  }
153  template <Player P>
154  bool hasMoreThan(PieceStand other) const
155  {
156  if (P == BLACK)
157  return isSuperiorOrEqualTo(other);
158  else
159  return other.isSuperiorOrEqualTo(*this);
160  }
161  bool hasMoreThan(Player P, PieceStand other) const
162  {
163  if (P == BLACK)
164  return hasMoreThan<BLACK>(other);
165  else
166  return hasMoreThan<WHITE>(other);
167  }
168  unsigned int getFlags() const { return flags; }
170  bool any() const { return flags; }
174  const PieceStand max(PieceStand other) const
175  {
176  // other以上の数持っているptypeに対応するcarryが1になる.
177  const unsigned int mask0 = ((flags|carryMask)-other.flags) & carryMask;
178  // ROOK BISHOP KING用のMASKを作る
179  unsigned int my_mask = mask0-((mask0&0x40000024)>>2);
180  // GOLD SILVER KNIGHT LANCE用のMASKを作る
181  my_mask -= (mask0&0x08022200)>>3;
182  // PAWN用のMASKのみ残す
183  my_mask -= (mask0&0x00800000)>>5;
184  // my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
185  return PieceStand((flags&my_mask)|(other.flags&~my_mask));
186  }
190  const PieceStand max2(PieceStand other) const
191  {
192  // other以上の数持っているptypeに対応するcarryが1になる.
193  const unsigned int diff0=((flags|carryMask)-other.flags);
194  const unsigned int mask0=diff0&carryMask;
195 
196  // ROOK BISHOP KING GOLD SILVER KNIGHT LANCE用のMASKを作る
197  const unsigned int mask02=(mask0&0x40000024u)+(mask0&0x48022224u);
198  unsigned int my_mask=mask0-(mask02>>3);
199 
200  // PAWN用のMASKのみ残す
201  my_mask -= (mask0&0x00800000)>>5;
202  // my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
203  return PieceStand((other.flags+(diff0&my_mask))&~carryMask);
204  }
205 
206  const PieceStand nextStand(Player pl, Move move) const
207  {
208  assert(move.isNormal());
209  PieceStand result = *this;
210  if (move.player() == pl)
211  {
212  if (const Ptype ptype = move.capturePtype())
213  {
214  result.add(unpromote(ptype));
215  }
216  else if (move.isDrop())
217  {
218  const Ptype ptype = move.ptype();
219  assert(get(ptype));
220  result.sub(ptype);
221  }
222  }
223  return result;
224  }
225  const PieceStand nextStand(Move move) const
226  {
227  return nextStand(move.player(), move);
228  }
229  const PieceStand previousStand(Player pl, Move move) const
230  {
231  assert(move.isNormal());
232  PieceStand result = *this;
233  if (move.player() == pl)
234  {
235  if (const Ptype ptype = move.capturePtype())
236  {
237  const Ptype before = unpromote(ptype);
238  assert(get(before));
239  result.sub(before);
240  }
241  else if (move.isDrop())
242  {
243  const Ptype ptype = move.ptype();
244  result.add(ptype);
245  }
246  }
247  return result;
248  }
249  const PieceStand previousStand(Move move) const
250  {
251  return previousStand(move.player(), move);
252  }
253  };
254 
255  inline bool operator==(PieceStand l, PieceStand r)
256  {
257  assert(! l.testCarries());
258  assert(! r.testCarries());
259  return l.getFlags() == r.getFlags();
260  }
261  inline bool operator!=(PieceStand l, PieceStand r)
262  {
263  return ! (l == r);
264  }
265  inline bool operator<(PieceStand l, PieceStand r)
266  {
267  assert(! l.testCarries());
268  assert(! r.testCarries());
269  return l.getFlags() < r.getFlags();
270  }
271  std::ostream& operator<<(std::ostream&, PieceStand l);
272 } // namespace osl
273 
274 #endif /* OSL_PIECESTAND_H */
275 // ;;; Local Variables:
276 // ;;; mode:c++
277 // ;;; c-basic-offset:2
278 // ;;; End: