00001
00002
00003
00004
00005
00006
00007 #include "SgSystem.h"
00008 #include "GoRegionBoard.h"
00009
00010 #include <iostream>
00011 #include "GoBlock.h"
00012 #include "GoChain.h"
00013 #include "GoEyeUtil.h"
00014 #include "GoRegion.h"
00015 #include "SgDebug.h"
00016 #include "SgConnCompIterator.h"
00017 #include "SgWrite.h"
00018
00019
00020
00021 namespace {
00022 static const bool CHECK = SG_CHECK && true;
00023
00024 static const bool HEAVYCHECK = SG_HEAVYCHECK && CHECK && false;
00025
00026 static const bool DEBUG_REGION_BOARD = false;
00027
00028 const int REGION_CODE_BASE = 2000;
00029 const int REGION_REMOVE = REGION_CODE_BASE + 0;
00030 const int REGION_ADD = REGION_CODE_BASE + 1;
00031 const int REGION_REMOVE_BLOCK = REGION_CODE_BASE + 2;
00032 const int REGION_ADD_BLOCK = REGION_CODE_BASE + 3;
00033 const int REGION_ADD_STONE = REGION_CODE_BASE + 4;
00034 const int REGION_ADD_STONE_TO_BLOCK = REGION_CODE_BASE + 5;
00035 }
00036
00037
00038 bool GoRegionBoard::IsSafeBlock(SgPoint p) const
00039 {
00040 return BlockAt(p)->IsSafe();
00041 }
00042
00043 void GoRegionBoard::SetToSafe(SgPoint p) const
00044 {
00045 BlockAt(p)->SetToSafe();
00046 }
00047
00048 void GoRegionBoard::Fini()
00049 {
00050 SG_ASSERT(s_alloc == s_free);
00051 }
00052
00053
00054 void GoRegionBoard::SetSafeFlags(const SgBWSet& safe)
00055 {
00056 for (SgBWIterator it; it; ++it)
00057 {
00058 SgBlackWhite color(*it);
00059 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00060 if ((*it)->Points().Overlaps(safe[color]))
00061 (*it)->SetToSafe();
00062 for (SgVectorIteratorOf<GoBlock> it(AllBlocks(color)); it; ++it)
00063 if ((*it)->Stones().Overlaps(safe[color]))
00064 (*it)->SetToSafe();
00065 }
00066 }
00067
00068
00069
00070 GoRegionBoard::GoRegionBoard(const GoBoard& board)
00071 : m_board(board),
00072 m_region(SgPointArray<GoRegion*>(0)),
00073 m_block(0),
00074 m_invalid(true),
00075 m_computedHealthy(false),
00076 m_boardSize(board.Size())
00077 {
00078 m_code.Invalidate();
00079 m_chainsCode.Invalidate();
00080 GenBlocksRegions();
00081 ++s_alloc;
00082 }
00083
00084 GoRegionBoard::~GoRegionBoard()
00085 {
00086 Clear();
00087 ++s_free;
00088 }
00089
00090 void GoRegionBoard::Clear()
00091 {
00092 if (DEBUG_REGION_BOARD)
00093 SgDebug() << "Clear\n";
00094 for (SgBWIterator it; it; ++it)
00095 {
00096 SgBlackWhite color(*it);
00097 for (SgVectorIteratorOf<GoBlock> it1(AllBlocks(color)); it1; ++it1)
00098 delete *it1;
00099 for (SgVectorIteratorOf<GoRegion> it2(AllRegions(color)); it2; ++it2)
00100 delete *it2;
00101 for (SgVectorIteratorOf<GoChain> it3(AllChains(color)); it3; ++it3)
00102 delete *it3;
00103 }
00104 m_allBlocks[SG_BLACK].Clear();
00105 m_allBlocks[SG_WHITE].Clear();
00106 m_allRegions[SG_BLACK].Clear();
00107 m_allRegions[SG_WHITE].Clear();
00108 m_allChains[SG_BLACK].Clear();
00109 m_allChains[SG_WHITE].Clear();
00110 m_stack.Clear();
00111 m_code.Invalidate();
00112 m_invalid = true;
00113 m_computedHealthy = false;
00114 m_boardSize = m_board.Size();
00115
00116 for (SgBWIterator it; it; ++it)
00117 {
00118 SgBlackWhite color(*it);
00119 for (SgPoint p = SgPointUtil::Pt(1, 1);
00120 p <= SgPointUtil::Pt(SG_MAX_SIZE, SG_MAX_SIZE);
00121 ++p)
00122 {
00123 m_region[color][p] = 0;
00124 }
00125 }
00126 for (SgPoint p = SgPointUtil::Pt(1, 1);
00127 p <= SgPointUtil::Pt(SG_MAX_SIZE, SG_MAX_SIZE); ++p)
00128 m_block[p] = 0;
00129 }
00130
00131 void GoRegionBoard::UpdateBlock(int move, SgBlackWhite moveColor)
00132 {
00133 SgPoint anchor = Board().Anchor(move);
00134 bool done = false;
00135 const int size = Board().Size();
00136 if (! Board().IsSingleStone(move))
00137 {
00138 SgVectorOf<GoBlock> old;
00139 for (SgNb4Iterator it(move); it; ++it)
00140 {
00141 if (IsColor(*it, moveColor))
00142 old.Include(BlockAt(*it));
00143 }
00144 if (old.IsLength(1))
00145 {
00146 GoBlock* b = old.Front();
00147 AppendStone(b, move);
00148 done = true;
00149 }
00150 else
00151 {
00152 for (SgVectorIteratorOf<GoBlock> it(old); it; ++it)
00153 RemoveBlock(*it, true, true);
00154 }
00155 }
00156
00157 if (! done)
00158 {
00159 GoBlock* b = GenBlock(anchor, moveColor);
00160 SgPointSet area(b->Stones().Border(size));
00161
00162 SgVectorOf<GoRegion> regions;
00163 RegionsAt(area, moveColor, ®ions);
00164 for (SgVectorIteratorOf<GoRegion> it(regions); it; ++it)
00165 (*it)->BlocksNonConst().PushBack(b);
00166 }
00167 }
00168
00169 void GoRegionBoard::AppendStone(GoBlock* b, SgPoint move)
00170 {
00171 m_block[move] = b;
00172 b->AddStone(move);
00173 m_stack.PushInt(move);
00174 m_stack.PushPtrEvent(REGION_ADD_STONE_TO_BLOCK, b);
00175 }
00176
00177
00178 void GoRegionBoard::OnExecutedMove(GoPlayerMove move)
00179 {
00180 OnExecutedUncodedMove(move.Point(), move.Color());
00181 }
00182
00183 void GoRegionBoard::ExecuteMovePrologue()
00184 {
00185 if (! UpToDate())
00186 {
00187 if (DEBUG_REGION_BOARD)
00188 SgDebug() << "recompute everything\n";
00189 GenBlocksRegions();
00190 }
00191 }
00192
00193 void GoRegionBoard::OnExecutedUncodedMove(int move, SgBlackWhite moveColor)
00194 {
00195 if (DEBUG_REGION_BOARD)
00196 SgDebug() << "OnExecutedUncodedMove " << SgWritePoint(move) << '\n';
00197 {
00198 m_stack.StartMoveInfo();
00199 if (move != SG_PASS)
00200 {
00201 SG_ASSERT(! Board().LastMoveInfo(GO_MOVEFLAG_SUICIDE));
00202
00203
00204 bool fWasCapture = Board().LastMoveInfo(GO_MOVEFLAG_CAPTURING);
00205
00206 UpdateBlock(move, moveColor);
00207
00208 {
00209 GoRegion* r = PreviousRegionAt(move, moveColor);
00210 bool split = GoEyeUtil::IsSplitPt(move, r->Points());
00211
00212 r->OnAddStone(move);
00213 PushStone(r, move);
00214 SgPointSet points = r->Points();
00215
00216 if (split || points.IsEmpty())
00217
00218
00219 RemoveRegion(r);
00220
00221 if (split)
00222 {
00223 for (SgConnCompIterator it(points, Board().Size());
00224 it; ++it)
00225 GenRegion(*it, moveColor);
00226 }
00227 }
00228
00229 if (fWasCapture)
00230 {
00231
00232 MergeAdjacentAndAddBlock(move, SgOppBW(moveColor));
00233 }
00234
00235 m_code = Board().GetHashCode();
00236 if (HEAVYCHECK)
00237 CheckConsistency();
00238 }
00239 }
00240
00241 {
00242 for (SgBWIterator it; it; ++it)
00243 {
00244 SgBlackWhite color(*it);
00245 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00246 { GoRegion* r1 = *it;
00247 if (! r1->IsValid())
00248 r1->ComputeBasicFlags();
00249 }
00250 }
00251 }
00252 }
00253
00254 void GoRegionBoard::CheckConsistency() const
00255 {
00256 SG_ASSERT(CHECK && UpToDate());
00257 for (SgBWIterator it; it; ++it)
00258 {
00259 SgBlackWhite color(*it);
00260 SgPointSet blockArea, regionArea;
00261 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00262 {
00263 SG_ASSERT((*it)->Points().Disjoint(regionArea));
00264 SG_ASSERT((*it)->Points().Disjoint(blockArea));
00265 (*it)->CheckConsistency();
00266 regionArea |= (*it)->Points();
00267 }
00268 for (SgVectorIteratorOf<GoBlock> it(AllBlocks(color)); it; ++it)
00269 {
00270 SG_ASSERT((*it)->Stones().Disjoint(regionArea));
00271 SG_ASSERT((*it)->Stones().Disjoint(blockArea));
00272 for (SgSetIterator it2((*it)->Stones()); it2; ++it2)
00273 SG_ASSERT(m_block[*it2] == *it);
00274 (*it)->CheckConsistency();
00275 blockArea |= (*it)->Stones();
00276 }
00277 SG_ASSERT(blockArea.Disjoint(regionArea));
00278 SG_ASSERT((blockArea | regionArea) == Board().AllPoints());
00279
00280
00281 for (SgPoint p = SgPointUtil::Pt(1, 1);
00282 p <= SgPointUtil::Pt(SG_MAX_SIZE, SG_MAX_SIZE);
00283 ++p)
00284 {
00285 SG_ASSERT((m_region[color][p] == 0) != regionArea.Contains(p));
00286 }
00287
00288 }
00289
00290 for (SgPoint p = SgPointUtil::Pt(1, 1);
00291 p <= SgPointUtil::Pt(SG_MAX_SIZE, SG_MAX_SIZE); ++p)
00292 {
00293 GoBlock* block = m_block[p];
00294 SG_DEBUG_ONLY(block);
00295 SG_ASSERT((block != 0) == Board().Occupied().Contains(p));
00296 }
00297 }
00298
00299 void GoRegionBoard::PushRegion(int type, GoRegion* r)
00300 {
00301 m_stack.PushPtrEvent(type, r);
00302 }
00303
00304 void GoRegionBoard::PushBlock(int type, GoBlock* b)
00305 {
00306 m_stack.PushPtrEvent(type, b);
00307 }
00308
00309 void GoRegionBoard::PushStone(GoRegion* r, SgPoint move)
00310 {
00311 m_stack.PushInt(move);
00312 m_stack.PushPtrEvent(REGION_ADD_STONE, r);
00313 m_region[r->Color()][move] = 0;
00314 }
00315
00316 void GoRegionBoard::RemoveRegion(GoRegion* r, bool isExecute)
00317 {
00318 SgBlackWhite color = r->Color();
00319
00320 for (SgSetIterator reg(r->Points()); reg; ++reg)
00321 {
00322 m_region[color][*reg] = 0;
00323 }
00324
00325 bool found = m_allRegions[r->Color()].Exclude(r);
00326 SG_UNUSED(found);
00327 SG_ASSERT(found);
00328
00329
00330 for (SgVectorIteratorOf<GoBlock> it(r->Blocks()); it; ++it)
00331 (*it)->RemoveRegion(r);
00332
00333 if (isExecute)
00334 PushRegion(REGION_REMOVE, r);
00335 else
00336 delete r;
00337 }
00338
00339 void GoRegionBoard::SetRegionArrays(GoRegion* r)
00340 {
00341 SgBlackWhite color = r->Color();
00342
00343 for (SgSetIterator reg(r->Points()); reg; ++reg)
00344 {
00345 m_region[color][*reg] = r;
00346 }
00347 }
00348
00349 void GoRegionBoard::RemoveBlock(GoBlock* b, bool isExecute,
00350 bool removeFromRegions)
00351 {
00352 SgBlackWhite color = b->Color();
00353 for (SgSetIterator it(b->Stones()); it; ++it)
00354 m_block[*it] = 0;
00355
00356 bool found = m_allBlocks[color].Exclude(b);
00357 SG_UNUSED(found);
00358 SG_ASSERT(found);
00359 const int size = Board().Size();
00360
00361 SgPointSet area(b->Stones().Border(size));
00362 SgVectorOf<GoRegion> regions;
00363 if (removeFromRegions)
00364 {
00365 RegionsAt(area, color, ®ions);
00366 for (SgVectorIteratorOf<GoRegion> it(regions); it; ++it)
00367 {
00368 (*it)->RemoveBlock(b);
00369 if (isExecute)
00370 m_stack.PushPtr(*it);
00371 }
00372 }
00373 if (isExecute)
00374 {
00375 m_stack.PushInt(regions.Length());
00376 PushBlock(REGION_REMOVE_BLOCK, b);
00377 }
00378 else
00379 delete b;
00380 }
00381
00382 void GoRegionBoard::AddBlock(GoBlock* b, bool isExecute)
00383 {
00384 SgBlackWhite color = b->Color();
00385 AllBlocks(color).PushBack(b);
00386 for (GoBoard::StoneIterator it(Board(), b->Anchor()); it; ++it)
00387 m_block[*it] = b;
00388 if (isExecute)
00389 PushBlock(REGION_ADD_BLOCK, b);
00390 }
00391
00392 GoBlock* GoRegionBoard::GenBlock(SgPoint anchor, SgBlackWhite color)
00393 {
00394 GoBlock* b = new GoBlock(color, anchor, Board());
00395 AddBlock(b);
00396 return b;
00397 }
00398
00399 void
00400 GoRegionBoard::PreviousBlocksAt(const SgVector<SgPoint>& area,
00401 SgBlackWhite color,
00402 SgVectorOf<GoBlock>* captures) const
00403 {
00404 SG_UNUSED(color);
00405
00406 for (SgVectorIterator<SgPoint> it(area); it; ++it)
00407 {
00408 GoBlock* b = m_block[*it];
00409 if (b)
00410 captures->Include(b);
00411 }
00412 }
00413
00414 #if UNUSED
00415 void GoRegionBoard::BlockToRegion(GoBlock* b)
00416
00417 {
00418 GoRegion* r = new GoRegion(Board(), b->Stones(), OppBW(b->Color()));
00419 SetRegionArrays(r);
00420
00421 }
00422
00423 void GoRegionBoard::FindNewNeighborRegions(SgPoint move,
00424 BlackWhite moveColor)
00425 {
00426
00427 SgVector<SgPoint> nb;
00428 for (Nb4Iterator it(move); it; ++it)
00429 if (Board().IsEmpty(*it))
00430 nb.PushBack(*it);
00431
00432 SgVectorOf<GoBlock> captures;
00433 PreviousBlocksAt(nb, OppBW(moveColor), &captures);
00434 SG_ASSERT(captures.NonEmpty());
00435
00436 for (SgVectorIteratorOf<GoBlock> it(captures); it; ++it)
00437 BlockToRegion(*it);
00438 }
00439 #endif
00440
00441
00442 void GoRegionBoard::RegionsAt(const SgPointSet& area, SgBlackWhite color,
00443 SgVectorOf<GoRegion>* regions) const
00444 {
00445 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00446 if ((*it)->Points().Overlaps(area))
00447 regions->PushBack(*it);
00448 }
00449
00450 void GoRegionBoard::AdjacentRegions(const SgVector<SgPoint>& anchors,
00451 SgBlackWhite color,
00452 SgVectorOf<GoRegion>* regions) const
00453 {
00454 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00455 if ((*it)->AdjacentToSomeBlock(anchors))
00456 regions->PushBack(*it);
00457 }
00458
00459 GoRegion* GoRegionBoard::MergeAll(const SgVectorOf<GoRegion>& regions,
00460 const SgPointSet& captured,
00461 SgBlackWhite color)
00462 {
00463 SgPointSet area(captured);
00464 for (SgVectorIteratorOf<GoRegion> it(regions); it; ++it)
00465 area |= (*it)->Points();
00466 {for (SgVectorIteratorOf<GoRegion> it(regions); it; ++it)
00467 RemoveRegion(*it);
00468 }
00469 GoRegion* r = GenRegion(area, color);
00470
00471 return r;
00472 }
00473
00474 void GoRegionBoard::MergeAdjacentAndAddBlock(SgPoint move,
00475 SgBlackWhite capturedColor)
00476 {
00477 SgVector<SgPoint> nb;
00478 for (SgNb4Iterator it(move); it; ++it)
00479 if (Board().IsEmpty(*it))
00480 nb.PushBack(*it);
00481
00482 SgVectorOf<GoBlock> captures;
00483 PreviousBlocksAt(nb, capturedColor, &captures);
00484 SG_ASSERT(captures.NonEmpty());
00485
00486 SgPointSet captured;
00487 {for (SgVectorIteratorOf<GoBlock> it(captures); it; ++it)
00488 captured |= (*it)->Stones();
00489 }
00490 SgVectorOf<GoRegion> adj;
00491 const int size = Board().Size();
00492 RegionsAt(captured.Border(size), capturedColor, &adj);
00493 SG_ASSERT(adj.NonEmpty());
00494 GoRegion* r = MergeAll(adj, captured, capturedColor);
00495 SG_UNUSED(r);
00496
00497 for (SgVectorIteratorOf<GoBlock> it(captures); it; ++it)
00498 RemoveBlock(*it, true, false);
00499
00500 }
00501
00502 void GoRegionBoard::OnUndoneMove()
00503
00504
00505 {
00506
00507 if (DEBUG_REGION_BOARD)
00508 SgDebug() << "OnUndoneMove " << '\n';
00509
00510 const bool IS_UNDO = false;
00511 SgVectorOf<GoRegion> changed;
00512
00513 for (int val = m_stack.PopEvent(); val != SG_NEXTMOVE;
00514 val = m_stack.PopEvent())
00515 {
00516
00517 switch (val)
00518 {
00519 case REGION_REMOVE:
00520 { GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
00521 AddRegion(r, IS_UNDO);
00522 changed.Insert(r);
00523 }
00524 break;
00525 case REGION_ADD:
00526 { GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
00527 RemoveRegion(r, IS_UNDO);
00528 }
00529 break;
00530 case REGION_REMOVE_BLOCK:
00531 { GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr());
00532 AddBlock(b, IS_UNDO);
00533 for (int nu = m_stack.PopInt(); nu > 0; --nu)
00534 {
00535 GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
00536 if (CHECK)
00537 SG_ASSERT(! r->Blocks().Contains(b));
00538 r->BlocksNonConst().PushBack(b);
00539 changed.Insert(r);
00540 }
00541 }
00542 break;
00543 case REGION_ADD_BLOCK:
00544 { GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr());
00545 RemoveBlock(b, IS_UNDO, true);
00546 }
00547 break;
00548 case REGION_ADD_STONE:
00549 { GoRegion* r = static_cast<GoRegion*>(m_stack.PopPtr());
00550 SgPoint p = m_stack.PopInt();
00551 r->OnRemoveStone(p);
00552 m_region[r->Color()][p] = r;
00553 changed.Insert(r);
00554 }
00555 break;
00556 case REGION_ADD_STONE_TO_BLOCK:
00557 { GoBlock* b = static_cast<GoBlock*>(m_stack.PopPtr());
00558 SgPoint p = m_stack.PopInt();
00559 b->RemoveStone(p);
00560 m_block[p] = 0;
00561 }
00562 break;
00563 default:
00564 SG_ASSERT(false);
00565 }
00566 }
00567
00568 for (SgVectorIteratorOf<GoRegion> it(changed); it; ++it)
00569 {
00570 (*it)->ResetNonBlockFlags();
00571 (*it)->ComputeBasicFlags();
00572 }
00573
00574 if (HEAVYCHECK)
00575 {
00576 for (SgBWIterator it; it; ++it)
00577 {
00578 SgBlackWhite color(*it);
00579 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00580 {
00581 const GoRegion* r = *it;
00582 SG_UNUSED(r);
00583 SG_ASSERT(r->IsValid());
00584 }
00585 }
00586 }
00587
00588 m_code = Board().GetHashCode();
00589 if (HEAVYCHECK)
00590 CheckConsistency();
00591 }
00592
00593 void GoRegionBoard::ReInitializeBlocksRegions()
00594 {
00595 SG_ASSERT(UpToDate());
00596
00597 for (SgBWIterator it; it; ++it)
00598 {
00599 SgBlackWhite color(*it);
00600 for (SgVectorIteratorOf<GoBlock> it(AllBlocks(color)); it; ++it)
00601 (*it)->ReInitialize();
00602 for (SgVectorIteratorOf<GoRegion> it2(AllRegions(color)); it2; ++it2)
00603 (*it2)->ReInitialize();
00604 }
00605 }
00606
00607 GoRegion* GoRegionBoard::GenRegion(const SgPointSet& area,
00608 SgBlackWhite color)
00609 {
00610 GoRegion* r = new GoRegion(Board(), area, color);
00611 AddRegion(r);
00612 return r;
00613 }
00614
00615 void GoRegionBoard::AddRegion(GoRegion* r, bool isExecute)
00616 {
00617 SetRegionArrays(r);
00618
00619 if (isExecute)
00620 {
00621 r->FindBlocks(*this);
00622 r->ComputeBasicFlags();
00623 }
00624
00625 SgBlackWhite color = r->Color();
00626 if (HEAVYCHECK)
00627 SG_ASSERT(! AllRegions(color).Contains(r));
00628 AllRegions(color).PushBack(r);
00629
00630 if (isExecute)
00631 PushRegion(REGION_ADD, r);
00632 }
00633
00634 void GoRegionBoard::FindBlocksWithEye()
00635 {
00636 for (SgBWIterator it; it; ++it)
00637 {
00638 SgBlackWhite color(*it);
00639 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00640 if ((*it)->Blocks().IsLength(1))
00641 {
00642 GoBlock* b = (*it)->Blocks().Front();
00643 (b)->TestFor1Eye(*it);
00644 }
00645 }
00646 }
00647
00648 void GoRegionBoard::GenBlocksRegions()
00649 {
00650 if (UpToDate())
00651 return;
00652
00653 Clear();
00654 GenBlocks();
00655
00656 for (SgBWIterator it; it; ++it)
00657 {
00658 SgBlackWhite color(*it);
00659 for (SgConnCompIterator it(AllPoints() - All(color), Board().Size());
00660 it; ++it)
00661 GenRegion(*it, color);
00662 }
00663
00664 FindBlocksWithEye();
00665
00666 m_code = Board().GetHashCode();
00667 m_invalid = false;
00668 if (HEAVYCHECK)
00669 CheckConsistency();
00670 }
00671
00672 void GoRegionBoard::GenChains()
00673 {
00674 if (ChainsUpToDate())
00675 return;
00676
00677 for (SgBWIterator it; it; ++it)
00678 {
00679 SgBlackWhite color(*it);
00680 SG_ASSERT(AllChains(color).IsEmpty());
00681
00682 for (SgVectorIteratorOf<GoBlock> it(AllBlocks(color)); it; ++it)
00683 AllChains(color).PushBack(new GoChain(*it, Board()));
00684 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00685 (*it)->FindChains(*this);
00686 }
00687 m_chainsCode = Board().GetHashCode();
00688 }
00689
00690 void GoRegionBoard::WriteBlocks(std::ostream& stream) const
00691 {
00692 for (SgBWIterator it; it; ++it)
00693 {
00694 SgBlackWhite color(*it);
00695 for (SgVectorIteratorOf<GoBlock> it(AllBlocks(color)); it; ++it)
00696 stream << **it;
00697 }
00698 }
00699
00700 void GoRegionBoard::WriteRegions(std::ostream& stream) const
00701 {
00702 for (SgBWIterator it; it; ++it)
00703 {
00704 SgBlackWhite color(*it);
00705 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00706 (*it)->Write(stream);
00707 }
00708 }
00709
00710 GoBlock* GoRegionBoard::GetBlock(const SgPointSet& boundary,
00711 SgBlackWhite color) const
00712 {
00713 SG_ASSERT(UpToDate());
00714
00715 for (SgVectorIteratorOf<GoBlock> it(AllBlocks(color)); it; ++it)
00716 { if (boundary.SubsetOf((*it)->Stones()))
00717 return *it;
00718 }
00719
00720 SgDebug() << "ERROR: no block on set";
00721 const int size = Board().Size();
00722 boundary.Write(SgDebug(), size);
00723 SgDebug() << "blocks:";
00724 for (SgVectorIteratorOf<GoBlock> it(AllBlocks(color));it; ++it)
00725 (*it)->Stones().Write(SgDebug(), size);
00726
00727 SG_ASSERT(false);
00728 return 0;
00729 }
00730
00731 GoChain* GoRegionBoard::ChainAt(SgPoint p) const
00732 {
00733 SG_ASSERT(ChainsUpToDate());
00734 const SgBlackWhite color = Board().GetStone(p);
00735
00736 for (SgVectorIteratorOf<GoChain> it(AllChains(color));it; ++it)
00737 if ((*it)->Stones().Contains(p))
00738 return *it;
00739
00740 SG_ASSERT(false);
00741 return 0;
00742 }
00743
00744 void GoRegionBoard::GenBlocks()
00745 {
00746 for (GoBlockIterator it(Board()); it; ++it)
00747 GenBlock(*it, Board().GetStone(*it));
00748 }
00749
00750 void GoRegionBoard::SetComputedFlagForAll(GoRegionFlag flag)
00751 {
00752
00753 for (SgBWIterator it; it; ++it)
00754 {
00755 SgBlackWhite color(*it);
00756 for (SgVectorIteratorOf<GoRegion> it(AllRegions(color)); it; ++it)
00757 (*it)->SetComputedFlag(flag);
00758 }
00759 }
00760
00761 void GoRegionBoard::SetComputedHealthy()
00762 {
00763 m_computedHealthy = true;
00764 }
00765
00766
00767
00768 int GoRegionBoard::s_alloc = 0;
00769 int GoRegionBoard::s_free = 0;