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;
}
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 GoSafetySolver::FindSafePoints(SgBWSet* safe)
{    
    GoStaticSafetySolver::FindSafePoints(safe);
    safe->AssertDisjoint();
    if (DEBUG_SAFETY_SOLVER)
        GoSafetyUtil::WriteStatistics("Base Solver", Regions(), safe);

    // find areas big enough for two eyes
    Find2VitalAreas(safe);
    safe->AssertDisjoint();
    if (DEBUG_SAFETY_SOLVER)
        GoSafetyUtil::WriteStatistics("2Vital", Regions(), safe);
 
//    GoStaticSafetySolver::FindSafePoints(safe); 
//called again before 030505,
// but now double-counts healthy regions for chains. Must change to
// set a computedHealthy flag
//    safe->AssertDisjoint();

    // find areas small enough that opponent cannot make two eyes
    for (SgBWIterator it; it; ++it)
    {
        FindSurroundedSafeAreas(safe, *it);
        safe->AssertDisjoint();
    }    

    if (DEBUG_SAFETY_SOLVER)
        GoSafetyUtil::WriteStatistics("SurroundedSafe-Final",
                                      Regions(), safe);
}
bool GoSafetySolver::FindSafePair(SgBWSet* safe,
                                  SgBlackWhite color,
                                  const SgPointSet& anySafe,
                                  const GoRegion* r1)
{
    for (SgVectorIteratorOf<GoRegion>
         it(Regions()->AllRegions(color)); it; ++it)
    {
        const GoRegion* r2 = *it;
        if (  r2 != r1
           && ! r2->Points().Overlaps(anySafe)
           && HaveSharedUnsafe(r1->Blocks(), r2->Blocks())
           )
        {
            const SgPointSet unionSet(r1->Points() | r2->Points());
            if (GoSafetyUtil::IsTerritory(Board(), unionSet,
                                          (*safe)[color], color))
            {
                GoSafetyUtil::AddToSafe(Board(), unionSet, color, safe,
                          "surr-safe-2", 0, true);
                Regions()->SetSafeFlags(*safe); 
                safe->AssertDisjoint();
                return true;
            }
        }
    }
    return false;
}
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();
}
Example #6
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;
}
Example #7
0
void GoBensonSolver::FindSafePoints(SgBWSet* safe)
{
    safe->Clear();
    GoStaticSafetySolver::FindSafePoints(safe);

    if (DEBUG_BENSON)
        GoSafetyUtil::WriteStatistics("GoBensonSolver", Regions(), safe);
}
// @todo: as a first cut, this simply checks if the regions has any
// stones in it. It does not check if the move is suitable for capturing the
// stones.
bool GoSafetySolver::PotentialCaptureMove(SgPoint p,
                                          SgBlackWhite regionColor) const
{
    SG_ASSERT(UpToDate());
    SG_ASSERT(Board().ToPlay() == regionColor);
    const GoRegion* r = Regions()->RegionAt(p, regionColor);
    SG_ASSERT(r);
    return r->Points().Overlaps(Board().All(SgOppBW(regionColor)));
}
void GoSafetySolver::FindSurroundedSafeAreas(SgBWSet* safe,
                                             SgBlackWhite color)
{
    // AR keep this always up to date earlier.
    Regions()->SetSafeFlags(*safe); 
        
    // try to find single regions that become safe.
    while (FindSurroundedSingleRegion(safe, color))
    { }
    while (FindSurroundedRegionPair(safe, color))
    	// if found new pair, re-run single region algorithm - it is faster
        while (FindSurroundedSingleRegion(safe, color))
        { }
}
Example #10
0
void GoSafetySolver::Find2VitalAreas(SgBWSet* safe)
{
    for (SgBWIterator it; it; ++it)
    {
        SgBlackWhite color(*it);
        for (SgVectorIteratorOf<GoRegion>
             it(Regions()->AllRegions(color)); it; ++it)
            if (  (*it)->Points().Disjoint((*safe)[SG_BLACK]) 
               && (*it)->Points().Disjoint((*safe)[SG_WHITE])
               )
            {
                Test2Vital(*it, safe);
                safe->AssertDisjoint();
            }
    }
}
Example #11
0
bool GoSafetySolver::FindSurroundedRegionPair(SgBWSet* safe,
                                               SgBlackWhite color)
{
    SgPointSet anySafe(safe->Both());
    for (SgVectorIteratorOf<GoRegion>
         it(Regions()->AllRegions(color)); it; ++it)
    {
        GoRegion* r1 = *it;
        if (  ! r1->GetFlag(GO_REGION_SAFE)
           && r1->SomeBlockIsSafe()
           && ! r1->Points().Overlaps(anySafe)
           && FindSafePair(safe, color, anySafe, r1)
           )
            return true;
    }
    return false;
}
Example #12
0
void GoSafetySolver::FindTestSets(SgVectorOf<SgVectorOf<GoBlock> >* sets,
                                  SgBlackWhite color) const
{
    SG_ASSERT(sets->IsEmpty());
    SgVectorOf<GoBlock> doneSoFar;
    for (SgVectorIteratorOf<GoChain>
         it(Regions()->AllChains(color)); it; ++it)
    {
        GoBlock* block = *it;
        if (! doneSoFar.Contains(block))
        {
            SgVectorOf<GoBlock>* blocks = new SgVectorOf<GoBlock>;
            blocks->PushBack(block);
            
            FindClosure(blocks);
            doneSoFar.PushBackList(*blocks);
            sets->PushBack(blocks);
        }
    }
}