Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoStaticSafetySolver.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoStaticSafetySolver.cpp
00003     See GoStaticSafetySolver.h.
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     // else m_regions belongs to the user, so leave it.
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)) // virtual call
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(&regions, *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()) // found safe blocks
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(); // find all blocks and regions on whole board
00210     FindHealthy(); // find healthy regions of blocks
00211 
00212     for (SgBWIterator it; it; ++it)
00213     {
00214         SgBlackWhite color(*it);
00215         SgVectorOf<SgVectorOf<GoBlock> > sets;
00216         // find maximal sets for aliveness testing
00217         FindTestSets(&sets, color);
00218 
00219         for (SgVectorIteratorOf<SgVectorOf<GoBlock> > it(sets); it; ++it)
00220         {   TestAlive(*it, safe, color);
00221             // find safe subset within each maximal set
00222             delete *it;
00223         }
00224     }
00225 
00226     Regions()->SetComputedFlagForAll(GO_REGION_SAFE);
00227 }
00228 


17 Jun 2010 Doxygen 1.4.7