Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoSafetySolver.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoSafetySolver.cpp
00003     See GoSafetySolver.h. */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "SgSystem.h"
00007 #include "GoSafetySolver.h"
00008 
00009 #include "GoBlock.h"
00010 #include "GoChain.h"
00011 #include "GoSafetyUtil.h"
00012 #include "SgConnCompIterator.h"
00013 
00014 //----------------------------------------------------------------------------
00015 
00016 namespace {
00017 
00018 const bool DEBUG_MERGE_CHAINS = false;
00019 const bool DEBUG_SAFETY_SOLVER = false;
00020 
00021 bool HaveSharedUnsafe(const SgVectorOf<GoBlock>& list1,
00022                       const SgVectorOf<GoBlock>& list2)
00023 {
00024     for (SgVectorIteratorOf<GoBlock> it(list1); it; ++it)
00025         if (! (*it)->IsSafe() && list2.Contains(*it))
00026             return true;
00027     return false;
00028 }
00029 
00030 } // namespace
00031 
00032 void GoSafetySolver::FindHealthy()
00033 {        
00034     for (SgBWIterator it; it; ++it)
00035     {
00036         SgBlackWhite color(*it);
00037         for (SgVectorIteratorOf<GoRegion>
00038              it(Regions()->AllRegions(color)); it; ++it)
00039             (*it)->ComputeFlag(GO_REGION_STATIC_1VITAL);
00040     }
00041    
00042     // used to just call GoStaticSafetySolver::FindHealthy() here, 
00043     // but that works with GoBlock's and now we use GoChain's.
00044     // Code is duplicated though. Can maybe use a template function.
00045    
00046     for (SgBWIterator it; it; ++it)
00047     {
00048         SgBlackWhite color(*it);
00049         for (SgVectorIteratorOf<GoRegion>
00050              it(Regions()->AllRegions(color)); it; ++it)
00051         {
00052             GoRegion* r = *it;
00053             for (SgVectorIteratorOf<GoChain> it2(r->Chains()); it2; ++it2)
00054             {
00055                 if (RegionHealthyForBlock(*r, **it2)) // virtual call
00056                     (*it2)->AddHealthy(r);
00057 }   }   }   }
00058 
00059 void GoSafetySolver::FindClosure(SgVectorOf<GoBlock>* blocks) const
00060 {
00061     SgVectorOf<GoBlock> toTest(*blocks);
00062     while (toTest.NonEmpty())
00063     {
00064         const GoBlock* b = toTest.Back();
00065         toTest.PopBack();
00066         for (SgVectorIteratorOf<GoRegion> it(b->Healthy()); it; ++it)
00067         {   GoRegion* r = *it;
00068             for (SgVectorIteratorOf<GoChain> it(r->Chains()); it; ++it)
00069             {   GoBlock* b2 = *it;
00070                 if (! blocks->Contains(b2))
00071                 //if (! blocks->Contains(b2) && b2->ContainsHealthy(r))
00072                 {
00073                     blocks->PushBack(b2);
00074                     toTest.PushBack(b2);
00075 }   }   }   }   }
00076 
00077 void GoSafetySolver::FindTestSets(SgVectorOf<SgVectorOf<GoBlock> >* sets,
00078                                   SgBlackWhite color) const
00079 {
00080     SG_ASSERT(sets->IsEmpty());
00081     SgVectorOf<GoBlock> doneSoFar;
00082     for (SgVectorIteratorOf<GoChain>
00083          it(Regions()->AllChains(color)); it; ++it)
00084     {
00085         GoBlock* block = *it;
00086         if (! doneSoFar.Contains(block))
00087         {
00088             SgVectorOf<GoBlock>* blocks = new SgVectorOf<GoBlock>;
00089             blocks->PushBack(block);
00090             
00091             FindClosure(blocks);
00092             doneSoFar.PushBackList(*blocks);
00093             sets->PushBack(blocks);
00094         }
00095     }
00096 }
00097 
00098 bool GoSafetySolver::RegionHealthyForBlock(const GoRegion& r,
00099                                            const GoBlock& b) const
00100 {
00101     return    GoStaticSafetySolver::RegionHealthyForBlock(r, b)
00102            || r.GetFlag(GO_REGION_STATIC_1VITAL);
00103 }
00104 
00105 
00106 void GoSafetySolver::Test2Vital(GoRegion* r, SgBWSet* safe)
00107 {
00108     if (r->ComputeAndGetFlag(GO_REGION_STATIC_2V))
00109         GoSafetyUtil::AddToSafe(Board(), r->Points(), r->Color(),
00110                   safe, "2-vital:", 0, true);
00111 }
00112 
00113 void GoSafetySolver::Find2VitalAreas(SgBWSet* safe)
00114 {
00115     for (SgBWIterator it; it; ++it)
00116     {
00117         SgBlackWhite color(*it);
00118         for (SgVectorIteratorOf<GoRegion>
00119              it(Regions()->AllRegions(color)); it; ++it)
00120             if (  (*it)->Points().Disjoint((*safe)[SG_BLACK]) 
00121                && (*it)->Points().Disjoint((*safe)[SG_WHITE])
00122                )
00123             {
00124                 Test2Vital(*it, safe);
00125                 safe->AssertDisjoint();
00126             }
00127     }
00128 }
00129 
00130 
00131 void GoSafetySolver::FindSurroundedSafeAreas(SgBWSet* safe,
00132                                              SgBlackWhite color)
00133 {
00134     // AR keep this always up to date earlier.
00135     Regions()->SetSafeFlags(*safe); 
00136         
00137     // try to find single regions that become safe.
00138     while (FindSurroundedSingleRegion(safe, color))
00139     { }
00140     while (FindSurroundedRegionPair(safe, color))
00141         // if found new pair, re-run single region algorithm - it is faster
00142         while (FindSurroundedSingleRegion(safe, color))
00143         { }
00144 }
00145 
00146 bool GoSafetySolver::FindSafePair(SgBWSet* safe,
00147                                   SgBlackWhite color,
00148                                   const SgPointSet& anySafe,
00149                                   const GoRegion* r1)
00150 {
00151     for (SgVectorIteratorOf<GoRegion>
00152          it(Regions()->AllRegions(color)); it; ++it)
00153     {
00154         const GoRegion* r2 = *it;
00155         if (  r2 != r1
00156            && ! r2->Points().Overlaps(anySafe)
00157            && HaveSharedUnsafe(r1->Blocks(), r2->Blocks())
00158            )
00159         {
00160             const SgPointSet unionSet(r1->Points() | r2->Points());
00161             if (GoSafetyUtil::IsTerritory(Board(), unionSet,
00162                                           (*safe)[color], color))
00163             {
00164                 GoSafetyUtil::AddToSafe(Board(), unionSet, color, safe,
00165                           "surr-safe-2", 0, true);
00166                 Regions()->SetSafeFlags(*safe); 
00167                 safe->AssertDisjoint();
00168                 return true;
00169             }
00170         }
00171     }
00172     return false;
00173 }
00174 
00175 bool GoSafetySolver::FindSurroundedRegionPair(SgBWSet* safe,
00176                                                SgBlackWhite color)
00177 {
00178     SgPointSet anySafe(safe->Both());
00179     for (SgVectorIteratorOf<GoRegion>
00180          it(Regions()->AllRegions(color)); it; ++it)
00181     {
00182         GoRegion* r1 = *it;
00183         if (  ! r1->GetFlag(GO_REGION_SAFE)
00184            && r1->SomeBlockIsSafe()
00185            && ! r1->Points().Overlaps(anySafe)
00186            && FindSafePair(safe, color, anySafe, r1)
00187            )
00188             return true;
00189     }
00190     return false;
00191 }
00192 
00193 bool GoSafetySolver::FindSurroundedSingleRegion(SgBWSet* safe,
00194                                              SgBlackWhite color)
00195 {
00196     SgPointSet anySafe(safe->Both());
00197     for (SgVectorIteratorOf<GoRegion>
00198          it(Regions()->AllRegions(color)); it; ++it)
00199     {
00200         GoRegion* r = *it;
00201         if (  ! r->GetFlag(GO_REGION_SAFE)
00202            && r->SomeBlockIsSafe()
00203            && ! r->Points().Overlaps(anySafe)
00204            && GoSafetyUtil::ExtendedIsTerritory(Board(), Regions(),
00205                                    r->PointsPlusInteriorBlocks(),
00206                                    (*safe)[color],
00207                                    color)
00208            )
00209         {
00210             GoSafetyUtil::AddToSafe(Board(), r->Points(), color, safe,
00211                       "surr-safe-1", 0, true);
00212             Regions()->SetSafeFlags(*safe); 
00213             return true;
00214         }
00215     }
00216     return false;
00217 }
00218 
00219 void GoSafetySolver::FindSafePoints(SgBWSet* safe)
00220 {    
00221     GoStaticSafetySolver::FindSafePoints(safe);
00222     safe->AssertDisjoint();
00223     if (DEBUG_SAFETY_SOLVER)
00224         GoSafetyUtil::WriteStatistics("Base Solver", Regions(), safe);
00225 
00226     // find areas big enough for two eyes
00227     Find2VitalAreas(safe);
00228     safe->AssertDisjoint();
00229     if (DEBUG_SAFETY_SOLVER)
00230         GoSafetyUtil::WriteStatistics("2Vital", Regions(), safe);
00231  
00232 //    GoStaticSafetySolver::FindSafePoints(safe); 
00233 //called again before 030505,
00234 // but now double-counts healthy regions for chains. Must change to
00235 // set a computedHealthy flag
00236 //    safe->AssertDisjoint();
00237 
00238     // find areas small enough that opponent cannot make two eyes
00239     for (SgBWIterator it; it; ++it)
00240     {
00241         FindSurroundedSafeAreas(safe, *it);
00242         safe->AssertDisjoint();
00243     }    
00244 
00245     if (DEBUG_SAFETY_SOLVER)
00246         GoSafetyUtil::WriteStatistics("SurroundedSafe-Final",
00247                                       Regions(), safe);
00248 }
00249 
00250 void GoSafetySolver::Merge(GoChain* c1, GoChain* c2,
00251                            GoRegion* r, bool bySearch)
00252 {
00253     SG_ASSERT(! r->GetFlag(GO_REGION_USED_FOR_MERGE));
00254     r->SetFlag(GO_REGION_USED_FOR_MERGE, true);
00255     
00256     GoChainCondition* c = 0;
00257     if (bySearch)
00258         c = new GoChainCondition(GO_CHAIN_BY_SEARCH);
00259     else
00260     {
00261         SgPoint lib1, lib2;
00262         r->Find2FreeLibs(c1, c2, &lib1, &lib2);
00263         c = new GoChainCondition(GO_CHAIN_TWO_LIBERTIES_IN_REGION,
00264                                  lib1, lib2);
00265     }
00266     
00267     GoChain* m = new GoChain(c1, c2, c);
00268 
00269     SgBlackWhite color = c1->Color();
00270     bool found = Regions()->AllChains(color).Exclude(c1);
00271     SG_ASSERT(found);
00272     found = Regions()->AllChains(color).Exclude(c2);
00273     SG_ASSERT(found);
00274     Regions()->AllChains(color).Include(m);
00275     SG_ASSERT(Regions()->AllChains(color).UniqueElements());
00276 
00277     for (SgVectorIteratorOf<GoRegion>
00278          it(Regions()->AllRegions(color)); it; ++it)
00279     {
00280         GoRegion* r = *it;
00281         bool replace1 = r->ReplaceChain(c1, m);
00282         bool replace2 = r->ReplaceChain(c2, m);
00283         if (replace1 || replace2)
00284         {
00285             r->ReInitialize();
00286             r->ComputeFlag(GO_REGION_STATIC_1VITAL);
00287         }
00288     }
00289 
00290     if (DEBUG_MERGE_CHAINS)
00291     {
00292         SgDebug() << "\nmerge:";
00293         c1->WriteID(SgDebug());
00294         SgDebug() << " + ";
00295         c2->WriteID(SgDebug());
00296         SgDebug() << " = ";
00297         m->WriteID(SgDebug());
00298         SgDebug() << '\n';
00299     }
00300 
00301     delete c1;
00302     delete c2;
00303 }
00304 
00305 void GoSafetySolver::GenBlocksRegions()
00306 {
00307     if (UpToDate())
00308         /* */ return; /* */
00309         
00310     GoStaticSafetySolver::GenBlocksRegions();
00311     
00312     Regions()->GenChains();
00313     
00314     // merge blocks adjacent to 1-vital with 2 conn. points
00315     for (SgBWIterator it; it; ++it)
00316     {
00317         SgBlackWhite color(*it);
00318         for (SgVectorIteratorOf<GoRegion> 
00319              it(Regions()->AllRegions(color)); it; ++it)
00320         {
00321             GoRegion* r = *it;
00322             r->ComputeFlag(GO_REGION_STATIC_1VITAL);
00323         }
00324 
00325         bool changed = true;
00326         while (changed)
00327         {   changed = false;
00328             for (SgVectorIteratorOf<GoRegion> 
00329                  it(Regions()->AllRegions(color)); it; ++it)
00330             {   GoRegion* r = *it;
00331                 if (  r->GetFlag(GO_REGION_STATIC_1VC)
00332                    && r->Chains().IsLength(2)
00333                    && r->Has2Conn() 
00334                         //  || r->Safe2Cuts(Board()) changed from && to ||
00335                         // @todo does not work if blocks are already chains???
00336                         // must explicitly keep chain libs info.
00337                    )
00338                 // easy case of only 2 chains
00339                 {
00340                     GoChain* c1 = r->Chains().Front();
00341                     GoChain* c2 = r->Chains().Back();
00342                     Merge(c1, c2, r, false); // false = not by search
00343                     changed = true;
00344                     break; // to leave iteration
00345                 }
00346                 else if (   r->GetFlag(GO_REGION_STATIC_1VITAL)
00347                          && r->GetFlag(GO_REGION_CORRIDOR)
00348                          && ! r->GetFlag(GO_REGION_USED_FOR_MERGE)
00349                         ) 
00350                 {
00351                     GoChain* c1 = 0;
00352                     GoChain* c2 = 0;
00353                     if (r->Find2Mergable(&c1, &c2))
00354                     {
00355                         Merge(c1, c2, r, false);
00356                         changed = true;
00357                         break; // to leave iteration
00358     }   }   }   }   }
00359     
00360     m_code = Board().GetHashCode();
00361 }
00362 


Sun Mar 13 2011 Doxygen 1.7.1