void GoBook::Entry::ApplyTo(GoBoard& bd) const { if (bd.Size() != m_size) bd.Init(m_size); GoBoardUtil::UndoAll(bd); for (vector<SgPoint>::const_iterator it = m_sequence.begin(); it != m_sequence.end(); ++it) { SG_ASSERT(bd.IsLegal(*it)); bd.Play(*it); } }
void GoBoardUpdater::Update(const SgNode* node, GoBoard& bd) { ////SG_ASSERT(node != 0); m_nodes.clear(); while (node != 0) { m_nodes.push_back(node); node = node->Father(); } const SgNode* root = m_nodes[m_nodes.size() - 1]; int size = GO_DEFAULT_SIZE; SgPropInt* boardSize = static_cast<SgPropInt*>(root->Get(SG_PROP_SIZE)); if (boardSize) { size = boardSize->Value(); ////SG_ASSERT(SgUtil::InRange(size, SG_MIN_SIZE, SG_MAX_SIZE)); } bd.Init(size); for (vector<const SgNode*>::reverse_iterator it = m_nodes.rbegin(); it != m_nodes.rend(); ++it) { const SgNode* node = *it; SgEmptyBlackWhite player = GetPlayer(node); if (node->HasProp(SG_PROP_ADD_EMPTY) || node->HasProp(SG_PROP_ADD_BLACK) || node->HasProp(SG_PROP_ADD_WHITE)) { // Compute the new initial setup position to re-initialize the // board with GoSetup setup = GoSetupUtil::CurrentPosSetup(bd); if (player != SG_EMPTY) setup.m_player = player; if (node->HasProp(SG_PROP_ADD_BLACK)) { SgPropAddStone* prop = dynamic_cast<SgPropAddStone*>(node->Get(SG_PROP_ADD_BLACK)); const SgVector<SgPoint>& addBlack = prop->Value(); for (SgVectorIterator<SgPoint> it2(addBlack); it2; ++it2) { SgPoint p = *it2; setup.m_stones[SG_WHITE].Exclude(p); if (! setup.m_stones[SG_BLACK].Contains(p)) setup.AddBlack(p); } } if (node->HasProp(SG_PROP_ADD_WHITE)) { SgPropAddStone* prop = dynamic_cast<SgPropAddStone*>(node->Get(SG_PROP_ADD_WHITE)); const SgVector<SgPoint>& addWhite = prop->Value(); for (SgVectorIterator<SgPoint> it2(addWhite); it2; ++it2) { SgPoint p = *it2; setup.m_stones[SG_BLACK].Exclude(p); if (! setup.m_stones[SG_WHITE].Contains(p)) setup.AddWhite(p); } } if (node->HasProp(SG_PROP_ADD_EMPTY)) { SgPropAddStone* prop = dynamic_cast<SgPropAddStone*>(node->Get(SG_PROP_ADD_EMPTY)); const SgVector<SgPoint>& addEmpty = prop->Value(); for (SgVectorIterator<SgPoint> it2(addEmpty); it2; ++it2) { SgPoint p = *it2; setup.m_stones[SG_BLACK].Exclude(p); setup.m_stones[SG_WHITE].Exclude(p); } } bd.Init(bd.Size(), setup); } else if (player != SG_EMPTY) bd.SetToPlay(player); if (node->HasProp(SG_PROP_MOVE)) { SgPropMove* prop = dynamic_cast<SgPropMove*>(node->Get(SG_PROP_MOVE)); SgPoint p = prop->Value(); if (p == SG_PASS || ! bd.Occupied(p)) bd.Play(p, prop->Player()); } } }
/** Insert a new position entry and all its transformations @param sequence A move sequence that leads to the position @param moves The moves to play in this position @param size @param tempBoard A local temporary work board, reused for efficiency (does not have to be initialized) @param line Line number of entry from the file (0 if unknown or entry is not from a file) */ void GoBook::InsertEntry(const vector<SgPoint>& sequence, const vector<SgPoint>& moves, int size, GoBoard& tempBoard, int line) { if (moves.size() == 0) ThrowError("Line contains no moves"); if (tempBoard.Size() != size) tempBoard.Init(size); Entry entry; entry.m_size = size; entry.m_line = line; entry.m_sequence = sequence; entry.m_moves = moves; m_entries.push_back(entry); size_t id = m_entries.size() - 1; vector<Map::iterator> newEntries; for (int rot = 0; rot < 8; ++rot) { GoBoardUtil::UndoAll(tempBoard); for (vector<SgPoint>::const_iterator it = sequence.begin(); it != sequence.end(); ++it) { SgPoint p = SgPointUtil::Rotate(rot, *it, size); if (! tempBoard.IsLegal(p)) ThrowError("Illegal move in variation"); tempBoard.Play(p); } // It is enough to check the moves for legality for one rotation if (rot == 0) for (vector<SgPoint>::const_iterator it = moves.begin(); it != moves.end(); ++it) if (! tempBoard.IsLegal(SgPointUtil::Rotate(rot, *it, size))) ThrowError("Illegal move in move list"); MapEntry mapEntry; mapEntry.m_size = size; mapEntry.m_id = id; mapEntry.m_rotation = rot; SgHashCode hashCode = tempBoard.GetHashCodeInclToPlay(); pair<Map::iterator,Map::iterator> e = m_map.equal_range(hashCode); bool isInNewEntries = false; for (Map::iterator it = e.first; it != e.second; ++it) if (it->second.m_size == size) { if (! Contains(newEntries, it)) { ostringstream o; o << "Entry duplicates line " << m_entries[it->second.m_id].m_line; ThrowError(o.str()); } isInNewEntries = true; break; } if (! isInNewEntries) { Map::iterator newIt = m_map.insert(Map::value_type(hashCode, mapEntry)); newEntries.push_back(newIt); } } }