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