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