説明を見る。00001
00002
00003 #include "osl/usi.h"
00004 #include <iostream>
00005 #include <sstream>
00006 #include <cctype>
00007
00008 const std::string osl::psn::
00009 show(Square pos)
00010 {
00011 const int x = pos.x();
00012 const int y = pos.y();
00013 std::string result = "XX";
00014 result[0] = x + '0';
00015 result[1] = y + 'a' - 1;
00016 return result;
00017 }
00018
00019 char osl::psn::
00020 show(Ptype ptype)
00021 {
00022 switch (ptype)
00023 {
00024 case PAWN: return 'P';
00025 case LANCE: return 'L';
00026 case KNIGHT: return 'N';
00027 case SILVER: return 'S';
00028 case GOLD: return 'G';
00029 case BISHOP: return 'B';
00030 case ROOK: return 'R';
00031 case KING: return 'K';
00032 default:
00033 assert("unsupported ptype" == 0);
00034 return '!';
00035 }
00036 }
00037
00038 const std::string osl::psn::
00039 show(Move m)
00040 {
00041 const Square from = m.from();
00042 const Square to = m.to();
00043 if (from.isPieceStand())
00044 {
00045 std::string result = "X*";
00046 result[0] = show(m.ptype());
00047 result += show(to);
00048 return result;
00049 }
00050 std::string result = show(from);
00051 result += show(to);
00052 if (m.promoteMask())
00053 result += '+';
00054 return result;
00055 }
00056
00057 const std::string osl::psn::
00058 showXP(Move m)
00059 {
00060 if (m.isInvalid())
00061 return "resign";
00062 if (m.isPass())
00063 return "pass";
00064 const Square from = m.from();
00065 const Square to = m.to();
00066 if (from.isPieceStand())
00067 {
00068 std::string result = "X*";
00069 result[0] = show(m.ptype());
00070 result += show(to);
00071 return result;
00072 }
00073 std::string result = show(from);
00074 if (m.capturePtype() != PTYPE_EMPTY)
00075 result += 'x';
00076 result += show(to);
00077 if (m.isPromotion())
00078 result += '+';
00079 else if (canPromote(m.ptype())
00080 && (from.canPromote(m.player()) || to.canPromote(m.player())))
00081 result += '=';
00082 return result;
00083 }
00084
00085
00086 const osl::Move osl::psn::
00087 strToMove(const std::string& str, const SimpleState& s)
00088 {
00089 if (str.size() < 4)
00090 throw ParseError("Invalid move string: " + str);
00091
00092 const Square to = strToPos(str.substr(2,2));
00093 if (str[1] == '*')
00094 {
00095 const Ptype ptype = charToPtype(str[0]);
00096 return Move(to, ptype, s.turn());
00097 }
00098
00099 const Square from = strToPos(str.substr(0,2));
00100 const Ptype ptype = s.pieceOnBoard(from).ptype();
00101 const Ptype captured = s.pieceOnBoard(to).ptype();
00102 if (! isPiece(ptype))
00103 throw ParseError("No piece on square: " + str);
00104 bool promotion = false;
00105 if (str.size() > 4)
00106 {
00107 assert(str[4] == '+');
00108 promotion = true;
00109 }
00110 return Move(from, to, (promotion ? promote(ptype) : ptype),
00111 captured, promotion, s.turn());
00112 }
00113
00114 const osl::Square osl::psn::
00115 strToPos(const std::string& str)
00116 {
00117 assert(str.size() == 2);
00118 const int x = str[0] - '0';
00119 const int y = str[1] - 'a' + 1;
00120 if (x <= 0 || x > 9 || y <= 0 || y > 9)
00121 throw ParseError("Invalid square character: " + str);
00122 return Square(x, y);
00123 }
00124
00125 osl::Ptype osl::psn::
00126 charToPtype(char c)
00127 {
00128 switch (c)
00129 {
00130 case 'P': return PAWN;
00131 case 'L': return LANCE;
00132 case 'N': return KNIGHT;
00133 case 'S': return SILVER;
00134 case 'G': return GOLD;
00135 case 'B': return BISHOP;
00136 case 'R': return ROOK;
00137 case 'K': return KING;
00138 default:
00139 return PTYPE_EMPTY;
00140 }
00141 }
00142
00143
00144
00145 const std::string osl::usi::
00146 show(Move m)
00147 {
00148 if (m.isPass())
00149 return "pass";
00150 if (m == Move::DeclareWin())
00151 return "win";
00152 if (! m.isNormal())
00153 return "resign";
00154 return psn::show(m);
00155 }
00156
00157 const std::string osl::usi::
00158 show(PtypeO ptypeo)
00159 {
00160 if (! isPiece(ptypeo))
00161 return "";
00162
00163 char c = psn::show(unpromote(getPtype(ptypeo)));
00164 if (getOwner(ptypeo) == WHITE)
00165 c = tolower(c);
00166 std::string ret(1,c);
00167 if (isPromoted(ptypeo))
00168 ret = "+" + ret;
00169 return ret;
00170 }
00171
00172 const std::string osl::usi::
00173 show(Piece p)
00174 {
00175 return show(p.ptypeO());
00176 }
00177
00178 const std::string osl::usi::
00179 show(const NumEffectState& state)
00180 {
00181 std::ostringstream ret;
00182 if (state == SimpleState(HIRATE)) {
00183 ret << "startpos";
00184 return ret.str();
00185 }
00186 ret << "sfen ";
00187 for (int y=1; y<=9; ++y) {
00188 int empty_count = 0;
00189 for (int x=9; x>=1; --x) {
00190 const Piece p = state.pieceOnBoard(Square(x,y));
00191 if (p.isEmpty()) {
00192 ++empty_count;
00193 continue;
00194 }
00195 if (empty_count) {
00196 ret << empty_count;
00197 empty_count = 0;
00198 }
00199 ret << show(p);
00200 }
00201 if (empty_count)
00202 ret << empty_count;
00203 if (y < 9) ret << "/";
00204 }
00205 ret << " " << "bw"[state.turn() == WHITE] << " ";
00206 bool has_any = false;
00207 for (int z=0; z<2; ++z) {
00208 const Player player = indexToPlayer(z);
00209 for (Ptype ptype: PieceStand::order) {
00210 const int count = state.countPiecesOnStand(player, ptype);
00211 if (count == 0)
00212 continue;
00213 if (count > 1)
00214 ret << count;
00215 ret << show(newPtypeO(player, ptype));
00216 has_any = true;
00217 }
00218 }
00219 if (! has_any)
00220 ret << "-";
00221 ret << " 1";
00222 return ret.str();
00223 }
00224
00225 const osl::Move osl::usi::
00226 strToMove(const std::string& str, const NumEffectState& s)
00227 {
00228 if (str == "win")
00229 return Move::DeclareWin();
00230 if (str == "pass")
00231 return Move::PASS(s.turn());
00232 if (str == "resign")
00233 return Move::INVALID();
00234 try {
00235 return psn::strToMove(str, s);
00236 }
00237 catch (std::exception& e) {
00238 throw ParseError("usi::strToMove failed for " + str + " by "+ e.what());
00239 }
00240 catch (...) {
00241 throw ParseError("usi::strToMove failed for " + str);
00242 }
00243 }
00244
00245 osl::PtypeO osl::usi::
00246 charToPtypeO(char c)
00247 {
00248 const Ptype ptype = psn::charToPtype(toupper(c));
00249 if (ptype == PTYPE_EMPTY)
00250 throw ParseError("Invalid piece character: " + std::string(1,c));
00251 const Player pl = isupper(c) ? BLACK : WHITE;
00252 return newPtypeO(pl, ptype);
00253 }
00254
00255 void osl::usi::parseBoard(const std::string& word, NumEffectState& out)
00256 {
00257 if (word.empty())
00258 throw ParseError(word);
00259
00260 SimpleState state;
00261 state.init();
00262 int x=9, y=1;
00263 for (size_t i=0; i<word.size(); ++i) {
00264 const char c = word[i];
00265 if (isalpha(c)) {
00266 const PtypeO ptypeo = charToPtypeO(c);
00267 state.setPiece(getOwner(ptypeo), Square(x,y), getPtype(ptypeo));
00268 --x;
00269 } else if (c == '+') {
00270 if ( (i+1) >= word.size() )
00271 throw ParseError(word);
00272 const char next = word[i+1];
00273 if (!isalpha(next))
00274 throw ParseError(word);
00275 const PtypeO ptypeo = charToPtypeO(next);
00276 if (!canPromote(ptypeo))
00277 throw ParseError(word);
00278 const PtypeO promoted = promote(ptypeo);
00279 state.setPiece(getOwner(promoted), Square(x,y), getPtype(promoted));
00280 --x;
00281 ++i;
00282 } else if (c == '/') {
00283 if (x != 0)
00284 throw ParseError(word);
00285 x = 9;
00286 ++y;
00287 } else if (isdigit(c)) {
00288 const int n = c - '0';
00289 if (n == 0)
00290 throw ParseError(word);
00291 x -= n;
00292 } else {
00293 throw ParseError("usi: unknown input " + std::string(1,c));
00294 }
00295 if (x < 0 || x > 9 || y < 0 || y > 9)
00296 throw ParseError(word);
00297 }
00298 out = NumEffectState(state);
00299 }
00300
00301 void osl::usi::parse(const std::string& line, NumEffectState& state)
00302 {
00303 NumEffectState board;
00304 std::vector<Move> moves;
00305 parse(line, board, moves);
00306 state.copyFrom(board);
00307 for (Move move: moves) {
00308 state.makeMove(move);
00309 }
00310 }
00311
00312 osl::NumEffectState osl::usi::makeState(const std::string& line){
00313 NumEffectState state;
00314 parse(line,state);
00315 return state;
00316 }
00317
00318 void osl::usi::parse(const std::string& line, NumEffectState& state, std::vector<Move>& moves)
00319 {
00320 moves.clear();
00321 std::istringstream is(line);
00322 std::string word;
00323 is >> word;
00324 if (word == "position")
00325 is >> word;
00326 if (word == "startpos")
00327 state.init(HIRATE);
00328 else {
00329 if (word != "sfen")
00330 throw ParseError("sfen not found "+word);
00331 is >> word;
00332 parseBoard(word, state);
00333 is >> word;
00334 if (word != "b" && word != "w")
00335 throw ParseError(" turn error "+word);
00336 state.setTurn((word == "b") ? BLACK : WHITE);
00337 is >> word;
00338 if (word != "-") {
00339 int prefix = 0;
00340 for (char c: word) {
00341 if (isalpha(c)) {
00342 PtypeO ptypeo = charToPtypeO(c);
00343 for (int j=0; j<std::max(1, prefix); ++j)
00344 state.setPiece(getOwner(ptypeo), Square::STAND(), getPtype(ptypeo));
00345 prefix = 0;
00346 }
00347 else {
00348 if (!isdigit(c))
00349 throw ParseError(word);
00350 prefix = (c - '0') + prefix*10;
00351 if (prefix == 0)
00352 throw ParseError(word);
00353 }
00354 }
00355 }
00356 state.initPawnMask();
00357 int move_number;
00358 if (! (is >> move_number))
00359 return;
00360 assert(is);
00361 }
00362 if (! (is >> word))
00363 return;
00364 if (word != "moves")
00365 throw ParseError("moves not found "+word);
00366 NumEffectState state_copy(state);
00367 while (is >> word) {
00368 Move m = strToMove(word, state_copy);
00369 moves.push_back(m);
00370 if (! m.isNormal() || ! state_copy.isValidMove(m))
00371 throw ParseError("invalid move "+word);
00372 state_copy.makeMove(m);
00373 }
00374 }
00375
00376
00377
00378
00379
00380
00381