説明を見る。00001
00002
00003 #ifndef OSL_PIECESTAND_H
00004 #define OSL_PIECESTAND_H
00005 #include "osl/basic_type.h"
00006 #include "osl/container.h"
00007 #include <iosfwd>
00008 #include <cassert>
00009 namespace osl
00010 {
00011 class SimpleState;
00037 class PieceStand
00038 {
00039 public:
00041 static const CArray<Ptype,7> order;
00042 static const unsigned int carryMask = 0x48822224;
00043 private:
00044 static const CArray<unsigned char,PTYPE_MAX+1> shift;
00045 static const CArray<unsigned char,PTYPE_MAX+1> mask;
00046 mutable unsigned int flags;
00047 public:
00048 explicit PieceStand(unsigned int value=0) : flags(value)
00049 {
00050 }
00051 explicit PieceStand(Player, const SimpleState&);
00052 PieceStand(int pawnCount, int lanceCount,
00053 int knightCount, int silverCount,
00054 int goldCount, int bishopCount,
00055 int rookCount, int kingCount)
00056 : flags(0)
00057 {
00058 add(PAWN, pawnCount);
00059 add(LANCE, lanceCount);
00060 add(KNIGHT, knightCount);
00061 add(SILVER, silverCount);
00062 add(GOLD, goldCount);
00063 add(BISHOP, bishopCount);
00064 add(ROOK, rookCount);
00065 add(KING, kingCount);
00066 }
00067
00068 void add(Ptype type, unsigned int num=1)
00069 {
00070 assert(isBasic(type));
00071 assert(num == (num & mask[type]));
00072 flags += (num << (shift[type]));
00073 assert(testCarries() == 0);
00074 }
00075 void sub(Ptype type, unsigned int num=1)
00076 {
00077 assert(isBasic(type));
00078 assert(num == (num & mask[type]));
00079 assert(get(type) >= num);
00080 flags -= (num << (shift[type]));
00081 }
00082
00087 void tryAdd(Ptype type);
00088 bool canAdd(Ptype type) const;
00092 void trySub(Ptype type)
00093 {
00094 if (get(type))
00095 sub(type);
00096 }
00097
00101 bool atMostOneKind() const;
00102
00108 void addAtmostOnePiece(PieceStand const& ps){
00109 #ifndef NDEBUG
00110 const PieceStand copy(*this);
00111 #endif
00112 assert(! ps.testCarries());
00113 assert(ps.atMostOneKind());
00114 flags += ps.getFlags();
00115 assert(carryUnchangedAfterAdd(copy, ps));
00116 }
00117
00118 void subAtmostOnePiece(PieceStand const& ps){
00119 #ifndef NDEBUG
00120 const PieceStand copy(*this);
00121 #endif
00122 assert(! ps.testCarries());
00123 assert(ps.atMostOneKind());
00124 flags -= ps.getFlags();
00125 assert(carryUnchangedAfterSub(copy, ps));
00126 }
00127 private:
00128 bool carryUnchangedAfterAdd(const PieceStand& original, const PieceStand& other) const;
00129 bool carryUnchangedAfterSub(const PieceStand& original, const PieceStand& other) const;
00130 public:
00131 unsigned int get(Ptype type) const
00132 {
00133 return (flags >> (shift[type])) & mask[type];
00134 }
00135 void carriesOff() const { flags &= (~carryMask); }
00136 void carriesOn() const { flags |= carryMask; }
00137 unsigned int testCarries() const { return (flags & carryMask); }
00138 bool isSuperiorOrEqualTo(PieceStand other) const
00139 {
00140 carriesOn();
00141 other.carriesOff();
00142 const bool result = (((flags - other.flags) & carryMask) == carryMask);
00143 carriesOff();
00144 return result;
00145 }
00150 template <Player P>
00151 bool hasMoreThan(PieceStand other) const
00152 {
00153 if (P == BLACK)
00154 return isSuperiorOrEqualTo(other);
00155 else
00156 return other.isSuperiorOrEqualTo(*this);
00157 }
00158 bool hasMoreThan(Player P, PieceStand other) const
00159 {
00160 if (P == BLACK)
00161 return hasMoreThan<BLACK>(other);
00162 else
00163 return hasMoreThan<WHITE>(other);
00164 }
00165 unsigned int getFlags() const { return flags; }
00167 bool any() const { return flags; }
00171 const PieceStand max(PieceStand other) const
00172 {
00173
00174 const unsigned int mask0 = ((flags|carryMask)-other.flags) & carryMask;
00175
00176 unsigned int my_mask = mask0-((mask0&0x40000024)>>2);
00177
00178 my_mask -= (mask0&0x08022200)>>3;
00179
00180 my_mask -= (mask0&0x00800000)>>5;
00181
00182 return PieceStand((flags&my_mask)|(other.flags&~my_mask));
00183 }
00187 const PieceStand max2(PieceStand other) const
00188 {
00189
00190 const unsigned int diff0=((flags|carryMask)-other.flags);
00191 const unsigned int mask0=diff0&carryMask;
00192
00193
00194 const unsigned int mask02=(mask0&0x40000024u)+(mask0&0x48022224u);
00195 unsigned int my_mask=mask0-(mask02>>3);
00196
00197
00198 my_mask -= (mask0&0x00800000)>>5;
00199
00200 return PieceStand((other.flags+(diff0&my_mask))&~carryMask);
00201 }
00202
00203 const PieceStand nextStand(Player pl, Move move) const
00204 {
00205 assert(move.isNormal());
00206 PieceStand result = *this;
00207 if (move.player() == pl)
00208 {
00209 if (const Ptype ptype = move.capturePtype())
00210 {
00211 result.add(unpromote(ptype));
00212 }
00213 else if (move.isDrop())
00214 {
00215 const Ptype ptype = move.ptype();
00216 assert(get(ptype));
00217 result.sub(ptype);
00218 }
00219 }
00220 return result;
00221 }
00222 const PieceStand nextStand(Move move) const
00223 {
00224 return nextStand(move.player(), move);
00225 }
00226 const PieceStand previousStand(Player pl, Move move) const
00227 {
00228 assert(move.isNormal());
00229 PieceStand result = *this;
00230 if (move.player() == pl)
00231 {
00232 if (const Ptype ptype = move.capturePtype())
00233 {
00234 const Ptype before = unpromote(ptype);
00235 assert(get(before));
00236 result.sub(before);
00237 }
00238 else if (move.isDrop())
00239 {
00240 const Ptype ptype = move.ptype();
00241 result.add(ptype);
00242 }
00243 }
00244 return result;
00245 }
00246 const PieceStand previousStand(Move move) const
00247 {
00248 return previousStand(move.player(), move);
00249 }
00250 };
00251
00252 inline bool operator==(PieceStand l, PieceStand r)
00253 {
00254 assert(! l.testCarries());
00255 assert(! r.testCarries());
00256 return l.getFlags() == r.getFlags();
00257 }
00258 inline bool operator!=(PieceStand l, PieceStand r)
00259 {
00260 return ! (l == r);
00261 }
00262 inline bool operator<(PieceStand l, PieceStand r)
00263 {
00264 assert(! l.testCarries());
00265 assert(! r.testCarries());
00266 return l.getFlags() < r.getFlags();
00267 }
00268 std::ostream& operator<<(std::ostream&, PieceStand l);
00269
00270 struct PieceStandIO
00271 {
00275 static std::ostream& writeNumbers(std::ostream&, const PieceStand& stand);
00276 static std::istream& readNumbers(std::istream&, PieceStand& stand);
00277 };
00278 }
00279
00280 #endif
00281
00282
00283
00284