bool GoSafetySolver::FindSurroundedSingleRegion(SgBWSet* safe,
                                             SgBlackWhite color)
{
    SgPointSet anySafe(safe->Both());
    for (SgVectorIteratorOf<GoRegion>
         it(Regions()->AllRegions(color)); it; ++it)
    {
        GoRegion* r = *it;
        if (  ! r->GetFlag(GO_REGION_SAFE)
           && r->SomeBlockIsSafe()
           && ! r->Points().Overlaps(anySafe)
           && GoSafetyUtil::ExtendedIsTerritory(Board(), Regions(),
                                   r->PointsPlusInteriorBlocks(),
                                   (*safe)[color],
                                   color)
           )
        {
            GoSafetyUtil::AddToSafe(Board(), r->Points(), color, safe,
                      "surr-safe-1", 0, true);
            Regions()->SetSafeFlags(*safe); 
            return true;
        }
    }
    return false;
}
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();
            }
        }
    }
}