00001 //---------------------------------------------------------------------------- 00002 /** @file GoChain.h 00003 A chain contained in a @see GoRegionBoard. 00004 */ 00005 //---------------------------------------------------------------------------- 00006 00007 #ifndef GO_CHAIN_H 00008 #define GO_CHAIN_H 00009 00010 #include <iosfwd> 00011 #include "GoBlock.h" 00012 #include "GoBoard.h" 00013 #include "SgBlackWhite.h" 00014 #include "SgPoint.h" 00015 #include "SgVector.h" 00016 00017 //---------------------------------------------------------------------------- 00018 00019 class GoRegionBoard; 00020 00021 //---------------------------------------------------------------------------- 00022 00023 /** The reason why two blocks or chains are merged into a single chain */ 00024 enum GoChainType 00025 { 00026 GO_CHAIN_TWO_LIBERTIES_IN_REGION, 00027 GO_CHAIN_TWO_SEPARATE_LIBERTIES, // unused 00028 GO_CHAIN_BY_SEARCH, 00029 _GO_CHAIN_COUNT 00030 }; 00031 00032 std::ostream& operator<<(std::ostream& stream, GoChainType f); 00033 00034 /** Condition that explains why two blocks or chains can be merged 00035 into a new, larger chain. 00036 */ 00037 class GoChainCondition 00038 { 00039 public: 00040 00041 /** A condition with no parameters */ 00042 GoChainCondition(GoChainType type) 00043 : m_type(type), 00044 m_lib1(SG_NULLPOINT), 00045 m_lib2(SG_NULLPOINT) 00046 { 00047 SG_ASSERT(type==GO_CHAIN_BY_SEARCH); 00048 } 00049 00050 /** A condition depending on two liberties */ 00051 GoChainCondition(GoChainType type, SgPoint lib1, SgPoint lib2) 00052 : m_type(type), 00053 m_lib1(lib1), 00054 m_lib2(lib2) 00055 { 00056 SG_ASSERT(type == GO_CHAIN_TWO_LIBERTIES_IN_REGION); 00057 // @todo: || type==GO_CHAIN_TWO_SEPARATE_LIBERTIES 00058 } 00059 00060 /** Is there a potential conflict between this and condition? */ 00061 bool Overlaps(const GoChainCondition& condition) const; 00062 00063 /** Is there a potential conflict between this and conditions? */ 00064 bool Overlaps(const SgVectorOf<GoChainCondition>& conditions) const; 00065 00066 /** Are liberties used? @todo make a base class without libs */ 00067 bool UsesLibs() const {return m_type != GO_CHAIN_BY_SEARCH;} 00068 00069 GoChainType Type() const {return m_type;} 00070 00071 /** first liberty used in condition */ 00072 SgPoint Lib1() const 00073 { 00074 SG_ASSERT(m_type != GO_CHAIN_BY_SEARCH); 00075 return m_lib1; 00076 } 00077 00078 /** second liberty used in condition */ 00079 SgPoint Lib2() const 00080 { 00081 SG_ASSERT(m_type != GO_CHAIN_BY_SEARCH); 00082 return m_lib2; 00083 } 00084 00085 private: 00086 /** Type @todo replace by class */ 00087 GoChainType m_type; 00088 00089 /** condition depends on these two liberties */ 00090 SgPoint m_lib1, m_lib2; 00091 }; 00092 00093 std::ostream& operator<<(std::ostream& stream, const GoChainCondition& c); 00094 00095 //---------------------------------------------------------------------------- 00096 00097 /** Set of GoBlock's that are a connected unit */ 00098 class GoChain : public GoBlock 00099 { 00100 public: 00101 00102 /** Constructor from single block */ 00103 GoChain(const GoBlock* b, const GoBoard& board) 00104 : GoBlock(b->Color(), b->Anchor(), board), 00105 m_isSingleBlock(true), 00106 m_freeLiberties(b->Liberties()) 00107 { ++s_alloc; 00108 if (b->IsSafe()) SetToSafe(); 00109 } 00110 00111 /** Constructor by merging two chains */ 00112 GoChain(const GoChain* c1, const GoChain* c2, 00113 GoChainCondition* cond); 00114 00115 /** Destructor */ 00116 virtual ~GoChain() 00117 { 00118 FreeChainConditions(); 00119 ++s_free; 00120 } 00121 00122 /** For debugging */ 00123 void CheckConsistency(const GoBoard& bd) const; 00124 00125 /** Write data of chain */ 00126 void Write(std::ostream& out) const; 00127 00128 /** Write short identifier */ 00129 void WriteID(std::ostream& out) const; 00130 00131 /** are all empty points in area liberties of this? */ 00132 virtual bool AllEmptyAreLiberties(const SgPointSet& area) const; 00133 00134 /** Does the chain consist of a single block, or more than one?*/ 00135 bool IsSingleBlock() const 00136 { 00137 return m_isSingleBlock; 00138 } 00139 00140 /** does chain have one eye? Uses blocks' eyes and 1vc regions */ 00141 void TestFor1Eye(const GoRegionBoard* ra); 00142 00143 /** Free liberties are liberties not used to define chains */ 00144 const SgPointSet& FreeLiberties() const {return m_freeLiberties;} 00145 00146 /** See m_chainConditions */ 00147 const SgVectorOf<GoChainCondition>& ChainConditions() const 00148 { 00149 return m_chainConditions; 00150 } 00151 00152 /** returns list of all blocks in chain */ 00153 void GetBlocks(const GoRegionBoard* ra, 00154 SgVectorOf<GoBlock>* blocks) const; 00155 00156 /** class Finalization */ 00157 static void Fini(); 00158 private: 00159 00160 void FreeChainConditions(); 00161 00162 /** Does the chain consist of a single block, or more than one?*/ 00163 bool m_isSingleBlock; 00164 00165 /** Free liberties are liberties not used to define chains */ 00166 SgPointSet m_freeLiberties; // . 00167 00168 /** All conditions used to create chain */ 00169 SgVectorOf<GoChainCondition> m_chainConditions; 00170 00171 /** Used for debugging only */ 00172 static int s_alloc, s_free; 00173 }; 00174 00175 std::ostream& operator<<(std::ostream& stream, const GoChain& c); 00176 00177 //---------------------------------------------------------------------------- 00178 00179 #endif // GO_CHAIN_H