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