void GoRegionBoard::MergeAdjacentAndAddBlock(SgPoint move, SgBlackWhite capturedColor) { SgVector<SgPoint> nb; for (GoNbIterator it(Board(), move); it; ++it) if (Board().IsEmpty(*it)) nb.PushBack(*it); SgVectorOf<GoBlock> captures; PreviousBlocksAt(nb, capturedColor, &captures); SG_ASSERT(captures.NonEmpty()); SgPointSet captured; {for (SgVectorIteratorOf<GoBlock> it(captures); it; ++it) captured |= (*it)->Stones(); } SgVectorOf<GoRegion> adj; const int size = Board().Size(); RegionsAt(captured.Border(size), capturedColor, &adj); SG_ASSERT(adj.NonEmpty()); GoRegion* r = MergeAll(adj, captured, capturedColor); SG_UNUSED(r); for (SgVectorIteratorOf<GoBlock> it(captures); it; ++it) RemoveBlock(*it, true, false); // don't remove from regions; already gone. }
void GoRegionBoard::RemoveBlock(GoBlock* b, bool isExecute, bool removeFromRegions) { SgBlackWhite color = b->Color(); for (SgSetIterator it(b->Stones()); it; ++it) m_block[*it] = 0; bool found = m_allBlocks[color].Exclude(b); SG_UNUSED(found); SG_ASSERT(found); const int size = Board().Size(); // remove from regions. SgPointSet area(b->Stones().Border(size)); SgVectorOf<GoRegion> regions; if (removeFromRegions) { RegionsAt(area, color, ®ions); for (SgVectorIteratorOf<GoRegion> it(regions); it; ++it) { (*it)->RemoveBlock(b); if (isExecute) m_stack.PushPtr(*it); } } if (isExecute) { m_stack.PushInt(regions.Length()); // 0 if ! removeFromRegions PushBlock(REGION_REMOVE_BLOCK, b); } else delete b; }
SgVectorOf<GoBlock> GoRegion::InteriorBlocks() const { SgVectorOf<GoBlock> interior; for (SgVectorIteratorOf<GoBlock> it(m_blocks); it; ++it) if (IsInteriorBlock(*it)) interior.PushBack(*it); return interior; }
void GoRegionBoard::FindNewNeighborRegions(SgPoint move, BlackWhite moveColor) { // move was capture -> new region for each captured block. SgVector<SgPoint> nb; for (Nb4Iterator it(move); it; ++it) if (Board().IsEmpty(*it)) nb.PushBack(*it); SgVectorOf<GoBlock> captures; PreviousBlocksAt(nb, OppBW(moveColor), &captures); SG_ASSERT(captures.NonEmpty()); for (SgVectorIteratorOf<GoBlock> it(captures); it; ++it) BlockToRegion(*it); }
void GoSafetySolver::FindTestSets(SgVectorOf<SgVectorOf<GoBlock> >* sets, SgBlackWhite color) const { SG_ASSERT(sets->IsEmpty()); SgVectorOf<GoBlock> doneSoFar; for (SgVectorIteratorOf<GoChain> it(Regions()->AllChains(color)); it; ++it) { GoBlock* block = *it; if (! doneSoFar.Contains(block)) { SgVectorOf<GoBlock>* blocks = new SgVectorOf<GoBlock>; blocks->PushBack(block); FindClosure(blocks); doneSoFar.PushBackList(*blocks); sets->PushBack(blocks); } } }
void GoRegion::SetBlocks(const SgVectorOf<GoBlock>& blocks) { SG_ASSERT(m_blocks.IsEmpty()); SG_ASSERT(! blocks.IsEmpty()); const int size = m_bd.Size(); SgPointSet area(Points().Border(size)); for (SgVectorIteratorOf<GoBlock> it(blocks); it; ++it) { if ((*it)->Stones().Overlaps(area)) m_blocks.PushBack(*it); } m_computedFlags.set(GO_REGION_COMPUTED_BLOCKS); }
void GoRegionBoard::UpdateBlock(int move, SgBlackWhite moveColor) { SgPoint anchor = Board().Anchor(move); // board is already up to date. bool done = false; const int size = Board().Size(); if (! Board().IsSingleStone(move)) // find old neighbor blocks { SgVectorOf<GoBlock> old; for (GoNbIterator it(Board(), move); it; ++it) { if (IsColor(*it, moveColor)) old.Include(BlockAt(*it)); } if (old.IsLength(1)) // append to single neighbor block { GoBlock* b = old.Front(); AppendStone(b, move); done = true; } else // delete old, recompute { for (SgVectorIteratorOf<GoBlock> it(old); it; ++it) RemoveBlock(*it, true, true); } } if (! done) // create new block. { GoBlock* b = GenBlock(anchor, moveColor); SgPointSet area(b->Stones().Border(size)); // link it to neighbor regions SgVectorOf<GoRegion> regions; RegionsAt(area, moveColor, ®ions); for (SgVectorIteratorOf<GoRegion> it(regions); it; ++it) (*it)->BlocksNonConst().PushBack(b); } }
void GoRegionBoard::OnUndoneMove() // Called after a move has been undone. The board is guaranteed to be in // a legal state. { //SG_ASSERT(false); // incremental code is incomplete, do not call if (DEBUG_REGION_BOARD) SgDebug() << "OnUndoneMove " << '\n'; const bool IS_UNDO = false; SgVectorOf<GoRegion> changed; for (int val = m_stack.PopEvent(); val != SG_NEXTMOVE; val = m_stack.PopEvent()) { switch (val) { case REGION_REMOVE: { GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr()); AddRegion(r, IS_UNDO); changed.Insert(r); } break; case REGION_ADD: { GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr()); RemoveRegion(r, IS_UNDO); } break; case REGION_REMOVE_BLOCK: { GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr()); AddBlock(b, IS_UNDO); for (int nu = m_stack.PopInt(); nu > 0; --nu) { GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr()); if (CHECK) SG_ASSERT(! r->Blocks().Contains(b)); r->BlocksNonConst().PushBack(b); changed.Insert(r); } } break; case REGION_ADD_BLOCK: { GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr()); RemoveBlock(b, IS_UNDO, true); } break; case REGION_ADD_STONE: { GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr()); SgPoint p = m_stack.PopInt(); r->OnRemoveStone(p); m_region[r->Color()][p] = r; changed.Insert(r); } break; case REGION_ADD_STONE_TO_BLOCK: { GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr()); SgPoint p = m_stack.PopInt(); b->RemoveStone(p); m_block[p] = 0; } break; default: SG_ASSERT(false); } } for (SgVectorIteratorOf<GoRegion> it(changed); it; ++it) { (*it)->ResetNonBlockFlags(); (*it)->ComputeBasicFlags(); } if (HEAVYCHECK) { for (SgBWIterator it; it; ++it) { SgBlackWhite color(*it); for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it) { const GoRegion* r = *it; SG_UNUSED(r); SG_ASSERT(r->IsValid()); } } } m_code = Board().GetHashCode(); if (HEAVYCHECK) CheckConsistency(); }