説明を見る。00001 #include "osl/record/csaRecord.h"
00002 #include "osl/simpleState.h"
00003 #include "osl/oslConfig.h"
00004 #include <boost/algorithm/string/classification.hpp>
00005 #include <boost/algorithm/string/split.hpp>
00006 #include <boost/algorithm/string/trim.hpp>
00007 #include <iostream>
00008 #include <fstream>
00009 #include <stdexcept>
00010 #include <cassert>
00011 #include <string>
00012 #include <sstream>
00013
00014
00015
00016 osl::record::SearchInfo
00017 osl::record::CsaFile::makeInfo(const SimpleState& initial,
00018 const std::string& line,
00019 Move last_move)
00020 {
00021 std::istringstream is(line);
00022 SearchInfo info;
00023 is >> info.value;
00024
00025 NumEffectState state(initial);
00026 std::string s;
00027 while (is >> s)
00028 {
00029 if (s == csa::show(last_move))
00030 continue;
00031 last_move = Move::INVALID();
00032 try
00033 {
00034 const Move move = ((s == "%PASS" || s == "<PASS>")
00035 ? Move::PASS(state.turn())
00036 : csa::strToMove(s, state));
00037 if (move.isPass()
00038 || (move.isNormal() && state.isValidMove(move,false)))
00039 {
00040 state.makeMove(move);
00041 if (! state.inCheck(alt(state.turn()))) {
00042 info.moves.push_back(move);
00043 continue;
00044 }
00045
00046 }
00047 }
00048 catch(CsaIOError& e)
00049 {
00050
00051 }
00052 std::cerr << "drop illegal move in comment " << s << std::endl;
00053 break;
00054 }
00055 return info;
00056 }
00057
00058 void osl::record::
00059 CsaFile::parseLine(SimpleState& state, Record& record, std::string s,
00060 bool parse_move_comment)
00061 {
00062 switch(s.at(0)){
00063 case '\'':
00064 if (s.substr(1,2) == "* ")
00065 {
00066 record.setMoveComment(s.substr(3));
00067 }
00068 else if (s.substr(1,2) == "**" && parse_move_comment)
00069 {
00070 record.setMoveInfo(makeInfo(state, s.substr(3), record.lastMove()));
00071 }
00072 return;
00073 case '$':
00074 if (s.find("$START_TIME:") == 0) {
00075 const std::string YYMMDD = s.substr(12,10);
00076 #if 0
00077 std::vector<std::string> e;
00078 boost::algorithm::split(e, YYMMDD, boost::algorithm::is_any_of("/"));
00079 if (e.size() < 3)
00080 throw CsaIOError("csa date fail "+YYMMDD);
00081 start_date = boost::gregorian::date(stoi(e[0]), stoi(e[1]), stoi(e[2]));
00082 assert(!start_date.is_special());
00083 #endif
00084 record.setDate(YYMMDD);
00085 return;
00086 }
00087 Record::addWithNewLine(record.initial_comment, s.substr(1));
00088 return;
00089 case 'V':
00090 record.version = s.substr(1);
00091 return;
00092 case 'N':
00093 switch(s.at(1)){
00094 case '+':
00095 case '-':
00096 record.player[csa::charToPlayer(s.at(1))] = s.substr(2);
00097 break;
00098 default:
00099 std::cerr << "Illegal csa line " << s << std::endl;
00100 throw CsaIOError("illegal csa line "+s);
00101 }
00102 break;
00103 case 'T':
00104 {
00105 record.setMoveTime(atoi(s.c_str()+1));
00106 return;
00107 }
00108 case '%':
00109 if (s.find("%TORYO") == 0 || s.find("%ILLEGAL_MOVE") == 0)
00110 record.result = ((state.turn() == BLACK)
00111 ? Record::WhiteWin : Record::BlackWin);
00112 else if (s.find("%SENNICHITE") == 0)
00113 record.result = Record::Sennnichite;
00114 else if (s.find("%KACHI") == 0)
00115 record.result = ((state.turn() == BLACK)
00116 ? Record::BlackWin : Record::WhiteWin);
00117 else if (s.find("%JISHOGI") == 0 || s.find("%HIKIWAKE") == 0)
00118 record.result = Record::JiShogi;
00119 else if (s.find("%+ILLEGAL_ACTION") == 0)
00120 record.result = Record::WhiteWin;
00121 else if (s.find("%-ILLEGAL_ACTION") == 0)
00122 record.result = Record::BlackWin;
00123 return;
00124 default:
00125 throw CsaIOError("unknown character in csaParseLine "+s);
00126 }
00127 }
00128
00129 osl::record::
00130 CsaFile::CsaFile(const std::string& filename)
00131 {
00132 std::ifstream ifs(filename);
00133 if (! ifs) {
00134 const std::string msg = "CsaFile::CsaFile file cannot read ";
00135 std::cerr << msg << filename << "\n";
00136 throw CsaIOError(msg + filename);
00137 }
00138 read(ifs);
00139 }
00140
00141 osl::record::
00142 CsaFile::CsaFile(std::istream& is)
00143 {
00144 read(is);
00145 }
00146
00147 osl::record::
00148 CsaFile::~CsaFile()
00149 {
00150 }
00151
00152 void osl::record::CsaFile::
00153 read(std::istream& is)
00154 {
00155 SimpleState work;
00156 work.init();
00157 std::string line;
00158 CArray<bool, 9> board_parsed = {{ false }};
00159 while (std::getline(is, line))
00160 {
00161
00162 if ((! line.empty())
00163 && (line[line.size()-1] == 13))
00164 line.erase(line.size()-1);
00165
00166 std::vector<std::string> elements;
00167 boost::algorithm::split(elements, line, boost::algorithm::is_any_of(","));
00168 for (auto& e: elements) {
00169 boost::algorithm::trim(e);
00170 boost::algorithm::trim_left(e);
00171 if (! CsaFileMinimal::parseLine(work, record.record, e, board_parsed))
00172 parseLine(work, record, e, !OslConfig::inUnitTest());
00173 }
00174 }
00175 if (*std::min_element(board_parsed.begin(), board_parsed.end()) == false)
00176 throw CsaIOError("incomplete position description in csaParseLine");
00177 assert(record.record.initial_state.isConsistent());
00178 }
00179
00180
00181
00182
00183
00184