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);
    }
}
Beispiel #2
0
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);
        }
    }
}