00001
00002
00003
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
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
00036 bool Has2IntersectionPoints(const GoBoard& board, const SgPointSet& region,
00037 const SgVector<SgPoint>& boundaryAnchors)
00038 {
00039 if (boundaryAnchors.IsLength(1))
00040 return Has2IntersectionPoints(board, region, boundaryAnchors.Back());
00041 else
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)
00055 first = false;
00056 else
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
00071
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
00085
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
00096
00097
00098
00099
00100
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 }
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;
00159 }
00160 else
00161 {
00162 boundary -= board.AllEmpty();
00163 SG_ASSERT(boundary.SubsetOf(board.All(color)));
00164 }
00165
00166
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
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
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))
00222 return true;
00223 else if (anchors.MinLength(5))
00224
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 {
00233 if (++nuConn >= 2)
00234 {
00235 is1Vital = true;
00236 break;
00237 }
00238 }
00239 }
00240 }
00241 return is1Vital;
00242 }
00243
00244