00001 //---------------------------------------------------------------------------- 00002 /** @file Groups.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "BitsetIterator.hpp" 00007 #include "Groups.hpp" 00008 00009 using namespace benzene; 00010 00011 //---------------------------------------------------------------------------- 00012 00013 namespace { 00014 00015 //---------------------------------------------------------------------------- 00016 00017 void Flow(const StoneBoard& brd, HexPoint start, HexColor color, 00018 bitset_t& members, bitset_t& nbs) 00019 { 00020 HexAssert(!members.test(start)); 00021 HexAssert(brd.GetColor(start) == color); 00022 members.set(start); 00023 for (BoardIterator p(brd.Const().Nbs(start)); p; ++p) 00024 { 00025 if (members.test(*p)) 00026 continue; 00027 if (color != EMPTY && brd.GetColor(*p) == color) 00028 Flow(brd, *p, color, members, nbs); 00029 else 00030 nbs.set(*p); 00031 } 00032 HexAssert((members & nbs).none()); 00033 } 00034 00035 //---------------------------------------------------------------------------- 00036 00037 } // anonymous namespace 00038 00039 //---------------------------------------------------------------------------- 00040 00041 void GroupBuilder::Build(const StoneBoard& brd, Groups& groups) 00042 { 00043 bitset_t visited; 00044 groups.m_brd = const_cast<StoneBoard*>(&brd); 00045 groups.m_groups.clear(); 00046 groups.m_group_index.resize(FIRST_INVALID); 00047 for (BoardIterator p(brd.Const().EdgesAndInterior()); p; ++p) 00048 { 00049 if (visited.test(*p)) 00050 continue; 00051 bitset_t nbs, members; 00052 HexColor color = brd.GetColor(*p); 00053 Flow(brd, *p, color, members, nbs); 00054 HexAssert((visited & members).none()); 00055 visited |= members; 00056 for (BitsetIterator m(members); m; ++m) 00057 groups.m_group_index[*m] = groups.m_groups.size(); 00058 groups.m_groups.push_back(Group(&groups, color, *p, members, nbs)); 00059 } 00060 for (std::size_t i = 0; i < groups.m_groups.size(); ++i) 00061 { 00062 Group& g = groups.m_groups[i]; 00063 g.m_nbs = groups.CaptainizeBitset(g.m_nbs); 00064 for (BitsetIterator p(g.m_nbs); p; ++p) 00065 g.m_nbs_index.push_back(groups.m_group_index[*p]); 00066 } 00067 } 00068 00069 //---------------------------------------------------------------------------- 00070 00071 std::size_t Groups::NumGroups(HexColorSet colorset) const 00072 { 00073 std::size_t num = 0; 00074 for (GroupIterator g(*this, colorset); g; ++g) 00075 ++num; 00076 return num; 00077 } 00078 00079 std::size_t Groups::GroupIndex(HexPoint point, HexColorSet colorset) const 00080 { 00081 std::size_t count = 0; 00082 for (GroupIterator g(*this, colorset); g; ++g) 00083 { 00084 if (g->IsMember(point)) 00085 break; 00086 ++count; 00087 } 00088 return count; 00089 } 00090 00091 bool Groups::IsGameOver() const 00092 { 00093 return (GetWinner() != EMPTY); 00094 } 00095 00096 HexColor Groups::GetWinner() const 00097 { 00098 for (BWIterator c; c; ++c) 00099 if (m_group_index[HexPointUtil::colorEdge1(*c)] == 00100 m_group_index[HexPointUtil::colorEdge2(*c)]) 00101 return *c; 00102 return EMPTY; 00103 } 00104 00105 bitset_t Groups::CaptainizeBitset(bitset_t locations) const 00106 { 00107 HexAssert(m_brd->Const().IsLocation(locations)); 00108 bitset_t captains; 00109 for (BitsetIterator i(locations); i; ++i) 00110 captains.set(CaptainOf(*i)); 00111 return captains; 00112 } 00113 00114 //---------------------------------------------------------------------------- 00115 00116 const bitset_t& Group::Nbs(HexColorSet colorset) const 00117 { 00118 if (!m_colorsets_computed) 00119 { 00120 ComputeColorsetNbs(); 00121 m_colorsets_computed = true; 00122 } 00123 return m_nbs_colorset[colorset]; 00124 } 00125 00126 void Group::ComputeColorsetNbs() const 00127 { 00128 for (int cs = 0; cs < NUM_COLOR_SETS; ++cs) 00129 { 00130 HexColorSet colorset = static_cast<HexColorSet>(cs); 00131 for (std::size_t i = 0; i < m_nbs_index.size(); ++i) 00132 { 00133 const Group* nb = &m_groups->m_groups[m_nbs_index[i]]; 00134 if (HexColorSetUtil::InSet(nb->Color(), colorset)) 00135 m_nbs_colorset[colorset].set(nb->Captain()); 00136 } 00137 } 00138 } 00139 00140 //----------------------------------------------------------------------------