00001
00002
00003
00004
00005
00006 #include "BookBuilder.hpp"
00007 #include "BookCommands.hpp"
00008 #include "VCUtils.hpp"
00009
00010 using namespace benzene;
00011
00012
00013
00014 BookCommands::BookCommands(Game& game, HexEnvironment& env,
00015 boost::scoped_ptr<Book>& book,
00016 BookCheck& bookCheck)
00017 : m_game(game),
00018 m_env(env),
00019 m_book(book),
00020 m_bookCheck(bookCheck)
00021 {
00022 }
00023
00024 BookCommands::~BookCommands()
00025 {
00026 }
00027
00028 void BookCommands::Register(GtpEngine& e)
00029 {
00030 Register(e, "book-open", &BookCommands::CmdBookOpen);
00031 Register(e, "book-close", &BookCommands::CmdBookClose);
00032 Register(e, "book-stat", &BookCommands::CmdBookStat);
00033 Register(e, "book-depths", &BookCommands::CmdBookMainLineDepth);
00034 Register(e, "book-counts", &BookCommands::CmdBookCounts);
00035 Register(e, "book-scores", &BookCommands::CmdBookScores);
00036 Register(e, "book-visualize", &BookCommands::CmdBookVisualize);
00037 Register(e, "book-dump-polarized-leafs",
00038 &BookCommands::CmdBookDumpPolarizedLeafs);
00039 Register(e, "book-import-solved",
00040 &BookCommands::CmdBookImportSolvedStates);
00041 Register(e, "book-set-value", &BookCommands::CmdBookSetValue);
00042 Register(e, "param_book", &BookCommands::CmdBookParam);
00043 }
00044
00045 void BookCommands::Register(GtpEngine& engine, const std::string& command,
00046 GtpCallback<BookCommands>::Method method)
00047 {
00048 engine.Register(command, new GtpCallback<BookCommands>(this, method));
00049 }
00050
00051
00052
00053
00054
00055
00056 void BookCommands::CmdBookOpen(HtpCommand& cmd)
00057 {
00058 cmd.CheckNuArgLessEqual(2);
00059 std::string fn = cmd.Arg(0);
00060 try {
00061 m_book.reset(new Book(fn));
00062 }
00063 catch (BenzeneException& e) {
00064 cmd << "Error opening book: '" << e.what() << "'\n";
00065 }
00066 }
00067
00068
00069 void BookCommands::CmdBookClose(HtpCommand& cmd)
00070 {
00071 cmd.CheckArgNone();
00072 if (m_book.get() == 0)
00073 throw HtpFailure() << "No open book.";
00074 m_book.reset(0);
00075 }
00076
00077 void BookCommands::CmdBookStat(HtpCommand& cmd)
00078 {
00079 cmd.CheckNuArg(0);
00080 if (m_book.get() == 0)
00081 throw HtpFailure("No open book!\n");
00082 cmd << m_book->BDBStatistics();
00083 }
00084
00085 void BookCommands::CmdBookMainLineDepth(HtpCommand& cmd)
00086 {
00087 if (m_book.get() == 0)
00088 throw HtpFailure() << "No open book.";
00089 HexState state(m_game.Board(), m_game.Board().WhoseTurn());
00090 for (BitsetIterator p(state.Position().GetEmpty()); p; ++p)
00091 {
00092 state.PlayMove(*p);
00093 cmd << " " << *p << " " << BookUtil::GetMainLineDepth(*m_book, state);
00094 state.UndoMove(*p);
00095 }
00096 }
00097
00098 void BookCommands::CmdBookCounts(HtpCommand& cmd)
00099 {
00100 if (m_book.get() == 0)
00101 throw HtpFailure() << "No open book.";
00102 HexState state(m_game.Board(), m_game.Board().WhoseTurn());
00103 for (BitsetIterator p(state.Position().GetEmpty()); p; ++p)
00104 {
00105 state.PlayMove(*p);
00106 HexBookNode node;
00107 if (m_book->Get(state, node))
00108 cmd << " " << *p << " " << node.m_count;
00109 state.UndoMove(*p);
00110 }
00111 }
00112
00113 void BookCommands::CmdBookScores(HtpCommand& cmd)
00114 {
00115 if (m_book.get() == 0)
00116 throw HtpFailure() << "No open book.";
00117 float countWeight = m_bookCheck.CountWeight();
00118 HexState state(m_game.Board(), m_game.Board().WhoseTurn());
00119
00120 std::map<HexPoint, HexEval> values;
00121 std::map<HexPoint, unsigned> counts;
00122 std::vector<std::pair<float, HexPoint> > scores;
00123 for (BitsetIterator p(state.Position().GetEmpty()); p; ++p)
00124 {
00125 state.PlayMove(*p);
00126 HexBookNode node;
00127 if (m_book->Get(state, node))
00128 {
00129 counts[*p] = node.m_count;
00130 values[*p] = BookUtil::InverseEval(BookUtil::Value(node, state));
00131 scores.push_back(std::make_pair
00132 (-BookUtil::Score(node, state, countWeight), *p));
00133 }
00134 state.UndoMove(*p);
00135 }
00136 std::stable_sort(scores.begin(), scores.end());
00137 std::vector<std::pair<float, HexPoint> >::const_iterator it
00138 = scores.begin();
00139 for (; it != scores.end(); ++it)
00140 {
00141 HexPoint p = it->second;
00142 HexEval value = values[p];
00143 cmd << ' ' << p;
00144 if (HexEvalUtil::IsWin(value))
00145 cmd << " W";
00146 else if (HexEvalUtil::IsLoss(value))
00147 cmd << " L";
00148 else
00149 cmd << " " << std::fixed << std::setprecision(3) << value;
00150 cmd << '@' << counts[p];
00151 }
00152 }
00153
00154 void BookCommands::CmdBookVisualize(HtpCommand& cmd)
00155 {
00156 if (m_book.get() == 0)
00157 throw HtpFailure() << "No open book.";
00158 cmd.CheckNuArg(1);
00159 std::string filename = cmd.Arg(0);
00160 HexState state(m_game.Board(), m_game.Board().WhoseTurn());
00161 std::ofstream f(filename.c_str());
00162 if (!f)
00163 throw HtpFailure() << "Could not open file for output.";
00164 BookUtil::DumpVisualizationData(*m_book, state, 0, f);
00165 f.close();
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 void BookCommands::CmdBookDumpPolarizedLeafs(HtpCommand& cmd)
00175 {
00176 if (m_book.get() == 0)
00177 throw HtpFailure() << "No open book.";
00178 cmd.CheckNuArgLessEqual(3);
00179 float polarization = cmd.FloatArg(0);
00180 std::string filename = cmd.Arg(1);
00181 StateSet ignoreSet;
00182 if (cmd.NuArg() == 3u)
00183 {
00184 std::string ignoreFile = cmd.Arg(2);
00185 HexState state(m_game.Board(), m_game.Board().WhoseTurn());
00186 std::ifstream ifs(ignoreFile.c_str());
00187 if (!ifs)
00188 throw HtpFailure() << "Could not open ignore file for reading.";
00189 std::string line;
00190 while (std::getline(ifs, line))
00191 {
00192 PointSequence seq;
00193 HexPointUtil::FromString(line, seq);
00194 if (!seq.empty())
00195 {
00196 state.Position().StartNewGame();
00197 state.SetToPlay(FIRST_TO_PLAY);
00198 for (std::size_t i = 0; i < seq.size(); ++i)
00199 state.PlayMove(seq[i]);
00200 ignoreSet.Insert(state);
00201 }
00202 }
00203 LogInfo() << "Read " << ignoreSet.Size() << " positions to ignore.\n";
00204 }
00205 HexState state(m_game.Board(), m_game.Board().WhoseTurn());
00206 PointSequence pv;
00207 GameUtil::HistoryToSequence(m_game.History(), pv);
00208 std::ofstream f(filename.c_str());
00209 if (!f)
00210 throw HtpFailure() << "Could not open file for output.";
00211 BookUtil::DumpPolarizedLeafs(*m_book, state, polarization, pv, f,
00212 ignoreSet);
00213 f.close();
00214 }
00215
00216
00217 void BookCommands::CmdBookImportSolvedStates(HtpCommand& cmd)
00218 {
00219 if (m_book.get() == 0)
00220 throw HtpFailure() << "No open book.";
00221 cmd.CheckNuArg(1);
00222 std::string filename = cmd.Arg(0);
00223 std::ifstream f(filename.c_str());
00224 if (!f)
00225 throw HtpFailure() << "Could not open file for reading.";
00226 BookUtil::ImportSolvedStates(*m_book, m_game.Board().Const(), f);
00227 f.close();
00228 }
00229
00230
00231
00232
00233
00234
00235 void BookCommands::CmdBookSetValue(HtpCommand& cmd)
00236 {
00237 if (m_book.get() == 0)
00238 throw HtpFailure() << "No open book.";
00239 float value = 0.5;
00240 std::string vstr = cmd.ArgToLower(0);
00241 if (vstr == "w")
00242 value = IMMEDIATE_WIN;
00243 else if (vstr == "l")
00244 value = IMMEDIATE_LOSS;
00245 else
00246 value = cmd.FloatArg(0);
00247 HexBookNode node;
00248 HexState state(m_game.Board(), m_game.Board().WhoseTurn());
00249 if (!m_book->Get(state, node))
00250 m_book->Put(state, HexBookNode(value));
00251 else
00252 {
00253 node.m_value = value;
00254 m_book->Put(state, node);
00255 }
00256 m_book->Flush();
00257 }
00258
00259 void BookCommands::CmdBookParam(HtpCommand& cmd)
00260 {
00261 if (cmd.NuArg() == 0)
00262 {
00263 cmd << '\n'
00264 << "[string] book_count_weight "
00265 << m_bookCheck.CountWeight() << '\n'
00266 << "[string] book_min_count "
00267 << m_bookCheck.MinCount() << '\n';
00268 }
00269 else if (cmd.NuArg() == 2)
00270 {
00271 std::string name = cmd.Arg(0);
00272 if (name == "book_min_count")
00273 m_bookCheck.SetMinCount(cmd.SizeTypeArg(1, 0));
00274 else if (name == "book_count_weight")
00275 m_bookCheck.SetCountWeight(cmd.FloatArg(1));
00276 else
00277 throw HtpFailure() << "Unknown parameter: " << name;
00278 }
00279 else
00280 throw HtpFailure("Expected 0 ore 2 arguments");
00281 }
00282
00283