Go to the documentation of this file.00001
00002
00003 #include "osl/record/kakinoki.h"
00004 #include "osl/record/kanjiMove.h"
00005 #include "osl/record/kanjiCode.h"
00006 #include "osl/misc/sjis2euc.h"
00007 #include "osl/state/simpleState.h"
00008 #include <iostream>
00009 #include <fstream>
00010 #include <stdexcept>
00011 #include <cassert>
00012 #include <string>
00013 #include <sstream>
00014
00015 namespace osl
00016 {
00017 namespace record
00018 {
00019 void kakinokiParseLine(boost::shared_ptr<RecordVisitor>& rv,
00020 std::string s)
00021 {
00022 Record *record=rv->getRecord();
00023 SimpleState* state=rv->getState();
00024 if (s[0] == '*')
00025 {
00026 MoveRecord *mr = rv->getLastMove();
00027 if (mr)
00028 mr->addComment(s.substr(1));
00029 return;
00030 }
00031 if (s.size() > 6)
00032 {
00033 if (equal(K_BLACK.begin(), K_BLACK.end(), s.begin())) {
00034 record->setPlayer(BLACK, s.substr(6));
00035 return;
00036 }
00037 if (equal(K_WHITE.begin(), K_WHITE.end(), s.begin())) {
00038 record->setPlayer(WHITE, s.substr(6));
00039 return;
00040 }
00041 if (s.substr(0,6) == (K_KISEN+K_COLON))
00042 {
00043 record->setTounamentName(s.substr(6));
00044 return;
00045 }
00046 }
00047 if (s[0] != ' ')
00048 {
00049 if (rv->getLastMove() == 0)
00050 record->addInitialComment(s);
00051 return;
00052 }
00053 if (s.find(K_TORYO) != s.npos)
00054 {
00055 record->setResult((state->turn() == BLACK)
00056 ? Record::WHITE_WIN : Record::BLACK_WIN);
00057 return;
00058 }
00059
00060 {
00061
00062 size_t p = s.find('(');
00063 if (p != s.npos)
00064 s.replace(p, 1, 1, ' ');
00065 p = s.find(')');
00066 if (p != s.npos)
00067 s.replace(p, 1, 1, ' ');
00068 }
00069 Move last_move;
00070 if (rv->getLastMove())
00071 last_move = rv->getLastMove()->getMove();
00072 const Move m = kakinoki::strToMove(s, *state, last_move);
00073 if (m.isNormal()) {
00074 if (! state->isValidMove(m)) {
00075 std::ostringstream ss;
00076 ss << *state << s << "\n" << m;
00077 std::cerr << ss.str();
00078 throw KakinokiIOError(ss.str());
00079 }
00080 rv->addMoveAndAdvance(m);
00081 }
00082 }
00083 }
00084 }
00085
00086 osl::Move osl::record::
00087 kakinoki::strToMove(const std::string& s, const SimpleState& state, Move last_move)
00088 {
00089 static KanjiMove Kanji_Move;
00090 std::istringstream is(s);
00091 int move_number, from_number;
00092 std::string move_string;
00093 is >> move_number >> move_string;
00094
00095 Square to, from;
00096 if (move_string.substr(0,2) == K_ONAZI)
00097 to = last_move.to();
00098 else
00099 to = Kanji_Move.toSquare(move_string.substr(0,4));
00100 if (to == Square())
00101 return Move();
00102
00103 Ptype ptype;
00104 size_t cur = 4;
00105 if (move_string.substr(cur,2) == K_NARU)
00106 {
00107 assert(move_string.size() >= cur+4);
00108 ptype = Kanji_Move.toPtype(move_string.substr(cur,4));
00109 cur += 4;
00110 }
00111 else
00112 {
00113 ptype = Kanji_Move.toPtype(move_string.substr(cur,2));
00114 cur += 2;
00115 }
00116 if (move_string.size() >= cur+2 && move_string.substr(cur,2)
00117 == K_UTSU)
00118 from = Square();
00119 else
00120 {
00121 if (! (is >> from_number))
00122 throw KakinokiIOError("error in move from");
00123 from = Square(from_number / 10, from_number % 10);
00124 }
00125
00126 bool is_promote = false;
00127 if (move_string.size() >= cur+2 && move_string.substr(cur,2) == K_NARU)
00128 is_promote = true;
00129
00130 if (from.isPieceStand())
00131 return Move(to, ptype, state.turn());
00132 Ptype captured = state.pieceOnBoard(to).ptype();
00133 return Move(from, to, is_promote ? promote(ptype) : ptype,
00134 captured, is_promote, state.turn());
00135 }
00136
00137 osl::record::kakinoki::
00138 InputStream::InputStream(std::istream& is)
00139 : is(is),
00140 rv(boost::shared_ptr<record::RecordVisitor>(new record::RecordVisitor()))
00141 {
00142 if (! is)
00143 {
00144 std::cerr << "InputStream::InputStream cannot read \n";
00145 abort();
00146 }
00147 }
00148
00149 osl::record::kakinoki::
00150 InputStream::InputStream(std::istream& is, boost::shared_ptr<record::RecordVisitor> rv)
00151 : is(is), rv(rv)
00152 {
00153 if (! is)
00154 {
00155 std::cerr << "InputStream::InputStream cannot read \n";
00156 throw KakinokiIOError("file open failed");
00157 }
00158 }
00159
00160 osl::record::kakinoki::
00161 InputStream::~InputStream(){}
00162
00163 void osl::record::kakinoki::
00164 InputStream::load(Record* rec)
00165 {
00166
00167 state.init(HIRATE);
00168 rv->setState(&state);
00169 rv->setRecord(rec);
00170 std::string line;
00171 while (std::getline(is, line))
00172 {
00173
00174 if ((! line.empty())
00175 && (line[line.size()-1] == 13))
00176 line.erase(line.size()-1);
00177 if (line.length()==0)
00178 continue;
00179
00180 line = misc::sjis2euc(line);
00181
00182 if (line.find(K_HENKA) == 0)
00183 break;
00184 if (! line.empty() && line[0] == '#'
00185 && line.find("separator") != line.npos)
00186 break;
00187
00188 kakinokiParseLine(rv, line);
00189 }
00190 assert(state.isConsistent());
00191 }
00192
00193 osl::record::kakinoki::
00194 KakinokiFile::KakinokiFile(const std::string& filename)
00195 {
00196 std::ifstream ifs(filename.c_str());
00197 if (! ifs)
00198 {
00199 const std::string msg = "KakinokiFile::KakinokiFile file cannot read ";
00200 std::cerr << msg << filename << "\n";
00201 throw KakinokiIOError(msg + filename);
00202 }
00203 InputStream irs(ifs);
00204 irs.load(&rec);
00205 }
00206
00207 osl::record::kakinoki::
00208 KakinokiFile::~KakinokiFile()
00209 {
00210 }
00211
00212 const osl::record::Record& osl::record::kakinoki::
00213 KakinokiFile::getRecord() const
00214 {
00215 return rec;
00216 }
00217
00218 const osl::NumEffectState osl::record::kakinoki::
00219 KakinokiFile::getInitialState() const
00220 {
00221 return NumEffectState(rec.getInitialState());
00222 }
00223
00224 bool osl::record::kakinoki::
00225 KakinokiFile::isKakinokiFile(const std::string& filename)
00226 {
00227 std::ifstream is(filename.c_str());
00228 std::string line;
00229 if (! is || ! getline(is, line))
00230 return false;
00231 line = misc::sjis2euc(line);
00232 return line.find("Kifu for Windows") != line.npos
00233 || line.find("KIFU") != line.npos
00234 || line.find(K_SENKEI) == 0
00235 || (line.find("#") == 0 && line.find(K_KIFU) != line.npos);
00236 }
00237
00238
00239
00240
00241