示例#1
0
void GoSafetySolver::FindHealthy()
{        
    for (SgBWIterator it; it; ++it)
    {
        SgBlackWhite color(*it);
        for (SgVectorIteratorOf<GoRegion>
             it(Regions()->AllRegions(color)); it; ++it)
            (*it)->ComputeFlag(GO_REGION_STATIC_1VITAL);
    }
   
    // used to just call GoStaticSafetySolver::FindHealthy() here, 
    // but that works with GoBlock's and now we use GoChain's.
    // Code is duplicated though. Can maybe use a template function.
   
    for (SgBWIterator it; it; ++it)
    {
        SgBlackWhite color(*it);
        for (SgVectorIteratorOf<GoRegion>
             it(Regions()->AllRegions(color)); it; ++it)
        {
            GoRegion* r = *it;
            for (SgVectorIteratorOf<GoChain> it2(r->Chains()); it2; ++it2)
            {
                if (RegionHealthyForBlock(*r, **it2)) // virtual call
                    (*it2)->AddHealthy(r);
}   }   }   }
void GoRegionBoard::OnExecutedUncodedMove(int move, SgBlackWhite moveColor)
{
    if (DEBUG_REGION_BOARD)
        SgDebug() << "OnExecutedUncodedMove " << SgWritePoint(move) << '\n';
    {
        m_stack.StartMoveInfo();
        if (move != SG_PASS)
        {
            SG_ASSERT(! Board().LastMoveInfo(GO_MOVEFLAG_SUICIDE));
            // can't handle yet,
            // should be forbidden anyway. @todo allowed in Chinese rules.
            bool fWasCapture = Board().LastMoveInfo(GO_MOVEFLAG_CAPTURING);

            UpdateBlock(move, moveColor);

            {
                GoRegion* r = PreviousRegionAt(move, moveColor);
                bool split = GoEyeUtil::IsSplitPt(move, r->Points());

                r->OnAddStone(move);
                PushStone(r, move);
                SgPointSet points = r->Points();
                // needed even after RemoveRegion(r).
                if (split || points.IsEmpty())
                // must remove old region before generating new ones,
                // because removing clears m_anchor[]
                    RemoveRegion(r);

                if (split) // find new regions
                {
                    for (SgConnCompIterator it(points, Board().Size());
                         it; ++it)
                        GenRegion(*it, moveColor);
                }
            }

            if (fWasCapture)
            {
            //  FindNewNeighborRegions(move, moveColor);
                MergeAdjacentAndAddBlock(move, SgOppBW(moveColor));
            }

            m_code = Board().GetHashCode();
            if (HEAVYCHECK)
                CheckConsistency();
        }
    }

    {
        for (SgBWIterator it; it; ++it)
        {
            SgBlackWhite color(*it);
            for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
            {   GoRegion* r1 = *it;
                if (! r1->IsValid())
                    r1->ComputeBasicFlags();
            }
        }
    }
}
示例#3
0
void GoSafetySolver::Merge(GoChain* c1, GoChain* c2,
                           GoRegion* r, bool bySearch)
{
    SG_ASSERT(! r->GetFlag(GO_REGION_USED_FOR_MERGE));
    r->SetFlag(GO_REGION_USED_FOR_MERGE, true);
    
    GoChainCondition* c = 0;
    if (bySearch)
        c = new GoChainCondition(GO_CHAIN_BY_SEARCH);
    else
    {
        SgPoint lib1, lib2;
        r->Find2FreeLibs(c1, c2, &lib1, &lib2);
        c = new GoChainCondition(GO_CHAIN_TWO_LIBERTIES_IN_REGION,
                                 lib1, lib2);
    }
    
    GoChain* m = new GoChain(c1, c2, c);

    SgBlackWhite color = c1->Color();
    bool found = Regions()->AllChains(color).Exclude(c1);
    SG_DEBUG_ONLY(found);
    SG_ASSERT(found);
    found = Regions()->AllChains(color).Exclude(c2);
    SG_ASSERT(found);
    Regions()->AllChains(color).Include(m);
    SG_ASSERT(Regions()->AllChains(color).UniqueElements());

    for (SgVectorIteratorOf<GoRegion>
         it(Regions()->AllRegions(color)); it; ++it)
    {
        GoRegion* r = *it;
        bool replace1 = r->ReplaceChain(c1, m);
        bool replace2 = r->ReplaceChain(c2, m);
        if (replace1 || replace2)
        {
            r->ReInitialize();
            r->ComputeFlag(GO_REGION_STATIC_1VITAL);
        }
    }

    if (DEBUG_MERGE_CHAINS)
    {
        SgDebug() << "\nmerge:";
        c1->WriteID(SgDebug());
        SgDebug() << " + ";
        c2->WriteID(SgDebug());
        SgDebug() << " = ";
        m->WriteID(SgDebug());
        SgDebug() << '\n';
    }

    delete c1;
    delete c2;
}
示例#4
0
void GoSafetySolver::FindClosure(SgVectorOf<GoBlock>* blocks) const
{
    SgVectorOf<GoBlock> toTest(*blocks);
    while (toTest.NonEmpty())
    {
        const GoBlock* b = toTest.Back();
        toTest.PopBack();
        for (SgVectorIteratorOf<GoRegion> it(b->Healthy()); it; ++it)
        {   GoRegion* r = *it;
            for (SgVectorIteratorOf<GoChain> it(r->Chains()); it; ++it)
            {   GoBlock* b2 = *it;
                if (! blocks->Contains(b2) && b2->ContainsHealthy(r))
                {
                    blocks->PushBack(b2);
                    toTest.PushBack(b2);
}   }   }   }   }
示例#5
0
bool GoSafetySolver::FindSurroundedSingleRegion(SgBWSet* safe,
                                             SgBlackWhite color)
{
    SgPointSet anySafe(safe->Both());
    for (SgVectorIteratorOf<GoRegion>
         it(Regions()->AllRegions(color)); it; ++it)
    {
        GoRegion* r = *it;
        if (  ! r->GetFlag(GO_REGION_SAFE)
           && r->SomeBlockIsSafe()
           && ! r->Points().Overlaps(anySafe)
           && GoSafetyUtil::ExtendedIsTerritory(Board(), Regions(),
                                   r->PointsPlusInteriorBlocks(),
                                   (*safe)[color],
                                   color)
           )
        {
            GoSafetyUtil::AddToSafe(Board(), r->Points(), color, safe,
                      "surr-safe-1", 0, true);
            Regions()->SetSafeFlags(*safe); 
            return true;
        }
    }
    return false;
}
示例#6
0
bool GoSafetySolver::RegionHealthyForBlock(const GoRegion& r,
                                           const GoBlock& b) const
{
    return    GoStaticSafetySolver::RegionHealthyForBlock(r, b)
           || r.GetFlag(GO_REGION_STATIC_1VITAL);
}
示例#7
0
void GoSafetySolver::GenBlocksRegions()
{
    if (UpToDate())
        /* */ return; /* */
        
    GoStaticSafetySolver::GenBlocksRegions();
    
    Regions()->GenChains();
    
    // merge blocks adjacent to 1-vital with 2 conn. points
    for (SgBWIterator it; it; ++it)
    {
        SgBlackWhite color(*it);
        for (SgVectorIteratorOf<GoRegion> 
             it(Regions()->AllRegions(color)); it; ++it)
        {
            GoRegion* r = *it;
            r->ComputeFlag(GO_REGION_STATIC_1VITAL);
        }

        bool changed = true;
        while (changed)
        {   changed = false;
            for (SgVectorIteratorOf<GoRegion> 
                 it(Regions()->AllRegions(color)); it; ++it)
            {   GoRegion* r = *it;
                if (  r->GetFlag(GO_REGION_STATIC_1VC)
                   && r->Chains().IsLength(2)
                   && r->Has2Conn() 
                        //  || r->Safe2Cuts(Board()) changed from && to ||
                        // @todo does not work if blocks are already chains???
                        // must explicitly keep chain libs info.
                   )
                // easy case of only 2 chains
                {
                    GoChain* c1 = r->Chains().Front();
                    GoChain* c2 = r->Chains().Back();
                    Merge(c1, c2, r, false); // false = not by search
                    changed = true;
                    break; // to leave iteration
                }
                else if (   r->GetFlag(GO_REGION_STATIC_1VITAL)
                         && r->GetFlag(GO_REGION_CORRIDOR)
                         && ! r->GetFlag(GO_REGION_USED_FOR_MERGE)
                        ) 
                {
                    GoChain* c1 = 0;
                    GoChain* c2 = 0;
                    if (r->Find2Mergable(&c1, &c2))
                    {
                        Merge(c1, c2, r, false);
                        changed = true;
                        break; // to leave iteration
    }   }   }   }   }
    
    m_code = Board().GetHashCode();
}
void GoRegionBoard::OnUndoneMove()
// Called after a move has been undone. The board is guaranteed to be in
// a legal state.
{
    //SG_ASSERT(false); // incremental code is incomplete, do not call
    if (DEBUG_REGION_BOARD)
        SgDebug() << "OnUndoneMove " << '\n';

    const bool IS_UNDO = false;
    SgVectorOf<GoRegion> changed;

    for (int val = m_stack.PopEvent(); val != SG_NEXTMOVE;
         val = m_stack.PopEvent())
    {

        switch (val)
        {
            case REGION_REMOVE:
            {   GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
                AddRegion(r, IS_UNDO);
                changed.Insert(r);
            }
            break;
            case REGION_ADD:
            {   GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
                RemoveRegion(r, IS_UNDO);
            }
            break;
            case REGION_REMOVE_BLOCK:
            {   GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr());
                AddBlock(b, IS_UNDO);
                for (int nu = m_stack.PopInt(); nu > 0; --nu)
                {
                    GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
                    if (CHECK)
                        SG_ASSERT(! r->Blocks().Contains(b));
                    r->BlocksNonConst().PushBack(b);
                    changed.Insert(r);
                }
            }
            break;
            case REGION_ADD_BLOCK:
            {   GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr());
                RemoveBlock(b, IS_UNDO, true);
            }
            break;
            case REGION_ADD_STONE:
            {   GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
                SgPoint p = m_stack.PopInt();
                r->OnRemoveStone(p);
                m_region[r->Color()][p] = r;
                changed.Insert(r);
            }
            break;
            case REGION_ADD_STONE_TO_BLOCK:
            {   GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr());
                SgPoint p = m_stack.PopInt();
                b->RemoveStone(p);
                m_block[p] = 0;
            }
            break;
            default:
                SG_ASSERT(false);
        }
    }

    for (SgVectorIteratorOf<GoRegion> it(changed); it; ++it)
    {
        (*it)->ResetNonBlockFlags();
        (*it)->ComputeBasicFlags();
    }

    if (HEAVYCHECK)
    {
        for (SgBWIterator it; it; ++it)
        {
            SgBlackWhite color(*it);
            for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
            {
                const GoRegion* r = *it;
                SG_UNUSED(r);
                SG_ASSERT(r->IsValid());
            }
        }
    }

    m_code = Board().GetHashCode();
    if (HEAVYCHECK)
        CheckConsistency();
}