00001 //---------------------------------------------------------------------------- 00002 /** @file GoBlock.h 00003 A block contained in a GoRegionBoard. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef GO_BLOCK_H 00007 #define GO_BLOCK_H 00008 00009 #include <iosfwd> 00010 #include "GoBoard.h" 00011 #include "GoBoardUtil.h" 00012 #include "SgBlackWhite.h" 00013 #include "SgDebug.h" 00014 #include "SgPoint.h" 00015 #include "SgVector.h" 00016 00017 class GoRegion; 00018 00019 //---------------------------------------------------------------------------- 00020 00021 /** A block augmented by a list of its healthy regions. 00022 Used together with GoRegion in GoRegionBoard. 00023 @todo Avoid cyclic dependency with GoBlock */ 00024 class GoBlock 00025 { 00026 public: 00027 /** GoBlock Constructor 00028 Parameters: 00029 color: color of block 00030 anchor: stone identifying block 00031 board: the board we are on */ 00032 GoBlock(SgBlackWhite color, SgPoint anchor, const GoBoard& board) 00033 : m_has1Eye(false), 00034 m_bd(board), 00035 m_color(color), 00036 m_anchor(anchor), 00037 m_isSafe(false) 00038 { 00039 ++s_alloc; 00040 for (GoBoard::StoneIterator it(board, anchor); it; ++it) 00041 m_stones.Include(*it); 00042 } 00043 00044 /** Destructor */ 00045 virtual ~GoBlock(){ ++s_free;} 00046 00047 /** For debugging */ 00048 void CheckConsistency() const; 00049 00050 /** Write data for block */ 00051 virtual void Write(std::ostream& out) const; 00052 00053 /** Write short identifier for block */ 00054 virtual void WriteID(std::ostream& out) const; 00055 00056 // Accessors 00057 SgBlackWhite Color() const 00058 { 00059 return m_color; 00060 } 00061 00062 /** The unique stone with smallest number identifying a block */ 00063 SgPoint Anchor() const 00064 { 00065 return m_anchor; 00066 } 00067 00068 /** set of all stones */ 00069 const SgPointSet& Stones() const 00070 { 00071 return m_stones; 00072 } 00073 00074 /** number of liberties */ 00075 int NuLiberties() const 00076 { 00077 return m_bd.NumLiberties(m_anchor); 00078 } 00079 00080 /** set of all liberties 00081 @todo slow */ 00082 SgPointSet Liberties() const 00083 { 00084 return m_stones.Border(m_bd.Size()) & m_bd.AllEmpty(); 00085 } 00086 00087 /** is block proven safe? */ 00088 bool IsSafe() const 00089 { 00090 return m_isSafe; 00091 } 00092 00093 /** Are all empty points in area our liberties? */ 00094 virtual bool AllEmptyAreLiberties(const SgPointSet& area) const; 00095 00096 /** is lib our liberty? */ 00097 bool HasLiberty(SgPoint lib) const 00098 { 00099 return m_bd.IsLibertyOfBlock(lib, m_anchor); 00100 } 00101 00102 /** Does block have a simple eye? */ 00103 bool Has1Eye() const 00104 { 00105 return m_has1Eye; 00106 } 00107 00108 /** Mark block as proven safe */ 00109 void SetToSafe() 00110 { 00111 m_isSafe = true; 00112 } 00113 00114 /** compute if block has 1 clear eye, if yes set the m_has1Eye flag */ 00115 void TestFor1Eye(const GoRegion* r); 00116 00117 /** Clear previous computation */ 00118 virtual void ReInitialize() 00119 { 00120 m_isSafe = false; 00121 m_has1Eye = false; 00122 m_healthy.Clear(); 00123 } 00124 00125 /** For incremental computation: add stone to block */ 00126 void AddStone(SgPoint stone); 00127 00128 /** For undo: remove added stone */ 00129 void RemoveStone(SgPoint stone); 00130 00131 /** r is healthy for this */ 00132 void AddHealthy(GoRegion* r) 00133 { 00134 if (! m_healthy.Contains(r)) 00135 m_healthy.PushBack(r); 00136 #ifndef NDEBUG 00137 else 00138 // @todo debug me! see case 1540-1550 in uct_move.tst 00139 // seems to happen after same position recomputed with second 00140 // color. 00141 SgDebug() << "DOUBLE ADD " << r << '\n'; 00142 #endif 00143 } 00144 00145 /** For incremental computation: r is no longer a neighbor region */ 00146 void RemoveRegion(GoRegion* r) 00147 { 00148 m_healthy.Exclude(r); 00149 } 00150 // @todo keep all regions stored. 00151 00152 /** is r in our healthy list? */ 00153 bool ContainsHealthy(const GoRegion* r) const 00154 { 00155 return m_healthy.Contains(r); 00156 } 00157 00158 /** list of healthy regions */ 00159 const SgVectorOf<GoRegion>& Healthy() const 00160 { 00161 return m_healthy; 00162 } 00163 00164 /** class finalization */ 00165 static void Fini(); 00166 00167 protected: 00168 /** list of healthy regions */ 00169 SgVectorOf<GoRegion> m_healthy; 00170 00171 /** does block have one eye? */ 00172 bool m_has1Eye; 00173 00174 /** board */ 00175 const GoBoard& m_bd; 00176 00177 /** This constructor used only in GoChain constructor 00178 Stones is set to the union of the merged chains. */ 00179 GoBlock(const GoBlock* b, const SgPointSet& stones, 00180 const SgVectorOf<GoRegion>& healthy) 00181 : m_healthy(healthy), 00182 m_has1Eye(false), 00183 m_bd(b->m_bd), 00184 m_color(b->Color()), 00185 m_stones(stones), 00186 m_anchor(SG_NULLPOINT), 00187 m_isSafe(false) 00188 00189 { 00190 ++s_alloc; 00191 } 00192 00193 private: 00194 /** Color of block */ 00195 SgBlackWhite m_color; 00196 00197 /** Stones of block */ 00198 SgPointSet m_stones; 00199 00200 /** Anchor*/ 00201 SgPoint m_anchor; 00202 00203 /** Is block marked as safe? */ 00204 bool m_isSafe; 00205 00206 /** Bookkeeping for debugging */ 00207 static int s_alloc, s_free; 00208 // AR add m_healthy2 for 2 sure liberty regions? 00209 }; 00210 00211 std::ostream& operator<<(std::ostream& stream, const GoBlock& b); 00212 00213 //---------------------------------------------------------------------------- 00214 00215 #endif // GO_BLOCK_H