00001 #include "osl/container/moveVector.h"
00002 #include "osl/oslConfig.h"
00003 #include "osl/game_playing/weightTracer.h"
00004 #include "osl/record/csaRecord.h"
00005 #include "osl/record/checkDuplicate.h"
00006 #include "osl/record/opening/openingBook.h"
00007
00008 #include <boost/algorithm/string/trim.hpp>
00009 #include <boost/foreach.hpp>
00010 #include <boost/format.hpp>
00011 #include <boost/multi_array.hpp>
00012 #include <boost/program_options.hpp>
00013 #include <fstream>
00014 #include <iostream>
00015 #include <vector>
00016
00017 using namespace osl;
00018
00019 enum GameResult
00020 {
00021 BLACK_WIN = 0,
00022 WHITE_WIN,
00023 OTHERS
00024 };
00025
00026 struct WinLoss
00027 {
00028 unsigned int wins;
00029 unsigned int losses;
00030
00031 WinLoss()
00032 : wins(0), losses(0)
00033 {}
00034
00035 double getRate() const
00036 {
00037 if (isEmpty())
00038 return 0.0;
00039
00040 return 1.0*wins/(wins+losses);
00041 }
00042
00043 bool isEmpty() const
00044 {
00045 return (wins + losses) == 0;
00046 }
00047 };
00048
00049 std::ostream& operator<<(std::ostream& out, const WinLoss& wl)
00050 {
00051 out << boost::format("%5.3f (#wins=%6d, #losses=%6d)")
00052 % wl.getRate() % wl.wins % wl.losses;
00053 return out;
00054 }
00055
00056 struct Result
00057 {
00058 enum {MAX_LEVEL = 99,
00059 MAX_DEPTH = 999};
00061 typedef boost::multi_array<unsigned int, 3> array_t;
00062 array_t winloss;
00063 unsigned int top_level;
00064 unsigned int top_depth;
00065
00066 Result()
00067 : winloss(boost::extents[MAX_DEPTH][MAX_LEVEL][2]),
00068 top_level(0), top_depth(0)
00069 {}
00070
00071 void add(const unsigned int depth,
00072 const unsigned int level,
00073 const bool win)
00074 {
00075 assert(depth < MAX_DEPTH);
00076 assert(level < MAX_LEVEL);
00077 if (win)
00078 winloss[depth][level][0] += 1;
00079 else
00080 winloss[depth][level][1] += 1;
00081
00082 top_level = std::max(top_level, level);
00083 top_depth = std::max(top_depth, depth);
00084 }
00085
00086 bool printAtDepth(std::ostream& out, const unsigned int depth) const;
00087 void printByLevel(std::ostream& out) const;
00088 void printByDepth(std::ostream& out) const;
00089 void showLevels(std::ostream& out,
00090 std::vector<WinLoss>& vector) const;
00091 };
00092
00093 void Result::showLevels(std::ostream& out,
00094 std::vector<WinLoss>& vector) const
00095 {
00096
00097 std::vector<WinLoss>::reverse_iterator empty = vector.rbegin();
00098 for (; empty != vector.rend(); ++empty) {
00099 if (!empty->isEmpty())
00100 break;
00101 }
00102 vector.erase(empty.base(), vector.end());
00103
00104 unsigned int level = 1;
00105 BOOST_FOREACH(const WinLoss& wl, vector) {
00106 out << boost::format("%2d: %s\n") % level++ % wl;
00107 }
00108 }
00109
00110 bool Result::printAtDepth(std::ostream& out,
00111 const unsigned int depth) const
00112 {
00113 std::vector<WinLoss> vector;
00114 for(unsigned int level=0; level < MAX_LEVEL; ++level) {
00115 WinLoss wl;
00116 wl.wins += winloss[depth][level][0];
00117 wl.losses += winloss[depth][level][1];
00118 vector.push_back(wl);
00119 }
00120
00121 showLevels(out, vector);
00122 return vector.empty();
00123 }
00124
00125 void Result::printByDepth(std::ostream& out) const
00126 {
00127 for (unsigned int depth=1; depth < top_depth; ++depth) {
00128 out << boost::format("\n>> Depth %2d\n") % depth;
00129 printAtDepth(out, depth);
00130 }
00131 }
00132
00133 void Result::printByLevel(std::ostream& out) const
00134 {
00135 std::vector<WinLoss> vector;
00136 for(unsigned int level=0; level < MAX_LEVEL; ++level) {
00137 WinLoss wl;
00138 for (unsigned int depth=0; depth < MAX_DEPTH; ++depth) {
00139 wl.wins += winloss[depth][level][0];
00140 wl.losses += winloss[depth][level][1];
00141 }
00142 vector.push_back(wl);
00143 }
00144
00145 showLevels(out, vector);
00146 }
00147
00148
00149
00150
00151 static Result result;
00152 osl::record::opening::WeightedBook book(osl::OslConfig::openingBook());
00153
00154
00155
00156
00157
00158
00159 GameResult getGameResult(const std::string& csa_file,
00160 const vector<Move>& moves)
00161 {
00162 std::ifstream in(csa_file.c_str());
00163 if (!in)
00164 {
00165 std::cerr << "File not found: " << csa_file << "\n";
00166 exit(-1);
00167 }
00168
00169 bool hit = false;
00170 std::string line;
00171 while (std::getline(in, line))
00172 {
00173 if (line.find("%TORYO") != std::string::npos)
00174 {
00175 hit = true;
00176 break;
00177 }
00178 }
00179
00180 if (hit)
00181 {
00182 return (moves.size() % 2 == 1 ? BLACK_WIN : WHITE_WIN);
00183 }
00184 else
00185 {
00186 return OTHERS;
00187 }
00188 }
00189
00190
00191 void increment(const vector<Move>& moves,
00192 const Player player,
00193 const bool win)
00194 {
00195 int stateIndex = book.getStartState();
00196 Player turn = BLACK;
00197 unsigned int depth = 1;
00198
00199 BOOST_FOREACH(const Move& move, moves) {
00200 osl::record::opening::WeightedBook::WMoveContainer wmoves =
00201 book.getMoves(stateIndex, (player == turn ? false : true));
00202 std::sort(wmoves.begin(), wmoves.end(),
00203 osl::record::opening::WMoveSort());
00204
00205
00206
00207
00208 osl::record::opening::WeightedBook::WMoveContainer::iterator found =
00209 wmoves.begin();
00210 for (; found != wmoves.end(); ++found) {
00211 if (found->getMove() == move)
00212 break;
00213 }
00214 if (found == wmoves.end())
00215 return;
00216
00217
00218
00219
00220 if (turn == player) {
00221 const unsigned int level = std::distance(wmoves.begin(), found);
00222 result.add(depth, level, win);
00223 }
00224
00225
00226
00227
00228 turn = alt(turn);
00229 depth += 1;
00230 stateIndex = found->getStateIndex();
00231 }
00232 }
00233
00234
00235 void readFile(const std::string& player_name,
00236 const std::string& csa_file,
00237 osl::record::CheckDuplicate& duplicates)
00238 {
00239 const osl::record::csa::CsaFile csa(csa_file);
00240 const osl::record::Record& record = csa.getRecord();
00241 const vector<Move> moves = record.getMoves();
00242
00243 const GameResult gr = getGameResult(csa_file, moves);
00244 if (gr == OTHERS)
00245 return;
00246
00247 if (duplicates.regist(moves))
00248 return;
00249
00250 const std::string& black = record.getPlayer(BLACK);
00251 const std::string& white = record.getPlayer(WHITE);
00252
00253 Player player = BLACK;
00254 bool win = true;
00255 if (black.find(player_name) != std::string::npos) {
00256 player = BLACK;
00257 win = (gr == BLACK_WIN);
00258 }
00259 else if (white.find(player_name) != std::string::npos) {
00260 player = WHITE;
00261 win = (gr == WHITE_WIN);
00262 }
00263 else {
00264 std::cerr << "Ignore this play: " << csa_file << "\n";
00265 return;
00266 }
00267
00268 increment(moves, player, win);
00269 }
00270
00271
00272 int main(int argc, char **argv)
00273 {
00274 std::string player_name;
00275
00276 boost::program_options::options_description command_line_options;
00277 command_line_options.add_options()
00278 ("input-file", boost::program_options::value<std::vector<std::string> >(),
00279 "input files in the CSA format")
00280 ("player", boost::program_options::value<std::string>(&player_name)->default_value("gps"),
00281 "input files in the CSA format")
00282 ("help", "Show help message");
00283 boost::program_options::variables_map vm;
00284 boost::program_options::positional_options_description p;
00285 p.add("input-file", -1);
00286
00287 try
00288 {
00289 boost::program_options::store(
00290 boost::program_options::command_line_parser(
00291 argc, argv).options(command_line_options).positional(p).run(), vm);
00292 boost::program_options::notify(vm);
00293 if (vm.count("help"))
00294 {
00295 std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
00296 std::cerr << " " << argv[0] << " [options]\n";
00297 std::cout << command_line_options << std::endl;
00298 return 0;
00299 }
00300 }
00301 catch (std::exception &e)
00302 {
00303 std::cerr << "error in parsing options" << std::endl
00304 << e.what() << std::endl;
00305 std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
00306 std::cerr << " " << argv[0] << " [options]\n";
00307 std::cerr << command_line_options << std::endl;
00308 return 1;
00309 }
00310
00311 std::vector<std::string> files;
00312 if (vm.count("input-file"))
00313 {
00314 const std::vector<std::string> temp = vm["input-file"].as<std::vector<std::string> >();
00315 files.insert(files.end(), temp.begin(), temp.end());
00316 }
00317 else
00318 {
00319 std::string line;
00320 while(std::getline(std::cin , line))
00321 {
00322 boost::algorithm::trim(line);
00323 files.push_back(line);
00324 }
00325 }
00326
00327 osl::record::CheckDuplicate check_duplicate;
00328
00329 BOOST_FOREACH(const std::string& file, files)
00330 {
00331 readFile(player_name, file, check_duplicate);
00332 }
00333
00334 result.printByLevel(std::cout);
00335 result.printByDepth(std::cout);
00336
00337 std::locale::global(std::locale(""));
00338 check_duplicate.print(std::cout);
00339
00340 return 0;
00341 }
00342
00343
00344
00345
00346