win-rate-openingbook-weight-level.cc
Go to the documentation of this file.
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   // GC
00097   std::vector<WinLoss>::reverse_iterator empty = vector.rbegin();
00098   for (/*none*/; 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 // Global variables
00150 // ==============================================
00151 static Result result;
00152 osl::record::opening::WeightedBook book(osl::OslConfig::openingBook());
00153 
00154 
00155 // ==============================================
00156 // Functions
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      * It ends if a move that is not included in the book is played.
00207      */
00208     osl::record::opening::WeightedBook::WMoveContainer::iterator found =
00209       wmoves.begin();
00210     for (/*none*/; found != wmoves.end(); ++found) {
00211       if (found->getMove() == move) 
00212         break;
00213     } 
00214     if (found == wmoves.end())
00215       return; // finish this record
00216 
00217     /*
00218      * Increment 
00219      */
00220     if (turn == player) {
00221       const unsigned int level = std::distance(wmoves.begin(), found); // 1, 2, ...
00222       result.add(depth, level, win);
00223     }
00224 
00225     /*
00226      * Prepare for the next iteration
00227      */
00228     turn = alt(turn);
00229     depth += 1;
00230     stateIndex = found->getStateIndex();
00231   } // each move
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 /* vim: set ts=2 sw=2 ft=cpp : */
00344 // ;;; Local Variables:
00345 // ;;; mode:c++
00346 // ;;; c-basic-offset:2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines