usi.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
usi.cc
Go to the documentation of this file.
1 /* usi.cc
2 */
3 #include "osl/record/usi.h"
4 #include "osl/record/psn.h"
5 #include "osl/state/simpleState.h"
6 #include "osl/pieceStand.h"
7 #include <boost/algorithm/string/replace.hpp>
8 #include <boost/foreach.hpp>
9 #include <iostream>
10 #include <fstream>
11 #include <sstream>
12 #include <cctype>
13
14 const std::string osl::record::usi::
15 show(Move m)
16 {
17 if (m.isPass())
18 return "pass";
19 if (m == Move::DeclareWin())
20 return "win";
21 if (! m.isNormal())
22 return "resign";
23 return psn::show(m);
24 }
25
26 const std::string osl::record::usi::
27 show(PtypeO ptypeo)
28 {
29 if (! isPiece(ptypeo))
30 return "";
31
32 char c = psn::show(unpromote(getPtype(ptypeo)));
33 if (getOwner(ptypeo) == WHITE)
34 c = tolower(c);
35 std::string ret(1,c);
36 if (isPromoted(ptypeo))
37 ret = "+" + ret;
38 return ret;
39 }
40
41 const std::string osl::record::usi::
42 show(Piece p)
43 {
44 return show(p.ptypeO());
45 }
46
47 const std::string osl::record::usi::
48 show(const SimpleState& state)
49 {
50 std::ostringstream ret;
51 if (state == SimpleState(HIRATE)) {
52 ret << "startpos";
53 return ret.str();
54 }
55 ret << "sfen ";
56 for (int y=1; y<=9; ++y) {
57 int empty_count = 0;
58 for (int x=9; x>=1; --x) {
59 const Piece p = state.pieceOnBoard(Square(x,y));
60 if (p.isEmpty()) {
61 ++empty_count;
62 continue;
63 }
64 if (empty_count) {
65 ret << empty_count;
66 empty_count = 0;
67 }
68 ret << show(p);
69 }
70 if (empty_count)
71 ret << empty_count;
72 if (y < 9) ret << "/";
73 }
74 ret << " " << "bw"[state.turn() == WHITE] << " ";
75 bool has_any = false;
76 for (int z=0; z<2; ++z) {
77 const Player player = indexToPlayer(z);
78 BOOST_FOREACH(Ptype ptype, PieceStand::order) {
79 const int count = state.countPiecesOnStand(player, ptype);
80 if (count == 0)
81 continue;
82 if (count > 1)
83 ret << count;
84 ret << show(newPtypeO(player, ptype));
85 has_any = true;
86 }
87 }
88 if (! has_any)
89 ret << "-";
90 ret << " 1";
91 return ret.str();
92 }
93
94 const osl::Move osl::record::usi::
95 strToMove(const std::string& str, const SimpleState& s)
96 {
97 if (str == "win")
98 return Move::DeclareWin();
99 if (str == "pass")
100 return Move::PASS(s.turn());
101 if (str == "resign")
102 return Move::INVALID();
103 try {
104 return psn::strToMove(str, s);
105 }
106 catch (std::exception& e) {
107 throw ParseError("usi::strToMove failed for " + str + " by "+ e.what());
108 }
109 catch (...) {
110 throw ParseError("usi::strToMove failed for " + str);
111 }
112 }
113
114 osl::PtypeO osl::record::usi::
115 charToPtypeO(char c)
116 {
117 const Ptype ptype = psn::charToPtype(toupper(c));
118 if (ptype == PTYPE_EMPTY)
119 throw ParseError("Invalid piece character: " + c);
120 const Player pl = isupper(c) ? BLACK : WHITE;
121 return newPtypeO(pl, ptype);
122 }
123
124 void osl::record::usi::parseBoard(const std::string& word, SimpleState& state)
125 {
126 if (word.empty())
127 throw ParseError(word);
128
129 state.init();
130 int x=9, y=1;
131 for (size_t i=0; i<word.size(); ++i) {
132 const char c = word[i];
133 if (isalpha(c)) {
134 const PtypeO ptypeo = charToPtypeO(c);
135 state.setPiece(getOwner(ptypeo), Square(x,y), getPtype(ptypeo));
136 --x;
137 } else if (c == '+') {
138 if ( (i+1) >= word.size() )
139 throw ParseError(word);
140 const char next = word[i+1];
141 if (!isalpha(next))
142 throw ParseError(word);
143 const PtypeO ptypeo = charToPtypeO(next);
144 if (!canPromote(ptypeo))
145 throw ParseError(word);
146 const PtypeO promoted = promote(ptypeo);
147 state.setPiece(getOwner(promoted), Square(x,y), getPtype(promoted));
148 --x;
149 ++i;
150 } else if (c == '/') {
151 if (x != 0)
152 throw ParseError(word);
153 x = 9;
154 ++y;
155 } else if (isdigit(c)) {
156 const int n = c - '0';
157 if (n == 0)
158 throw ParseError(word);
159 x -= n;
160 } else {
161 throw ParseError("usi: unknown input " + c);
162 }
163 if (x < 0 || x > 9 || y < 0 || y > 9)
164 throw ParseError(word);
165 }
166 }
167
168 void osl::record::usi::parse(const std::string& line, NumEffectState& state)
169 {
170 SimpleState board;
171 vector<Move> moves;
172 parse(line, board, moves);
173 state.copyFrom(NumEffectState(board));
174 BOOST_FOREACH(Move move, moves) {
175 state.makeMove(move);
176 }
177 }
178
179 osl::state::NumEffectState osl::record::usi::makeState(const std::string& line){
180 osl::state::NumEffectState state;
181 parse(line,state);
182 return state;
183 }
184
185 void osl::record::usi::parse(const std::string& line, SimpleState& state, vector<Move>& moves)
186 {
187 moves.clear();
188 std::istringstream is(line);
189 std::string word;
190 is >> word;
191 if (word == "position")
192 is >> word;
193 if (word == "startpos")
194 state.init(HIRATE);
195 else {
196 if (word != "sfen")
197 throw ParseError("sfen not found "+word);
198 is >> word;
199 parseBoard(word, state);
200 is >> word;
201 if (word != "b" && word != "w")
202 throw ParseError(" turn error "+word);
203 state.setTurn((word == "b") ? BLACK : WHITE);
204 is >> word;
205 if (word != "-") {
206 int prefix = 0;
207 BOOST_FOREACH(char c, word) {
208 if (isalpha(c)) {
209 PtypeO ptypeo = charToPtypeO(c);
210 for (int j=0; j<std::max(1, prefix); ++j)
211 state.setPiece(getOwner(ptypeo), Square::STAND(), getPtype(ptypeo));
212 prefix = 0;
213 }
214 else {
215 if (!isdigit(c))
216 throw ParseError(word);
217 prefix = (c - '0') + prefix*10;
218 if (prefix == 0)
219 throw ParseError(word);
220 }
221 }
222 }
223 state.initPawnMask();
224 int move_number; // will not be used
225 if (! (is >> move_number))
226 return;
227 assert(is);
228 }
229 if (! (is >> word))
230 return;
231 if (word != "moves")
232 throw ParseError("moves not found "+word);
233 NumEffectState state_copy(state);
234 while (is >> word) {
235 Move m = strToMove(word, state_copy);
236 moves.push_back(m);
237 if (! m.isNormal() || ! state_copy.isValidMove(m))
238 throw ParseError("invalid move "+word);
239 state_copy.makeMove(m);
240 }
241 }
242
243 void osl::record::usi::
244 escape(std::string& str)
245 {
246 boost::algorithm::replace_all(str, "/", "_");
247 boost::algorithm::replace_all(str, "+", "@");
248 boost::algorithm::replace_all(str, " ", ".");
249 }
250
251 void osl::record::usi::
252 unescape(std::string& str)
253 {
254 boost::algorithm::replace_all(str, "_", "/");
255 boost::algorithm::replace_all(str, "@", "+");
256 boost::algorithm::replace_all(str, ".", " ");
257 }
258
259
260 osl::record::usi::
261 UsiFile::UsiFile(const std::string& filename)
262 {
263 std::ifstream is(filename.c_str());
264 std::string line;
265 if (! std::getline(is, line))
266 {
267 const std::string msg = "UsiFile::UsiFile file cannot read ";
268 std::cerr << msg << filename << "\n";
269 throw usi::ParseError(msg + filename);
270 }
271 SimpleState initial;
272 vector<Move> moves;
273 parse(line, initial, moves);
274 assert(initial.isConsistent());
275 record.setInitialState(initial);
276 record::RecordVisitor visitor;
277 visitor.setRecord(&record);
278 visitor.setState(&initial);
279 BOOST_FOREACH(Move move, moves)
280 visitor.addMoveAndAdvance(move);
281 }
282
283 osl::record::usi::
284 UsiFile::~UsiFile()
285 {
286 }
287
288 const osl::record::Record& osl::record::usi::
289 UsiFile::getRecord() const
290 {
291 return record;
292 }
293
294 const osl::NumEffectState osl::record::usi::
295 UsiFile::getInitialState() const
296 {
297 return NumEffectState(record.getInitialState());
298 }
299
300 /* ------------------------------------------------------------------------- */
301 // ;;; Local Variables:
302 // ;;; mode:c++
303 // ;;; c-basic-offset:2
304 // ;;; End: