/usr/include/osl/pieceStand.h is in libosl-dev 0.4.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | /* pieceStand.h
*/
#ifndef OSL_PIECESTAND_H
#define OSL_PIECESTAND_H
#include "osl/move.h"
#include "osl/misc/carray.h"
#include <iosfwd>
#include <cassert>
namespace osl
{
namespace state
{
class SimpleState;
}
/**
* 片方の手番の持駒の枚数を記録するクラス.
* - bit field を使うべきか迷う
* - 一応 king を持駒にして良いことにしておく
* レイアウト 長さ:index
* - reserved : 1;31
* - carry : 1;
* - KING : 2;28
* - carry : 1;
* - GOLD : 3;24
* - carry : 1;
* - PAWN : 5;18
* - carry : 1;
* - LANCE : 3;14
* - carry : 1;
* - KNIGHT : 3;10
* - carry : 1;
* - SILVER : 3; 6
* - carry : 1;
* - BISHOP : 2; 3
* - carry : 1;
* - ROOK : 2; 0
*
* == を軽くするために carry off の状態を基本とする
*/
class PieceStand
{
public:
/** 持駒の表示で良く使われる順番. KINGや成駒は -1 */
static const CArray<Ptype,7> order;
static const unsigned int carryMask = 0x48822224;
private:
static const CArray<unsigned char,PTYPE_MAX+1> shift;
static const CArray<unsigned char,PTYPE_MAX+1> mask;
mutable unsigned int flags;
public:
explicit PieceStand(unsigned int value=0) : flags(value)
{
}
explicit PieceStand(Player, const state::SimpleState&);
PieceStand(int pawnCount, int lanceCount,
int knightCount, int silverCount,
int goldCount, int bishopCount,
int rookCount, int kingCount)
: flags(0)
{
add(PAWN, pawnCount);
add(LANCE, lanceCount);
add(KNIGHT, knightCount);
add(SILVER, silverCount);
add(GOLD, goldCount);
add(BISHOP, bishopCount);
add(ROOK, rookCount);
add(KING, kingCount);
}
void add(Ptype type, unsigned int num=1)
{
assert(isBasic(type));
assert(num == (num & mask[type]));
flags += (num << (shift[type]));
assert(testCarries() == 0); // overflow 検出
}
void sub(Ptype type, unsigned int num=1)
{
assert(isBasic(type));
assert(num == (num & mask[type]));
assert(get(type) >= num);
flags -= (num << (shift[type]));
}
/**
* 加算可能なら加える.
* 速度が必要なところでは使ってないので .cc に移動.
*/
void tryAdd(Ptype type);
bool canAdd(Ptype type) const;
/**
* 1枚以上持っていれば減らす
*/
void trySub(Ptype type)
{
if (get(type))
sub(type);
}
/**
* 一種類の駒しかない
*/
bool atMostOneKind() const;
/**
* pieceStand同士の加算,減算.
* 足して良いのは,carry が立っていないpiecestandで
* かつ,含まれる駒が高々1つ
*/
void addAtmostOnePiece(PieceStand const& ps){
#ifndef NDEBUG
const PieceStand copy(*this);
#endif
assert(! ps.testCarries());
assert(ps.atMostOneKind());
flags += ps.getFlags();
assert(carryUnchangedAfterAdd(copy, ps));
}
void subAtmostOnePiece(PieceStand const& ps){
#ifndef NDEBUG
const PieceStand copy(*this);
#endif
assert(! ps.testCarries());
assert(ps.atMostOneKind());
flags -= ps.getFlags();
assert(carryUnchangedAfterSub(copy, ps));
}
private:
bool carryUnchangedAfterAdd(const PieceStand& original, const PieceStand& other) const;
bool carryUnchangedAfterSub(const PieceStand& original, const PieceStand& other) const;
public:
unsigned int get(Ptype type) const
{
return (flags >> (shift[type])) & mask[type];
}
void carriesOff() const { flags &= (~carryMask); }
void carriesOn() const { flags |= carryMask; }
unsigned int testCarries() const { return (flags & carryMask); }
bool isSuperiorOrEqualTo(PieceStand other) const
{
carriesOn();
other.carriesOff();
const bool result = (((flags - other.flags) & carryMask) == carryMask);
carriesOff();
return result;
}
/**
* this と other が BLACK の持駒と考えた時に,
* this の方が同じか沢山持っていれば真.
*/
template <Player P>
bool hasMoreThan(PieceStand other) const
{
if (P == BLACK)
return isSuperiorOrEqualTo(other);
else
return other.isSuperiorOrEqualTo(*this);
}
bool hasMoreThan(Player P, PieceStand other) const
{
if (P == BLACK)
return hasMoreThan<BLACK>(other);
else
return hasMoreThan<WHITE>(other);
}
unsigned int getFlags() const { return flags; }
/** どれかの駒を一枚でも持っている */
bool any() const { return flags; }
/**
* 種類毎に this と other の持駒の多い方を取る
*/
const PieceStand max(PieceStand other) const
{
// other以上の数持っているptypeに対応するcarryが1になる.
const unsigned int mask0 = ((flags|carryMask)-other.flags) & carryMask;
// ROOK BISHOP KING用のMASKを作る
unsigned int my_mask = mask0-((mask0&0x40000024)>>2);
// GOLD SILVER KNIGHT LANCE用のMASKを作る
my_mask -= (mask0&0x08022200)>>3;
// PAWN用のMASKのみ残す
my_mask -= (mask0&0x00800000)>>5;
// my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
return PieceStand((flags&my_mask)|(other.flags&~my_mask));
}
/**
* 種類毎に this と other の持駒の多い方を取る (max のalternative)
*/
const PieceStand max2(PieceStand other) const
{
// other以上の数持っているptypeに対応するcarryが1になる.
const unsigned int diff0=((flags|carryMask)-other.flags);
const unsigned int mask0=diff0&carryMask;
// ROOK BISHOP KING GOLD SILVER KNIGHT LANCE用のMASKを作る
const unsigned int mask02=(mask0&0x40000024u)+(mask0&0x48022224u);
unsigned int my_mask=mask0-(mask02>>3);
// PAWN用のMASKのみ残す
my_mask -= (mask0&0x00800000)>>5;
// my_mask が1のptypeの数は自分から,0のptypeはotherのところの値を
return PieceStand((other.flags+(diff0&my_mask))&~carryMask);
}
const PieceStand nextStand(Player pl, Move move) const
{
assert(move.isNormal());
PieceStand result = *this;
if (move.player() == pl)
{
if (const Ptype ptype = move.capturePtype())
{
result.add(unpromote(ptype));
}
else if (move.isDrop())
{
const Ptype ptype = move.ptype();
assert(get(ptype));
result.sub(ptype);
}
}
return result;
}
const PieceStand nextStand(Move move) const
{
return nextStand(move.player(), move);
}
const PieceStand previousStand(Player pl, Move move) const
{
assert(move.isNormal());
PieceStand result = *this;
if (move.player() == pl)
{
if (const Ptype ptype = move.capturePtype())
{
const Ptype before = unpromote(ptype);
assert(get(before));
result.sub(before);
}
else if (move.isDrop())
{
const Ptype ptype = move.ptype();
result.add(ptype);
}
}
return result;
}
const PieceStand previousStand(Move move) const
{
return previousStand(move.player(), move);
}
};
inline bool operator==(PieceStand l, PieceStand r)
{
assert(! l.testCarries());
assert(! r.testCarries());
return l.getFlags() == r.getFlags();
}
inline bool operator!=(PieceStand l, PieceStand r)
{
return ! (l == r);
}
inline bool operator<(PieceStand l, PieceStand r)
{
assert(! l.testCarries());
assert(! r.testCarries());
return l.getFlags() < r.getFlags();
}
std::ostream& operator<<(std::ostream&, PieceStand l);
} // namespace osl
#endif /* OSL_PIECESTAND_H */
// ;;; Local Variables:
// ;;; mode:c++
// ;;; c-basic-offset:2
// ;;; End:
|