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