Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoRegionBoard.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoRegionBoard.h
00003     A GoRegionBoard provides the connected components of a GoBoard.
00004 */
00005 //----------------------------------------------------------------------------
00006 
00007 #ifndef GO_REGIONBOARD_H
00008 #define GO_REGIONBOARD_H
00009 
00010 #include "GoBoard.h"
00011 #include "GoRegion.h"
00012 
00013 class GoBlock;
00014 class GoChain;
00015 
00016 //----------------------------------------------------------------------------
00017 
00018 /** GoRegionBoard provides GoRegion, GoBlock and optionally GoChain.
00019     To keep it updated during search, call OnExecutedMove
00020     (or OnExecutedUncodedMove) and OnUndoneMove when Executing/Undoing a move.
00021 
00022     A GoRegionBoard depends on a GoBoard (supplied at construction)
00023     for keeping the low-level board state, Go rules etc.
00024 
00025     There is a certain amount of duplication between the private blocks of a
00026     GoBoard and the GoBlock's in a GoRegionBoard.
00027 
00028     GoChain's are not updated automatically for performance reasons
00029     - call GenChains() to update them.
00030 */
00031 class GoRegionBoard
00032 {
00033 public:
00034 
00035     /** Constructor */
00036     explicit GoRegionBoard(const GoBoard& board);
00037 
00038     /** release memory. Calls Clear() */
00039     virtual ~GoRegionBoard();
00040 
00041     /** delete all blocks and regions, set board size */
00042     void Clear();
00043 
00044     /** For debugging */
00045     void CheckConsistency() const;
00046 
00047     /** Have blocks and regions been computed for current board position? */
00048     bool UpToDate() const
00049     {
00050         return    ! m_invalid
00051                && m_boardSize == m_board.Size()
00052                && m_code == Board().GetHashCode();
00053     }
00054     
00055     bool ComputedHealthy() const
00056     {
00057         return m_computedHealthy;
00058     }
00059 
00060     /** Have chains been computed for current board position? */
00061     bool ChainsUpToDate() const
00062     {
00063         return UpToDate() && m_chainsCode == Board().GetHashCode();
00064     }
00065 
00066     /** MUST call before playing move on GoBoard */
00067     void ExecuteMovePrologue();
00068 
00069     /** Called after a move or added stone has been successfully executed.
00070         The board is guaranteed to be in a legal state.
00071     */
00072     void OnExecutedMove(GoPlayerMove playerMove);
00073 
00074     /** Similar to OnExecutedMove, but move is not coded into one int. */
00075     void OnExecutedUncodedMove(int move, SgBlackWhite moveColor);
00076 
00077     /** Called after a move has been undone.
00078         The board is guaranteed to be in a legal state.
00079     */
00080     void OnUndoneMove();
00081 
00082     /** All GoBlock's of given color */
00083     SgVectorOf<GoBlock>& AllBlocks(SgBlackWhite color)
00084     {
00085         return m_allBlocks[color];
00086     }
00087 
00088     /** All GoBlock's of given color */
00089     const SgVectorOf<GoBlock>& AllBlocks(SgBlackWhite color) const
00090     {
00091         return m_allBlocks[color];
00092     }
00093 
00094     /** All GoChain's of given color */
00095     SgVectorOf<GoChain>& AllChains(SgBlackWhite color)
00096     {
00097         return m_allChains[color];
00098     }
00099 
00100     /** All GoChain's of given color */
00101     const SgVectorOf<GoChain>& AllChains(SgBlackWhite color) const
00102     {
00103         return m_allChains[color];
00104     }
00105 
00106     /** All GoRegion's of given color */
00107     SgVectorOf<GoRegion>& AllRegions(SgBlackWhite color)
00108     {
00109         return m_allRegions[color];
00110     }
00111 
00112     /** All GoRegion's of given color */
00113     const SgVectorOf<GoRegion>& AllRegions(SgBlackWhite color) const
00114     {
00115         return m_allRegions[color];
00116     }
00117 
00118     /** See GoBoard::All */
00119     const SgPointSet& All(SgBlackWhite color) const
00120     {
00121         return Board().All(color);
00122     }
00123 
00124     /** See GoBoard::AllEmpty */
00125     const SgPointSet& AllEmpty() const {return Board().AllEmpty();}
00126 
00127     /** See GoBoard::AllPoints */
00128     const SgPointSet& AllPoints() const {return Board().AllPoints();}
00129 
00130     /** See GoBoard::IsColor */
00131     bool IsColor(SgPoint p, int c) const {return Board().IsColor(p, c);}
00132 
00133     /** write information on all GoBlock's */
00134     void WriteBlocks(std::ostream& stream) const;
00135 
00136     /** write information on all GoRegion's */
00137     void WriteRegions(std::ostream& stream) const;
00138 
00139     /** generate all blocks and regions */
00140     void GenBlocksRegions();
00141 
00142     /** Compute all GoChain's
00143         @todo currently this only creates 1 chain for each block.
00144         The merging is only done in GoSafetySolver::GenBlocksRegions()
00145         and must be moved here.
00146     */
00147     void GenChains();
00148 
00149     /** Clear all flags etc. to recompute regions and blocks */
00150     void ReInitializeBlocksRegions();
00151 
00152     /** mark all regions that the given attribute has been computed */
00153     void SetComputedFlagForAll(GoRegionFlag flag);
00154 
00155     const GoBoard& Board() const
00156     {
00157         return m_board;
00158     }
00159 
00160     /** Searches the list of all blocks for the block.
00161         Boundary must belong to a single block.
00162     */
00163     GoBlock* GetBlock(const SgPointSet& boundary,
00164                          SgBlackWhite color) const;
00165 
00166     /** For incremental update, region where stone was just played */
00167     GoRegion* PreviousRegionAt(SgPoint p, SgBlackWhite color) const
00168     {
00169         SG_ASSERT(Board().Occupied(p));
00170         SG_ASSERT(m_region[color][p] != 0);
00171         return m_region[color][p];
00172     }
00173 
00174     /** Region of color at point p */
00175     GoRegion* RegionAt(SgPoint p, SgBlackWhite color) const
00176     {
00177         SG_ASSERT(UpToDate());
00178         SG_ASSERT(! Board().IsColor(p, color));
00179         SG_ASSERT(m_region[color][p] != 0);
00180         return m_region[color][p];
00181     }
00182 
00183     /** Region of color in area */
00184     void RegionsAt(const SgPointSet& area, SgBlackWhite color,
00185                             SgVectorOf<GoRegion>* regions) const;
00186 
00187     /** Region of color adjacent to points */
00188     void AdjacentRegions(const SgVector<SgPoint>& points, SgBlackWhite color,
00189                             SgVectorOf<GoRegion>* regions) const;
00190 
00191     /** Return GoBlock's just captured on last move, before update.
00192         For incremental update.
00193         Can be called for any empty point.
00194         returns 0 if no previous block there.
00195     */
00196     void PreviousBlocksAt(const SgVector<SgPoint>& area, SgBlackWhite color,
00197                             SgVectorOf<GoBlock>* captures) const;
00198 
00199     /** GoBlock at point p*/
00200     GoBlock* BlockAt(SgPoint p) const
00201     {
00202         SG_ASSERT(m_block[p] != 0);
00203         return m_block[p];
00204     }
00205 
00206     /** GoChain at point p*/
00207     GoChain* ChainAt(SgPoint p) const;
00208 
00209     /** Is block at point p marked as safe?*/
00210     bool IsSafeBlock(SgPoint p) const;
00211 
00212     /** Set safe flag for block at p*/
00213     void SetToSafe(SgPoint p) const;
00214 
00215     /** Set safe flags for all blocks in safe*/
00216     void SetSafeFlags(const SgBWSet& safe);
00217 
00218     /** Set m_computedHealthy flag to true */
00219     void SetComputedHealthy();
00220     
00221     /** class initialization */
00222     static bool Init();
00223 
00224     /** class finalization */
00225     static void Fini();
00226 
00227 private:
00228 
00229     // Compute from scratch helpers
00230     /** Generate blocks */
00231     void GenBlocks();
00232 
00233     /** Set the m_has1Eye flag for all blocks with 1 eye */
00234     void FindBlocksWithEye();
00235 
00236     // Execute move helpers
00237     /** Generate the block with given anchor */
00238     GoBlock* GenBlock(SgPoint anchor, SgBlackWhite color);
00239 
00240     /** Generate a region of color in area */
00241     GoRegion* GenRegion(const SgPointSet& area, SgBlackWhite color);
00242 
00243     /** incremental update of block after move */
00244     void UpdateBlock(int move, SgBlackWhite moveColor);
00245 
00246     /** Sets m_region elements to point to r */
00247     void SetRegionArrays(GoRegion* r);
00248 
00249     /** add block to GoRegionBoard */
00250     void AddBlock(GoBlock* b, bool isExecute = true);
00251 
00252     /** remove block from GoRegionBoard */
00253     void RemoveBlock(GoBlock* b, bool isExecute, bool removeFromRegions);
00254 
00255     /** add region to GoRegionBoard */
00256     void AddRegion(GoRegion* r, bool isExecute = true);
00257 
00258     /** remove region from GoRegionBoard */
00259     void RemoveRegion(GoRegion* r, bool isExecute = true);
00260 
00261     /** For all captured stones: merge its adjacent previous regions into one.
00262         then for all captured stones: add their area to its single adjacent
00263         region.
00264     */
00265     void MergeAdjacentAndAddBlock(SgPoint move, SgBlackWhite capturedColor);
00266 
00267     /** Merge all regions and the captured area into new large region */
00268     GoRegion* MergeAll(const SgVectorOf<GoRegion>& regions,
00269                       const SgPointSet& captured, SgBlackWhite color);
00270 
00271     // Undo move helpers
00272     /** stores incremental state changes for execute/undo moves */
00273     SgIncrementalStack m_stack;
00274 
00275     /** push on m_stack */
00276     void PushRegion(int type, GoRegion* r);
00277 
00278     /** push on m_stack */
00279     void PushStone(GoRegion* r, SgPoint move);
00280 
00281     /** push on m_stack */
00282     void PushBlock(int type, GoBlock* b);
00283 
00284     /** add stome to b and push information on m_stack */
00285     void AppendStone(GoBlock* b, SgPoint move);
00286 
00287     // data members
00288 
00289     const GoBoard& m_board;
00290 
00291     /** pointer to region, defined only at anchor of region */
00292     SgBWArray<SgPointArray<GoRegion*> > m_region;
00293 
00294     /** pointer from stone to block, 0 if empty point */
00295     SgPointArray<GoBlock*> m_block;
00296 
00297     /** All blocks on board */
00298     SgBWArray<SgVectorOf<GoBlock> > m_allBlocks;
00299 
00300     /** All chains on board */
00301     SgBWArray<SgVectorOf<GoChain> > m_allChains;
00302 
00303     /** All regions on board */
00304     SgBWArray<SgVectorOf<GoRegion> > m_allRegions;
00305 
00306     /** Code for last time block and region information was computed */
00307     SgHashCode m_code;
00308 
00309     /** Code for last time chain information was computed */
00310     SgHashCode m_chainsCode;
00311 
00312     /** does block and region data match current board? */
00313     bool m_invalid;
00314     
00315     /** has healthy count been computed for all blocks?
00316         @todo in fully incremental mode, this should be determined locally
00317         for each block, not globally.
00318     */
00319     bool m_computedHealthy;
00320     
00321     /** Boardsize is needed to avoid problems with resizing an empty board */
00322     int m_boardSize;
00323 
00324     /** debugging bookkeeping. @todo do it in debug only */
00325     static int s_alloc, s_free;
00326 
00327 };
00328 
00329 //----------------------------------------------------------------------------
00330 
00331 #endif // GO_REGIONBOARD_H


17 Jun 2010 Doxygen 1.4.7