00001 #include "osl/record/csaRecord.h"
00002 #include "osl/record/csaIOError.h"
00003 #include "osl/state/simpleState.h"
00004 #include "osl/apply_move/applyMove.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 SimpleState 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"
00038 ? Move::PASS(state.getTurn())
00039 : csa::strToMove(s, state));
00040 if (move.isPass() || (move.isNormal() && state.isValidMove(move)))
00041 {
00042 info.moves.push_back(move);
00043 ApplyMoveOfTurn::doMove(state, move);
00044 }
00045 continue;
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 {
00058 Record *rec=rv->getRecord();
00059 SimpleState* state=rv->getState();
00060 while (! s.empty() && isspace(s[s.size()-1]))
00061 s.resize(s.size()-1);
00062 if (s.length()==0)
00063 return;
00064 switch(s.at(0)){
00065 case '\'':
00066 if (s.substr(1,2) == "* ")
00067 rv->getLastMove()->addComment(s.substr(3));
00068 else if (s.substr(1,2) == "**")
00069 {
00070 MoveRecord *mr = rv->getLastMove();
00071 rv->getLastMove()->info = makeInfo(*state, s.substr(3), mr ? mr->getMove() : Move::INVALID());
00072 }
00073 return;
00074 case '$':
00075 rec->addInitialComment(s.substr(1));
00076 return;
00077 case 'V':
00078 rec->setVersion(s.substr(1));
00079 return;
00080 case 'N':
00081 switch(s.at(1)){
00082 case '+':
00083 case '-':
00084 rec->setPlayer(csa::charToPlayer(s.at(1)),s.substr(2));
00085 break;
00086 default:
00087 std::cerr << "Illegal csa line " << s << std::endl;
00088 throw CsaIOError("illegal csa line "+s);
00089 }
00090 break;
00091 case 'P':
00092 switch(s.at(1)){
00093 case 'I':
00094 state->init(HIRATE);
00095 break;
00096 case '+':
00097 case '-':{
00098 Player pl=csa::charToPlayer(s.at(1));
00099 for(int i=2;i<=(int)s.length()-4;i+=4){
00100 Position pos=csa::strToPos(s.substr(i,2));
00101 if(s.substr(i+2,2) == "AL"){
00102 state->setPieceAll(pl);
00103 }
00104 else{
00105 Ptype ptype=csa::strToPtype(s.substr(i+2,2));
00106 state->setPiece(pl,pos,ptype);
00107 }
00108 }
00109 break;
00110 }
00111 default:
00112 if(isdigit(s.at(1))){
00113 int y=s.at(1)-'0';
00114 for(unsigned int x=9,i=2;i<s.length();i+=3,x--){
00115 if(s.at(i)==' ') continue;
00116 Player pl=csa::charToPlayer(s.at(i));
00117 Position pos(x,y);
00118 Ptype ptype=csa::strToPtype(s.substr(i+1,2));
00119 state->setPiece(pl,pos,ptype);
00120 }
00121 }
00122 }
00123 break;
00124 case '+':
00125 case '-':{
00126 Player pl=csa::charToPlayer(s.at(0));
00127 if(s.length()==1){
00128 state->setTurn(pl);
00129 rec->setInitialState(*state);
00130 state->initPawnMask();
00131 }
00132 else{
00133 const Move m = csa::strToMove(s,*state);
00134 if (! state->isValidMove(m))
00135 {
00136 std::cerr << "Illegal move " << m << std::endl;
00137 throw CsaIOError("illegal move "+s);
00138 }
00139 rv->addMoveAndAdvance(m);
00140 return;
00141 }
00142 break;
00143 }
00144 case 'T':
00145 (rv->getLastMove())->setTime(atoi(s.c_str()+1));
00146 return;
00147 case '%':
00148 if (s.find("%TORYO") == 0 || s.find("%ILLEGAL_MOVE") == 0)
00149 rec->setResult((state->getTurn() == BLACK)
00150 ? Record::WHITE_WIN : Record::BLACK_WIN);
00151 else if (s.find("%SENNICHITE") == 0)
00152 rec->setResult(Record::SENNNICHITE);
00153 else if (s.find("%KACHI") == 0)
00154 rec->setResult((state->getTurn() == BLACK)
00155 ? Record::BLACK_WIN : Record::WHITE_WIN);
00156 else if (s.find("%JISHOGI") == 0 || s.find("%HIKIWAKE") == 0)
00157 rec->setResult(Record::JISHOGI);
00158 else if (s.find("%+ILLEGAL_ACTION") == 0)
00159 rec->setResult(Record::WHITE_WIN);
00160 else if (s.find("%-ILLEGAL_ACTION") == 0)
00161 rec->setResult(Record::BLACK_WIN);
00162 return;
00163 default:
00164 throw CsaIOError("unknown character in csaParseLine "+s);
00165 }
00166 }
00167 }
00168 }
00169 }
00170
00171 osl::record::csa::
00172 InputStream::InputStream(std::istream& is)
00173 : is(is),
00174 rv(boost::shared_ptr<record::RecordVisitor>(new record::RecordVisitor()))
00175 {
00176 if (! is)
00177 {
00178 std::cerr << "InputStream::InputStream cannot read \n";
00179 abort();
00180 }
00181 }
00182
00183 osl::record::csa::
00184 InputStream::InputStream(std::istream& is, boost::shared_ptr<record::RecordVisitor> rv)
00185 : is(is), rv(rv)
00186 {
00187 if (! is)
00188 {
00189 std::cerr << "InputStream::InputStream cannot read \n";
00190 abort();
00191 }
00192 }
00193
00194 osl::record::csa::
00195 InputStream::~InputStream(){}
00196
00197 void osl::record::csa::
00198 InputStream::load(Record* rec)
00199 {
00200
00201 state.init();
00202 rv->setState(&state);
00203 rv->setRecord(rec);
00204 std::string line;
00205 while (std::getline(is, line))
00206 {
00207
00208 if ((! line.empty())
00209 && (line[line.size()-1] == 13))
00210 line.erase(line.size()-1);
00211 csaParseLine(rv, line);
00212 }
00213 assert(state.isConsistent());
00214 }
00215
00216 osl::record::csa::
00217 CsaFile::CsaFile(const std::string& fileName)
00218 {
00219 std::ifstream ifs(fileName.c_str());
00220 if (! ifs)
00221 {
00222 const std::string msg = "CsaFile::CsaFile file cannot read ";
00223 std::cerr << msg << fileName << "\n";
00224 throw CsaIOError(msg + fileName);
00225 }
00226 InputStream irs(ifs);
00227 irs.load(&rec);
00228 }
00229
00230 osl::record::csa::
00231 CsaFile::~CsaFile()
00232 {
00233 }
00234
00235 const osl::record::Record& osl::record::csa::
00236 CsaFile::getRecord() const
00237 {
00238 return rec;
00239 }
00240
00241 const osl::NumEffectState osl::record::csa::
00242 CsaFile::getInitialState() const
00243 {
00244 return NumEffectState(rec.getInitialState());
00245 }
00246
00247
00248
00249
00250
00251