00001 //---------------------------------------------------------------------------- 00002 /** @file VCSet.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "Hex.hpp" 00007 #include "ChangeLog.hpp" 00008 #include "VCSet.hpp" 00009 #include "VC.hpp" 00010 #include "VCList.hpp" 00011 00012 using namespace benzene; 00013 00014 //---------------------------------------------------------------------------- 00015 00016 VCSet::VCSet(const ConstBoard& brd, HexColor color) 00017 : m_brd(&brd), 00018 m_color(color) 00019 { 00020 int softlimit_full = 25; 00021 int softlimit_semi = 50; 00022 00023 // Create a list for each valid pair; also create lists 00024 // for pairs (x,x) for ease of use later on. These lists 00025 // between the same point will also be empty. 00026 for (BoardIterator y(m_brd->EdgesAndInterior()); y; ++y) { 00027 for (BoardIterator x(m_brd->EdgesAndInterior()); x; ++x) { 00028 m_vc[VC::FULL][*x][*y] = 00029 m_vc[VC::FULL][*y][*x] = 00030 new VCList(*y, *x, softlimit_full); 00031 00032 m_vc[VC::SEMI][*x][*y] = 00033 m_vc[VC::SEMI][*y][*x] = 00034 new VCList(*y, *x, softlimit_semi); 00035 00036 if (*x == *y) break; 00037 } 00038 } 00039 } 00040 00041 VCSet::VCSet(const VCSet& other) 00042 : m_brd(other.m_brd), 00043 m_color(other.m_color) 00044 { 00045 AllocateAndCopyLists(other); 00046 } 00047 00048 void VCSet::operator=(const VCSet& other) 00049 { 00050 m_brd = other.m_brd; 00051 m_color = other.m_color; 00052 FreeLists(); 00053 AllocateAndCopyLists(other); 00054 } 00055 00056 void VCSet::AllocateAndCopyLists(const VCSet& other) 00057 { 00058 for (BoardIterator y = m_brd->EdgesAndInterior(); y; ++y) { 00059 for (BoardIterator x = m_brd->EdgesAndInterior(); x; ++x) { 00060 m_vc[VC::FULL][*x][*y] = 00061 m_vc[VC::FULL][*y][*x] = 00062 new VCList(*other.m_vc[VC::FULL][*y][*x]); 00063 00064 m_vc[VC::SEMI][*x][*y] = 00065 m_vc[VC::SEMI][*y][*x] = 00066 new VCList(*other.m_vc[VC::SEMI][*y][*x]); 00067 00068 if (*x == *y) break; 00069 } 00070 } 00071 } 00072 00073 VCSet::~VCSet() 00074 { 00075 FreeLists(); 00076 } 00077 00078 void VCSet::FreeLists() 00079 { 00080 for (BoardIterator y = m_brd->EdgesAndInterior(); y; ++y) { 00081 for (BoardIterator x = m_brd->EdgesAndInterior(); x; ++x) { 00082 for (int i=0; i<VC::NUM_TYPES; ++i) 00083 delete m_vc[i][*x][*y]; 00084 if (*x == *y) break; 00085 } 00086 } 00087 } 00088 00089 //---------------------------------------------------------------------------- 00090 00091 bool VCSet::Exists(HexPoint x, HexPoint y, VC::Type type) const 00092 { 00093 return !m_vc[type][x][y]->empty(); 00094 } 00095 00096 bool VCSet::SmallestVC(HexPoint x, HexPoint y, 00097 VC::Type type, VC& out) const 00098 { 00099 if (!Exists(x, y, type)) 00100 return false; 00101 out = *m_vc[type][x][y]->begin(); 00102 return true; 00103 } 00104 00105 void VCSet::VCs(HexPoint x, HexPoint y, VC::Type type, 00106 std::vector<VC>& out) const 00107 { 00108 out.clear(); 00109 const VCList* who = m_vc[type][x][y]; 00110 for (VCList::const_iterator it(who->begin()); it != who->end(); ++it) 00111 out.push_back(*it); 00112 } 00113 00114 //---------------------------------------------------------------------------- 00115 00116 void VCSet::SetSoftLimit(VC::Type type, int limit) 00117 { 00118 for (BoardIterator y(m_brd->EdgesAndInterior()); y; ++y) { 00119 for (BoardIterator x(m_brd->EdgesAndInterior()); *x != *y; ++x) 00120 m_vc[type][*x][*y]->setSoftLimit(limit); 00121 } 00122 } 00123 00124 void VCSet::Clear() 00125 { 00126 for (BoardIterator y(m_brd->EdgesAndInterior()); y; ++y) { 00127 for (BoardIterator x(m_brd->EdgesAndInterior()); *x != *y; ++x) { 00128 for (int i=0; i<VC::NUM_TYPES; ++i) { 00129 m_vc[i][*x][*y]->clear(); 00130 } 00131 } 00132 } 00133 } 00134 00135 void VCSet::Revert(ChangeLog<VC>& log) 00136 { 00137 while (!log.empty()) { 00138 int action = log.topAction(); 00139 if (action == ChangeLog<VC>::MARKER) { 00140 log.pop(); 00141 break; 00142 } 00143 00144 VC vc(log.topData()); 00145 log.pop(); 00146 00147 VCList* list = m_vc[vc.type()][vc.x()][vc.y()]; 00148 if (action == ChangeLog<VC>::ADD) { 00149 #ifdef NDEBUG 00150 list->remove(vc, 0); 00151 #else 00152 HexAssert(list->remove(vc, 0)); 00153 #endif 00154 } else if (action == ChangeLog<VC>::REMOVE) { 00155 list->simple_add(vc); 00156 } else if (action == ChangeLog<VC>::PROCESSED) { 00157 VCList::iterator it = list->find(vc); 00158 HexAssert(it != list->end()); 00159 HexAssert(it->processed()); 00160 it->setProcessed(false); 00161 } 00162 } 00163 } 00164 00165 //---------------------------------------------------------------------------- 00166 00167 bool VCSet::operator==(const VCSet& other) const 00168 { 00169 for (BoardIterator x(m_brd->EdgesAndInterior()); x; ++x) 00170 { 00171 for (BoardIterator y(m_brd->EdgesAndInterior()); *y != *x; ++y) 00172 { 00173 const VCList& full1 = *m_vc[VC::FULL][*x][*y]; 00174 const VCList& full2 = *other.m_vc[VC::FULL][*x][*y]; 00175 if (full1 != full2) return false; 00176 00177 const VCList& semi1 = *m_vc[VC::SEMI][*x][*y]; 00178 const VCList& semi2 = *other.m_vc[VC::SEMI][*x][*y]; 00179 if (semi1 != semi2) return false; 00180 } 00181 } 00182 return true; 00183 } 00184 00185 bool VCSet::operator!=(const VCSet& other) const 00186 { 00187 return !operator==(other); 00188 } 00189 00190 //---------------------------------------------------------------------------- 00191 00192 bitset_t VCSetUtil::ConnectedTo(const VCSet& con, const Groups& groups, 00193 HexPoint x, VC::Type type) 00194 { 00195 bitset_t ret; 00196 const StoneBoard& brd = groups.Board(); 00197 HexColorSet not_other = HexColorSetUtil::ColorOrEmpty(con.Color()); 00198 for (BoardIterator y(brd.Stones(not_other)); y; ++y) 00199 if (con.Exists(groups.CaptainOf(x), groups.CaptainOf(*y), type)) 00200 ret.set(*y); 00201 return ret; 00202 } 00203 00204 bool VCSetUtil::EqualOnGroups(const VCSet& c1, const VCSet& c2, 00205 const Groups& groups) 00206 { 00207 if (c1.Color() != c2.Color()) 00208 return false; 00209 if (c1.Board() != c2.Board()) 00210 return false; 00211 00212 HexColorSet not_other = HexColorSetUtil::ColorOrEmpty(c1.Color()); 00213 for (GroupIterator x(groups, not_other); x; ++x) 00214 { 00215 HexPoint xc = x->Captain(); 00216 for (GroupIterator y(groups, not_other); &*y != &*x; ++y) 00217 { 00218 HexPoint yc = y->Captain(); 00219 if (c1.GetList(VC::FULL, xc, yc) != c2.GetList(VC::FULL, xc, yc)) 00220 { 00221 std::cout << "FULL " << xc << ", " << yc << "\n"; 00222 std::cout << c1.GetList(VC::FULL, xc, yc).dump() << '\n'; 00223 std::cout << "==============\n"; 00224 std::cout << c2.GetList(VC::FULL, xc, yc).dump() << '\n'; 00225 return false; 00226 } 00227 if (c1.GetList(VC::SEMI, xc, yc) != c2.GetList(VC::SEMI, xc, yc)) 00228 { 00229 std::cout << "SEMI " << xc << ", " << yc << "\n"; 00230 std::cout << c1.GetList(VC::SEMI, xc, yc).dump() << '\n'; 00231 std::cout << "==============\n"; 00232 std::cout << c2.GetList(VC::SEMI, xc, yc).dump() << '\n'; 00233 return false; 00234 } 00235 } 00236 } 00237 return true; 00238 } 00239 00240 //---------------------------------------------------------------------------- 00241 00242 VCSetStatistics::VCSetStatistics() 00243 : m_fulls(0), 00244 m_semis(0) 00245 { 00246 } 00247 00248 std::string VCSetStatistics::Write() const 00249 { 00250 std::ostringstream os; 00251 os << "[\n"; 00252 os << "fulls=" << m_fulls << '\n'; 00253 os << "semis=" << m_semis << '\n'; 00254 os << "fullCounts="; m_fullCounts.Write(os); os << '\n'; 00255 os << "semiCounts="; m_semiCounts.Write(os); os << '\n'; 00256 os << "fullCountsCell="; m_fullCountsCell.Write(os); os << '\n'; 00257 os << "semiCountsCell="; m_semiCountsCell.Write(os); os << '\n'; 00258 os << "fullConnectedTo="; m_fullConnectedTo.Write(os); os << '\n'; 00259 os << "semiConnectedTo="; m_semiConnectedTo.Write(os); os << '\n'; 00260 os << "fullHisto=\n"; m_fullHisto.Write(os); os << '\n'; 00261 os << "semiHisto=\n"; m_semiHisto.Write(os); os << '\n'; 00262 os << "]\n"; 00263 os << '\n'; 00264 return os.str(); 00265 } 00266 00267 VCSetStatistics VCSetUtil::ComputeStatistics(const VCSet& con, 00268 const Groups& groups, 00269 std::size_t maxConnections, 00270 int numBins) 00271 00272 { 00273 VCSetStatistics stats; 00274 stats.m_fullHisto.Init(0, maxConnections, numBins); 00275 stats.m_semiHisto.Init(0, maxConnections, numBins); 00276 std::vector<size_t> cellFullCounts(BITSETSIZE, 0); 00277 std::vector<size_t> cellSemiCounts(BITSETSIZE, 0); 00278 00279 HexColorSet not_other = HexColorSetUtil::ColorOrEmpty(con.Color()); 00280 for (GroupIterator x(groups, not_other); x; ++x) 00281 { 00282 for (GroupIterator y(groups, not_other); &*y != &*x; ++y) 00283 { 00284 std::size_t full_size = con.GetList(VC::FULL, x->Captain(), 00285 y->Captain()).size(); 00286 std::size_t semi_size = con.GetList(VC::SEMI, x->Captain(), 00287 y->Captain()).size(); 00288 stats.m_fulls += full_size; 00289 stats.m_semis += semi_size; 00290 stats.m_fullCounts.Add(full_size); 00291 stats.m_semiCounts.Add(semi_size); 00292 stats.m_fullHisto.Add(full_size); 00293 stats.m_semiHisto.Add(semi_size); 00294 cellFullCounts[x->Captain()] += full_size; 00295 cellSemiCounts[x->Captain()] += semi_size; 00296 cellFullCounts[y->Captain()] += full_size; 00297 cellSemiCounts[y->Captain()] += semi_size; 00298 } 00299 std::size_t full_connected 00300 = ConnectedTo(con, groups, x->Captain(), VC::FULL).count(); 00301 std::size_t semi_connected 00302 = ConnectedTo(con, groups, x->Captain(), VC::SEMI).count(); 00303 stats.m_fullConnectedTo.Add(full_connected); 00304 stats.m_semiConnectedTo.Add(semi_connected); 00305 } 00306 for (GroupIterator x(groups, not_other); x; ++x) 00307 { 00308 stats.m_fullCountsCell.Add(cellFullCounts[x->Captain()]); 00309 stats.m_semiCountsCell.Add(cellSemiCounts[x->Captain()]); 00310 } 00311 return stats; 00312 } 00313 00314 //---------------------------------------------------------------------------- 00315