00001
00002
00003
00004
00005
00006 #include "BitsetIterator.hpp"
00007 #include "EndgameUtils.hpp"
00008 #include "DfpnCommands.hpp"
00009
00010 using namespace benzene;
00011
00012
00013
00014 DfpnCommands::DfpnCommands(Game& game, HexEnvironment& env,
00015 DfpnSolver& solver,
00016 boost::scoped_ptr<DfpnHashTable>& tt,
00017 boost::scoped_ptr<DfpnDB>& db,
00018 DfpnStates& positions)
00019 : m_game(game),
00020 m_env(env),
00021 m_solver(solver),
00022 m_tt(tt),
00023 m_db(db),
00024 m_positions(positions)
00025 {
00026 }
00027
00028 void DfpnCommands::Register(GtpEngine& e)
00029 {
00030 Register(e, "param_dfpn", &DfpnCommands::CmdParam);
00031 Register(e, "param_dfpn_db", &DfpnCommands::CmdParamSolverDB);
00032 Register(e, "dfpn-clear-tt", &DfpnCommands::CmdClearTT);
00033 Register(e, "dfpn-get-bounds", &DfpnCommands::CmdGetBounds);
00034 Register(e, "dfpn-get-state", &DfpnCommands::CmdGetState);
00035 Register(e, "dfpn-get-work", &DfpnCommands::CmdGetWork);
00036 Register(e, "dfpn-get-pv", &DfpnCommands::CmdGetPV);
00037 Register(e, "dfpn-solve-state", &DfpnCommands::CmdSolveState);
00038 Register(e, "dfpn-solver-find-winning", &DfpnCommands::CmdFindWinning);
00039 Register(e, "dfpn-open-db", &DfpnCommands::CmdOpenDB);
00040 Register(e, "dfpn-close-db", &DfpnCommands::CmdCloseDB);
00041 Register(e, "dfpn-db-stat", &DfpnCommands::CmdDBStat);
00042 Register(e, "dfpn-evaluation-info", &DfpnCommands::CmdEvaluationInfo);
00043 }
00044
00045 void DfpnCommands::Register(GtpEngine& engine, const std::string& command,
00046 GtpCallback<DfpnCommands>::Method method)
00047 {
00048 engine.Register(command, new GtpCallback<DfpnCommands>(this, method));
00049 }
00050
00051
00052
00053 void DfpnCommands::CmdParamSolverDB(HtpCommand& cmd)
00054 {
00055 SolverDBParameters& param = m_positions.Parameters();
00056 if (cmd.NuArg() == 0)
00057 {
00058 cmd << '\n'
00059 << "[bool] use_flipped_states " << param.m_useFlippedStates << '\n'
00060 << "[bool] use_proof_transpositions "
00061 << param.m_useProofTranspositions << '\n'
00062 << "[string] max_stones " << param.m_maxStones << '\n'
00063 << "[string] trans_stones " << param.m_transStones << '\n';
00064 }
00065 else if (cmd.NuArg() == 2)
00066 {
00067 std::string name = cmd.Arg(0);
00068 if (name == "use_flipped_states")
00069 param.m_useFlippedStates = cmd.BoolArg(1);
00070 else if (name == "use_proof_transpositions")
00071 param.m_useProofTranspositions = cmd.BoolArg(1);
00072 else if (name == "max_stones")
00073 param.m_maxStones = cmd.IntArg(1, 0);
00074 else if (name == "trans_stones")
00075 param.m_transStones = cmd.IntArg(1, 0);
00076 else
00077 throw HtpFailure() << "unknown parameter: " << name;
00078 }
00079 else
00080 throw HtpFailure("Expected 0 or 2 arguments");
00081 }
00082
00083 void DfpnCommands::CmdParam(HtpCommand& cmd)
00084 {
00085 if (cmd.NuArg() == 0)
00086 {
00087 cmd << '\n'
00088 << "[bool] use_guifx "
00089 << m_solver.UseGuiFx() << '\n'
00090 << "[string] timelimit "
00091 << m_solver.Timelimit() << '\n'
00092 << "[string] tt_bits "
00093 << ((m_tt.get() == 0) ? 0 : m_tt->Bits()) << '\n'
00094 << "[string] widening_base "
00095 << m_solver.WideningBase() << '\n'
00096 << "[string] widening_factor "
00097 << m_solver.WideningFactor() << '\n';
00098 }
00099 else if (cmd.NuArg() == 2)
00100 {
00101 std::string name = cmd.Arg(0);
00102 if (name == "use_guifx")
00103 m_solver.SetUseGuiFx(cmd.BoolArg(1));
00104 else if (name == "timelimit")
00105 m_solver.SetTimelimit(cmd.FloatArg(1));
00106 else if (name == "tt_bits")
00107 {
00108 int bits = cmd.IntArg(1, 0);
00109 if (bits == 0)
00110 m_tt.reset(0);
00111 else
00112 m_tt.reset(new DfpnHashTable(bits));
00113 }
00114 else if (name == "widening_base")
00115 {
00116 int value = cmd.IntArg(1, 0);
00117 if (0 < value)
00118 m_solver.SetWideningBase(value);
00119 else
00120 throw GtpFailure() << "widening_base must be positive.";
00121 }
00122 else if (name == "widening_factor")
00123 {
00124 float value = cmd.FloatArg(1);
00125 if (0.0f < value && value <= 1.0f)
00126 m_solver.SetWideningFactor(value);
00127 else
00128 throw GtpFailure() << "widening_factor must be in (0, 1]";
00129 }
00130 else
00131 throw GtpFailure() << "Unknown parameter: " << name;
00132 }
00133 else
00134 throw GtpFailure() << "Expected 0 or 2 arguments";
00135 }
00136
00137
00138 void DfpnCommands::CmdSolveState(HtpCommand& cmd)
00139 {
00140 cmd.CheckNuArgLessEqual(3);
00141 HexColor colorToMove = m_game.Board().WhoseTurn();
00142 if (cmd.NuArg() >= 1)
00143 colorToMove = HtpUtil::ColorArg(cmd, 0);
00144 DfpnBoundType maxPhi = DfpnBounds::MAX_WORK;
00145 DfpnBoundType maxDelta = DfpnBounds::MAX_WORK;
00146 if (cmd.NuArg() >= 2)
00147 maxPhi = cmd.IntArg(1, 0);
00148 if (cmd.NuArg() >= 3)
00149 maxDelta = cmd.IntArg(2, 0);
00150 DfpnBounds maxBounds(maxPhi, maxDelta);
00151 PointSequence pv;
00152 HexBoard& brd = m_env.SyncBoard(m_game.Board());
00153 HexColor winner
00154 = m_solver.StartSearch(HexState(m_game.Board(), colorToMove), brd,
00155 m_positions, pv, maxBounds);
00156 cmd << winner;
00157 }
00158
00159
00160
00161 void DfpnCommands::CmdFindWinning(HtpCommand& cmd)
00162 {
00163 cmd.CheckNuArg(1);
00164 HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00165 HexBoard& brd = m_env.SyncBoard(m_game.Board());
00166 brd.ComputeAll(colorToMove);
00167 bitset_t consider = (EndgameUtils::IsDeterminedState(brd, colorToMove) ?
00168 brd.GetPosition().GetEmpty() :
00169 EndgameUtils::MovesToConsider(brd, colorToMove));
00170 bitset_t winning;
00171 SgTimer timer;
00172
00173 HexState state(m_game.Board(), colorToMove);
00174 for (BitsetIterator p(consider); p; ++p)
00175 {
00176 state.PlayMove(*p);
00177 HexBoard& brd = m_env.SyncBoard(state.Position());
00178 LogInfo() << "****** Trying " << *p << " ******\n" << brd << '\n';
00179 PointSequence pv;
00180 HexColor winner = m_solver.StartSearch(state, brd, m_positions, pv);
00181 if (winner == colorToMove)
00182 winning.set(*p);
00183 LogInfo() << "****** " << winner << " wins ******\n";
00184 state.UndoMove(*p);
00185 }
00186 LogInfo() << "Total Elapsed Time: " << timer.GetTime() << '\n';
00187 cmd << HexPointUtil::ToString(winning);
00188 }
00189
00190
00191 void DfpnCommands::CmdClearTT(HtpCommand& cmd)
00192 {
00193 UNUSED(cmd);
00194 m_tt->Clear();
00195 }
00196
00197
00198
00199 void DfpnCommands::CmdGetState(HtpCommand& cmd)
00200 {
00201 cmd.CheckNuArg(1);
00202 HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00203 HexState state(m_game.Board(), colorToMove);
00204 DfpnData data;
00205 if (m_positions.Get(state, data))
00206 cmd << data << '\n';
00207 }
00208
00209
00210
00211 void DfpnCommands::CmdGetBounds(HtpCommand& cmd)
00212 {
00213 cmd.CheckNuArg(1);
00214 HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00215 HexState state(m_game.Board(), colorToMove);
00216 for (BitsetIterator it(state.Position().GetEmpty()); it; ++it)
00217 {
00218 state.PlayMove(*it);
00219 DfpnData data;
00220 if (m_positions.Get(state, data))
00221 {
00222 cmd << ' ' << *it << ' ';
00223 if (data.m_bounds.IsWinning())
00224 cmd << 'L';
00225 else if (data.m_bounds.IsLosing())
00226 cmd << 'W';
00227 else
00228 cmd << data.m_bounds.phi << ':' << data.m_bounds.delta;
00229 }
00230 state.UndoMove(*it);
00231 }
00232 }
00233
00234
00235
00236 void DfpnCommands::CmdGetWork(HtpCommand& cmd)
00237 {
00238 cmd.CheckNuArg(1);
00239 HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00240 HexState state(m_game.Board(), colorToMove);
00241 for (BitsetIterator it(state.Position().GetEmpty()); it; ++it)
00242 {
00243 state.PlayMove(*it);
00244 DfpnData data;
00245 if (m_positions.Get(state, data))
00246 cmd << ' ' << *it << ' ' << data.m_work;
00247 state.UndoMove(*it);
00248 }
00249 }
00250
00251
00252 void DfpnCommands::CmdGetPV(HtpCommand& cmd)
00253 {
00254 cmd.CheckNuArg(1);
00255 HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00256 PointSequence pv;
00257 SolverDBUtil::GetVariation(HexState(m_game.Board(), colorToMove),
00258 m_positions, pv);
00259 cmd << HexPointUtil::ToString(pv);
00260 }
00261
00262
00263
00264
00265 void DfpnCommands::CmdOpenDB(HtpCommand& cmd)
00266 {
00267 cmd.CheckNuArgLessEqual(3);
00268 std::string filename = cmd.Arg(0);
00269 try {
00270 m_db.reset(new DfpnDB(filename));
00271 }
00272 catch (BenzeneException& e) {
00273 m_db.reset(0);
00274 throw HtpFailure() << "Error opening db: '" << e.what() << "'\n";
00275 }
00276 }
00277
00278
00279 void DfpnCommands::CmdCloseDB(HtpCommand& cmd)
00280 {
00281 cmd.CheckNuArg(0);
00282 if (m_db.get() == 0)
00283 throw HtpFailure("No open database!\n");
00284 m_db.reset(0);
00285 }
00286
00287
00288 void DfpnCommands::CmdDBStat(HtpCommand& cmd)
00289 {
00290 cmd.CheckNuArg(0);
00291 if (m_db.get() == 0)
00292 throw HtpFailure("No open database!\n");
00293 cmd << m_db->BDBStatistics();
00294 }
00295
00296 void DfpnCommands::CmdEvaluationInfo(HtpCommand& cmd)
00297 {
00298 cmd.CheckNuArg(0);
00299 cmd << m_solver.EvaluationInfo();
00300 }
00301
00302