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