pieceStand.h
Go to the documentation of this file.
00001 /* pieceStand.h
00002  */
00003 #ifndef OSL_PIECESTAND_H
00004 #define OSL_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);       // overflow 検出
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       // other以上の数持っているptypeに対応するcarryが1になる.
00177       const unsigned int mask0 = ((flags|carryMask)-other.flags) & carryMask;
00178       // ROOK BISHOP KING用のMASKを作る
00179       unsigned int my_mask = mask0-((mask0&0x40000024)>>2);
00180       // GOLD SILVER KNIGHT LANCE用のMASKを作る
00181       my_mask -= (mask0&0x08022200)>>3;
00182       // PAWN用のMASKのみ残す
00183       my_mask -= (mask0&0x00800000)>>5;
00184       // my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
00185       return PieceStand((flags&my_mask)|(other.flags&~my_mask));
00186     }     
00190     const PieceStand max2(PieceStand other) const
00191     {
00192       // other以上の数持っているptypeに対応するcarryが1になる.
00193       const unsigned int diff0=((flags|carryMask)-other.flags);
00194       const unsigned int mask0=diff0&carryMask;
00195 
00196       // ROOK BISHOP KING GOLD SILVER KNIGHT LANCE用のMASKを作る
00197       const unsigned int mask02=(mask0&0x40000024u)+(mask0&0x48022224u);
00198       unsigned int my_mask=mask0-(mask02>>3);
00199 
00200       // PAWN用のMASKのみ残す
00201       my_mask -= (mask0&0x00800000)>>5;
00202       // my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
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 } // namespace osl
00273 
00274 #endif /* OSL_PIECESTAND_H */
00275 // ;;; Local Variables:
00276 // ;;; mode:c++
00277 // ;;; c-basic-offset:2
00278 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines