// 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; }
/** Play prey move and update all the relevant information. Extend the prey by playing at its only liberty, or capture a block adjacent to the prey. */ int GoLadder::PlayPreyMove(int depth, SgPoint move, SgPoint lib1, const GoPointList& adjBlk, SgVector<SgPoint>* sequence) { int result = 0; GoPointList newAdj(adjBlk); SgVector<SgPoint> newLib; SgVector<SgPoint> newStones; SgVector<SgPoint> neighbors; if (move == lib1) { NeighborsOfColor(*m_bd, move, m_preyColor, &neighbors); for (SgVectorIterator<SgPoint> iter(neighbors); iter; ++iter) { SgPoint block = *iter; if (! m_partOfPrey[block]) { MarkStonesAsPrey(block, &newStones); GoPointList temp = GoBoardUtil::AdjacentStones(*m_bd, block); newAdj.PushBackList(temp); for (GoBoard::LibertyIterator it(*m_bd, block); it; ++it) newLib.Include(*it); } } m_partOfPrey.Include(move); } if (PlayIfLegal(*m_bd, move, m_preyColor)) { if (move == lib1) { NeighborsOfColor(*m_bd, move, SG_EMPTY, &neighbors); for (SgVectorIterator<SgPoint> iter(newLib); iter; ++iter) { SgPoint point = *iter; // Test for Empty is necessary because newLib will include // the move just played. if (m_bd->IsEmpty(point)) neighbors.Include(point); } } else { neighbors.PushBack(lib1); } if (m_bd->CapturingMove()) { // Add the points at the captured stones that are adjacent to the // prey to the liberties, at least if exactly one stone captured. for (GoPointList::Iterator it(m_bd->CapturedStones()); it; ++it) { SgPoint stone = *it; if (PointIsAdjToPrey(stone)) neighbors.Include(stone); } } SG_ASSERT(! neighbors.IsEmpty()); lib1 = neighbors[0]; SG_ASSERT(m_bd->IsEmpty(lib1)); SgArrayList<SgPoint,4> temp = NeighborsOfColor(*m_bd, move, m_hunterColor); newAdj.PushBackList(temp); FilterAdjacent(newAdj); if (neighbors.Length() == 1) result = HunterLadder(depth + 1, lib1, newAdj, sequence); else if (neighbors.Length() == 2) { SgPoint lib2 = neighbors[1]; SG_ASSERT(m_bd->IsEmpty(lib2)); result = HunterLadder(depth + 1, lib1, lib2, newAdj, sequence); } else // 3 <= numLib { if (sequence) sequence->Clear(); result = GOOD_FOR_PREY - (depth + 1); } if (sequence) sequence->PushBack(move); m_bd->Undo(); } else { if (sequence) sequence->Clear(); result = GOOD_FOR_HUNTER + depth; } m_partOfPrey.Exclude(move); m_partOfPrey.Exclude(newStones); return result; }