pieceStand.h Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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: