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