00001 //---------------------------------------------------------------------------- 00002 /** @file GoStaticSafetySolver.cpp 00003 See GoStaticSafetySolver.h. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "SgSystem.h" 00007 #include "GoStaticSafetySolver.h" 00008 00009 #include "GoBlock.h" 00010 #include "GoChain.h" 00011 #include "GoSafetyUtil.h" 00012 #include "SgDebug.h" 00013 00014 using GoSafetyUtil::AddToSafe; 00015 00016 //---------------------------------------------------------------------------- 00017 00018 GoStaticSafetySolver::GoStaticSafetySolver(const GoBoard& board, 00019 GoRegionBoard* regions) 00020 : m_board(board), 00021 m_allocRegion(! regions) 00022 { 00023 if (regions) 00024 m_regions = regions; 00025 else 00026 m_regions = new GoRegionBoard(board); 00027 } 00028 00029 GoStaticSafetySolver::~GoStaticSafetySolver() 00030 { 00031 if (m_allocRegion) 00032 delete m_regions; 00033 // else m_regions belongs to the user, so leave it. 00034 } 00035 00036 bool GoStaticSafetySolver::RegionHealthyForBlock(const GoRegion& r, 00037 const GoBlock& b) const 00038 { 00039 return b.AllEmptyAreLiberties(r.Points()); 00040 } 00041 00042 bool GoStaticSafetySolver::UpToDate() const 00043 { 00044 return Regions()->UpToDate(); 00045 } 00046 00047 void GoStaticSafetySolver::GenBlocksRegions() 00048 { 00049 if (UpToDate()) 00050 Regions()->ReInitializeBlocksRegions(); 00051 else 00052 { 00053 Regions()->GenBlocksRegions(); 00054 } 00055 } 00056 00057 00058 void GoStaticSafetySolver::FindHealthy() 00059 { 00060 if (Regions()->ComputedHealthy()) 00061 return; 00062 for (SgBWIterator it; it; ++it) 00063 { 00064 SgBlackWhite color(*it); 00065 for (SgVectorIteratorOf<GoRegion> 00066 it(Regions()->AllRegions(color)); it; ++it) 00067 { 00068 GoRegion* r = *it; 00069 for (SgVectorIteratorOf<GoBlock> it2(r->Blocks()); it2; ++it2) 00070 { 00071 if (RegionHealthyForBlock(*r, **it2)) // virtual call 00072 { 00073 (*it2)->AddHealthy(r); 00074 } 00075 } 00076 } 00077 } 00078 Regions()->SetComputedHealthy(); 00079 } 00080 00081 void GoStaticSafetySolver::TestAdjacent(SgVectorOf<GoRegion>* regions, 00082 const SgVectorOf<GoBlock>& blocks) const 00083 { 00084 SgVectorOf<GoRegion> newregions; 00085 for (SgVectorIteratorOf<GoRegion> it(*regions); it; ++it) 00086 if ((*it)->IsSurrounded(blocks)) 00087 newregions.PushBack(*it); 00088 *regions = newregions; 00089 } 00090 00091 void GoStaticSafetySolver::TestAlive(SgVectorOf<GoBlock>* blocks, 00092 SgBWSet* safe, 00093 SgBlackWhite color) 00094 { 00095 SgVectorOf<GoRegion> regions(Regions()->AllRegions(color)); 00096 SgVectorOf<GoBlock> toDelete; 00097 00098 bool changed = true; 00099 while (changed) 00100 { 00101 TestAdjacent(®ions, *blocks); 00102 toDelete.Clear(); 00103 for (SgVectorIteratorOf<GoBlock> it(*blocks); it; ++it) 00104 { 00105 const SgVectorOf<GoRegion>& br = (*it)->Healthy(); 00106 00107 bool has2 = br.MinLength(2); 00108 if (has2) 00109 { 00110 int nuRegions = 0; 00111 for (SgVectorIteratorOf<GoRegion> it(br); it; ++it) 00112 { 00113 if (regions.Contains(*it)) 00114 { 00115 ++nuRegions; 00116 if (nuRegions >= 2) 00117 break; 00118 } 00119 } 00120 has2 = (nuRegions >= 2); 00121 } 00122 if (! has2) 00123 toDelete.PushBack(*it); 00124 } 00125 00126 changed = toDelete.NonEmpty(); 00127 if (changed) 00128 { 00129 for (SgVectorIteratorOf<GoBlock> it(toDelete); it; ++it) 00130 { 00131 bool found = blocks->Exclude(*it); 00132 SG_DEBUG_ONLY(found); 00133 SG_ASSERT(found); 00134 } 00135 } 00136 } 00137 00138 if (blocks->NonEmpty()) // found safe blocks 00139 { 00140 SgPointSet blockPoints; 00141 for (SgVectorIteratorOf<GoBlock> it(*blocks); it; ++it) 00142 { 00143 blockPoints |= (*it)->Stones(); 00144 (*it)->SetToSafe(); 00145 } 00146 00147 color = blocks->Front()->Color(); 00148 AddToSafe(m_board, blockPoints, color, safe, 00149 "TestAlive-Blocks", 0, false); 00150 00151 for (SgVectorIteratorOf<GoRegion> it(regions); it; ++it) 00152 if ((*it)->HealthyForSomeBlock(*blocks)) 00153 { 00154 (*it)->SetToSafe(); 00155 AddToSafe(m_board, (*it)->Points(), color, safe, 00156 "TestAlive-Region", 0, false); 00157 } 00158 } 00159 } 00160 00161 void GoStaticSafetySolver::FindClosure(SgVectorOf<GoBlock>* blocks) const 00162 { 00163 SgVectorOf<GoBlock> toTest(*blocks); 00164 while (toTest.NonEmpty()) 00165 { 00166 const GoBlock* b = toTest.Back(); 00167 toTest.PopBack(); 00168 for (SgVectorIteratorOf<GoRegion> it(b->Healthy()); it; ++it) 00169 { 00170 const GoRegion* r = *it; 00171 for (SgVectorIteratorOf<GoBlock> it(r->Blocks()); it; ++it) 00172 { 00173 const GoBlock* b2 = *it; 00174 if (! blocks->Contains(b2)) 00175 { 00176 blocks->PushBack(b2); 00177 toTest.PushBack(b2); 00178 } 00179 } 00180 } 00181 } 00182 } 00183 00184 void GoStaticSafetySolver::FindTestSets( 00185 SgVectorOf<SgVectorOf<GoBlock> >* sets, 00186 SgBlackWhite color) const 00187 { 00188 SG_ASSERT(sets->IsEmpty()); 00189 SgVectorOf<GoBlock> doneSoFar; 00190 for (SgVectorIteratorOf<GoBlock> 00191 it(Regions()->AllBlocks(color)); it; ++it) 00192 { 00193 GoBlock* block = *it; 00194 if (! doneSoFar.Contains(block)) 00195 { 00196 SgVectorOf<GoBlock>* blocks = new SgVectorOf<GoBlock>; 00197 blocks->PushBack(block); 00198 00199 FindClosure(blocks); 00200 doneSoFar.PushBackList(*blocks); 00201 sets->PushBack(blocks); 00202 } 00203 } 00204 } 00205 00206 void GoStaticSafetySolver::FindSafePoints(SgBWSet* safe) 00207 { 00208 GenBlocksRegions(); // find all blocks and regions on whole board 00209 FindHealthy(); // find healthy regions of blocks 00210 00211 for (SgBWIterator it; it; ++it) 00212 { 00213 SgBlackWhite color(*it); 00214 SgVectorOf<SgVectorOf<GoBlock> > sets; 00215 // find maximal sets for aliveness testing 00216 FindTestSets(&sets, color); 00217 00218 for (SgVectorIteratorOf<SgVectorOf<GoBlock> > it(sets); it; ++it) 00219 { TestAlive(*it, safe, color); 00220 // find safe subset within each maximal set 00221 delete *it; 00222 } 00223 } 00224 00225 Regions()->SetComputedFlagForAll(GO_REGION_SAFE); 00226 } 00227