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
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
94std::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
123std::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
130osl::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}
139std::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}
152unsigned 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}
162unsigned 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}
170std::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}
183boost::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
203osl::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
213std::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
276#ifndef MINIMAL
281
283KisenWriter::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
328KisenIpxWriter::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
345{
346 int high = rating / 256;
347 int low = rating % 256;
348 os << static_cast<char>(low) << static_cast<char>(high);
349}
350
352KisenIpxWriter::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
365KisenIpxWriter::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の表現 .
static const Move INVALID()
bool isInvalid() const
state に apply 可能でない場合にtrue
bool isPromotion() const
Ptype ptype() const
Player player() const
bool isDrop() const
const Square to() const
const Square from() const
利きを持つ局面
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
bool isValidMove(Move move, bool show_error=true) const
合法手かどうかを検査する. isValidMoveByRule, isAlmostValidMove をおこなう. 玉の素抜きや王手を防いでいるか, 千日手,打歩詰かどうかは検査しない.
Player turn() const
int countPiecesOnStand(Player pl, Ptype ptype) const
持駒の枚数を数える
const Piece pieceAt(Square sq) const
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
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)
std::vector< Move > moves() const
Definition record.h:41
std::vector< int > times
Definition record.h:24
CArray< std::string, 2 > player
Definition record.h:29
boost::gregorian::date start_date
Definition record.h:31