Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoRegionUtil.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoRegionUtil.cpp
00003     See GoRegionUtil.h. */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "SgSystem.h"
00007 #include "GoRegionUtil.h"
00008 
00009 #include "GoBoard.h"
00010 #include "GoBoardUtil.h"
00011 #include "GoEyeUtil.h"
00012 #include "SgVector.h"
00013 #include "SgPointSet.h"
00014 
00015 //----------------------------------------------------------------------------
00016 
00017 namespace {
00018 
00019 /** Special case of single boundary block */
00020 bool Has2IntersectionPoints(const GoBoard& board, const SgPointSet& region, 
00021                             const SgPoint boundaryAnchor)
00022 {
00023     int nuIPs = 0;
00024     for (GoBoard::LibertyIterator it(board, boundaryAnchor); it; ++it)
00025     {
00026         if (  region.Contains(*it)
00027            && GoEyeUtil::IsSplitPt(*it, region)
00028            && ++nuIPs >= 2
00029            )
00030             return true;
00031     }
00032     return false;
00033 }
00034 
00035 /** Do liberties of boundary blocks contain 2 intersection points? */
00036 bool Has2IntersectionPoints(const GoBoard& board, const SgPointSet& region, 
00037                             const SgVector<SgPoint>& boundaryAnchors)
00038 {
00039     if (boundaryAnchors.IsLength(1)) // single block
00040         return Has2IntersectionPoints(board, region, boundaryAnchors.Back());
00041     else // compute joint liberties of all blocks in region.
00042     {
00043         SgVector<SgPoint> sharedLibs;
00044         for (GoBoard::LibertyIterator it(board, boundaryAnchors.Front()); it;
00045              ++it)
00046             if (region.Contains(*it))
00047                 sharedLibs.PushBack(*it);
00048 
00049         if (sharedLibs.MaxLength(1))
00050             return false;
00051         bool first = true;
00052         for (SgVectorIterator<SgPoint> it(boundaryAnchors); it; ++it)
00053         {
00054             if (first) // we already have the liberties of first block.
00055                 first = false;
00056             else // keep those sharedLibs that are libs of block
00057             {
00058                 SgVector<SgPoint> newShared;
00059                 const SgPoint block = *it;
00060                 for (GoBoard::LibertyIterator it(board, block); it; ++it)
00061                     if (sharedLibs.Contains(*it))
00062                         newShared.PushBack(*it);
00063                 if (newShared.MaxLength(1))
00064                     return false;
00065                 else
00066                     newShared.SwapWith(&sharedLibs);
00067             }
00068         }
00069         
00070         // now we have at least two shared libs, check if at least two are
00071         // split points that divide the area into two eyes.
00072         int nuIPs = 0;
00073         for (SgVectorIterator<SgPoint> it(sharedLibs); it; ++it)
00074         {
00075             if (  GoEyeUtil::IsSplitPt(*it, region)
00076                && ++nuIPs >= 2
00077                )
00078                     /* */ return true; /* */
00079         }
00080         return false;
00081     }
00082 }
00083 
00084 /** Is p adjacent to all blocks represented by anchors?
00085     GoRegion has an identical function taking a list of GoBlock's. */
00086 inline bool IsAdjacentToAll(const GoBoard& board, SgPoint p,
00087                             const SgVector<SgPoint>& anchors)
00088 {
00089     for (SgVectorIterator<SgPoint> it(anchors); it; ++it)
00090         if (! board.IsLibertyOfBlock(p, *it))
00091             return false;
00092     return true;
00093 }
00094 
00095 /** A simple test if the 2-vital search has produced a two-eyed group.
00096     @todo To be replaced by incremental region code, which will recognize the
00097     eye regions.
00098     Right now, test only for special cases, not even Benson.
00099         1. single block 2 eyes
00100         2. simple check for 2 blocks */
00101 bool TwoSeparateEyes(const GoBoard& bd, const SgPointSet& pts,
00102                      const SgPointSet& boundary, SgBlackWhite color)
00103 {
00104     SG_ASSERT((pts & bd.AllEmpty()).SubsetOf(boundary.Border(bd.Size())));
00105     
00106     if (pts.Disjoint(bd.All(color)) && ! pts.IsConnected())
00107     {
00108         if (GoRegionUtil::IsSingleBlock(bd, boundary, color))
00109             return true;
00110         else
00111         {
00112             const SgPointSet area = pts & bd.AllEmpty();
00113             if (area.MinSetSize(2))
00114             {
00115                 for (SgSetIterator it(area); it; ++it)
00116                     if (bd.IsLegal(*it, SgOppBW(color)))
00117                         return false;
00118                 return true;
00119             }
00120         }
00121     }
00122     return false;
00123 }
00124 
00125 } // namespace
00126 
00127 //----------------------------------------------------------------------------
00128 
00129 void GoRegionUtil::FindCurrentAnchors(const GoBoard& board,
00130                                       const SgVector<SgPoint>& origAnchors,
00131                                       SgVector<SgPoint>* currentAnchors)
00132 {
00133     SG_ASSERT(currentAnchors->IsEmpty());
00134     for (SgVectorIterator<SgPoint> it(origAnchors); it; ++it)
00135         currentAnchors->Insert(board.Anchor(*it));
00136 }
00137 
00138 bool GoRegionUtil::Has2IPorEyes(const GoBoard& board, const SgPointSet& pts,
00139                                 SgBlackWhite color,
00140                                 const SgVector<SgPoint>& boundaryAnchors)
00141 {
00142     return     Has2IntersectionPoints(board, pts, boundaryAnchors) 
00143             || (  boundaryAnchors.IsLength(1) 
00144                && pts.Disjoint(board.All(color)) 
00145                && ! pts.IsConnected()
00146                );
00147 }
00148 
00149 bool GoRegionUtil::Has2SureLiberties(const GoBoard& board,
00150                                      const SgPointSet& pts,
00151                                      SgBlackWhite color,
00152                                      const SgVector<SgPoint>& boundaryAnchors)
00153 {
00154     const int size = board.Size();
00155     SgPointSet boundary(pts.Border(size));
00156     if (! boundary.SubsetOf(board.All(color)))
00157     {
00158         return false; // no result of open area
00159     }
00160     else
00161     {
00162         boundary -= board.AllEmpty();
00163         SG_ASSERT(boundary.SubsetOf(board.All(color)));
00164     }
00165     // Cond 1: all empty points are in liberties of some boundary block
00166     // Cond 2: two intersection points
00167     
00168     if (  (pts & board.AllEmpty()).SubsetOf(boundary.Border(size))
00169        && (  Has2IntersectionPoints(board, pts, boundaryAnchors)
00170           || TwoSeparateEyes(board, pts, boundary, color)
00171           )
00172        )
00173         /* */ return true; /* */
00174     
00175     return false;
00176 }
00177 
00178 bool GoRegionUtil::IsSingleBlock(const GoBoard& board, const SgPointSet& pts,
00179                                  SgBlackWhite color)
00180 {
00181     SG_DEBUG_ONLY(color);
00182     // exception for completely empty board. @todo catch this elsewhere???
00183     SG_ASSERT(pts.NonEmpty()
00184               || board.TotalNumEmpty() == board.Size() * board.Size());
00185     
00186     SgPoint firstAnchor(SG_NULLPOINT);
00187     for (SgSetIterator it(pts); it; ++it)
00188     {
00189         SG_ASSERT(board.IsColor(*it, color));
00190         const SgPoint anchor = board.Anchor(*it);
00191         if (anchor != firstAnchor)
00192         {
00193             if (firstAnchor == SG_NULLPOINT)
00194                 firstAnchor = anchor;
00195             else
00196                 return false;
00197         }
00198     }
00199     return true;
00200 }
00201 
00202 bool GoRegionUtil::IsSmallRegion(const GoBoard& board, const SgPointSet& pts,
00203                                  SgBlackWhite opp)
00204 {
00205     const int size = board.Size();
00206     return pts.Kernel(size).SubsetOf(board.All(opp));
00207 }
00208 
00209 bool GoRegionUtil::StaticIs1VitalAndConnected(const GoBoard& board,
00210                                               const SgPointSet& pts,
00211                                               SgBlackWhite color)
00212 {
00213     // type 1:small region with two connection points for all blocks
00214     SgVector<SgPoint> anchors;
00215     GoBoardUtil::BlocksAdjacentToPoints(board, pts, color, &anchors);
00216     
00217     bool is1Vital = false;
00218     
00219     if (IsSmallRegion(board, pts, SgOppBW(color)))
00220     {
00221         if (anchors.MaxLength(1)) // single block, connected.
00222             /* */ return true; /* */
00223         else if (anchors.MinLength(5)) 
00224         // no way so many blocks can be connected.
00225             return false;
00226             
00227         int nuConn = 0;
00228         for (SgSetIterator it(pts); it; ++it)
00229         {
00230             const SgPoint p(*it);
00231             if (board.IsEmpty(p) && IsAdjacentToAll(board, p, anchors))
00232             {   // test if boundary stones can be connected by playing p
00233                 if (++nuConn >= 2)
00234                 {
00235                     is1Vital = true;
00236                     break;
00237                 }
00238             }
00239         }
00240     }
00241     return is1Vital;    
00242 }
00243 
00244 //----------------------------------------------------------------------------


Sun Mar 13 2011 Doxygen 1.7.1