00001
00002
00003
00004
00005
00006
00007 #include "SgSystem.h"
00008 #include "GoRegionUtil.h"
00009
00010 #include "GoBoard.h"
00011 #include "GoBoardUtil.h"
00012 #include "GoEyeUtil.h"
00013 #include "SgVector.h"
00014 #include "SgPointSet.h"
00015
00016
00017
00018 namespace {
00019
00020
00021 bool Has2IntersectionPoints(const GoBoard& board, const SgPointSet& region,
00022 const SgPoint boundaryAnchor)
00023 {
00024 int nuIPs = 0;
00025 for (GoBoard::LibertyIterator it(board, boundaryAnchor); it; ++it)
00026 {
00027 if ( region.Contains(*it)
00028 && GoEyeUtil::IsSplitPt(*it, region)
00029 && ++nuIPs >= 2
00030 )
00031 return true;
00032 }
00033 return false;
00034 }
00035
00036
00037 bool Has2IntersectionPoints(const GoBoard& board, const SgPointSet& region,
00038 const SgVector<SgPoint>& boundaryAnchors)
00039 {
00040 if (boundaryAnchors.IsLength(1))
00041 return Has2IntersectionPoints(board, region, boundaryAnchors.Back());
00042 else
00043 {
00044 SgVector<SgPoint> sharedLibs;
00045 for (GoBoard::LibertyIterator it(board, boundaryAnchors.Front()); it;
00046 ++it)
00047 if (region.Contains(*it))
00048 sharedLibs.PushBack(*it);
00049
00050 if (sharedLibs.MaxLength(1))
00051 return false;
00052 bool first = true;
00053 for (SgVectorIterator<SgPoint> it(boundaryAnchors); it; ++it)
00054 {
00055 if (first)
00056 first = false;
00057 else
00058 {
00059 SgVector<SgPoint> newShared;
00060 const SgPoint block = *it;
00061 for (GoBoard::LibertyIterator it(board, block); it; ++it)
00062 if (sharedLibs.Contains(*it))
00063 newShared.PushBack(*it);
00064 if (newShared.MaxLength(1))
00065 return false;
00066 else
00067 newShared.SwapWith(&sharedLibs);
00068 }
00069 }
00070
00071
00072
00073 int nuIPs = 0;
00074 for (SgVectorIterator<SgPoint> it(sharedLibs); it; ++it)
00075 {
00076 if ( GoEyeUtil::IsSplitPt(*it, region)
00077 && ++nuIPs >= 2
00078 )
00079 return true;
00080 }
00081 return false;
00082 }
00083 }
00084
00085
00086
00087
00088 inline bool IsAdjacentToAll(const GoBoard& board, SgPoint p,
00089 const SgVector<SgPoint>& anchors)
00090 {
00091 for (SgVectorIterator<SgPoint> it(anchors); it; ++it)
00092 if (! board.IsLibertyOfBlock(p, *it))
00093 return false;
00094 return true;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104 bool TwoSeparateEyes(const GoBoard& bd, const SgPointSet& pts,
00105 const SgPointSet& boundary, SgBlackWhite color)
00106 {
00107 SG_ASSERT((pts & bd.AllEmpty()).SubsetOf(boundary.Border(bd.Size())));
00108
00109 if (pts.Disjoint(bd.All(color)) && ! pts.IsConnected())
00110 {
00111 if (GoRegionUtil::IsSingleBlock(bd, boundary, color))
00112 return true;
00113 else
00114 {
00115 const SgPointSet area = pts & bd.AllEmpty();
00116 if (area.MinSetSize(2))
00117 {
00118 for (SgSetIterator it(area); it; ++it)
00119 if (bd.IsLegal(*it, SgOppBW(color)))
00120 return false;
00121 return true;
00122 }
00123 }
00124 }
00125 return false;
00126 }
00127
00128 }
00129
00130
00131
00132 void GoRegionUtil::FindCurrentAnchors(const GoBoard& board,
00133 const SgVector<SgPoint>& origAnchors,
00134 SgVector<SgPoint>* currentAnchors)
00135 {
00136 SG_ASSERT(currentAnchors->IsEmpty());
00137 for (SgVectorIterator<SgPoint> it(origAnchors); it; ++it)
00138 currentAnchors->Insert(board.Anchor(*it));
00139 }
00140
00141 bool GoRegionUtil::Has2IPorEyes(const GoBoard& board, const SgPointSet& pts,
00142 SgBlackWhite color,
00143 const SgVector<SgPoint>& boundaryAnchors)
00144 {
00145 return Has2IntersectionPoints(board, pts, boundaryAnchors)
00146 || ( boundaryAnchors.IsLength(1)
00147 && pts.Disjoint(board.All(color))
00148 && ! pts.IsConnected()
00149 );
00150 }
00151
00152 bool GoRegionUtil::Has2SureLiberties(const GoBoard& board,
00153 const SgPointSet& pts,
00154 SgBlackWhite color,
00155 const SgVector<SgPoint>& boundaryAnchors)
00156 {
00157 const int size = board.Size();
00158 SgPointSet boundary(pts.Border(size));
00159 if (! boundary.SubsetOf(board.All(color)))
00160 {
00161 return false;
00162 }
00163 else
00164 {
00165 boundary -= board.AllEmpty();
00166 SG_ASSERT(boundary.SubsetOf(board.All(color)));
00167 }
00168
00169
00170
00171 if ( (pts & board.AllEmpty()).SubsetOf(boundary.Border(size))
00172 && ( Has2IntersectionPoints(board, pts, boundaryAnchors)
00173 || TwoSeparateEyes(board, pts, boundary, color)
00174 )
00175 )
00176 return true;
00177
00178 return false;
00179 }
00180
00181 bool GoRegionUtil::IsSingleBlock(const GoBoard& board, const SgPointSet& pts,
00182 SgBlackWhite color)
00183 {
00184 SG_DEBUG_ONLY(color);
00185
00186 SG_ASSERT(pts.NonEmpty()
00187 || board.TotalNumEmpty() == board.Size() * board.Size());
00188
00189 SgPoint firstAnchor(SG_NULLPOINT);
00190 for (SgSetIterator it(pts); it; ++it)
00191 {
00192 SG_ASSERT(board.IsColor(*it, color));
00193 const SgPoint anchor = board.Anchor(*it);
00194 if (anchor != firstAnchor)
00195 {
00196 if (firstAnchor == SG_NULLPOINT)
00197 firstAnchor = anchor;
00198 else
00199 return false;
00200 }
00201 }
00202 return true;
00203 }
00204
00205 bool GoRegionUtil::IsSmallRegion(const GoBoard& board, const SgPointSet& pts,
00206 SgBlackWhite opp)
00207 {
00208 const int size = board.Size();
00209 return pts.Kernel(size).SubsetOf(board.All(opp));
00210 }
00211
00212 bool GoRegionUtil::StaticIs1VitalAndConnected(const GoBoard& board,
00213 const SgPointSet& pts,
00214 SgBlackWhite color)
00215 {
00216
00217 SgVector<SgPoint> anchors;
00218 GoBoardUtil::BlocksAdjacentToPoints(board, pts, color, &anchors);
00219
00220 bool is1Vital = false;
00221
00222 if (IsSmallRegion(board, pts, SgOppBW(color)))
00223 {
00224 if (anchors.MaxLength(1))
00225 return true;
00226 else if (anchors.MinLength(5))
00227
00228 return false;
00229
00230 int nuConn = 0;
00231 for (SgSetIterator it(pts); it; ++it)
00232 {
00233 const SgPoint p(*it);
00234 if (board.IsEmpty(p) && IsAdjacentToAll(board, p, anchors))
00235 {
00236 if (++nuConn >= 2)
00237 {
00238 is1Vital = true;
00239 break;
00240 }
00241 }
00242 }
00243 }
00244 return is1Vital;
00245 }
00246
00247