00001
00002
00003
00004
00005
00006
00007 #ifndef GO_EYEUTIL_H
00008 #define GO_EYEUTIL_H
00009
00010 #include "GoBoard.h"
00011 #include "GoBoardUtil.h"
00012 #include "SgPoint.h"
00013
00014
00015
00016 namespace GoEyeUtil
00017 {
00018
00019 const int NAKADE_LIMIT = 6;
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 int DegreeCode(const SgPointSet& points);
00044
00045
00046 long DegreeCode8(const SgPointSet& points);
00047
00048
00049 template<class BOARD>
00050 SgPoint EmptyNeighbor(const BOARD& bd, SgPoint p);
00051
00052
00053
00054
00055
00056
00057 bool IsNakadeShape(const SgPointSet& area);
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 bool IsSimpleEye(const GoBoard& bd, SgPoint p, SgBlackWhite c);
00070
00071
00072 bool IsSinglePointEye(const GoBoard& bd, SgPoint p, SgBlackWhite c);
00073
00074
00075
00076 bool IsPossibleEye(const GoBoard& board, SgBlackWhite color, SgPoint p);
00077
00078
00079
00080
00081 bool CanBecomeSinglePointEye(const GoBoard& board, SgPoint p,
00082 const SgPointSet& oppSafe);
00083
00084
00085 template<class BOARD>
00086 bool MakesNakadeShape(const BOARD& bd, SgPoint p,
00087 SgBlackWhite toPlay);
00088
00089
00090
00091
00092 bool NumberOfMoveToEye(const GoBoard& bd, SgBlackWhite c, SgPoint p,
00093 int& number);
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 bool IsSinglePointEye2(const GoBoard& bd, SgPoint p, SgBlackWhite c);
00107
00108
00109 bool IsSinglePointEye2(const GoBoard& bd, SgPoint p,
00110 SgBlackWhite c, SgVector<SgPoint>& eyes);
00111
00112
00113 template<class BOARD>
00114 bool IsTwoPointEye(const BOARD& bd, SgPoint p,
00115 SgBlackWhite c);
00116
00117
00118
00119
00120 bool NumberOfMoveToEye2(const GoBoard& bd, SgBlackWhite c,
00121 SgPoint p, int& nummoves);
00122
00123
00124 int CountSinglePointEyes2(const GoBoard& bd, SgPoint p);
00125
00126
00127 bool SinglePointSafe2(const GoBoard& bd, SgPoint p);
00128
00129
00130 bool IsSplitPt(SgPoint p, const SgPointSet& s);
00131
00132
00133
00134
00135
00136 bool IsLocalSplitPt(SgPoint p, const SgPointSet& set);
00137
00138
00139 bool IsTreeShape(const SgPointSet& area);
00140
00141
00142
00143
00144 bool IsVitalPt(const SgPointSet& points, SgPoint p, SgBlackWhite opp,
00145 const GoBoard& bd);
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 void TestNakade(const SgPointSet& points, const GoBoard& bd,
00158 SgBlackWhite color, bool isFullyEnclosed, bool& isNakade,
00159 bool& makeNakade, bool& makeFalse, bool& maybeSeki,
00160 bool& sureSeki, SgPoint* vital);
00161
00162 bool CheckInterior(const GoBoard& bd, const SgPointSet& area,
00163 SgBlackWhite opp, bool checkBlocks);
00164 }
00165
00166 namespace {
00167 inline bool AreSameBlocks(const SgPoint anchors1[], const SgPoint anchors2[])
00168 {
00169 int i = 0;
00170 for (; anchors1[i] != SG_ENDPOINT; ++i)
00171 {
00172 if (! GoBoardUtil::ContainsAnchor(anchors2, anchors1[i]))
00173 return false;
00174 }
00175 return (anchors2[i] == SG_ENDPOINT);
00176 }
00177 }
00178
00179 template<class BOARD>
00180 SgPoint GoEyeUtil::EmptyNeighbor(const BOARD& bd, SgPoint p)
00181 {
00182 if (bd.IsEmpty(p + SG_NS))
00183 return p + SG_NS;
00184 if (bd.IsEmpty(p - SG_NS))
00185 return p - SG_NS;
00186 if (bd.IsEmpty(p + SG_WE))
00187 return p + SG_WE;
00188 if (bd.IsEmpty(p - SG_WE))
00189 return p - SG_WE;
00190 SG_ASSERT(false);
00191 return SG_NULLPOINT;
00192 }
00193
00194 inline bool GoEyeUtil::IsSimpleEye(const GoBoard& bd, SgPoint p,
00195 SgBlackWhite c)
00196 {
00197
00198
00199
00200 SgBlackWhite opp = SgOppBW(c);
00201 if (bd.HasEmptyNeighbors(p) || bd.HasNeighbors(p, opp))
00202 return false;
00203 SgSList<SgPoint,2> anchors;
00204 for (SgNb4Iterator it(p); it; ++it)
00205 {
00206 SgPoint nbPoint = *it;
00207 if (bd.IsBorder(nbPoint))
00208 continue;
00209 SG_ASSERT(bd.GetColor(nbPoint) == c);
00210 SgPoint nbAnchor = bd.Anchor(nbPoint);
00211 if (! anchors.Contains(nbAnchor))
00212 {
00213 if (anchors.Length() > 1)
00214 return false;
00215 anchors.PushBack(nbAnchor);
00216 }
00217 }
00218 if (anchors.Length() == 1)
00219 return true;
00220 for (GoBoard::LibertyIterator it(bd, anchors[0]); it; ++it)
00221 {
00222 SgPoint lib = *it;
00223 if (lib == p)
00224 continue;
00225 bool isSecondSharedEye = true;
00226 SgSList<SgPoint,2> foundAnchors;
00227 for (SgNb4Iterator it2(lib); it2; ++it2)
00228 {
00229 SgPoint nbPoint = *it2;
00230 if (bd.IsBorder(nbPoint))
00231 continue;
00232 if (bd.GetColor(nbPoint) != c)
00233 {
00234 isSecondSharedEye = false;
00235 break;
00236 }
00237 SgPoint nbAnchor = bd.Anchor(nbPoint);
00238 if (! anchors.Contains(nbAnchor))
00239 {
00240 isSecondSharedEye = false;
00241 break;
00242 }
00243 if (! foundAnchors.Contains(nbAnchor))
00244 foundAnchors.PushBack(nbAnchor);
00245 }
00246 if (isSecondSharedEye && foundAnchors.Length() == 2)
00247 return true;
00248 }
00249 return false;
00250 }
00251
00252 template<class BOARD>
00253 bool GoEyeUtil::IsTwoPointEye(const BOARD& bd, SgPoint p,
00254 SgBlackWhite color)
00255 {
00256 const SgBlackWhite opp = SgOppBW(color);
00257 if (bd.NumEmptyNeighbors(p) == 1
00258 && bd.NumNeighbors(p, opp) == 0
00259 )
00260 {
00261 const SgPoint p2 = GoBoardUtil::FindNeighbor(bd, p, SG_EMPTY);
00262 if ( bd.NumEmptyNeighbors(p2) == 1
00263 && bd.NumNeighbors(p2, opp) == 0
00264 )
00265 {
00266
00267 SgPoint nbanchorp[4 + 1];
00268 SgPoint nbanchorp2[4 + 1];
00269 bd.NeighborBlocks(p, color, nbanchorp);
00270 bd.NeighborBlocks(p2, color, nbanchorp2);
00271 SG_ASSERT(nbanchorp[0] != SG_ENDPOINT);
00272 SG_ASSERT(nbanchorp2[0] != SG_ENDPOINT);
00273 return AreSameBlocks(nbanchorp, nbanchorp2);
00274 }
00275 }
00276 return false;
00277 }
00278
00279 template<class BOARD>
00280 bool GoEyeUtil::MakesNakadeShape(const BOARD& bd, SgPoint p,
00281 SgBlackWhite toPlay)
00282 {
00283 SgPointSet area;
00284 area.Include(p);
00285 int nu = 1;
00286 SgVector<SgPoint> toProcess;
00287 toProcess.PushBack(p);
00288 while (toProcess.NonEmpty())
00289 {
00290 SgPoint p = toProcess.Back();
00291 toProcess.PopBack();
00292 for (SgNb4Iterator it(p); it; ++it)
00293 if (bd.IsColor(*it, toPlay) && ! area.Contains(*it))
00294 {
00295 area.Include(*it);
00296 toProcess.PushBack(*it);
00297 if (++nu > NAKADE_LIMIT)
00298 return false;
00299 }
00300 }
00301 return IsNakadeShape(area);
00302 }
00303
00304
00305
00306 #endif // GO_EYEUTIL_H
00307