00001 #include "osl/csa.h"
00002 #include "osl/simpleState.h"
00003 #include "osl/bits/pieceTable.h"
00004 #include "osl/oslConfig.h"
00005 #include <boost/algorithm/string/split.hpp>
00006 #include <boost/algorithm/string/trim.hpp>
00007 #include <iostream>
00008 #include <sstream>
00009 #include <stdexcept>
00010 #include <cassert>
00011 #include <string>
00012 #include <fstream>
00013 #include <array>
00014
00015
00016
00017 osl::Player osl::csa::
00018 charToPlayer(char c)
00019 {
00020 if(c=='+')
00021 return BLACK;
00022 if(c=='-')
00023 return WHITE;
00024 throw CsaIOError("not a csa PlayerCharacter "+std::string(1,c));
00025 }
00026
00027 const osl::Square osl::csa::
00028 strToPos(const std::string& s)
00029 {
00030 int x=s.at(0)-'0';
00031 int y=s.at(1)-'0';
00032 if(x==0 && y==0)
00033 return Square::STAND();
00034 return Square(x,y);
00035 }
00036
00037 osl::Ptype osl::csa::
00038 strToPtype(const std::string& s)
00039 {
00040 for(int i=0;i<16;i++){
00041 if(s == Ptype_Table.getCsaName(static_cast<Ptype>(i)))
00042 return static_cast<Ptype>(i);
00043 }
00044 throw CsaIOError("unknown std::string in csa::strToPtype "+s);
00045 }
00046
00047 const osl::Move osl::csa::
00048 strToMove(const std::string& s,const SimpleState& state)
00049 {
00050 if (s == "%KACHI")
00051 return Move::DeclareWin();
00052 if (s == "%TORYO")
00053 return Move::INVALID();
00054 if (s == "%PASS")
00055 return Move::PASS(state.turn());
00056
00057 Player pl=csa::charToPlayer(s.at(0));
00058 Square fromPos=csa::strToPos(s.substr(1,2));
00059 Square toPos=csa::strToPos(s.substr(3,2));
00060 Ptype ptype=csa::strToPtype(s.substr(5,2));
00061 if(fromPos==Square::STAND()){
00062 if (isPromoted(ptype))
00063 throw CsaIOError("drop with promote ?! in csa::strToMove "+s);
00064 return Move(toPos,ptype,pl);
00065 }
00066 else{
00067 Piece p0=state.pieceAt(fromPos);
00068 Piece p1=state.pieceAt(toPos);
00069 Ptype capturePtype=p1.ptype();
00070 bool isPromote=(p0.ptype()!=ptype);
00071 if (! ((p0.ptype()==ptype)||(p0.ptype()==unpromote(ptype))))
00072 throw CsaIOError("bad promotion in csa::strToMove "+s);
00073 return Move(fromPos,toPos,ptype,
00074 capturePtype,isPromote,pl);
00075 }
00076 }
00077
00078
00079 const std::string osl::csa::
00080 show(Player player, std::string& buf, size_t offset)
00081 {
00082 assert(buf.size() >= offset+1);
00083 buf[offset] = (player==BLACK) ? '+' : '-';
00084 return buf;
00085 }
00086
00087 const std::string osl::csa::
00088 show(Move move, std::string& buf)
00089 {
00090 assert(buf.capacity() >= 7);
00091 buf.resize(7);
00092 if (move == Move::DeclareWin())
00093 return buf = "%KACHI";
00094 if (move.isInvalid())
00095 return buf = "%TORYO";
00096 if (move.isPass())
00097 return buf = "%PASS";
00098 show(move.player(), buf);
00099 show(move.from(), buf, 1);
00100 show(move.to(), buf, 3);
00101 show(move.ptype(), buf, 5);
00102 return buf;
00103 }
00104
00105 const std::string osl::csa::
00106 show(Square pos, std::string& buf, size_t offset)
00107 {
00108 assert(buf.size() >= offset+2);
00109 if (pos.isPieceStand())
00110 {
00111 buf[0+offset] = '0';
00112 buf[1+offset] = '0';
00113 return buf;
00114 }
00115 const int x = pos.x();
00116 const int y = pos.y();
00117 buf[offset+0] = x + '0';
00118 buf[offset+1] = y + '0';
00119 return buf;
00120 }
00121
00122 const std::string osl::csa::
00123 show(Ptype ptype, std::string& buf, size_t offset)
00124 {
00125 assert(buf.size() >= offset+2);
00126 const char *name = Ptype_Table.getCsaName(ptype);
00127 buf[0+offset] = name[0];
00128 buf[1+offset] = name[1];
00129 return buf;
00130 }
00131
00132 const std::string osl::csa::
00133 show(Move move)
00134 {
00135
00136 std::string buf("+7776FU");
00137 return show(move, buf);
00138 }
00139
00140 const std::string osl::csa::
00141 fancyShow(Move move)
00142 {
00143 std::string ret = show(move);
00144 if (move.isNormal()) {
00145 if (move.capturePtype() != PTYPE_EMPTY)
00146 ret += "x" + show(move.capturePtype());
00147 if (move.isPromotion())
00148 ret += '+';
00149 }
00150 return ret;
00151 }
00152
00153 const std::string osl::csa::
00154 show(Player player)
00155 {
00156 std::string buf("+");
00157 return show(player, buf);
00158 }
00159
00160 const std::string osl::csa::
00161 show(Square position)
00162 {
00163 std::string buf("00");
00164 return show(position, buf);
00165 }
00166
00167 const std::string osl::csa::
00168 show(Ptype ptype)
00169 {
00170 std::string buf("OU");
00171 return show(ptype, buf);
00172 }
00173
00174 const std::string osl::csa::
00175 show(Piece piece)
00176 {
00177 if (piece.isEdge())
00178 return " ";
00179 if (piece.isEmpty())
00180 return " * ";
00181
00182 assert(piece.isPiece() && isPiece(piece.ptype()));
00183 assert(unpromote(piece.ptype()) == Piece_Table.getPtypeOf(piece.number()));
00184 return show(piece.owner())
00185 + show(piece.ptype());
00186 }
00187
00188 const std::string osl::csa::
00189 show(const Move *first, const Move *last)
00190 {
00191 std::ostringstream out;
00192 for (; first != last; ++first) {
00193 if (first->isInvalid())
00194 break;
00195 out << show(*first);
00196 }
00197 return out.str();
00198 }
00199
00200
00201 osl::csa::CsaFileMinimal::CsaFileMinimal(const std::string& filename)
00202 {
00203 std::ifstream is(filename);
00204 if (! is) {
00205 const std::string msg = "CsaFileMinimal::CsaFileMinimal file open failed ";
00206 std::cerr << msg << filename << "\n";
00207 throw CsaIOError(msg + filename);
00208 }
00209 load(is);
00210 }
00211
00212 osl::csa::CsaFileMinimal::CsaFileMinimal(std::istream& is)
00213 {
00214 load(is);
00215 }
00216 osl::csa::CsaFileMinimal::~CsaFileMinimal()
00217 {
00218 }
00219
00220 void osl::csa::CsaFileMinimal::load(std::istream& is)
00221 {
00222 SimpleState work;
00223 work.init();
00224 std::string line;
00225 CArray<bool, 9> board_parsed = {{ false }};
00226 while (std::getline(is, line))
00227 {
00228
00229 if ((! line.empty())
00230 && (line[line.size()-1] == 13))
00231 line.erase(line.size()-1);
00232
00233 std::vector<std::string> elements;
00234 boost::algorithm::split(elements, line, boost::algorithm::is_any_of(","));
00235 for (auto& e: elements) {
00236 boost::algorithm::trim(e);
00237 boost::algorithm::trim_left(e);
00238 parseLine(work, record, e, board_parsed);
00239 }
00240 }
00241 if (*std::min_element(board_parsed.begin(), board_parsed.end()) == false)
00242 throw CsaIOError("incomplete position description in csaParseLine");
00243 assert(record.initial_state.isConsistent());
00244 }
00245
00246 bool osl::csa::
00247 CsaFileMinimal::parseLine(SimpleState& state, RecordMinimal& record, std::string s,
00248 CArray<bool,9>& board_parsed)
00249 {
00250 while (! s.empty() && isspace(s[s.size()-1]))
00251 s.resize(s.size()-1);
00252 if (s.length()==0)
00253 return true;
00254 switch(s.at(0)){
00255 case 'P':
00256 switch(s.at(1)){
00257 case 'I':
00258 board_parsed.fill(true);
00259 state.init(HIRATE);
00260 break;
00261 case '+':
00262 case '-':{
00263 Player pl=csa::charToPlayer(s.at(1));
00264 for(int i=2;i<=(int)s.length()-4;i+=4){
00265 Square pos=csa::strToPos(s.substr(i,2));
00266 if(s.substr(i+2,2) == "AL"){
00267 state.setPieceAll(pl);
00268 }
00269 else{
00270 Ptype ptype=csa::strToPtype(s.substr(i+2,2));
00271 state.setPiece(pl,pos,ptype);
00272 }
00273 }
00274 break;
00275 }
00276 default:
00277 if(isdigit(s.at(1))){
00278 const int y=s.at(1)-'0';
00279 board_parsed[y-1] = true;
00280 for(unsigned int x=9,i=2;i<s.length();i+=3,x--){
00281 if (s.at(i) != '+' && s.at(i) != '-' && s.find(" *",i)!=i) {
00282 if (OslConfig::inUnitTest())
00283 throw CsaIOError("parse board error " + s);
00284 else
00285 std::cerr << "possible typo for empty square " << s << "\n";
00286 }
00287 if (s.at(i) != '+' && s.at(i) != '-') continue;
00288 Player pl=csa::charToPlayer(s.at(i));
00289 Square pos(x,y);
00290 Ptype ptype=csa::strToPtype(s.substr(i+1,2));
00291 state.setPiece(pl,pos,ptype);
00292 }
00293 }
00294 }
00295 break;
00296 case '+':
00297 case '-':{
00298 Player pl=csa::charToPlayer(s.at(0));
00299 if(s.length()==1){
00300 state.setTurn(pl);
00301 state.initPawnMask();
00302 record.initial_state = NumEffectState(state);
00303 }
00304 else{
00305 const Move m = csa::strToMove(s,state);
00306 if (! state.isValidMove(m))
00307 {
00308 std::cerr << "Illegal move " << m << std::endl;
00309 throw CsaIOError("illegal move "+s);
00310 }
00311 record.moves.push_back(m);
00312 NumEffectState copy(state);
00313 copy.makeMove(m);
00314 state = copy;
00315 }
00316 break;
00317 }
00318 default:
00319 return false;
00320 }
00321 return true;
00322 }
00323
00324
00325 osl::csa::CsaString::CsaString(const std::string& s)
00326 {
00327 std::istringstream is(s);
00328 load(is);
00329 }
00330
00331
00332
00333
00334
00335