00001 //---------------------------------------------------------------------------- 00002 /** @file GoChain.cpp 00003 See GoChain.h. 00004 */ 00005 //---------------------------------------------------------------------------- 00006 00007 #include "SgSystem.h" 00008 #include "GoChain.h" 00009 00010 #include <iostream> 00011 #include "GoBlock.h" 00012 #include "GoRegion.h" 00013 #include "GoRegionBoard.h" 00014 #include "SgWrite.h" 00015 00016 //---------------------------------------------------------------------------- 00017 00018 GoChain::GoChain(const GoChain* c1, const GoChain* c2, 00019 GoChainCondition* cond) : 00020 GoBlock(c1, c1->Stones() | c2->Stones(), 00021 c1->Healthy()), 00022 m_isSingleBlock(false), 00023 m_freeLiberties(c1->FreeLiberties() | c2->FreeLiberties()) 00024 { 00025 ++s_alloc; 00026 SG_ASSERT(c1 != c2); 00027 m_healthy.Union(c2->Healthy()); 00028 SG_ASSERT(! cond->Overlaps(m_chainConditions)); 00029 m_chainConditions.PushBack(cond); 00030 00031 if (cond->UsesLibs()) 00032 { 00033 SG_ASSERT(m_freeLiberties.Contains(cond->Lib1())); 00034 m_freeLiberties.Exclude(cond->Lib1()); 00035 SG_ASSERT(m_freeLiberties.Contains(cond->Lib2())); 00036 m_freeLiberties.Exclude(cond->Lib2()); 00037 } 00038 } 00039 00040 void GoChain::TestFor1Eye(const GoRegionBoard* ra) 00041 { 00042 SgVectorOf<GoBlock> blocks; 00043 GetBlocks(ra, &blocks); 00044 for (SgVectorIteratorOf<GoBlock> it(blocks); it; ++it) 00045 if ((*it)->Has1Eye()) 00046 { 00047 m_has1Eye = true; 00048 /* */ return; /* */ 00049 } 00050 00051 for (SgVectorIteratorOf<GoRegion> it(ra->AllRegions(Color())); it; ++it) 00052 if ((*it)->GetFlag(GO_REGION_1VC) && (*it)->Chains().Contains(this)) 00053 { 00054 m_has1Eye = true; 00055 /* */ return; /* */ 00056 } 00057 00058 m_has1Eye = false; 00059 } 00060 00061 void GoChain::FreeChainConditions() 00062 { 00063 for (SgVectorIteratorOf<GoChainCondition> it(m_chainConditions); it; ++it) 00064 delete *it; 00065 m_chainConditions.Clear(); 00066 } 00067 00068 void GoChain::GetBlocks(const GoRegionBoard* ra, 00069 SgVectorOf<GoBlock>* blocks) const 00070 { 00071 SgBlackWhite color = Color(); 00072 SgPointSet chainPts = Stones(); 00073 for (SgVectorIteratorOf<GoBlock> it(ra->AllBlocks(color)); it; ++it) 00074 if (chainPts.Contains((*it)->Anchor())) 00075 blocks->PushBack(*it); 00076 } 00077 00078 bool GoChain::AllEmptyAreLiberties(const SgPointSet& area) const 00079 { 00080 return (area & m_bd.AllEmpty()).SubsetOf(Liberties()); 00081 } 00082 00083 void GoChain::WriteID(std::ostream& stream) const 00084 { 00085 stream << ' '<< SgBW(Color()) << " GoChain " 00086 << SgWritePoint(Anchor()); 00087 } 00088 00089 void GoChain::Fini() 00090 { 00091 SG_ASSERT(s_alloc == s_free); 00092 } 00093 00094 void GoChain::Write(std::ostream& stream) const 00095 { 00096 GoBlock::Write(stream); 00097 stream << "Chain conditions: "; 00098 for (SgVectorIteratorOf<GoChainCondition> it(ChainConditions()); it; ++it) 00099 stream << **it; 00100 if (ChainConditions().IsEmpty()) 00101 stream << "none"; 00102 stream << '\n'; 00103 } 00104 00105 //---------------------------------------------------------------------------- 00106 00107 int GoChain::s_alloc = 0; 00108 int GoChain::s_free = 0; 00109 00110 //---------------------------------------------------------------------------- 00111 00112 std::ostream& operator<<(std::ostream& stream, const GoChain& c) 00113 { 00114 c.Write(stream); 00115 return stream; 00116 } 00117 00118 //---------------------------------------------------------------------------- 00119 00120 bool GoChainCondition::Overlaps(const GoChainCondition& condition) const 00121 { 00122 if (! UsesLibs() || ! condition.UsesLibs()) 00123 return false; // AR needs some other check. 00124 00125 return m_lib1 == condition.m_lib1 00126 || m_lib1 == condition.m_lib2 00127 || m_lib2 == condition.m_lib1 00128 || m_lib2 == condition.m_lib2; 00129 } 00130 00131 bool GoChainCondition::Overlaps(const SgVectorOf<GoChainCondition>& 00132 conditions) const 00133 { 00134 for (SgVectorIteratorOf<GoChainCondition> it(conditions); it; ++it) 00135 { 00136 if (Overlaps(**it)) 00137 /* */ return true; /* */ 00138 } 00139 return false; 00140 } 00141 00142 //---------------------------------------------------------------------------- 00143 00144 std::ostream& operator<<(std::ostream& stream, GoChainType f) 00145 { 00146 static const char* s_string[_GO_CHAIN_COUNT] = 00147 { 00148 "GO_CHAIN_TWO_LIBERTIES_IN_REGION", 00149 "GO_CHAIN_TWO_SEPARATE_LIBERTIES", 00150 "GO_CHAIN_BY_SEARCH" 00151 }; 00152 00153 stream << s_string[f]; 00154 return stream; 00155 } 00156 00157 //---------------------------------------------------------------------------- 00158 00159 std::ostream& operator<<(std::ostream& stream, const GoChainCondition& c) 00160 { 00161 stream << " GoChainCondition: type = " << c.Type(); 00162 if (c.UsesLibs()) 00163 stream << ", lib1 = " << SgWritePoint(c.Lib1()) 00164 << ", lib2 = " << SgWritePoint(c.Lib2()); 00165 return stream; 00166 } 00167 00168 //---------------------------------------------------------------------------- 00169