Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoRegion.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoRegion.h
00003     A GoRegion contained in a @see GoRegionBoard.
00004 
00005     A GoRegion is a maximal connected set of points surrounded by stones 
00006     of the same color.
00007 
00008     Regions compute properties such as 1-vitality,
00009     2-vitality [Mueller 95, p. 62-63],[Mueller 97b].
00010     They are used for static and search-based safety solvers.
00011     They are also used for better move generation, e.g. in semeai. */
00012 //----------------------------------------------------------------------------
00013 
00014 #ifndef GO_REGION_H
00015 #define GO_REGION_H
00016 
00017 #include <bitset>
00018 #include <iosfwd>
00019 #include "GoBoard.h"
00020 #include "GoBoardUtil.h"
00021 #include "GoEyeCount.h"
00022 #include "SgVector.h"
00023 #include "SgIncrementalStack.h"
00024 #include "SgMiaiStrategy.h"
00025 #include "SgPointArray.h"
00026 
00027 class GoBlock;
00028 class GoChain;
00029 class GoRegionBoard;
00030 
00031 //----------------------------------------------------------------------------
00032 
00033 /** Information computed about a GoRegion.
00034     @todo Does not follow naming convention for constants in global
00035     namespace; rename to all-uppercase and use prefix GO_ */
00036 enum GoRegionFlag
00037 {
00038     GO_REGION_SMALL,
00039     GO_REGION_CORRIDOR,
00040     GO_REGION_STATIC_1VC,
00041     GO_REGION_1VC,
00042     GO_REGION_STATIC_2V,
00043     GO_REGION_2V,
00044     GO_REGION_SINGLE_BLOCK_BOUNDARY,
00045     GO_REGION_OPP_CAN_LIVE_INSIDE,
00046     GO_REGION_AT_LEAST_SEKI,
00047     GO_REGION_SAFE,
00048     GO_REGION_PROTECTED_CUTS,
00049     GO_REGION_STATIC_1VITAL,
00050     GO_REGION_1VITAL,
00051     GO_REGION_USED_FOR_MERGE,
00052     GO_REGION_VALID,
00053     GO_REGION_COMPUTED_BLOCKS,
00054     GO_REGION_COMPUTED_CHAINS,
00055     GO_REGION_COMPUTED_NAKADE,
00056     _GO_REGION_FLAG_COUNT
00057 };
00058 
00059 /** Set of GoRegionFlag */
00060 typedef std::bitset<_GO_REGION_FLAG_COUNT> GoRegionFlags;
00061 
00062 //----------------------------------------------------------------------------
00063 
00064 /** GoRegion represents a region surrounded by blocks of one color.
00065 
00066     Each empty point, and each point occupied by white,
00067     is contained in exactly one black region.
00068     Similarly each empty point, and each point occupied by black,
00069     is contained in exactly one white region.
00070 
00071     A region keeps data such as its color, the blocks and chains of its color,
00072     the eye status, and a strategy to follow to keep the region safe.
00073 
00074     Regions can provide liberties for its boundary blocks.
00075     They can be "1-vital" or "2-vital". This is used by safety solvers.
00076     For details see [Mueller 1997]:
00077     Playing it safe: Recognizing secure territories in computer Go by using
00078     static rules and search. In H. Matsubara, editor, Game Programming
00079     Workshop in Japan '97, pages 80-86, Computer Shogi Association, Tokyo, 
00080     Japan, 1997.
00081 
00082     @todo Avoid cyclic dependency with GoBlock */
00083 class GoRegion
00084 {
00085 public:
00086     /** Construct region on points in color */
00087     GoRegion(const GoBoard& board, const SgPointSet& points,
00088              SgBlackWhite color);
00089 
00090     /** Destructor */
00091     ~GoRegion()
00092     {
00093 #ifndef NDEBUG
00094         ++s_free;
00095 #endif
00096     }
00097 
00098     /** Clear all flags etc. to recompute region */
00099     void ReInitialize();
00100 
00101     /** For debugging */
00102     void CheckConsistency() const;
00103 
00104     // Accessors
00105     /** The points of the region */
00106     const SgPointSet& Points() const
00107     {
00108         return m_points;
00109     }
00110 
00111     /** The dependency set, outside neighbors of m_points */
00112     SgPointSet Dep() const
00113     {
00114         return m_points.Border(m_bd.Size());
00115     }
00116 
00117     /** liberties not adjacent to boundary stones */
00118     SgPointSet AllInsideLibs() const;
00119 
00120     /** Chains of region */
00121     const SgVectorOf<GoChain>& Chains() const
00122     {
00123         return m_chains;
00124     }
00125 
00126     /** Blocks of region */
00127     const SgVectorOf<GoBlock>& Blocks() const
00128     {
00129         return m_blocks;
00130     }
00131 
00132     /** Blocks of region.
00133         Non const version used by GoRegionBoard. */
00134     SgVectorOf<GoBlock>& BlocksNonConst()
00135     {
00136         return m_blocks;
00137     }
00138 
00139     /** Interior blocks of region: all liberties are in m_points */
00140     SgVectorOf<GoBlock> InteriorBlocks() const;
00141 
00142     /** Is block an interior block of this region? */
00143     bool IsInteriorBlock(const GoBlock* block) const;
00144 
00145     /** Is block a boundary block of this region? */
00146     bool IsBoundaryBlock(const GoBlock* block) const
00147     {
00148         return ! IsInteriorBlock(block);
00149     }
00150 
00151     /** all points of region's blocks - even those not contained in Dep() */
00152     SgPointSet BlocksPoints() const;
00153 
00154     /** area of points plus interior blocks */
00155     SgPointSet PointsPlusInteriorBlocks() const;
00156 
00157     /** color of region */
00158     SgBlackWhite Color() const
00159     {
00160         return m_color;
00161     }
00162 
00163     /** minimum number of eyes in region */
00164     int MinEyes() const {return m_eyes.MinEyes();}
00165 
00166     /** maximum number of eyes in region */
00167     int MaxEyes() const {return m_eyes.MaxEyes();}
00168 
00169     /** minimum number of potential eyes in region */
00170     int MinPotEyes() const {return m_eyes.MinPotEyes();}
00171 
00172     /** maximum number of potential eyes in region */
00173     int MaxPotEyes() const {return m_eyes.MaxPotEyes();}
00174 
00175     /** Write all information */
00176     void Write(std::ostream& out) const;
00177 
00178     /** Write short identifier */
00179     void WriteID(std::ostream& out) const;
00180 
00181     // Flags
00182     /** get value of precomputed flag */
00183     bool GetFlag(GoRegionFlag flag) const;
00184 
00185     /** compute, then get value of precomputed flag */
00186     bool ComputeAndGetFlag(GoRegionFlag flag);
00187 
00188     /** test if flag has been computed */
00189     bool ComputedFlag(GoRegionFlag flag) const;
00190 
00191     /** compute the flag, set it to true or false */
00192     void ComputeFlag(GoRegionFlag flag);
00193 
00194     /** Only blocks are incrementally updated, others must be reset after
00195         move */
00196     void ResetNonBlockFlags()
00197     {   m_computedFlags.reset(); // clear all other flags.
00198         m_computedFlags.set(GO_REGION_COMPUTED_BLOCKS);
00199         m_eyes.Clear();
00200         Invalidate();
00201     }
00202 
00203     /** is region data valid? */
00204     bool IsValid() const {return m_flags.test(GO_REGION_VALID);}
00205 
00206     /** reset valid flag, region data not current anymore */
00207     void Invalidate() {m_flags.reset(GO_REGION_VALID);}
00208 
00209     /** Computes GO_REGION_SMALL, GO_REGION_CORRIDOR, 
00210         GO_REGION_SINGLE_BLOCK_BOUNDARY, 
00211         GO_REGION_STATIC_1VC, GO_REGION_STATIC_2V */
00212     void ComputeBasicFlags();
00213 
00214     /** compute flag */
00215     void DoComputeFlag(GoRegionFlag flag);
00216 
00217     /** mark that flag is computed now */
00218     void SetComputedFlag(GoRegionFlag flag) {m_computedFlags.set(flag);}
00219 
00220     /** set flag to value */
00221     void SetFlag(GoRegionFlag flag, bool value)
00222     {   m_computedFlags.set(flag);
00223         m_flags.set(flag, value);
00224     }
00225 
00226     /** store search depth used in ExVital1Task for 1vc search */
00227     void Set1VCDepth(int depth) {m_1vcDepth = depth;}
00228 
00229     // Queries
00230     /** does region have two free (unused) liberties to connect chains? */
00231     bool Has2ConnForChains(const GoChain* c1, const GoChain* c2) const;
00232 
00233     /** call Has2ConnForBlocks for region with exactly two chains*/
00234     bool Has2Conn() const;
00235 
00236     /** is this healthy for a block in list? */
00237     bool HealthyForSomeBlock(const SgVectorOf<GoBlock>& blocks) const;
00238 
00239     /** Is region completely surrounded by blocks? */
00240     bool IsSurrounded(const SgVectorOf<GoBlock>& blocks) const;
00241 
00242     /** did ExVital1Task have at least this search depth? */
00243     bool ComputedVitalForDepth(int depth) const;
00244 
00245     /** is any adjacent block safe? */
00246     bool SomeBlockIsSafe() const;
00247 
00248     /** are all adjacent block safe? */
00249     bool AllBlockIsSafe() const;
00250 
00251     /** Is block of anchor adjacent to region? */
00252     bool AdjacentToBlock(SgPoint anchor) const;
00253 
00254     /** Is one of blocks given by anchors adjacent to region? */
00255     bool AdjacentToSomeBlock(const SgVector<SgPoint>& anchors) const;
00256 
00257     /** For flat region: cuts not occupied is enough to make region 1-vital */
00258     bool Safe2Cuts(const GoBoard& board) const;
00259 
00260     /** Test if all empty points are liberties of blocks
00261         @todo does not test only for boundary block libs, but all libs. */
00262     bool AllEmptyAreLibs() const;
00263 
00264     /** Test if points of region are 2-vital for color.
00265         Condition 1: all empty points are in liberties of some boundary block
00266         Condition 2: two intersection points (@see Has2IPs)
00267         refined version: points need not be liberty, if next to both IP.
00268         Example: bent-5 in the corner, as in Berlekamp/Wolfe C.11 top left
00269         corner */
00270     bool Has2SureLibs(SgMiaiStrategy* miaiStrategy) const;
00271 
00272     /** block liberties in this region */
00273     void InsideLibs(const GoBlock* b, SgVector<SgPoint>* libs) const;
00274 
00275     /** Is a liberty of b in region? */
00276     bool HasBlockLibs(const GoBlock* b) const;
00277 
00278     /** Can a block get n libs inside region? */
00279     bool HasLibsForBlock(const GoBlock* b, int n) const;
00280 
00281     /** Does each adjacent block have a liberty in region? */
00282     bool HasLibForAllBlocks() const;
00283 
00284     /** Does each block have n liberties in region? */
00285     bool HasLibsForAllBlocks(int n) const;
00286 
00287     /** Can we find two connection paths to each interior empty point? 
00288         This implements only the simple, non-recursive case.
00289         See Find2ConnForAllInterior() for a more general solution. */
00290     bool Find2ConnForAll() const;
00291 
00292     /** find 2-connection paths for all interior empty points, using recursive
00293         extension. Erik v.d.Werf's recursive extension to Find2ConnForAll. */
00294     bool Find2ConnForAllInterior(SgMiaiStrategy* miaiStrategy,
00295                                  SgVector<SgPoint>& usedLibs) const;
00296 
00297     /** An IP divides a region into two eyes AND connects all surrounding
00298         blocks, this one defines that ip has to be adjancent to all interior
00299         points. */
00300     bool Has2IPs(const SgVector<SgPoint>& interiorEmpty, SgMiaiPair* ips)
00301         const;
00302 
00303     /** whether there are 2 intersection points, doesn't have to be adjacent
00304         to all interior points. */
00305     bool Has2IntersectionPoints(const SgVector<SgPoint>& usedLibs) const;
00306 
00307     /** Get all intersections points inside region */
00308     void GetIPs(SgVector<SgPoint>* ips) const;
00309 
00310     /** Get all SgMiaiPairs that can divide the region. A dividing 
00311         SgMiaiPair has two adjacent points that are libs from the 
00312         same boundary block, and they are split points for region.
00313         This is a loose condition for SgMiaiPairs.  */
00314     void GetDivideMiaiPairs(SgVector<SgMiaiPair>& pairs) const;
00315 
00316     /** Compute joint liberties of all m_blocks. Since we need at least 2
00317         joint libs, we stop computing if we find that this is impossible. */
00318     void JointLibs(SgVector<SgPoint>* libs) const;
00319 
00320     /** See ExEye::IsCorridor() */
00321     bool IsCorridor() const;
00322 
00323     /** update region if affected: old was merged into newChain */
00324     bool ReplaceChain(const GoChain* old, const GoChain* newChain); 
00325 
00326     /** chains are mergable if two connections are found */
00327     bool Find2Mergable(GoChain** c1, GoChain** c2) const;
00328 
00329     /** Find two so far unused liberties for connecting c1 and c2 
00330         @todo In future, must respect all other chain conditions 
00331               active in this region. */
00332     void Find2FreeLibs(const GoChain* c1, const GoChain* c2, 
00333                         SgPoint* lib1, SgPoint* lib2) const;
00334 
00335     /** Get blocks of color in area */
00336     void FindBlocks(const GoRegionBoard& ra);
00337 
00338     /** Set blocks for this region from pre-found blocks list */
00339     void SetBlocks(const SgVectorOf<GoBlock>& blocks);
00340 
00341     /** Get chain of color in area.
00342             @todo There must be faster ways to do this. */
00343     void FindChains(const GoRegionBoard& ra);
00344 
00345     /** Set safe flag for region */
00346     void SetToSafe() {SetFlag(GO_REGION_SAFE, true);}
00347 
00348     // Execute move helpers
00349     /** For incremental update - block no longer adjacent */
00350     void RemoveBlock(const GoBlock* b);
00351 
00352     /** Stone was played: remove from m_points */
00353     void OnAddStone(SgPoint p);
00354 
00355     /** Stone removed: add to m_points */
00356     void OnRemoveStone(SgPoint p);
00357 
00358     /** class finalization */
00359     static void Fini();
00360 
00361 private:
00362 
00363     /** The board */
00364     const GoBoard& m_bd;
00365 
00366     /** Flags describing attributes of region */
00367     GoRegionFlags m_flags;
00368 
00369     /** Which flags have been computed? */
00370     GoRegionFlags m_computedFlags;
00371 
00372     /** Points of region */
00373     SgPointSet m_points;
00374 
00375     /** Color of region = color of surrounding stones */
00376     SgBlackWhite m_color;
00377 
00378     /** Blocks of m_color adjacent to region. Some may be on inside */
00379     SgVectorOf<GoBlock> m_blocks;
00380 
00381     /** Chains of region */
00382     SgVectorOf<GoChain> m_chains;  
00383 
00384     /** Number of eyes in region */
00385     GoEyeCount m_eyes;
00386 
00387     /** Point to change eye status. Can be SG_NULLPOINT */
00388     SgPoint m_vitalPoint;
00389 
00390     /** search depth used in ExVital1Task for 1vc search */
00391     int m_1vcDepth;
00392 
00393     /** Miai strategy to keep region safe. */
00394     SgMiaiStrategy m_miaiStrategy;
00395 
00396     /** A simple test if all cuts between blocks are protected. 
00397         Works only for corridors (@see IsCorridor):
00398         If corridor, then opp. can get at most 2 libs (Opp2L).
00399         If Opp2L && cut point empty then opp cut move is self atari,
00400         therefore cut is protected (and remains protected if opponent
00401         is captured and plays inside again) */
00402     bool ProtectedCuts(const GoBoard& board) const;
00403 
00404     /** Static test if region is 1-vital.
00405         @todo explain the algorithm. */
00406     bool ComputeIs1Vital() const;
00407 
00408     /** Static test if region is 1-vital and all blocks are connected. */
00409     bool StaticIs1VitalAndConnected() const;
00410 
00411     /** Compute eye status for some standard small regions */
00412     void ComputeNakade();
00413 
00414     /** Compute eye space for region having only 1 block */
00415     void ComputeSingleBlockEyeSpace();
00416 
00417     /** Compute eye space for region having more than 1 block */
00418     void ComputeMultipleBlockEyeSpace();
00419 
00420     /** Compute eye space for region */
00421     void ComputeEyeSpace();
00422 
00423     /** compute at most maxNu empty points in the interior
00424         @todo does not test only for boundary block libs, but all libs. */
00425     void InteriorEmpty(SgVector<SgPoint>* interiorEmpty, int maxNu) const;
00426 
00427 #ifndef NDEBUG
00428     /** debugging bookkeeping. */
00429     static int s_alloc, s_free;
00430 #endif
00431 };
00432 
00433 std::ostream& operator<<(std::ostream& stream, const GoRegion& r);
00434 
00435 //----------------------------------------------------------------------------
00436 
00437 #endif // GO_REGION_H
00438 


Sun Mar 13 2011 Doxygen 1.7.1