My Project
usi.cc
Go to the documentation of this file.
1/* usi.cc
2 */
3#include "osl/usi.h"
4#include <iostream>
5#include <sstream>
6#include <cctype>
7
8const std::string osl::psn::
9show(Square pos)
10{
11 const int x = pos.x();
12 const int y = pos.y();
13 std::string result = "XX";
14 result[0] = x + '0';
15 result[1] = y + 'a' - 1;
16 return result;
17}
18
20show(Ptype ptype)
21{
22 switch (ptype)
23 {
24 case PAWN: return 'P';
25 case LANCE: return 'L';
26 case KNIGHT: return 'N';
27 case SILVER: return 'S';
28 case GOLD: return 'G';
29 case BISHOP: return 'B';
30 case ROOK: return 'R';
31 case KING: return 'K';
32 default:
33 assert("unsupported ptype" == 0);
34 return '!';
35 }
36}
37
38const std::string osl::psn::
39show(Move m)
40{
41 const Square from = m.from();
42 const Square to = m.to();
43 if (from.isPieceStand())
44 {
45 std::string result = "X*";
46 result[0] = show(m.ptype());
47 result += show(to);
48 return result;
49 }
50 std::string result = show(from);
51 result += show(to);
52 if (m.promoteMask())
53 result += '+';
54 return result;
55}
56
57const std::string osl::psn::
58showXP(Move m)
59{
60 if (m.isInvalid())
61 return "resign";
62 if (m.isPass())
63 return "pass";
64 const Square from = m.from();
65 const Square to = m.to();
66 if (from.isPieceStand())
67 {
68 std::string result = "X*";
69 result[0] = show(m.ptype());
70 result += show(to);
71 return result;
72 }
73 std::string result = show(from);
74 if (m.capturePtype() != PTYPE_EMPTY)
75 result += 'x';
76 result += show(to);
77 if (m.isPromotion())
78 result += '+';
79 else if (canPromote(m.ptype())
80 && (from.canPromote(m.player()) || to.canPromote(m.player())))
81 result += '=';
82 return result;
83}
84
85
87strToMove(const std::string& str, const SimpleState& s)
88{
89 if (str.size() < 4)
90 throw ParseError("Invalid move string: " + str);
91
92 const Square to = strToPos(str.substr(2,2));
93 if (str[1] == '*')
94 {
95 const Ptype ptype = charToPtype(str[0]);
96 return Move(to, ptype, s.turn());
97 }
98
99 const Square from = strToPos(str.substr(0,2));
100 const Ptype ptype = s.pieceOnBoard(from).ptype();
101 const Ptype captured = s.pieceOnBoard(to).ptype();
102 if (! isPiece(ptype))
103 throw ParseError("No piece on square: " + str);
104 bool promotion = false;
105 if (str.size() > 4)
106 {
107 assert(str[4] == '+');
108 promotion = true;
109 }
110 return Move(from, to, (promotion ? promote(ptype) : ptype),
111 captured, promotion, s.turn());
112}
113
115strToPos(const std::string& str)
116{
117 assert(str.size() == 2);
118 const int x = str[0] - '0';
119 const int y = str[1] - 'a' + 1;
120 if (x <= 0 || x > 9 || y <= 0 || y > 9)
121 throw ParseError("Invalid square character: " + str);
122 return Square(x, y);
123}
124
126charToPtype(char c)
127{
128 switch (c)
129 {
130 case 'P': return PAWN;
131 case 'L': return LANCE;
132 case 'N': return KNIGHT;
133 case 'S': return SILVER;
134 case 'G': return GOLD;
135 case 'B': return BISHOP;
136 case 'R': return ROOK;
137 case 'K': return KING;
138 default:
139 return PTYPE_EMPTY;
140 }
141}
142
143/* ------------------------------------------------------------------------- */
144
145const std::string osl::usi::
146show(Move m)
147{
148 if (m.isPass())
149 return "pass";
150 if (m == Move::DeclareWin())
151 return "win";
152 if (! m.isNormal())
153 return "resign";
154 return psn::show(m);
155}
156
157const std::string osl::usi::
158show(PtypeO ptypeo)
159{
160 if (! isPiece(ptypeo))
161 return "";
162
163 char c = psn::show(unpromote(getPtype(ptypeo)));
164 if (getOwner(ptypeo) == WHITE)
165 c = tolower(c);
166 std::string ret(1,c);
167 if (isPromoted(ptypeo))
168 ret = "+" + ret;
169 return ret;
170}
171
172const std::string osl::usi::
173show(Piece p)
174{
175 return show(p.ptypeO());
176}
177
178const std::string osl::usi::
179show(const NumEffectState& state)
180{
181 std::ostringstream ret;
182 if (state == SimpleState(HIRATE)) {
183 ret << "startpos";
184 return ret.str();
185 }
186 ret << "sfen ";
187 for (int y=1; y<=9; ++y) {
188 int empty_count = 0;
189 for (int x=9; x>=1; --x) {
190 const Piece p = state.pieceOnBoard(Square(x,y));
191 if (p.isEmpty()) {
192 ++empty_count;
193 continue;
194 }
195 if (empty_count) {
196 ret << empty_count;
197 empty_count = 0;
198 }
199 ret << show(p);
200 }
201 if (empty_count)
202 ret << empty_count;
203 if (y < 9) ret << "/";
204 }
205 ret << " " << "bw"[state.turn() == WHITE] << " ";
206 bool has_any = false;
207 for (int z=0; z<2; ++z) {
208 const Player player = indexToPlayer(z);
209 for (Ptype ptype: PieceStand::order) {
210 const int count = state.countPiecesOnStand(player, ptype);
211 if (count == 0)
212 continue;
213 if (count > 1)
214 ret << count;
215 ret << show(newPtypeO(player, ptype));
216 has_any = true;
217 }
218 }
219 if (! has_any)
220 ret << "-";
221 ret << " 1";
222 return ret.str();
223}
224
226strToMove(const std::string& str, const NumEffectState& s)
227{
228 if (str == "win")
229 return Move::DeclareWin();
230 if (str == "pass")
231 return Move::PASS(s.turn());
232 if (str == "resign")
233 return Move::INVALID();
234 try {
235 return psn::strToMove(str, s);
236 }
237 catch (std::exception& e) {
238 throw ParseError("usi::strToMove failed for " + str + " by "+ e.what());
239 }
240 catch (...) {
241 throw ParseError("usi::strToMove failed for " + str);
242 }
243}
244
246charToPtypeO(char c)
247{
248 const Ptype ptype = psn::charToPtype(toupper(c));
249 if (ptype == PTYPE_EMPTY)
250 throw ParseError("Invalid piece character: " + std::string(1,c));
251 const Player pl = isupper(c) ? BLACK : WHITE;
252 return newPtypeO(pl, ptype);
253}
254
255void osl::usi::parseBoard(const std::string& word, NumEffectState& out)
256{
257 if (word.empty())
258 throw ParseError(word);
259
260 SimpleState state;
261 state.init();
262 int x=9, y=1;
263 for (size_t i=0; i<word.size(); ++i) {
264 const char c = word[i];
265 if (isalpha(c)) {
266 const PtypeO ptypeo = charToPtypeO(c);
267 state.setPiece(getOwner(ptypeo), Square(x,y), getPtype(ptypeo));
268 --x;
269 } else if (c == '+') {
270 if ( (i+1) >= word.size() )
271 throw ParseError(word);
272 const char next = word[i+1];
273 if (!isalpha(next))
274 throw ParseError(word);
275 const PtypeO ptypeo = charToPtypeO(next);
276 if (!canPromote(ptypeo))
277 throw ParseError(word);
278 const PtypeO promoted = promote(ptypeo);
279 state.setPiece(getOwner(promoted), Square(x,y), getPtype(promoted));
280 --x;
281 ++i;
282 } else if (c == '/') {
283 if (x != 0)
284 throw ParseError(word);
285 x = 9;
286 ++y;
287 } else if (isdigit(c)) {
288 const int n = c - '0';
289 if (n == 0)
290 throw ParseError(word);
291 x -= n;
292 } else {
293 throw ParseError("usi: unknown input " + std::string(1,c));
294 }
295 if (x < 0 || x > 9 || y < 0 || y > 9)
296 throw ParseError(word);
297 }
298 out = NumEffectState(state);
299}
300
301void osl::usi::parse(const std::string& line, NumEffectState& state)
302{
303 NumEffectState board;
304 std::vector<Move> moves;
305 parse(line, board, moves);
306 state.copyFrom(board);
307 for (Move move: moves) {
308 state.makeMove(move);
309 }
310}
311
313 NumEffectState state;
314 parse(line,state);
315 return state;
316}
317
318void osl::usi::parse(const std::string& line, NumEffectState& state, std::vector<Move>& moves)
319{
320 moves.clear();
321 std::istringstream is(line);
322 std::string word;
323 is >> word;
324 if (word == "position")
325 is >> word;
326 if (word == "startpos")
327 state.init(HIRATE);
328 else {
329 if (word != "sfen")
330 throw ParseError("sfen not found "+word);
331 is >> word;
332 parseBoard(word, state);
333 is >> word;
334 if (word != "b" && word != "w")
335 throw ParseError(" turn error "+word);
336 state.setTurn((word == "b") ? BLACK : WHITE);
337 is >> word;
338 if (word != "-") {
339 int prefix = 0;
340 for (char c: word) {
341 if (isalpha(c)) {
342 PtypeO ptypeo = charToPtypeO(c);
343 for (int j=0; j<std::max(1, prefix); ++j)
344 state.setPiece(getOwner(ptypeo), Square::STAND(), getPtype(ptypeo));
345 prefix = 0;
346 }
347 else {
348 if (!isdigit(c))
349 throw ParseError(word);
350 prefix = (c - '0') + prefix*10;
351 if (prefix == 0)
352 throw ParseError(word);
353 }
354 }
355 }
356 state.initPawnMask();
357 int move_number; // will not be used
358 if (! (is >> move_number))
359 return;
360 assert(is);
361 }
362 if (! (is >> word))
363 return;
364 if (word != "moves")
365 throw ParseError("moves not found "+word);
366 NumEffectState state_copy(state);
367 while (is >> word) {
368 Move m = strToMove(word, state_copy);
369 moves.push_back(m);
370 if (! m.isNormal() || ! state_copy.isValidMove(m))
371 throw ParseError("invalid move "+word);
372 state_copy.makeMove(m);
373 }
374}
375
376
377/* ------------------------------------------------------------------------- */
378// ;;; Local Variables:
379// ;;; mode:c++
380// ;;; c-basic-offset:2
381// ;;; End:
圧縮していない moveの表現 .
bool isInvalid() const
state に apply 可能でない場合にtrue
bool isPromotion() const
Ptype ptype() const
Player player() const
bool isPass() const
Ptype capturePtype() const
bool isNormal() const
INVALID でも PASS でもない.
int promoteMask() const
pieceに使うためのmaskなので
const Square to() const
const Square from() const
利きを持つ局面
void makeMove(Move move)
void copyFrom(const NumEffectState &src)
主要部分を高速にコピーする.
PtypeO ptypeO() const
Definition basic_type.h:824
Ptype ptype() const
Definition basic_type.h:821
bool isEmpty() const
Definition basic_type.h:913
const Piece pieceOnBoard(Square sq) const
bool isValidMove(Move move, bool show_error=true) const
合法手かどうかを検査する. isValidMoveByRule, isAlmostValidMove をおこなう. 玉の素抜きや王手を防いでいるか, 千日手,打歩詰かどうかは検査しない.
void setTurn(Player player)
void init()
盤面が空の状態に初期化
Player turn() const
void setPiece(Player player, Square sq, Ptype ptype)
int countPiecesOnStand(Player pl, Ptype ptype) const
持駒の枚数を数える
bool isPieceStand() const
Definition basic_type.h:576
int y() const
将棋としてのY座標を返す.
Definition basic_type.h:567
bool canPromote() const
Definition basic_type.h:659
int x() const
将棋としてのX座標を返す.
Definition basic_type.h:563
const Square strToPos(const std::string &)
Definition usi.cc:115
const std::string showXP(Move)
decorate capture by 'x', promote by '+', and unpromote by '='
Definition usi.cc:58
const std::string show(Move)
Definition usi.cc:39
Ptype charToPtype(char)
Definition usi.cc:126
const Move strToMove(const std::string &, const SimpleState &)
Definition usi.cc:87
const Move strToMove(const std::string &, const NumEffectState &)
Definition usi.cc:226
NumEffectState makeState(const std::string &line)
Definition usi.cc:312
PtypeO charToPtypeO(char)
Definition usi.cc:246
void parse(const std::string &line, NumEffectState &)
[sfen <sfenstring> | startpos ] moves <move1> ... <movei>
Definition usi.cc:301
void parseBoard(const std::string &board, NumEffectState &)
盤面を取得する.
Definition usi.cc:255
const std::string show(Move)
Definition usi.cc:146
Ptype
駒の種類を4ビットでコード化する
Definition basic_type.h:84
@ ROOK
Definition basic_type.h:100
@ BISHOP
Definition basic_type.h:99
@ PAWN
Definition basic_type.h:95
@ KING
Definition basic_type.h:93
@ KNIGHT
Definition basic_type.h:97
@ PTYPE_EMPTY
Definition basic_type.h:85
@ SILVER
Definition basic_type.h:98
@ GOLD
Definition basic_type.h:94
@ LANCE
Definition basic_type.h:96
Ptype getPtype(PtypeO ptypeO)
Definition basic_type.h:217
constexpr Player indexToPlayer(int n)
Definition basic_type.h:19
bool canPromote(Ptype ptype)
ptypeがpromote可能な型かどうかのチェック promote済みの場合はfalseを返す
Definition basic_type.h:147
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に,promote前の型を返す. promoteしていない型の時はそのまま返す
Definition basic_type.h:157
Player getOwner(PtypeO ptypeO)
Definition basic_type.h:256
bool isPromoted(Ptype ptype)
ptypeがpromote後の型かどうかのチェック
Definition basic_type.h:137
Player
Definition basic_type.h:8
@ WHITE
Definition basic_type.h:10
@ BLACK
Definition basic_type.h:9
constexpr bool isPiece(Ptype ptype)
ptypeが空白やEDGEでないかのチェック
Definition basic_type.h:120
@ HIRATE
Definition simpleState.h:21
PtypeO
Player + Ptype [-15, 15] PtypeO の O は Owner の O.
Definition basic_type.h:199
PtypeO newPtypeO(Player player, Ptype ptype)
Definition basic_type.h:211
Ptype promote(Ptype ptype)
promote可能なptypeに対して,promote後の型を返す promote不可のptypeを与えてはいけない.
Definition basic_type.h:173
PtypeO captured(PtypeO ptypeO)
unpromoteすると共に,ownerを反転する.
Definition basic_type.h:264