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