void GoSafetySolver::GenBlocksRegions() { if (UpToDate()) /* */ return; /* */ GoStaticSafetySolver::GenBlocksRegions(); Regions()->GenChains(); // merge blocks adjacent to 1-vital with 2 conn. points for (SgBWIterator it; it; ++it) { SgBlackWhite color(*it); for (SgVectorIteratorOf<GoRegion> it(Regions()->AllRegions(color)); it; ++it) { GoRegion* r = *it; r->ComputeFlag(GO_REGION_STATIC_1VITAL); } bool changed = true; while (changed) { changed = false; for (SgVectorIteratorOf<GoRegion> it(Regions()->AllRegions(color)); it; ++it) { GoRegion* r = *it; if ( r->GetFlag(GO_REGION_STATIC_1VC) && r->Chains().IsLength(2) && r->Has2Conn() // || r->Safe2Cuts(Board()) changed from && to || // @todo does not work if blocks are already chains??? // must explicitly keep chain libs info. ) // easy case of only 2 chains { GoChain* c1 = r->Chains().Front(); GoChain* c2 = r->Chains().Back(); Merge(c1, c2, r, false); // false = not by search changed = true; break; // to leave iteration } else if ( r->GetFlag(GO_REGION_STATIC_1VITAL) && r->GetFlag(GO_REGION_CORRIDOR) && ! r->GetFlag(GO_REGION_USED_FOR_MERGE) ) { GoChain* c1 = 0; GoChain* c2 = 0; if (r->Find2Mergable(&c1, &c2)) { Merge(c1, c2, r, false); changed = true; break; // to leave iteration } } } } } m_code = Board().GetHashCode(); }
void GoSafetySolver::Merge(GoChain* c1, GoChain* c2, GoRegion* r, bool bySearch) { SG_ASSERT(! r->GetFlag(GO_REGION_USED_FOR_MERGE)); r->SetFlag(GO_REGION_USED_FOR_MERGE, true); GoChainCondition* c = 0; if (bySearch) c = new GoChainCondition(GO_CHAIN_BY_SEARCH); else { SgPoint lib1, lib2; r->Find2FreeLibs(c1, c2, &lib1, &lib2); c = new GoChainCondition(GO_CHAIN_TWO_LIBERTIES_IN_REGION, lib1, lib2); } GoChain* m = new GoChain(c1, c2, c); SgBlackWhite color = c1->Color(); bool found = Regions()->AllChains(color).Exclude(c1); SG_DEBUG_ONLY(found); SG_ASSERT(found); found = Regions()->AllChains(color).Exclude(c2); SG_ASSERT(found); Regions()->AllChains(color).Include(m); SG_ASSERT(Regions()->AllChains(color).UniqueElements()); for (SgVectorIteratorOf<GoRegion> it(Regions()->AllRegions(color)); it; ++it) { GoRegion* r = *it; bool replace1 = r->ReplaceChain(c1, m); bool replace2 = r->ReplaceChain(c2, m); if (replace1 || replace2) { r->ReInitialize(); r->ComputeFlag(GO_REGION_STATIC_1VITAL); } } if (DEBUG_MERGE_CHAINS) { SgDebug() << "\nmerge:"; c1->WriteID(SgDebug()); SgDebug() << " + "; c2->WriteID(SgDebug()); SgDebug() << " = "; m->WriteID(SgDebug()); SgDebug() << '\n'; } delete c1; delete c2; }