00001
00002
00003
00004
00005
00006 #include "BoardUtils.hpp"
00007 #include "StoneBoard.hpp"
00008
00009 using namespace benzene;
00010
00011
00012
00013 StoneBoard::StoneBoard()
00014 : m_const(0),
00015 m_hash(0, 0)
00016 {
00017 }
00018
00019 StoneBoard::StoneBoard(unsigned size)
00020 : m_const(&ConstBoard::Get(size)),
00021 m_hash(size, size)
00022 {
00023 StartNewGame();
00024 }
00025
00026 StoneBoard::StoneBoard(unsigned width, unsigned height)
00027 : m_const(&ConstBoard::Get(width, height)),
00028 m_hash(width, height)
00029 {
00030 StartNewGame();
00031 }
00032
00033 StoneBoard::StoneBoard(unsigned width, unsigned height, const std::string& str)
00034 : m_const(&ConstBoard::Get(width, height)),
00035 m_hash(width, height)
00036 {
00037 SetPosition(str);
00038 }
00039
00040 StoneBoard::~StoneBoard()
00041 {
00042 }
00043
00044
00045
00046 HexColor StoneBoard::GetColor(HexPoint cell) const
00047 {
00048 HexAssert(Const().IsValid(cell));
00049 if (IsBlack(cell)) return BLACK;
00050 if (IsWhite(cell)) return WHITE;
00051 return EMPTY;
00052 }
00053
00054 bitset_t StoneBoard::GetLegal() const
00055 {
00056 bitset_t legal;
00057 if (IsPlayed(RESIGN))
00058 return legal;
00059
00060 legal = ~GetPlayed() & Const().GetCells();
00061 legal.set(RESIGN);
00062
00063
00064
00065 if (GetPlayed().count() == 5)
00066 {
00067 HexAssert(!IsPlayed(SWAP_PIECES));
00068 HexAssert(GetColor(FIRST_TO_PLAY).count() >= 3);
00069 HexAssert((GetPlayed(FIRST_TO_PLAY)).count() == 3);
00070 HexAssert(GetColor(!FIRST_TO_PLAY).count() == 2);
00071 legal.set(SWAP_PIECES);
00072 }
00073 HexAssert(Const().IsValid(legal));
00074 return legal;
00075 }
00076
00077 bool StoneBoard::IsLegal(HexPoint cell) const
00078 {
00079 HexAssert(Const().IsValid(cell));
00080 return GetLegal().test(cell);
00081 }
00082
00083 BoardIterator StoneBoard::Stones(HexColorSet colorset) const
00084 {
00085 if (!m_stones_calculated)
00086 {
00087 for (int i = 0; i < NUM_COLOR_SETS; ++i)
00088 {
00089 m_stones_list[i].clear();
00090 for (BoardIterator p(Const().EdgesAndInterior()); p; ++p)
00091 if (HexColorSetUtil::InSet(GetColor(*p), (HexColorSet)i))
00092 m_stones_list[i].push_back(*p);
00093 m_stones_list[i].push_back(INVALID_POINT);
00094 }
00095 m_stones_calculated = true;
00096 }
00097 return BoardIterator(m_stones_list[colorset]);
00098 }
00099
00100
00101
00102 void StoneBoard::MarkAsDirty()
00103 {
00104 m_stones_calculated = false;
00105 }
00106
00107 void StoneBoard::AddColor(HexColor color, const bitset_t& b)
00108 {
00109 HexAssert(HexColorUtil::isBlackWhite(color));
00110 m_stones[color] |= b;
00111 HexAssert(IsBlackWhiteDisjoint());
00112 if (b.any()) MarkAsDirty();
00113 }
00114
00115 void StoneBoard::RemoveColor(HexColor color, const bitset_t& b)
00116 {
00117 HexAssert(HexColorUtil::isBlackWhite(color));
00118 m_stones[color] = m_stones[color] - b;
00119 HexAssert(IsBlackWhiteDisjoint());
00120 if (b.any()) MarkAsDirty();
00121 }
00122
00123 void StoneBoard::SetColor(HexColor color, HexPoint cell)
00124 {
00125 HexAssert(HexColorUtil::isValidColor(color));
00126 HexAssert(Const().IsValid(cell));
00127
00128 if (color == EMPTY) {
00129 for (BWIterator it; it; ++it)
00130 m_stones[*it].reset(cell);
00131 } else {
00132 m_stones[color].set(cell);
00133 HexAssert(IsBlackWhiteDisjoint());
00134 }
00135
00136 MarkAsDirty();
00137 }
00138
00139 void StoneBoard::SetColor(HexColor color, const bitset_t& bs)
00140 {
00141
00142 HexAssert(HexColorUtil::isBlackWhite(color));
00143 HexAssert(Const().IsValid(bs));
00144
00145 m_stones[color] = bs;
00146 HexAssert(IsBlackWhiteDisjoint());
00147
00148 MarkAsDirty();
00149 }
00150
00151 void StoneBoard::SetPlayed(const bitset_t& played)
00152 {
00153 m_played = played;
00154 ComputeHash();
00155 MarkAsDirty();
00156 }
00157
00158
00159
00160 void StoneBoard::ComputeHash()
00161 {
00162
00163 bitset_t mask = m_played & Const().GetLocations();
00164 m_hash.Compute(m_stones[BLACK] & mask, m_stones[WHITE] & mask);
00165 }
00166
00167 void StoneBoard::StartNewGame()
00168 {
00169 m_played.reset();
00170 for (BWIterator it; it; ++it)
00171 {
00172 m_stones[*it].reset();
00173 PlayMove(*it, HexPointUtil::colorEdge1(*it));
00174 PlayMove(*it, HexPointUtil::colorEdge2(*it));
00175 }
00176 ComputeHash();
00177 MarkAsDirty();
00178 }
00179
00180 void StoneBoard::PlayMove(HexColor color, HexPoint cell)
00181 {
00182 HexAssert(HexColorUtil::isBlackWhite(color));
00183 HexAssert(Const().IsValid(cell));
00184
00185 m_played.set(cell);
00186 if (Const().IsLocation(cell))
00187 m_hash.Update(color, cell);
00188 SetColor(color, cell);
00189
00190 MarkAsDirty();
00191 }
00192
00193 void StoneBoard::UndoMove(HexPoint cell)
00194 {
00195 HexAssert(Const().IsValid(cell));
00196 HexColor color = GetColor(cell);
00197 HexAssert(color != EMPTY);
00198
00199 m_played.reset(cell);
00200 if (Const().IsLocation(cell))
00201 m_hash.Update(color, cell);
00202 SetColor(EMPTY, cell);
00203
00204 MarkAsDirty();
00205 }
00206
00207
00208
00209 void StoneBoard::RotateBoard()
00210 {
00211 m_played = BoardUtils::Rotate(Const(), m_played);
00212 for (BWIterator it; it; ++it)
00213 m_stones[*it] = BoardUtils::Rotate(Const(), m_stones[*it]);
00214 ComputeHash();
00215 MarkAsDirty();
00216 }
00217
00218 bool StoneBoard::IsSelfRotation() const
00219 {
00220 if (m_stones[BLACK] != BoardUtils::Rotate(Const(), m_stones[BLACK]))
00221 return false;
00222 if (m_stones[WHITE] != BoardUtils::Rotate(Const(), m_stones[WHITE]))
00223 return false;
00224 return true;
00225 }
00226
00227 void StoneBoard::MirrorBoard()
00228 {
00229 m_played = BoardUtils::Mirror(Const(), m_played);
00230 for (BWIterator it; it; ++it)
00231 m_stones[*it] = BoardUtils::Mirror(Const(), m_stones[*it]);
00232 ComputeHash();
00233 MarkAsDirty();
00234 }
00235
00236
00237
00238 BoardID StoneBoard::GetBoardID() const
00239 {
00240
00241
00242 std::size_t n = (Width() * Height() + 3) / 4 * 4;
00243
00244
00245
00246
00247
00248
00249 std::size_t i = 0;
00250 std::vector<byte> val(n, 0);
00251 bitset_t played = GetPlayed();
00252 for (BoardIterator p(Const().Interior()); p; ++p, ++i)
00253 val[i] = (played.test(*p))
00254 ? static_cast<byte>(GetColor(*p))
00255 : static_cast<byte>(EMPTY);
00256
00257 BoardID id;
00258 for (i = 0; i < n; i += 4)
00259 id.push_back(static_cast<byte>(val[i]
00260 + (val[i+1] << 2)
00261 + (val[i+2] << 4)
00262 + (val[i+3] << 6)));
00263 return id;
00264 }
00265
00266 std::string StoneBoard::GetBoardIDString() const
00267 {
00268 std::string hexval[16] = {"0", "1", "2", "3", "4", "5", "6", "7",
00269 "8", "9", "a", "b", "c", "d", "e", "f"};
00270 BoardID brdID = GetBoardID();
00271 std::string idString;
00272 for (std::size_t i = 0; i < brdID.size(); ++i) {
00273 byte b = brdID[i];
00274 idString += hexval[((b >> 4) & 0xF)];
00275 idString += hexval[b & 0x0F];
00276 }
00277 return idString;
00278 }
00279
00280 void StoneBoard::SetPosition(const StoneBoard& brd)
00281 {
00282 StartNewGame();
00283 SetColor(BLACK, brd.GetBlack());
00284 SetColor(WHITE, brd.GetWhite());
00285 SetPlayed(brd.GetPlayed());
00286 }
00287
00288 void StoneBoard::SetPositionOnlyPlayed(const StoneBoard& brd)
00289 {
00290 StartNewGame();
00291 SetColor(BLACK, brd.GetBlack() & brd.GetPlayed());
00292 SetColor(WHITE, brd.GetWhite() & brd.GetPlayed());
00293 SetPlayed(brd.GetPlayed());
00294 }
00295
00296 void StoneBoard::SetPosition(const BoardID& id)
00297 {
00298 std::size_t n = (Width() * Height() + 3) / 4 * 4;
00299 HexAssert(id.size() == n / 4);
00300
00301 std::vector<byte> val(n, 0);
00302 for (std::size_t i = 0; i < n; i += 4)
00303 {
00304 byte packed = id[i/4];
00305 val[i] = packed & 0x3;
00306 val[i+1] = (packed >> 2) & 0x3;
00307 val[i+2] = (packed >> 4) & 0x3;
00308 val[i+3] = (packed >> 6) & 0x3;
00309 }
00310
00311
00312
00313 StartNewGame();
00314 std::size_t i = 0;
00315 for (BoardIterator p(Const().Interior()); p; ++p, ++i)
00316 {
00317 HexColor color = static_cast<HexColor>(val[i]);
00318 if (color == BLACK || color == WHITE)
00319 PlayMove(color, *p);
00320 }
00321
00322 ComputeHash();
00323 MarkAsDirty();
00324 }
00325
00326 void StoneBoard::SetPosition(const std::string& str)
00327 {
00328
00329 StartNewGame();
00330 int cell = 0;
00331 for (std::size_t i = 0;
00332 i < str.size() && cell < Width() * Height();
00333 ++i)
00334 {
00335 int x = cell % Width();
00336 int y = cell / Width();
00337 HexPoint p = HexPointUtil::coordsToPoint(x, y);
00338 if (str[i] == '.')
00339 cell++;
00340 else if (str[i] == 'B')
00341 {
00342 PlayMove(BLACK, p);
00343 cell++;
00344 }
00345 else if (str[i] == 'W')
00346 {
00347 PlayMove(WHITE, p);
00348 cell++;
00349 }
00350 else if (str[i] == 'b')
00351 {
00352 SetColor(BLACK, p);
00353 cell++;
00354 }
00355 else if (str[i] == 'w')
00356 {
00357 SetColor(WHITE, p);
00358 cell++;
00359 }
00360 }
00361 ComputeHash();
00362 MarkAsDirty();
00363 }
00364
00365
00366
00367 std::string StoneBoard::Write() const
00368 {
00369 return Write(EMPTY_BITSET);
00370 }
00371
00372 std::string StoneBoard::Write(const bitset_t& b) const
00373 {
00374 std::ostringstream out;
00375 out << '\n';
00376 out << " " << HashUtil::toString(Hash()) << '\n';
00377 out << " ";
00378 for (int i = 0; i < Width(); i++)
00379 out << (char)('a' + i) << " ";
00380 out << '\n';
00381 for (int i = 0; i < Height(); i++)
00382 {
00383 for (int j = 0; j < i; j++)
00384 out << " ";
00385 if (i + 1 < 10)
00386 out << " ";
00387 out << (i + 1) << "\\";
00388 for (int j = 0; j < Width(); j++)
00389 {
00390 HexPoint p = HexPointUtil::coordsToPoint(j, i);
00391 if (j)
00392 out << " ";
00393 if (b.test(p))
00394 out << "*";
00395 else if (IsBlack(p) && IsPlayed(p))
00396 out << "B";
00397 else if (IsBlack(p))
00398 out << "b";
00399 else if (IsWhite(p) && IsPlayed(p))
00400 out << "W";
00401 else if (IsWhite(p))
00402 out << "w";
00403 else
00404 out << ".";
00405 }
00406 out << "\\";
00407 out << (i + 1);
00408 out << '\n';
00409 }
00410 for (int j = 0; j < Height(); j++)
00411 out << " ";
00412 out << " ";
00413 for (int i = 0; i < Width(); i++)
00414 out << (char)('a' + i) << " ";
00415 return out.str();
00416 }
00417
00418 bool StoneBoard::IsBlackWhiteDisjoint()
00419 {
00420 if ((m_stones[BLACK] & m_stones[WHITE]).any())
00421 {
00422 for (BWIterator it; it; ++it)
00423 LogWarning() << HexPointUtil::ToString(m_stones[*it]) << '\n';
00424 return false;
00425 }
00426 return true;
00427 }
00428
00429