My Project
kisen.cc
Go to the documentation of this file.
1 #include "osl/record/kisen.h"
2 #include "osl/misc/filePath.h"
4 #include "osl/misc/sjis2euc.h"
5 #include <boost/filesystem/convenience.hpp>
6 #include <iostream>
7 
9  assert(1<=pos && pos<=0x51);
10  int y=((pos-1)/9)+1, x=((pos-1)%9)+1;
11  return Square(x,y);
12 }
14 {
15  return ((pos.y() - 1) * 9 + 1) + pos.x() - 1;
16 }
17 
19  Move move;
20 
21  if(1<=c1 && c1<=0x51){
22  Square from=convertSquare(c1),to;
23  Piece fromPiece=state.pieceOnBoard(from);
24  if (! fromPiece.isPiece())
25  throw CsaIOError("Square error");
26  assert(fromPiece.isPiece());
27  assert(fromPiece.owner()==state.turn() ||
28  (std::cerr << c1 << "," << from << "," << fromPiece << std::endl,0)
29  );
30  bool isPromote=false;
31  if(1<=c0 && c0<=0x51){
32  to=convertSquare(c0);
33  }
34  else if(0x65<=c0 && c0<=0xb5){
35  to=convertSquare(c0-0x64);
36  isPromote=true;
37  }
38  else{
39  throw CsaIOError("c0 range error");
40  }
41  Piece toPiece=state.pieceAt(to);
42  if (! toPiece.isEmpty() && toPiece.owner()!=alt(state.turn()))
43  throw CsaIOError("inconsintent move (to)");
44  Ptype ptype=fromPiece.ptype();
45  if(isPromote)ptype=promote(ptype);
46  const Ptype captured = toPiece.ptype();
47  if (captured == KING)
48  return Move::INVALID();
49  move=Move(from,to,ptype,captured,isPromote,state.turn());
50  }
51  else{
52  assert(0x65<=c1);
53  if (!(1<=c0&&c0<=0x51)) {
54  throw CsaIOError("unknown kisen move "+std::to_string((int)c0));
55  }
56  assert(1<=c0&&c0<=0x51);
57  Square to=convertSquare(c0);
58  Ptype ptype=PTYPE_EMPTY;
59  int piece_on_stand = c1;
60  const Ptype ptypes[]={ROOK,BISHOP,GOLD,SILVER,KNIGHT,LANCE,PAWN};
61  for(size_t i=0;i<sizeof(ptypes)/sizeof(Ptype);i++){
62  int count=state.countPiecesOnStand(state.turn(),ptypes[i]);
63  if(count>0){
64  if(piece_on_stand>0x64){
65  piece_on_stand-=count;
66  if(piece_on_stand<=0x64) ptype=ptypes[i];
67  }
68  }
69  }
70  assert(ptype!=PTYPE_EMPTY ||
71  (std::cerr << state << to << " " << c1
72  << " " << piece_on_stand << std::endl, false));
73  move=Move(to,ptype,state.turn());
74  }
75  if (! state.isValidMove(move,true)) {
76  std::cerr << "warning: bad move in kisen\n" << state << move << "\n";
77  return Move();
78  }
79  assert(state.isValidMove(move,true) ||
80  (std::cerr << state << move << std::endl, false));
81  return move;
82 }
83 
84 osl::record::KisenFile::KisenFile(const std::string& f)
85  :ifs(f), filename(f)
86 {
87  if (! ifs)
88  throw CsaIOError("KisenFile not found "+f);
89  ifs.seekg(0,std::ios::end);
90  assert((ifs.tellg() % 512)==0);
91  number_of_games=ifs.tellg()/512;
92 }
93 
94 std::vector<osl::Move> osl::record::KisenFile::moves(size_t index)
95 {
96  assert(index<size());
97  std::vector<Move> moves;
98  // std::cerr << "Game[" << index << "]" << std::endl;
99  ifs.seekg(index*512,std::ios::beg);
101  ifs.read(reinterpret_cast<char *>(&cbuf[0]),512);
102  NumEffectState state;
103  //
104  Player turn=BLACK;
105  for(size_t turn_count=0;
106  (turn_count*2 < cbuf.size())
107  && cbuf[turn_count*2]!=0 && cbuf[turn_count*2+1]!=0;
108  turn_count++, turn=alt(turn)){
109  if(turn_count==KisenFile::MaxMoves || cbuf[ turn_count *2 ] == 0 || cbuf[ turn_count * 2 + 1 ] == 0 ){ break; }
110  int c0=cbuf[turn_count*2], c1=cbuf[turn_count*2+1];
111  if (moves.empty() && c0 == 0xff && c1 == 0xff) // komaochi
112  break;
113  const Move move=KisenUtils::convertMove(state,c0,c1);
114  if (move.isInvalid())
115  break;
116  moves.push_back(move);
117  state.makeMove(move);
118  assert(state.isConsistent( true ) );
119  }
120  return moves;
121 }
122 #ifndef MINIMAL
123 std::string osl::record::KisenFile::ipxFileName(const std::string& filename)
124 {
125  namespace bf = boost::filesystem;
126  const bf::path ipxfilename = bf::change_extension(bf::path(filename), ".ipx");
127  return misc::file_string(ipxfilename);
128 }
129 
130 osl::record::KisenIpxFile::KisenIpxFile(const std::string& filename)
131  :ifs(filename), file_name(filename)
132 {
133  if (! ifs)
134  throw CsaIOError("KisenIpxFile not found "+filename);
135  ifs.seekg(0,std::ios::end);
136  assert((ifs.tellg() % 256)==0);
137  number_of_games=ifs.tellg()/256;
138 }
139 std::string osl::record::KisenIpxFile::player(size_t index,Player pl)
140 {
141  assert(index<size());
142  ifs.seekg(index*256,std::ios::beg);
144  ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
145  int startIndex=0;
146  if(pl==WHITE)startIndex=14;
147  CArray<char,15> buf;
148  buf[14]='\0';
149  strncpy(&buf[0],reinterpret_cast<char *>(&cbuf[startIndex]),14);
150  return misc::sjis2euc(std::string(&buf[0]));
151 }
152 unsigned int osl::record::KisenIpxFile::rating(size_t index,Player pl)
153 {
154  assert(index<size());
155  ifs.seekg(index*256,std::ios::beg);
157  ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
158  int startIndex=0324;
159  if(pl==WHITE)startIndex=0326;
160  return cbuf[startIndex]+256*cbuf[startIndex+1];
161 }
162 unsigned int osl::record::KisenIpxFile::result(size_t index)
163 {
164  assert(index<size());
165  ifs.seekg(index*256,std::ios::beg);
167  ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
168  return cbuf[64+48+6];
169 }
170 std::string osl::record::KisenIpxFile::title(size_t index,Player pl)
171 {
172  assert(index<size());
173  ifs.seekg(index*256,std::ios::beg);
175  ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
176  int startIndex=28;
177  if(pl==WHITE)startIndex+=8;
178  CArray<char,9> buf;
179  buf[8]='\0';
180  strncpy(&buf[0],reinterpret_cast<const char*>(&cbuf[startIndex]),8);
181  return misc::sjis2euc(std::string(&buf[0]));
182 }
183 boost::gregorian::date osl::record::KisenIpxFile::startDate(size_t index)
184 {
185  assert(index<size());
186  ifs.seekg(index*256,std::ios::beg);
188  ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
189  const int startIndex=84;
190  const unsigned int year = cbuf[startIndex] + 256*cbuf[startIndex+1];
191  const unsigned int month = cbuf[startIndex+2];
192  const unsigned int day = cbuf[startIndex+3];
193  try {
194  const boost::gregorian::date d = boost::gregorian::date(year, month, day);
195  return d;
196  } catch (std::out_of_range& e) {
197  std::cerr << e.what() << ": ["
198  << index << "] " << year << "-" << month << "-" << day << "\n";
199  return boost::gregorian::date(boost::gregorian::not_a_date_time);
200  }
201 }
202 
203 osl::record::KisenPlusFile::KisenPlusFile(const std::string& filename)
204  :ifs(filename)
205 {
206  if (! ifs)
207  throw CsaIOError("KisenPlusFile not found");
208  ifs.seekg(0,std::ios::end);
209  assert((ifs.tellg() % 2048)==0);
210  number_of_games=ifs.tellg()/2048;
211 }
212 
213 std::vector<osl::Move> osl::record::KisenPlusFile::moves(size_t index)
214 {
215  std::vector<Move> moves;
216  std::vector<int> times;
217  load(index, moves, times);
218  return moves;
219 }
220 
222  std::vector<Move>& moves, std::vector<int>& times)
223 {
224  assert(index<size());
225  // std::cerr << "Game[" << index << "]" << std::endl;
226  ifs.seekg(index*2048,std::ios::beg);
228  ifs.read(reinterpret_cast<char *>(&cbuf[0]),2048);
229  NumEffectState state;
230  for (size_t i = 0;
231  i < 2048 && cbuf[i]!=0 && cbuf[i+1]!=0;
232  i += 8)
233  {
234  int c0 = cbuf[i];
235  int c1 = cbuf[i + 1];
236  bool is_promote = false;
237  Move move;
238 
239  if (c0 > 100)
240  {
241  is_promote = true;
242  c0 = 256 - c0;
243  }
244 
245  Square to(c0 % 10, c0 / 10);
246 
247  if (c1 < 10)
248  {
249  // drop
250  move = Move(to,
251  PieceStand::order[c1 - 1],
252  state.turn());
253  }
254  else
255  {
256  Square from(c1 % 10, c1 / 10);
257  Ptype type = state.pieceAt(from).ptype();
258  if (is_promote)
259  type = promote(type);
260  move = Move(from, to,
261  type, state.pieceAt(to).ptype(),
262  is_promote, state.turn());
263  }
264  moves.push_back(move);
265  times.push_back(cbuf[i + 7] * 60 + cbuf[i + 6]);
266  state.makeMove(move);
267  assert(state.isConsistent( true ) );
268  }
269 }
270 #endif
271 
274 {
275 }
276 #ifndef MINIMAL
279 {
280 }
281 
283 KisenWriter::save(const RecordMinimal& record)
284 {
285  if (!(record.initial_state == NumEffectState()))
286  {
287  std::cerr << "Can not save non-HIRATE record" << std::endl;
288  return;
289  }
290  NumEffectState state;
291  const int max_length = std::min(256, static_cast<int>(record.moves.size()));
292  for (int i = 0; i < max_length; ++i)
293  {
294  const Move move = record.moves[i];
295  if (!move.isDrop())
296  {
297  int from = KisenUtils::convertSquare(move.from());
298  int to = KisenUtils::convertSquare(move.to());
299  if (move.isPromotion())
300  {
301  to += 100;
302  }
303  os << static_cast<char>(to) << static_cast<char>(from);
304  }
305  else
306  {
307  int to = KisenUtils::convertSquare(move.to());
308  int count = 1;
309  for (Ptype ptype: PieceStand::order) {
310  if (ptype == move.ptype())
311  {
312  break;
313  }
314  count += state.countPiecesOnStand(move.player(), ptype);
315  }
316  count += 100;
317  os << static_cast<char>(to) << static_cast<char>(count);
318  }
319  state.makeMove(record.moves[i]);
320  }
321  for (int i = max_length; i < 256; ++i)
322  {
323  os << '\0' << '\0';
324  }
325 }
326 
328 KisenIpxWriter::writeString(const std::string &name, size_t length)
329 {
330  for (size_t i = 0; i < length; ++i)
331  {
332  if (i < name.length())
333  {
334  os << name[i];
335  }
336  else
337  {
338  os << '\0';
339  }
340  }
341 }
342 
344 KisenIpxWriter::writeRating(int rating)
345 {
346  int high = rating / 256;
347  int low = rating % 256;
348  os << static_cast<char>(low) << static_cast<char>(high);
349 }
350 
352 KisenIpxWriter::writeStartDate(int year, int month, int day, int hour, int min)
353 {
354  const int high_year = year / 256;
355  const int low_year = year % 256;
356  os << static_cast<char>(low_year)
357  << static_cast<char>(high_year)
358  << static_cast<char>(month)
359  << static_cast<char>(day)
360  << static_cast<char>(hour)
361  << static_cast<char>(min);
362 }
363 
365 KisenIpxWriter::save(const Record &record,
366  int black_rating, int white_rating,
367  const std::string &black_title,
368  const std::string &white_title)
369 {
370  // total 256 bytes
371  // Player name: 14 bytes each
372 #ifndef _WIN32
373  writeString(IconvConvert::convert("EUC-JP", "SJIS", record.player[BLACK]), 14);
374  writeString(IconvConvert::convert("EUC-JP", "SJIS", record.player[WHITE]), 14);
375  writeString(IconvConvert::convert("EUC-JP", "SJIS", black_title), 8);
376  writeString(IconvConvert::convert("EUC-JP", "SJIS", white_title), 8);
377 #else
378  writeString("", 14);
379  writeString("", 14);
380  writeString("", 8);
381  writeString("", 8);
382 #endif
383  for (int i = 44; i < 84; ++i)
384  {
385  os << '\0';
386  }
387  const boost::gregorian::date start_date = record.start_date;
388  if (!start_date.is_special()) {
389  // time is fixed with 9am
390  writeStartDate(start_date.year(), start_date.month(), start_date.day(), 9, 0);
391  } else {
392  for (int i = 84; i < 90; ++i)
393  {
394  os << '\0';
395  }
396  }
397  for (int i = 90; i < 118; ++i)
398  {
399  os << '\0';
400  }
401  std::vector<Move> moves = record.moves();
402  std::vector<int> time = record.times;
403  // TODO: sennichite, jishogi
404  if (moves.size() <= 256)
405  {
406  if (moves.size() % 2 == 0)
407  os << static_cast<char>(KisenIpxFile::WHITE_WIN);
408  else
409  os << static_cast<char>(KisenIpxFile::BLACK_WIN);
410  }
411  else
412  {
413  if (moves.size() % 2 == 0)
414  os << static_cast<char>(KisenIpxFile::WHITE_WIN_256);
415  else
416  os << static_cast<char>(KisenIpxFile::BLACK_WIN_256);
417  }
418  for (int i = 119; i < 212; ++i)
419  {
420  os << '\0';
421  }
422  writeRating(black_rating);
423  writeRating(white_rating);
424  for (int i = 216; i < 256; ++i)
425  {
426  os << '\0';
427  }
428 }
429 #endif
430 // ;;; Local Variables:
431 // ;;; mode:c++
432 // ;;; c-basic-offset:2
433 // ;;; End:
static size_t size()
Definition: container.h:76
圧縮していない moveの表現 .
Definition: basic_type.h:1052
static const Move INVALID()
Definition: basic_type.h:1095
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 isDrop() const
Definition: basic_type.h:1150
const Square to() const
Definition: basic_type.h:1132
const Square from() const
Definition: basic_type.h:1125
利きを持つ局面
void makeMove(Move move)
bool isConsistent(bool showError=true) const
static const CArray< Ptype, 7 > order
持駒の表示で良く使われる順番.
Ptype ptype() const
Definition: basic_type.h:821
bool isEmpty() const
Definition: basic_type.h:913
Player owner() const
Definition: basic_type.h:963
bool isPiece() const
Definition: basic_type.h:953
const Piece pieceOnBoard(Square sq) const
Definition: simpleState.h:170
bool isValidMove(Move move, bool show_error=true) const
合法手かどうかを検査する. isValidMoveByRule, isAlmostValidMove をおこなう. 玉の素抜きや王手を防いでいるか, 千日手,打歩詰かどうかは検査しない.
Definition: simpleState.cc:435
Player turn() const
Definition: simpleState.h:220
int countPiecesOnStand(Player pl, Ptype ptype) const
持駒の枚数を数える
Definition: simpleState.h:182
const Piece pieceAt(Square sq) const
Definition: simpleState.h:167
int y() const
将棋としてのY座標を返す.
Definition: basic_type.h:567
int x() const
将棋としてのX座標を返す.
Definition: basic_type.h:563
static const size_t MaxMoves
Definition: kisen.h:31
size_t number_of_games
Definition: kisen.h:28
std::vector< Move > moves(size_t index)
Definition: kisen.cc:94
KisenFile(const std::string &filename)
Definition: kisen.cc:84
std::string ipxFileName() const
Definition: kisen.h:39
std::ifstream ifs
Definition: kisen.h:27
boost::gregorian::date startDate(size_t index)
開始日の年月日を返す
Definition: kisen.cc:183
std::ifstream ifs
Definition: kisen.h:68
std::string player(size_t index, Player pl)
Definition: kisen.cc:139
std::string title(size_t index, Player pl)
Definition: kisen.cc:170
unsigned int rating(size_t index, Player pl)
Definition: kisen.cc:152
KisenIpxFile(std::string const &filename)
Definition: kisen.cc:130
unsigned int result(size_t index)
Definition: kisen.cc:162
void save(const Record &, int black_rating, int white_rating, const std::string &black_title, const std::string &white_title)
Definition: kisen.cc:365
void writeStartDate(int year, int month, int day, int hour, int min)
Definition: kisen.cc:352
void writeRating(int rating)
Definition: kisen.cc:344
void writeString(const std::string &name, size_t length)
Definition: kisen.cc:328
void load(size_t index, std::vector< Move > &, std::vector< int > &)
Definition: kisen.cc:221
std::ifstream ifs
Definition: kisen.h:104
std::vector< Move > moves(size_t index)
Definition: kisen.cc:213
KisenPlusFile(const std::string &fileName)
Definition: kisen.cc:203
static Move convertMove(SimpleState const &state, int c0, int c1)
Definition: kisen.cc:18
static Square convertSquare(int pos)
Definition: kisen.cc:8
void save(const RecordMinimal &)
Definition: kisen.cc:283
int min(Player p, int v1, int v2)
Definition: evalTraits.h:92
std::string sjis2euc(const std::string &str)
Convert character encoding from Shift_JIS to EUC-JP.
Definition: sjis2euc.cc:9
std::string file_string(const boost::filesystem::path &path)
Definition: filePath.cc:6
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
Player
Definition: basic_type.h:8
@ WHITE
Definition: basic_type.h:10
@ BLACK
Definition: basic_type.h:9
constexpr Player alt(Player player)
Definition: basic_type.h:13
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
NumEffectState initial_state
Definition: csa.h:44
std::vector< Move > moves
Definition: csa.h:45
static std::string convert(const std::string &fromcode, const std::string &tocode, const std::string &src)
Definition: iconvConvert.cc:60
std::vector< int > times
Definition: record.h:24
std::vector< Move > moves() const
Definition: record.h:41
CArray< std::string, 2 > player
Definition: record.h:29
boost::gregorian::date start_date
Definition: record.h:31