00001
00002
00003
00004
00005
00006 #include "Time.hpp"
00007 #include "BoardUtils.hpp"
00008 #include "BitsetIterator.hpp"
00009 #include "Groups.hpp"
00010 #include "VCSet.hpp"
00011 #include "HexBoard.hpp"
00012 #include "VCUtils.hpp"
00013
00014 using namespace benzene;
00015
00016
00017
00018 HexBoard::HexBoard(int width, int height, const ICEngine& ice,
00019 VCBuilderParam& param)
00020 : m_brd(width, height),
00021 m_ice(&ice),
00022 m_groups(),
00023 m_patterns(m_brd),
00024 m_builder(param),
00025 m_use_vcs(true),
00026 m_use_ice(true),
00027 m_use_decompositions(true),
00028 m_backup_ice_info(true)
00029 {
00030 Initialize();
00031 }
00032
00033
00034
00035 HexBoard::HexBoard(const HexBoard& other)
00036 : m_brd(other.m_brd),
00037 m_ice(other.m_ice),
00038 m_groups(other.m_groups),
00039 m_patterns(m_brd),
00040 m_builder(other.m_builder),
00041 m_history(other.m_history),
00042 m_inf(other.m_inf),
00043 m_use_vcs(other.m_use_vcs),
00044 m_use_ice(other.m_use_ice),
00045 m_use_decompositions(other.m_use_decompositions),
00046 m_backup_ice_info(other.m_backup_ice_info)
00047 {
00048 m_patterns.CopyState(other.GetPatternState());
00049 for (BWIterator color; color; ++color)
00050 {
00051 m_cons[*color].reset(new VCSet(*other.m_cons[*color]));
00052 m_log[*color] = m_log[*color];
00053 }
00054 }
00055
00056 void HexBoard::Initialize()
00057 {
00058 GroupBuilder::Build(m_brd, m_groups);
00059 for (BWIterator c; c; ++c)
00060 m_cons[*c].reset(new VCSet(Const(), *c));
00061 ClearHistory();
00062 }
00063
00064 HexBoard::~HexBoard()
00065 {
00066 }
00067
00068
00069
00070 void HexBoard::ComputeInferiorCells(HexColor color_to_move)
00071 {
00072 if (m_use_ice)
00073 {
00074 InferiorCells inf;
00075 m_ice->ComputeInferiorCells(color_to_move, m_groups, m_patterns, inf);
00076 IceUtil::Update(m_inf, inf);
00077 }
00078 }
00079
00080 void HexBoard::BuildVCs()
00081 {
00082 for (BWIterator c; c; ++c)
00083 m_builder.Build(*m_cons[*c], m_groups, m_patterns);
00084 }
00085
00086 void HexBoard::BuildVCs(const Groups& oldGroups,
00087 bitset_t added[BLACK_AND_WHITE], bool use_changelog)
00088 {
00089 HexAssert((added[BLACK] & added[WHITE]).none());
00090 for (BWIterator c; c; ++c)
00091 {
00092 ChangeLog<VC>* log = (use_changelog) ? &m_log[*c] : 0;
00093 m_builder.Build(*m_cons[*c], oldGroups, m_groups, m_patterns,
00094 added, log);
00095 }
00096 }
00097
00098 void HexBoard::MarkChangeLog()
00099 {
00100 m_log[BLACK].push(ChangeLog<VC>::MARKER, VC());
00101 m_log[WHITE].push(ChangeLog<VC>::MARKER, VC());
00102 }
00103
00104 void HexBoard::RevertVCs()
00105 {
00106 for (BWIterator c; c; ++c)
00107 m_cons[*c]->Revert(m_log[*c]);
00108 }
00109
00110
00111
00112
00113
00114 void HexBoard::HandleVCDecomposition(HexColor color_to_move, bool use_changelog)
00115 {
00116 if (!m_use_decompositions)
00117 return;
00118
00119
00120
00121 if (m_groups.IsGameOver())
00122 return;
00123
00124 int decompositions = 0;
00125 for (;;)
00126 {
00127 bool found = false;
00128 for (BWIterator c; c; ++c)
00129 {
00130 bitset_t captured;
00131 if (BoardUtils::FindCombinatorialDecomposition(*this, *c,
00132 captured))
00133 {
00134 LogFine() << "Decomposition " << decompositions << ": for "
00135 << *c << ".\n" << m_brd.Write(captured) << '\n';
00136
00137 AddStones(*c, captured, color_to_move, use_changelog);
00138 m_inf.AddCaptured(*c, captured);
00139
00140 LogFine() << "After decomposition " << decompositions
00141 << ": " << m_brd << '\n';
00142
00143 decompositions++;
00144 found = true;
00145 break;
00146 }
00147 }
00148 if (!found)
00149 break;
00150 }
00151 LogFine() << "Found " << decompositions << " decompositions.\n";
00152 }
00153
00154 void HexBoard::ComputeAll(HexColor color_to_move)
00155 {
00156 double s = Time::Get();
00157
00158 m_patterns.Update();
00159 GroupBuilder::Build(m_brd, m_groups);
00160 m_inf.Clear();
00161
00162 ComputeInferiorCells(color_to_move);
00163
00164 if (m_use_vcs)
00165 {
00166 m_builder.ClearStatistics();
00167 BuildVCs();
00168 HandleVCDecomposition(color_to_move, false);
00169 }
00170
00171 double e = Time::Get();
00172 LogFine() << (e-s) << "s to compute all.\n";
00173 }
00174
00175 void HexBoard::PlayMove(HexColor color, HexPoint cell)
00176 {
00177 LogFine() << "Playing (" << color << ", " << cell << ")\n";
00178
00179 double s = Time::Get();
00180 PushHistory(color, cell);
00181 bitset_t old_black = m_brd.GetColor(BLACK);
00182 bitset_t old_white = m_brd.GetColor(WHITE);
00183
00184 m_brd.PlayMove(color, cell);
00185 m_patterns.Update(cell);
00186 Groups oldGroups(m_groups);
00187 GroupBuilder::Build(m_brd, m_groups);
00188
00189 ComputeInferiorCells(!color);
00190
00191 bitset_t added[BLACK_AND_WHITE];
00192 added[BLACK] = m_brd.GetColor(BLACK) - old_black;
00193 added[WHITE] = m_brd.GetColor(WHITE) - old_white;
00194
00195 if (m_use_vcs)
00196 {
00197 m_builder.ClearStatistics();
00198 MarkChangeLog();
00199 BuildVCs(oldGroups, added, true);
00200 HandleVCDecomposition(!color, true);
00201 }
00202 double e = Time::Get();
00203 LogFine() << (e-s) << "s to play stones.\n";
00204 }
00205
00206 void HexBoard::PlayStones(HexColor color, const bitset_t& played,
00207 HexColor color_to_move)
00208 {
00209 LogFine() << "Playing (" << color << ","
00210 << HexPointUtil::ToString(played) << ")\n";
00211 HexAssert(BitsetUtil::IsSubsetOf(played, GetPosition().GetEmpty()));
00212
00213 double s = Time::Get();
00214 PushHistory(color, INVALID_POINT);
00215 bitset_t old_black = m_brd.GetColor(BLACK);
00216 bitset_t old_white = m_brd.GetColor(WHITE);
00217
00218 m_brd.AddColor(color, played);
00219 m_patterns.Update(played);
00220 Groups oldGroups(m_groups);
00221 GroupBuilder::Build(m_brd, m_groups);
00222
00223 ComputeInferiorCells(color_to_move);
00224
00225 bitset_t added[BLACK_AND_WHITE];
00226 added[BLACK] = m_brd.GetColor(BLACK) - old_black;
00227 added[WHITE] = m_brd.GetColor(WHITE) - old_white;
00228
00229 if (m_use_vcs)
00230 {
00231 m_builder.ClearStatistics();
00232 MarkChangeLog();
00233 BuildVCs(oldGroups, added, true);
00234 HandleVCDecomposition(color_to_move, true);
00235 }
00236
00237 double e = Time::Get();
00238 LogFine() << (e-s) << "s to play stones.\n";
00239 }
00240
00241
00242
00243
00244
00245
00246 void HexBoard::AddStones(HexColor color, const bitset_t& played,
00247 HexColor color_to_move, bool use_changelog)
00248 {
00249 HexAssert(BitsetUtil::IsSubsetOf(played, GetPosition().GetEmpty()));
00250 LogFine() << "Adding (" << color << ", "
00251 << HexPointUtil::ToString(played) << ")\n";
00252
00253 double s = Time::Get();
00254 bitset_t old_black = m_brd.GetColor(BLACK);
00255 bitset_t old_white = m_brd.GetColor(WHITE);
00256
00257 m_brd.AddColor(color, played);
00258 m_patterns.Update(played);
00259 Groups oldGroups(m_groups);
00260 GroupBuilder::Build(m_brd, m_groups);
00261
00262 ComputeInferiorCells(color_to_move);
00263
00264 bitset_t added[BLACK_AND_WHITE];
00265 added[BLACK] = m_brd.GetColor(BLACK) - old_black;
00266 added[WHITE] = m_brd.GetColor(WHITE) - old_white;
00267
00268 if (m_use_vcs)
00269 BuildVCs(oldGroups, added, use_changelog);
00270
00271 double e = Time::Get();
00272 LogFine() << (e-s) << "s to add stones.\n";
00273 }
00274
00275 void HexBoard::UndoMove()
00276 {
00277 double s = Time::Get();
00278
00279 PopHistory();
00280 m_patterns.Update();
00281
00282 double e = Time::Get();
00283 LogFine() << (e-s) << "s to undo move.\n";
00284 }
00285
00286
00287
00288 void HexBoard::ClearHistory()
00289 {
00290 m_history.clear();
00291 }
00292
00293 void HexBoard::PushHistory(HexColor color, HexPoint cell)
00294 {
00295 m_history.push_back(History(m_brd, m_groups, m_inf, color, cell));
00296 }
00297
00298
00299
00300 void HexBoard::PopHistory()
00301 {
00302 HexAssert(!m_history.empty());
00303
00304 History hist = m_history.back();
00305 m_history.pop_back();
00306
00307 m_brd.SetPosition(hist.board);
00308 if (m_backup_ice_info && hist.last_played != INVALID_POINT)
00309 {
00310
00311
00312
00313 bitset_t a = m_brd.GetEmpty() - hist.inf.All();
00314 a &= m_inf.Dead() | m_inf.Captured(hist.to_play);
00315
00316 for (BitsetIterator p(a); p; ++p)
00317 hist.inf.AddDominated(*p, hist.last_played);
00318 }
00319 m_inf = hist.inf;
00320 m_groups = hist.groups;
00321 RevertVCs();
00322 }
00323
00324