My Project
csa.cc
Go to the documentation of this file.
1#include "osl/csa.h"
2#include "osl/simpleState.h"
4#include "osl/oslConfig.h"
5#include <boost/algorithm/string/split.hpp>
6#include <boost/algorithm/string/trim.hpp>
7#include <iostream>
8#include <sstream>
9#include <stdexcept>
10#include <cassert>
11#include <string>
12#include <fstream>
13#include <array>
14
15/* ------------------------------------------------------------------------- */
16
18charToPlayer(char c)
19{
20 if(c=='+')
21 return BLACK;
22 if(c=='-')
23 return WHITE;
24 throw CsaIOError("not a csa PlayerCharacter "+std::string(1,c));
25}
26
28strToPos(const std::string& s)
29{
30 int x=s.at(0)-'0';
31 int y=s.at(1)-'0';
32 if(x==0 && y==0)
33 return Square::STAND();
34 return Square(x,y);
35}
36
38strToPtype(const std::string& s)
39{
40 for(int i=0;i<16;i++){
41 if(s == Ptype_Table.getCsaName(static_cast<Ptype>(i)))
42 return static_cast<Ptype>(i);
43 }
44 throw CsaIOError("unknown std::string in csa::strToPtype "+s);
45}
46
48strToMove(const std::string& s,const SimpleState& state)
49{
50 if (s == "%KACHI")
51 return Move::DeclareWin();
52 if (s == "%TORYO")
53 return Move::INVALID();
54 if (s == "%PASS") // FIXME: not in CSA protocol
55 return Move::PASS(state.turn());
56
57 Player pl=csa::charToPlayer(s.at(0));
58 Square fromPos=csa::strToPos(s.substr(1,2));
59 Square toPos=csa::strToPos(s.substr(3,2));
60 Ptype ptype=csa::strToPtype(s.substr(5,2));
61 if(fromPos==Square::STAND()){
62 if (isPromoted(ptype))
63 throw CsaIOError("drop with promote ?! in csa::strToMove "+s);
64 return Move(toPos,ptype,pl);
65 }
66 else{
67 Piece p0=state.pieceAt(fromPos);
68 Piece p1=state.pieceAt(toPos);
69 Ptype capturePtype=p1.ptype();
70 bool isPromote=(p0.ptype()!=ptype);
71 if (! ((p0.ptype()==ptype)||(p0.ptype()==unpromote(ptype))))
72 throw CsaIOError("bad promotion in csa::strToMove "+s);
73 return Move(fromPos,toPos,ptype,
74 capturePtype,isPromote,pl);
75 }
76}
77
78/* ------------------------------------------------------------------------- */
79const std::string osl::csa::
80show(Player player, std::string& buf, size_t offset)
81{
82 assert(buf.size() >= offset+1);
83 buf[offset] = (player==BLACK) ? '+' : '-';
84 return buf;
85}
86
87const std::string osl::csa::
88show(Move move, std::string& buf)
89{
90 assert(buf.capacity() >= 7);
91 buf.resize(7);
92 if (move == Move::DeclareWin())
93 return buf = "%KACHI";
94 if (move.isInvalid())
95 return buf = "%TORYO";
96 if (move.isPass())
97 return buf = "%PASS"; // FIXME: not in CSA protocol
98 show(move.player(), buf);
99 show(move.from(), buf, 1);
100 show(move.to(), buf, 3);
101 show(move.ptype(), buf, 5);
102 return buf;
103}
104
105const std::string osl::csa::
106show(Square pos, std::string& buf, size_t offset)
107{
108 assert(buf.size() >= offset+2);
109 if (pos.isPieceStand())
110 {
111 buf[0+offset] = '0';
112 buf[1+offset] = '0';
113 return buf;
114 }
115 const int x = pos.x();
116 const int y = pos.y();
117 buf[offset+0] = x + '0';
118 buf[offset+1] = y + '0';
119 return buf;
120}
121
122const std::string osl::csa::
123show(Ptype ptype, std::string& buf, size_t offset)
124{
125 assert(buf.size() >= offset+2);
126 const char *name = Ptype_Table.getCsaName(ptype);
127 buf[0+offset] = name[0];
128 buf[1+offset] = name[1];
129 return buf;
130}
131
132const std::string osl::csa::
133show(Move move)
134{
135 // NOTE: copy コピーを返すので dangling pointer ではない
136 std::string buf("+7776FU");
137 return show(move, buf);
138}
139
140const std::string osl::csa::
141fancyShow(Move move)
142{
143 std::string ret = show(move);
144 if (move.isNormal()) {
145 if (move.capturePtype() != PTYPE_EMPTY)
146 ret += "x" + show(move.capturePtype());
147 if (move.isPromotion())
148 ret += '+';
149 }
150 return ret;
151}
152
153const std::string osl::csa::
154show(Player player)
155{
156 std::string buf("+");
157 return show(player, buf);
158}
159
160const std::string osl::csa::
161show(Square position)
162{
163 std::string buf("00");
164 return show(position, buf);
165}
166
167const std::string osl::csa::
168show(Ptype ptype)
169{
170 std::string buf("OU");
171 return show(ptype, buf);
172}
173
174const std::string osl::csa::
175show(Piece piece)
176{
177 if (piece.isEdge())
178 return " ";
179 if (piece.isEmpty())
180 return " * ";
181
182 assert(piece.isPiece() && isPiece(piece.ptype()));
183 assert(unpromote(piece.ptype()) == Piece_Table.getPtypeOf(piece.number()));
184 return show(piece.owner())
185 + show(piece.ptype());
186}
187
188const std::string osl::csa::
189show(const Move *first, const Move *last)
190{
191 std::ostringstream out;
192 for (; first != last; ++first) {
193 if (first->isInvalid())
194 break;
195 out << show(*first);
196 }
197 return out.str();
198}
199
200/* ------------------------------------------------------------------------- */
202{
203 std::ifstream is(filename);
204 if (! is) {
205 const std::string msg = "CsaFileMinimal::CsaFileMinimal file open failed ";
206 std::cerr << msg << filename << "\n";
207 throw CsaIOError(msg + filename);
208 }
209 load(is);
210}
211
213{
214 load(is);
215}
217{
218}
219
220void osl::csa::CsaFileMinimal::load(std::istream& is)
221{
222 SimpleState work;
223 work.init();
224 std::string line;
225 CArray<bool, 9> board_parsed = {{ false }};
226 while (std::getline(is, line))
227 {
228 // quick hack for \r
229 if ((! line.empty())
230 && (line[line.size()-1] == 13))
231 line.erase(line.size()-1);
232
233 std::vector<std::string> elements;
234 boost::algorithm::split(elements, line, boost::algorithm::is_any_of(","));
235 for (auto& e: elements) {
236 boost::algorithm::trim(e);
237 boost::algorithm::trim_left(e);
238 parseLine(work, record, e, board_parsed);
239 }
240 }
241 if (*std::min_element(board_parsed.begin(), board_parsed.end()) == false)
242 throw CsaIOError("incomplete position description in csaParseLine");
243 assert(record.initial_state.isConsistent());
244}
245
247CsaFileMinimal::parseLine(SimpleState& state, RecordMinimal& record, std::string s,
248 CArray<bool,9>& board_parsed)
249{
250 while (! s.empty() && isspace(s[s.size()-1])) // ignore trailing garbage
251 s.resize(s.size()-1);
252 if (s.length()==0)
253 return true;
254 switch(s.at(0)){
255 case 'P': /* 開始盤面 */
256 switch(s.at(1)){
257 case 'I': /* 平手初期配置 */
258 board_parsed.fill(true);
259 state.init(HIRATE);
260 break;
261 case '+': /* 先手の駒 */
262 case '-':{ /* 後手の駒 */
263 Player pl=csa::charToPlayer(s.at(1));
264 for(int i=2;i<=(int)s.length()-4;i+=4){
265 Square pos=csa::strToPos(s.substr(i,2));
266 if(s.substr(i+2,2) == "AL"){
267 state.setPieceAll(pl);
268 }
269 else{
270 Ptype ptype=csa::strToPtype(s.substr(i+2,2));
271 state.setPiece(pl,pos,ptype);
272 }
273 }
274 break;
275 }
276 default:
277 if(isdigit(s.at(1))){
278 const int y=s.at(1)-'0';
279 board_parsed[y-1] = true;
280 for(unsigned int x=9,i=2;i<s.length();i+=3,x--){
281 if (s.at(i) != '+' && s.at(i) != '-' && s.find(" *",i)!=i) {
283 throw CsaIOError("parse board error " + s);
284 else
285 std::cerr << "possible typo for empty square " << s << "\n";
286 }
287 if (s.at(i) != '+' && s.at(i) != '-') continue;
288 Player pl=csa::charToPlayer(s.at(i));
289 Square pos(x,y);
290 Ptype ptype=csa::strToPtype(s.substr(i+1,2));
291 state.setPiece(pl,pos,ptype);
292 }
293 }
294 }
295 break;
296 case '+':
297 case '-':{
298 Player pl=csa::charToPlayer(s.at(0));
299 if(s.length()==1){
300 state.setTurn(pl);
301 state.initPawnMask();
302 record.initial_state = NumEffectState(state);
303 }
304 else{ // actual moves
305 const Move m = csa::strToMove(s,state);
306 if (! state.isValidMove(m))
307 {
308 std::cerr << "Illegal move " << m << std::endl;
309 throw CsaIOError("illegal move "+s);
310 }
311 record.moves.push_back(m);
312 NumEffectState copy(state);
313 copy.makeMove(m);
314 state = copy;
315 }
316 break;
317 }
318 default:
319 return false; // there are unhandled contents
320 }
321 return true;
322}
323
324/* ------------------------------------------------------------------------- */
325osl::csa::CsaString::CsaString(const std::string& s)
326{
327 std::istringstream is(s);
328 load(is);
329}
330
331/* ------------------------------------------------------------------------- */
332// ;;; Local Variables:
333// ;;; mode:c++
334// ;;; c-basic-offset:2
335// ;;; End:
void fill(const T_simple &value=T_simple())
Definition: container.h:67
iterator end()
Definition: container.h:65
iterator begin()
Definition: container.h:64
圧縮していない moveの表現 .
Definition: basic_type.h:1052
bool isInvalid() const
state に apply 可能でない場合にtrue
Definition: basic_type.h:1202
bool isPromotion() const
Definition: basic_type.h:1147
Ptype ptype() const
Definition: basic_type.h:1155
Player player() const
Definition: basic_type.h:1195
bool isPass() const
Definition: basic_type.h:1092
Ptype capturePtype() const
Definition: basic_type.h:1180
bool isNormal() const
INVALID でも PASS でもない.
Definition: basic_type.h:1088
const Square to() const
Definition: basic_type.h:1132
const Square from() const
Definition: basic_type.h:1125
利きを持つ局面
void makeMove(Move move)
Ptype getPtypeOf(int num) const
Definition: pieceTable.h:18
Ptype ptype() const
Definition: basic_type.h:821
bool isEmpty() const
Definition: basic_type.h:913
bool isEdge() const
Definition: basic_type.h:919
Player owner() const
Definition: basic_type.h:963
bool isPiece() const
Definition: basic_type.h:953
int number() const
Definition: basic_type.h:828
const char * getCsaName(Ptype ptype) const
Definition: ptypeTable.h:80
bool isValidMove(Move move, bool show_error=true) const
合法手かどうかを検査する. isValidMoveByRule, isAlmostValidMove をおこなう. 玉の素抜きや王手を防いでいるか, 千日手,打歩詰かどうかは検査しない.
Definition: simpleState.cc:435
void setTurn(Player player)
Definition: simpleState.h:217
void init()
盤面が空の状態に初期化
Definition: simpleState.cc:44
Player turn() const
Definition: simpleState.h:220
void setPieceAll(Player player)
Definition: simpleState.cc:139
void setPiece(Player player, Square sq, Ptype ptype)
Definition: simpleState.cc:114
const Piece pieceAt(Square sq) const
Definition: simpleState.h:167
bool isPieceStand() const
Definition: basic_type.h:576
int y() const
将棋としてのY座標を返す.
Definition: basic_type.h:567
int x() const
将棋としてのX座標を返す.
Definition: basic_type.h:563
static bool parseLine(SimpleState &, RecordMinimal &, std::string element, CArray< bool, 9 > &)
Definition: csa.cc:247
virtual ~CsaFileMinimal()
Definition: csa.cc:216
RecordMinimal load() const
Definition: csa.h:58
CsaString(const std::string &)
Definition: csa.cc:325
const Square strToPos(const std::string &s)
Definition: csa.cc:28
Ptype strToPtype(const std::string &s)
Definition: csa.cc:38
const std::string show(Move)
Definition: csa.cc:133
Player charToPlayer(char c)
Definition: csa.cc:18
const Move strToMove(const std::string &s, const SimpleState &st)
Definition: csa.cc:48
const std::string fancyShow(Move)
Definition: csa.cc:141
Ptype
駒の種類を4ビットでコード化する
Definition: basic_type.h:84
@ PTYPE_EMPTY
Definition: basic_type.h:85
const PtypeTable Ptype_Table
Definition: tables.cc:97
const PieceTable Piece_Table
Definition: tables.cc:94
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に,promote前の型を返す. promoteしていない型の時はそのまま返す
Definition: basic_type.h:157
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
static int inUnitTest()
Definition: oslConfig.h:87
NumEffectState initial_state
Definition: csa.h:44
std::vector< Move > moves
Definition: csa.h:45