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