Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoRegionBoard.cpp

Go to the documentation of this file.
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, &regions);
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, &regions);
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;


17 Jun 2010 Doxygen 1.4.7