checkmate-kisen.cc
Go to the documentation of this file.
00001 #include "osl/container/moveVector.h"
00002 #include "osl/hash/hashKey.h"
00003 #include "osl/state/numEffectState.h"
00004 #include "osl/state/historyState.h"
00005 #include "osl/record/kisen.h"
00006 #include "osl/record/csaRecord.h"
00007 #include "osl/checkmate/dualDfpn.h"
00008 #include "osl/eval/see.h"
00009 #include "osl/misc/filePath.h"
00010 
00011 #include <boost/accumulators/accumulators.hpp>
00012 #include <boost/accumulators/statistics/mean.hpp>
00013 #include <boost/accumulators/statistics/max.hpp>
00014 #include <boost/scoped_ptr.hpp>
00015 #include <boost/program_options.hpp>
00016 #include <boost/filesystem/convenience.hpp>
00017 #include <boost/foreach.hpp>
00018 #include <boost/format.hpp>
00019 #include <iostream>
00020 #include <fstream>
00021 
00022 static void 
00023 convert_from_first(const osl::NumEffectState& initial,
00024                    const osl::vector<osl::Move> &in,
00025                    osl::vector<osl::Move> &out, size_t checkmate_limit)
00026 {
00027   osl::DualDfpn dfpn;
00028   osl::NumEffectState state(initial);
00029   BOOST_FOREACH(osl::Move move, in) 
00030   {
00031     const int see = osl::See::see
00032       (state, move, state.pin(state.turn()), state.pin(alt(state.turn())));
00033     out.push_back(move);
00034     state.makeMove(move);
00035     if (state.inCheck() && see < 0
00036         && dfpn.isLosingState(checkmate_limit, state, 
00037                               osl::HashKey(state), osl::PathEncoding(state.turn())))
00038       break;
00039   }
00040 }
00041 
00042 static void 
00043 trim_last(const osl::NumEffectState& initial,
00044           const osl::vector<osl::Move> &in,
00045           osl::vector<osl::Move> &out, size_t checkmate_limit)
00046 {
00047   if (in.empty())
00048     return;
00049   osl::DualDfpn dfpn;
00050   osl::HistoryState history(initial);
00051   BOOST_FOREACH(osl::Move move, in) 
00052     history.makeMove(move);
00053   const osl::Player last_played = in.back().player();
00054   int length = in.size();
00055   for (; length > 0; length -= 2)
00056   {
00057     osl::NumEffectState current = history.state();
00058     assert(current.turn() == alt(last_played));
00059     if (! current.inCheck())
00060       break;
00061     if (! dfpn.isLosingState(checkmate_limit, current, 
00062                              osl::HashKey(current), osl::PathEncoding(last_played)))
00063       break;
00064     history.unmakeMove();
00065     history.unmakeMove();
00066   }
00067   out = in;
00068   out.resize(length);
00069 }
00070 
00071 static void convert(const std::vector<std::string> &input_filename,
00072                     const std::string &output_kisen_filename,
00073                     size_t checkmate_limit, bool output_ipx, bool trim)
00074 {
00075   namespace acc = boost::accumulators;
00076   acc::accumulator_set<double, acc::features<acc::tag::max, acc::tag::mean> > accumulator;
00077   std::ofstream ofs(output_kisen_filename.c_str());
00078   osl::record::OKisenStream ks(ofs);
00079 
00080   boost::scoped_ptr<osl::record::KisenIpxWriter> ipx_writer;
00081   boost::scoped_ptr<std::ofstream> ipx_ofs;
00082   if (output_ipx)
00083   {
00084     const boost::filesystem::path ipx_path =
00085       boost::filesystem::change_extension(boost::filesystem::path(output_kisen_filename), ".ipx");
00086     const std::string ipx = osl::misc::file_string(ipx_path);
00087     ipx_ofs.reset(new std::ofstream(ipx.c_str()));
00088     ipx_writer.reset(new osl::record::KisenIpxWriter(*ipx_ofs));
00089   }
00090 
00091   for (size_t i = 0; i < input_filename.size(); ++i)
00092   {
00093     osl::KisenFile kisen(input_filename[i]);
00094     osl::KisenIpxFile ipx(kisen.ipxFileName());
00095     for (size_t j=0; j<kisen.size(); ++j) 
00096     {
00097       osl::NumEffectState state = kisen.getInitialState();
00098       osl::vector<osl::Move> moves = kisen.getMoves(j);
00099       osl::vector<osl::Move> new_moves;
00100       if (trim)
00101         trim_last(state, moves, new_moves, checkmate_limit);
00102       else
00103         convert_from_first(state, moves, new_moves, checkmate_limit);
00104 
00105       osl::record::Record new_record;
00106       new_record.setPlayer(osl::BLACK, ipx.getPlayer(j, osl::BLACK));
00107       new_record.setPlayer(osl::WHITE, ipx.getPlayer(j, osl::WHITE));
00108       new_record.setDate(ipx.getStartDate(j));
00109       osl::SimpleState record_state = state;
00110       osl::record::RecordVisitor visitor;
00111       visitor.setState(&record_state);
00112       visitor.setRecord(&new_record);
00113       for (size_t k=0; k<new_moves.size(); ++k) 
00114       {
00115         visitor.addMoveAndAdvance(new_moves[k]);
00116         state.makeMove(new_moves[k]);
00117       }
00118       new_record.setResult(state.turn() == osl::BLACK
00119                            ? osl::Record::WHITE_WIN : osl::Record::BLACK_WIN);
00120       accumulator(moves.size() - new_moves.size());
00121       if (new_moves.size() >= 256)
00122         std::cerr << "long record " << j << ' ' << new_moves.size() << "\n";
00123       ks.save(&new_record);
00124       if (output_ipx)
00125       {
00126         ipx_writer->save(new_record,
00127                          ipx.getRating(j, osl::BLACK),ipx.getRating(j, osl::WHITE), 
00128                          ipx.getTitle(j, osl::BLACK), ipx.getTitle(j, osl::WHITE));
00129       }
00130       if ((j % 1000) == 999)
00131         std::cerr << input_filename[i] << " " << j
00132                   << " max " << acc::max(accumulator)
00133                   << " mean " << acc::mean(accumulator) << "\n";
00134     }
00135     std::cerr << input_filename[i]
00136               << " max " << acc::max(accumulator)
00137               << " mean " << acc::mean(accumulator) << "\n";
00138   }
00139 }
00140 
00141 int main(int argc, char **argv)
00142 {
00143   bool output_ipx, trim;
00144   std::string kisen_filename;
00145   size_t checkmate_limit;
00146   boost::program_options::options_description command_line_options;
00147   command_line_options.add_options()
00148     ("trim-from-last",
00149      boost::program_options::value<bool>(&trim)->default_value(true),
00150      "trim last checkmate sequence")
00151     ("output-ipx",
00152      boost::program_options::value<bool>(&output_ipx)->default_value(true),
00153      "Whether output IPX file in addition to KIF file")
00154     ("output-kisen-filename,o",
00155      boost::program_options::value<std::string>(&kisen_filename)->
00156      default_value("test.kif"),
00157      "Output filename of Kisen file")
00158     ("checkmate-limit,l",
00159      boost::program_options::value<size_t>(&checkmate_limit)->default_value(1000),
00160      "Whether output IPX file in addition to KIF file")
00161     ("input-file", boost::program_options::value< std::vector<std::string> >(),
00162      "input files in kisen format")
00163     ("help", "Show help message");
00164   boost::program_options::variables_map vm;
00165   boost::program_options::positional_options_description p;
00166   p.add("input-file", -1);
00167 
00168   try
00169   {
00170     boost::program_options::store(
00171       boost::program_options::command_line_parser(
00172         argc, argv).options(command_line_options).positional(p).run(), vm);
00173     boost::program_options::notify(vm);
00174     if (vm.count("help"))
00175     {
00176       std::cerr << "Usage: " << argv[0] << " [options] kisen-files\n";
00177       std::cerr << "       " << argv[0] << " [options]\n";
00178       std::cout << command_line_options << std::endl;
00179       return 0;
00180     }
00181   }
00182   catch (std::exception &e)
00183   {
00184     std::cerr << "error in parsing options" << std::endl
00185               << e.what() << std::endl;
00186     std::cerr << "Usage: " << argv[0] << " [options] kisen-files\n";
00187     std::cerr << "       " << argv[0] << " [options]\n";
00188     std::cerr << command_line_options << std::endl;
00189     return 1;
00190   }
00191 
00192   std::vector<std::string> files;
00193   if (vm.count("input-file"))
00194     files = vm["input-file"].as<std::vector<std::string> >();
00195 
00196   convert(files, kisen_filename, checkmate_limit, output_ipx, trim);
00197   return 0;
00198 }
00199 // ;;; Local Variables:
00200 // ;;; mode:c++
00201 // ;;; c-basic-offset:2
00202 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines