Go to the documentation of this file.00001 #include "osl/record/csaRecord.h"
00002 #include "osl/record/csaIOError.h"
00003 #include "osl/state/simpleState.h"
00004 #include "osl/oslConfig.h"
00005 #include <iostream>
00006 #include <fstream>
00007 #include <stdexcept>
00008 #include <cassert>
00009 #include <string>
00010 #include <sstream>
00011
00012
00013
00014 namespace osl
00015 {
00016 namespace record
00017 {
00018 namespace
00019 {
00020 const SearchInfo makeInfo(const SimpleState& initial,
00021 const std::string& line,
00022 Move last_move)
00023 {
00024 std::istringstream is(line);
00025 SearchInfo info;
00026 is >> info.value;
00027
00028 NumEffectState state(initial);
00029 std::string s;
00030 while (is >> s)
00031 {
00032 if (s == csa::show(last_move))
00033 continue;
00034 last_move = Move::INVALID();
00035 try
00036 {
00037 const Move move = ((s == "%PASS" || s == "<PASS>")
00038 ? Move::PASS(state.turn())
00039 : csa::strToMove(s, state));
00040 if (move.isPass() || (move.isNormal() && state.isValidMove(move,false)))
00041 {
00042 info.moves.push_back(move);
00043 state.makeMove(move);
00044 continue;
00045 }
00046 }
00047 catch(CsaIOError& e)
00048 {
00049
00050 }
00051 std::cerr << "drop illegal move in comment " << s << std::endl;
00052 break;
00053 }
00054 return info;
00055 }
00056 void csaParseLine(boost::shared_ptr<RecordVisitor>& rv, std::string s,
00057 CArray<bool,9>& line_parsed,
00058 bool parse_move_comment=true)
00059 {
00060 Record *rec=rv->getRecord();
00061 SimpleState* state=rv->getState();
00062 while (! s.empty() && isspace(s[s.size()-1]))
00063 s.resize(s.size()-1);
00064 if (s.length()==0)
00065 return;
00066 switch(s.at(0)){
00067 case '\'':
00068 if (s.substr(1,2) == "* ")
00069 rv->getLastMove()->addComment(s.substr(3));
00070 else if (s.substr(1,2) == "**" && parse_move_comment)
00071 {
00072 MoveRecord *mr = rv->getLastMove();
00073 rv->getLastMove()->info = makeInfo(*state, s.substr(3), mr ? mr->getMove() : Move::INVALID());
00074 }
00075 return;
00076 case '$':
00077 if (s.find("$START_TIME:") == 0) {
00078 const std::string YYMMDD = s.substr(12,10);
00079 rec->setDate(YYMMDD);
00080 return;
00081 }
00082 rec->addInitialComment(s.substr(1));
00083 return;
00084 case 'V':
00085 rec->setVersion(s.substr(1));
00086 return;
00087 case 'N':
00088 switch(s.at(1)){
00089 case '+':
00090 case '-':
00091 rec->setPlayer(csa::charToPlayer(s.at(1)),s.substr(2));
00092 break;
00093 default:
00094 std::cerr << "Illegal csa line " << s << std::endl;
00095 throw CsaIOError("illegal csa line "+s);
00096 }
00097 break;
00098 case 'P':
00099 switch(s.at(1)){
00100 case 'I':
00101 line_parsed.fill(true);
00102 state->init(HIRATE);
00103 break;
00104 case '+':
00105 case '-':{
00106 Player pl=csa::charToPlayer(s.at(1));
00107 for(int i=2;i<=(int)s.length()-4;i+=4){
00108 Square pos=csa::strToPos(s.substr(i,2));
00109 if(s.substr(i+2,2) == "AL"){
00110 state->setPieceAll(pl);
00111 }
00112 else{
00113 Ptype ptype=csa::strToPtype(s.substr(i+2,2));
00114 state->setPiece(pl,pos,ptype);
00115 }
00116 }
00117 break;
00118 }
00119 default:
00120 if(isdigit(s.at(1))){
00121 const int y=s.at(1)-'0';
00122 line_parsed[y-1] = true;
00123 for(unsigned int x=9,i=2;i<s.length();i+=3,x--){
00124 if(s.at(i)==' ') continue;
00125 Player pl=csa::charToPlayer(s.at(i));
00126 Square pos(x,y);
00127 Ptype ptype=csa::strToPtype(s.substr(i+1,2));
00128 state->setPiece(pl,pos,ptype);
00129 }
00130 }
00131 }
00132 break;
00133 case '+':
00134 case '-':{
00135 Player pl=csa::charToPlayer(s.at(0));
00136 if(s.length()==1){
00137 state->setTurn(pl);
00138 rec->setInitialState(*state);
00139 state->initPawnMask();
00140 }
00141 else{
00142 const Move m = csa::strToMove(s,*state);
00143 if (! state->isValidMove(m))
00144 {
00145 std::cerr << "Illegal move " << m << std::endl;
00146 throw CsaIOError("illegal move "+s);
00147 }
00148 rv->addMoveAndAdvance(m);
00149 return;
00150 }
00151 break;
00152 }
00153 case 'T':
00154 (rv->getLastMove())->setTime(atoi(s.c_str()+1));
00155 return;
00156 case '%':
00157 if (s.find("%TORYO") == 0 || s.find("%ILLEGAL_MOVE") == 0)
00158 rec->setResult((state->turn() == BLACK)
00159 ? Record::WHITE_WIN : Record::BLACK_WIN);
00160 else if (s.find("%SENNICHITE") == 0)
00161 rec->setResult(Record::SENNNICHITE);
00162 else if (s.find("%KACHI") == 0)
00163 rec->setResult((state->turn() == BLACK)
00164 ? Record::BLACK_WIN : Record::WHITE_WIN);
00165 else if (s.find("%JISHOGI") == 0 || s.find("%HIKIWAKE") == 0)
00166 rec->setResult(Record::JISHOGI);
00167 else if (s.find("%+ILLEGAL_ACTION") == 0)
00168 rec->setResult(Record::WHITE_WIN);
00169 else if (s.find("%-ILLEGAL_ACTION") == 0)
00170 rec->setResult(Record::BLACK_WIN);
00171 return;
00172 default:
00173 throw CsaIOError("unknown character in csaParseLine "+s);
00174 }
00175 }
00176 }
00177 }
00178 }
00179
00180 osl::record::csa::
00181 InputStream::InputStream(std::istream& is)
00182 : is(is),
00183 rv(boost::shared_ptr<record::RecordVisitor>(new record::RecordVisitor()))
00184 {
00185 if (! is)
00186 {
00187 std::cerr << "InputStream::InputStream cannot read \n";
00188 abort();
00189 }
00190 }
00191
00192 osl::record::csa::
00193 InputStream::InputStream(std::istream& is, boost::shared_ptr<record::RecordVisitor> rv)
00194 : is(is), rv(rv)
00195 {
00196 if (! is)
00197 {
00198 std::cerr << "InputStream::InputStream cannot read \n";
00199 abort();
00200 }
00201 }
00202
00203 osl::record::csa::
00204 InputStream::~InputStream(){}
00205
00206 void osl::record::csa::
00207 InputStream::load(Record* rec)
00208 {
00209
00210 state.init();
00211 rv->setState(&state);
00212 rv->setRecord(rec);
00213 std::string line;
00214 CArray<bool, 9> line_parsed = {{ false }};
00215 while (std::getline(is, line))
00216 {
00217
00218 if ((! line.empty())
00219 && (line[line.size()-1] == 13))
00220 line.erase(line.size()-1);
00221 csaParseLine(rv, line, line_parsed, !OslConfig::inUnitTest());
00222 }
00223 if (*std::min_element(line_parsed.begin(), line_parsed.end()) == false)
00224 throw CsaIOError("incomplete position description in csaParseLine");
00225 assert(state.isConsistent());
00226 }
00227
00228 osl::record::csa::
00229 CsaFile::CsaFile(const std::string& fileName)
00230 {
00231 std::ifstream ifs(fileName.c_str());
00232 if (! ifs)
00233 {
00234 const std::string msg = "CsaFile::CsaFile file cannot read ";
00235 std::cerr << msg << fileName << "\n";
00236 throw CsaIOError(msg + fileName);
00237 }
00238 InputStream irs(ifs);
00239 irs.load(&rec);
00240 }
00241
00242 osl::record::csa::
00243 CsaFile::~CsaFile()
00244 {
00245 }
00246
00247 const osl::record::Record& osl::record::csa::
00248 CsaFile::getRecord() const
00249 {
00250 return rec;
00251 }
00252
00253 const osl::NumEffectState osl::record::csa::
00254 CsaFile::getInitialState() const
00255 {
00256 return NumEffectState(rec.getInitialState());
00257 }
00258
00259
00260
00261
00262
00263