00001
00002
00003
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 }
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
00043
00044
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))
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
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
00135 Regions()->SetSafeFlags(*safe);
00136
00137
00138 while (FindSurroundedSingleRegion(safe, color))
00139 { }
00140 while (FindSurroundedRegionPair(safe, color))
00141
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
00227 Find2VitalAreas(safe);
00228 safe->AssertDisjoint();
00229 if (DEBUG_SAFETY_SOLVER)
00230 GoSafetyUtil::WriteStatistics("2Vital", Regions(), safe);
00231
00232
00233
00234
00235
00236
00237
00238
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
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
00335
00336
00337 )
00338
00339 {
00340 GoChain* c1 = r->Chains().Front();
00341 GoChain* c2 = r->Chains().Back();
00342 Merge(c1, c2, r, false);
00343 changed = true;
00344 break;
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;
00358 } } } } }
00359
00360 m_code = Board().GetHashCode();
00361 }
00362