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}
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の表現 .
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 でもない.
const Square to() const
const Square from() const
利きを持つ局面
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 をおこなう. 玉の素抜きや王手を防いでいるか, 千日手,打歩詰かどうかは検査しない.
void setTurn(Player player)
void init()
盤面が空の状態に初期化
Player turn() const
void setPieceAll(Player player)
void setPiece(Player player, Square sq, Ptype ptype)
const Piece pieceAt(Square sq) const
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