void GoRegionBoard::OnExecutedUncodedMove(int move, SgBlackWhite moveColor) { if (DEBUG_REGION_BOARD) SgDebug() << "OnExecutedUncodedMove " << SgWritePoint(move) << '\n'; { m_stack.StartMoveInfo(); if (move != SG_PASS) { SG_ASSERT(! Board().LastMoveInfo(GO_MOVEFLAG_SUICIDE)); // can't handle yet, // should be forbidden anyway. @todo allowed in Chinese rules. bool fWasCapture = Board().LastMoveInfo(GO_MOVEFLAG_CAPTURING); UpdateBlock(move, moveColor); { GoRegion* r = PreviousRegionAt(move, moveColor); bool split = GoEyeUtil::IsSplitPt(move, r->Points()); r->OnAddStone(move); PushStone(r, move); SgPointSet points = r->Points(); // needed even after RemoveRegion(r). if (split || points.IsEmpty()) // must remove old region before generating new ones, // because removing clears m_anchor[] RemoveRegion(r); if (split) // find new regions { for (SgConnCompIterator it(points, Board().Size()); it; ++it) GenRegion(*it, moveColor); } } if (fWasCapture) { // FindNewNeighborRegions(move, moveColor); MergeAdjacentAndAddBlock(move, SgOppBW(moveColor)); } m_code = Board().GetHashCode(); if (HEAVYCHECK) CheckConsistency(); } } { for (SgBWIterator it; it; ++it) { SgBlackWhite color(*it); for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it) { GoRegion* r1 = *it; if (! r1->IsValid()) r1->ComputeBasicFlags(); } } } }
// improved by using recursive extension to find 2-conn paths. bool GoRegion::Find2ConnForAllInterior(SgMiaiStrategy* miaiStrategy, SgVector<SgPoint>& usedLibs) const { SgVector<SgMiaiPair> myStrategy; const int size = m_bd.Size(); SgPointSet interior = AllInsideLibs(); if (interior.IsEmpty()) { return true; } //if (GetFlag(GO_REGION_SINGLE_BLOCK_BOUNDARY)) { SgPointSet testSet = interior; SgPointSet originalLibs = testSet.Border(size) & Dep().Border(size) & m_bd.AllEmpty() & Points(); SgPointSet updateLibs = originalLibs; // now try to find miai-paths to remaining interior points recursively bool changed = true; while (changed) { changed = false; if (testSet.IsEmpty()) { SgVector<SgPoint> jlibs; JointLibs(&jlibs); SgVector<SgPoint> ips; GetIPs(&ips); SgVector<SgMiaiPair> updateStrg; for (SgSetIterator it(interior); it; ++it) { SgPoint p = *it; SgPointSet s1; s1.Include(p); SgPointSet rest = s1.Border(size) & updateLibs; if (! rest.IsEmpty()) { for (SgVectorIterator<SgMiaiPair> it2(myStrategy); it2; ++it2) { SgMiaiPair x = *it2; if ( SgPointUtil::AreAdjacent(p, x.first) && SgPointUtil::AreAdjacent(p, x.second) ) { if (ips.Contains(x.first)) { updateLibs.Include(x.first); usedLibs.Exclude(x.first); SgPoint t = rest.PointOf(); x.first = t; updateLibs.Exclude(t); rest.Exclude(t); usedLibs.Include(t); } if ( ips.Contains(x.second) && ! rest.IsEmpty() ) { updateLibs.Include(x.second); usedLibs.Exclude(x.second); SgPoint t = rest.PointOf(); x.second = t; updateLibs.Exclude(t); rest.Exclude(t); usedLibs.Include(t); } updateStrg.Include(x); } } } } miaiStrategy->SetStrategy(updateStrg); /* */ return true; /* */ } for (SgSetIterator it(interior); it; ++it) { SgMiaiPair miaiPair; if (Find2BestLibs(*it, updateLibs, testSet, &miaiPair)) { if (miaiPair.first == miaiPair.second) { SgDebug() <<"\nmiaipair are same: " << SgWritePoint(miaiPair.first) << SgWritePoint(miaiPair.second); SgDebug() <<"\ncurrent region is:\n"; Points().Write(SgDebug(), size); SG_ASSERT(false); } myStrategy.PushBack(miaiPair); usedLibs.PushBack(miaiPair.first); usedLibs.PushBack(miaiPair.second); updateLibs.Exclude(miaiPair.first); updateLibs.Exclude(miaiPair.second); updateLibs.Include(*it); testSet.Exclude(*it); changed = true; } } } // while loop for recursive finding } miaiStrategy->Clear(); return false; }