csa.cc
Go to the documentation of this file.
1 #include "osl/csa.h"
2 #include "osl/simpleState.h"
3 #include "osl/bits/pieceTable.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 
18 charToPlayer(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 
28 strToPos(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 
38 strToPtype(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 
48 strToMove(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 /* ------------------------------------------------------------------------- */
79 const std::string osl::csa::
80 show(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 
87 const std::string osl::csa::
88 show(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 
105 const std::string osl::csa::
106 show(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 
122 const std::string osl::csa::
123 show(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 
132 const std::string osl::csa::
133 show(Move move)
134 {
135  // NOTE: copy コピーを返すので dangling pointer ではない
136  std::string buf("+7776FU");
137  return show(move, buf);
138 }
139 
140 const std::string osl::csa::
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 
153 const std::string osl::csa::
154 show(Player player)
155 {
156  std::string buf("+");
157  return show(player, buf);
158 }
159 
160 const std::string osl::csa::
161 show(Square position)
162 {
163  std::string buf("00");
164  return show(position, buf);
165 }
166 
167 const std::string osl::csa::
168 show(Ptype ptype)
169 {
170  std::string buf("OU");
171  return show(ptype, buf);
172 }
173 
174 const std::string osl::csa::
175 show(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 
188 const std::string osl::csa::
189 show(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 /* ------------------------------------------------------------------------- */
201 osl::csa::CsaFileMinimal::CsaFileMinimal(const std::string& filename)
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 
220 void 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");
244 }
245 
246 bool osl::csa::
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) {
282  if (OslConfig::inUnitTest())
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 /* ------------------------------------------------------------------------- */
325 osl::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:
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に,promote前の型を返す. promoteしていない型の時はそのまま返す ...
Definition: basic_type.h:157
iterator begin()
Definition: container.h:64
RecordMinimal record
Definition: csa.h:53
int number() const
Definition: basic_type.h:828
Ptype ptype() const
Definition: basic_type.h:821
void setPieceAll(Player player)
Definition: simpleState.cc:139
void setPiece(Player player, Square sq, Ptype ptype)
Definition: simpleState.cc:114
bool isPiece() const
Definition: basic_type.h:953
const Piece pieceAt(Square sq) const
Definition: simpleState.h:167
bool isNormal() const
INVALID でも PASS でもない.
Definition: basic_type.h:1088
static int inUnitTest()
Definition: oslConfig.h:87
NumEffectState initial_state
Definition: csa.h:44
int y() const
将棋としてのY座標を返す.
Definition: basic_type.h:567
int x() const
将棋としてのX座標を返す.
Definition: basic_type.h:563
const char * getCsaName(Ptype ptype) const
Definition: ptypeTable.h:80
bool isConsistent(bool showError=true) const
bool isValidMove(Move move, bool show_error=true) const
合法手かどうかを検査する. isValidMoveByRule, isAlmostValidMove をおこなう. 玉の素抜きや王手を防いで...
Definition: simpleState.cc:435
Ptype
駒の種類を4ビットでコード化する
Definition: basic_type.h:83
void init()
盤面が空の状態に初期化
Definition: simpleState.cc:44
Ptype ptype() const
Definition: basic_type.h:1155
const PtypeTable Ptype_Table
Definition: tables.cc:97
const Square from() const
Definition: basic_type.h:1125
Player charToPlayer(char c)
Definition: csa.cc:18
圧縮していない moveの表現 .
Definition: basic_type.h:1051
bool isPass() const
Definition: basic_type.h:1092
void makeMove(Move move)
const PieceTable Piece_Table
Definition: tables.cc:94
Player player() const
Definition: basic_type.h:1195
Player turn() const
Definition: simpleState.h:220
const Square strToPos(const std::string &s)
Definition: csa.cc:28
bool isEdge() const
Definition: basic_type.h:919
利きを持つ局面
virtual ~CsaFileMinimal()
Definition: csa.cc:216
Ptype capturePtype() const
Definition: basic_type.h:1180
RecordMinimal load() const
Definition: csa.h:58
const Square to() const
Definition: basic_type.h:1132
void fill(const T_simple &value=T_simple())
Definition: container.h:67
const Move strToMove(const std::string &s, const SimpleState &st)
Definition: csa.cc:48
iterator end()
Definition: container.h:65
const std::string show(Move)
Definition: csa.cc:133
constexpr bool isPiece(Ptype ptype)
ptypeが空白やEDGEでないかのチェック
Definition: basic_type.h:120
Ptype getPtypeOf(int num) const
Definition: pieceTable.h:18
bool isPromoted(Ptype ptype)
ptypeがpromote後の型かどうかのチェック
Definition: basic_type.h:137
bool isPromotion() const
Definition: basic_type.h:1147
bool isEmpty() const
Definition: basic_type.h:913
CsaString(const std::string &)
Definition: csa.cc:325
Player
Definition: basic_type.h:8
const std::string fancyShow(Move)
Definition: csa.cc:141
std::vector< Move > moves
Definition: csa.h:45
bool isPieceStand() const
Definition: basic_type.h:576
static bool parseLine(SimpleState &, RecordMinimal &, std::string element, CArray< bool, 9 > &)
Definition: csa.cc:247
Ptype strToPtype(const std::string &s)
Definition: csa.cc:38
bool isInvalid() const
state に apply 可能でない場合にtrue
Definition: basic_type.h:1202
void setTurn(Player player)
Definition: simpleState.h:217
Player owner() const
Definition: basic_type.h:963