00001 //---------------------------------------------------------------------------- 00002 /** @file GoRegionBoard.cpp 00003 See GoRegionBoard.h. */ 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); // board is already up to date. 00133 bool done = false; 00134 const int size = Board().Size(); 00135 if (! Board().IsSingleStone(move)) // find old neighbor blocks 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)) // append to single neighbor block 00144 { 00145 GoBlock* b = old.Front(); 00146 AppendStone(b, move); 00147 done = true; 00148 } 00149 else // delete old, recompute 00150 { 00151 for (SgVectorIteratorOf<GoBlock> it(old); it; ++it) 00152 RemoveBlock(*it, true, true); 00153 } 00154 } 00155 00156 if (! done) // create new block. 00157 { 00158 GoBlock* b = GenBlock(anchor, moveColor); 00159 SgPointSet area(b->Stones().Border(size)); 00160 // link it to neighbor regions 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()) // full recomputation 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 // can't handle yet, 00202 // should be forbidden anyway. AR: allowed in Chinese rules. 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 // needed even after RemoveRegion(r). 00215 if (split || points.IsEmpty()) 00216 // must remove old region before generating new ones, 00217 // because removing clears m_anchor[] 00218 RemoveRegion(r); 00219 00220 if (split) // find new regions 00221 { 00222 for (SgConnCompIterator it(points, Board().Size()); 00223 it; ++it) 00224 GenRegion(*it, moveColor); 00225 } 00226 } 00227 00228 if (fWasCapture) 00229 { 00230 // FindNewNeighborRegions(move, moveColor); 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 // check m_region array 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 // check block array 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; // remove link of region. 00322 } 00323 00324 bool found = m_allRegions[r->Color()].Exclude(r); 00325 SG_UNUSED(found); 00326 SG_ASSERT(found); 00327 00328 // remove from blocks. 00329 for (SgVectorIteratorOf<GoBlock> it(r->Blocks()); it; ++it) 00330 (*it)->RemoveRegion(r); 00331 00332 if (isExecute) 00333 PushRegion(REGION_REMOVE, r); 00334 else // undo 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 // remove from regions. 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()); // 0 if ! removeFromRegions 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 // convert a captured block into an opponent region. 00416 { 00417 GoRegion* r = new GoRegion(Board(), b->Stones(), OppBW(b->Color())); 00418 SetRegionArrays(r); 00419 // AR anchor array should still be OK, don't need to set it. 00420 } 00421 00422 void GoRegionBoard::FindNewNeighborRegions(SgPoint move, 00423 BlackWhite moveColor) 00424 { // move was capture -> new region for each captured block. 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 // don't remove from regions; already gone. 00499 } 00500 00501 void GoRegionBoard::OnUndoneMove() 00502 // Called after a move has been undone. The board is guaranteed to be in 00503 // a legal state. 00504 { 00505 //SG_ASSERT(false); // incremental code is incomplete, do not call 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) // not needed if restoring during undo. 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 // mark all regions that their safety has been computed. 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;