5 #include <boost/algorithm/string/classification.hpp>
6 #include <boost/algorithm/string/split.hpp>
7 #include <boost/algorithm/string/trim.hpp>
8 #include <boost/foreach.hpp>
24 const SearchInfo makeInfo(
const SimpleState& initial,
25 const std::string& line,
28 std::istringstream is(line);
32 NumEffectState state(initial);
41 const Move move = ((s ==
"%PASS" || s ==
"<PASS>")
45 || (move.isNormal() && state.isValidMove(move,
false)))
48 if (! state.inCheck(
alt(state.turn()))) {
49 info.moves.push_back(move);
59 std::cerr <<
"drop illegal move in comment " << s << std::endl;
64 void csaParseLine(boost::shared_ptr<RecordVisitor>& rv, std::string s,
65 CArray<bool,9>& board_parsed,
66 bool parse_move_comment=
true)
68 Record *rec=rv->getRecord();
69 SimpleState* state=rv->getState();
70 while (! s.empty() && isspace(s[s.size()-1]))
76 if (s.substr(1,2) ==
"* ")
78 MoveRecord *mr = rv->getLastMove();
80 mr->addComment(s.substr(3));
82 else if (s.substr(1,2) ==
"**" && parse_move_comment)
84 MoveRecord *mr = rv->getLastMove();
86 mr->info = makeInfo(*state, s.substr(3), mr->getMove());
90 if (s.find(
"$START_TIME:") == 0) {
91 const std::string YYMMDD = s.substr(12,10);
95 rec->addInitialComment(s.substr(1));
98 rec->setVersion(s.substr(1));
107 std::cerr <<
"Illegal csa line " << s << std::endl;
108 throw CsaIOError(
"illegal csa line "+s);
114 board_parsed.fill(
true);
120 for(
int i=2;i<=(int)s.length()-4;i+=4){
122 if(s.substr(i+2,2) ==
"AL"){
123 state->setPieceAll(pl);
127 state->setPiece(pl,pos,ptype);
133 if(isdigit(s.at(1))){
134 const int y=s.at(1)-
'0';
135 board_parsed[y-1] =
true;
136 for(
unsigned int x=9,i=2;i<s.length();i+=3,x--){
137 if (s.at(i) !=
'+' && s.at(i) !=
'-' && s.find(
" *",i)!=i) {
139 throw CsaIOError(
"parse board error " + s);
141 std::cerr <<
"possible typo for empty square " << s <<
"\n";
143 if (s.at(i) !=
'+' && s.at(i) !=
'-')
continue;
147 state->setPiece(pl,pos,ptype);
157 rec->setInitialState(*state);
158 state->initPawnMask();
162 if (! state->isValidMove(m))
164 std::cerr <<
"Illegal move " << m << std::endl;
165 throw CsaIOError(
"illegal move "+s);
167 rv->addMoveAndAdvance(m);
174 MoveRecord *mr = rv->getLastMove();
176 mr->setTime(atoi(s.c_str()+1));
180 if (s.find(
"%TORYO") == 0 || s.find(
"%ILLEGAL_MOVE") == 0)
181 rec->setResult((state->turn() ==
BLACK)
183 else if (s.find(
"%SENNICHITE") == 0)
185 else if (s.find(
"%KACHI") == 0)
186 rec->setResult((state->turn() ==
BLACK)
188 else if (s.find(
"%JISHOGI") == 0 || s.find(
"%HIKIWAKE") == 0)
190 else if (s.find(
"%+ILLEGAL_ACTION") == 0)
191 rec->setResult(Record::WHITE_WIN);
192 else if (s.find(
"%-ILLEGAL_ACTION") == 0)
193 rec->setResult(Record::BLACK_WIN);
196 throw CsaIOError(
"unknown character in csaParseLine "+s);
210 std::cerr <<
"InputStream::InputStream cannot read \n";
221 std::cerr <<
"InputStream::InputStream cannot read \n";
234 rv->setState(&state);
237 CArray<bool, 9> board_parsed = {{
false }};
238 while (std::getline(is, line))
242 && (line[line.size()-1] == 13))
243 line.erase(line.size()-1);
245 std::vector<std::string> elements;
246 boost::algorithm::split(elements, line, boost::algorithm::is_any_of(
","));
247 BOOST_FOREACH(std::string e, elements) {
248 boost::algorithm::trim(e);
249 boost::algorithm::trim_left(e);
253 if (*std::min_element(board_parsed.begin(), board_parsed.end()) ==
false)
254 throw CsaIOError(
"incomplete position description in csaParseLine");
255 assert(state.isConsistent());
261 std::ifstream ifs(fileName.c_str());
264 const std::string msg =
"CsaFile::CsaFile file cannot read ";
265 std::cerr << msg << fileName <<
"\n";
286 return NumEffectState(rec.getInitialState());