kisen.cc
Go to the documentation of this file.
#include "osl/record/kisen.h"
#include "osl/misc/filePath.h"
#include "osl/misc/iconvConvert.h"
#include "osl/misc/sjis2euc.h"
#include <boost/filesystem.hpp>
#include <iostream>
osl::Square osl::record::KisenUtils::convertSquare( int pos ){
assert(1<=pos && pos<=0x51);
int y=((pos-1)/9)+1, x=((pos-1)%9)+1;
return Square(x,y);
}
int osl::record::KisenUtils::convertSquare(Square pos)
{
return ((pos.y() - 1) * 9 + 1) + pos.x() - 1;
}
osl::Move osl::record::KisenUtils::convertMove(SimpleState const& state,int c0,int c1){
Move move;
if(1<=c1 && c1<=0x51){
Square from=convertSquare(c1),to;
Piece fromPiece=state.pieceOnBoard(from);
if (! fromPiece.isPiece())
throw CsaIOError("Square error");
assert(fromPiece.isPiece());
assert(fromPiece.owner()==state.turn() ||
(std::cerr << c1 << "," << from << "," << fromPiece << std::endl,0)
);
bool isPromote=false;
if(1<=c0 && c0<=0x51){
to=convertSquare(c0);
}
else if(0x65<=c0 && c0<=0xb5){
to=convertSquare(c0-0x64);
isPromote=true;
}
else{
throw CsaIOError("c0 range error");
}
Piece toPiece=state.pieceAt(to);
if (! toPiece.isEmpty() && toPiece.owner()!=alt(state.turn()))
throw CsaIOError("inconsintent move (to)");
Ptype ptype=fromPiece.ptype();
if(isPromote)ptype=promote(ptype);
const Ptype captured = toPiece.ptype();
if (captured == KING)
return Move::INVALID();
move=Move(from,to,ptype,captured,isPromote,state.turn());
}
else{
assert(0x65<=c1);
if (!(1<=c0&&c0<=0x51)) {
throw CsaIOError("unknown kisen move "+std::to_string((int)c0));
}
assert(1<=c0&&c0<=0x51);
Square to=convertSquare(c0);
Ptype ptype=PTYPE_EMPTY;
int piece_on_stand = c1;
const Ptype ptypes[]={ROOK,BISHOP,GOLD,SILVER,KNIGHT,LANCE,PAWN};
for(size_t i=0;i<sizeof(ptypes)/sizeof(Ptype);i++){
int count=state.countPiecesOnStand(state.turn(),ptypes[i]);
if(count>0){
if(piece_on_stand>0x64){
piece_on_stand-=count;
if(piece_on_stand<=0x64) ptype=ptypes[i];
}
}
}
assert(ptype!=PTYPE_EMPTY ||
(std::cerr << state << to << " " << c1
<< " " << piece_on_stand << std::endl, false));
move=Move(to,ptype,state.turn());
}
if (! state.isValidMove(move,true)) {
std::cerr << "warning: bad move in kisen\n" << state << move << "\n";
return Move();
}
assert(state.isValidMove(move,true) ||
(std::cerr << state << move << std::endl, false));
return move;
}
osl::record::KisenFile::KisenFile(const std::string& f)
:ifs(f), filename(f)
{
if (! ifs)
throw CsaIOError("KisenFile not found "+f);
ifs.seekg(0,std::ios::end);
assert((ifs.tellg() % 512)==0);
number_of_games=ifs.tellg()/512;
}
std::vector<osl::Move> osl::record::KisenFile::moves(size_t index)
{
assert(index<size());
std::vector<Move> moves;
// std::cerr << "Game[" << index << "]" << std::endl;
ifs.seekg(index*512,std::ios::beg);
CArray<unsigned char, 512> cbuf;
ifs.read(reinterpret_cast<char *>(&cbuf[0]),512);
NumEffectState state;
//
Player turn=BLACK;
for(size_t turn_count=0;
(turn_count*2 < cbuf.size())
&& cbuf[turn_count*2]!=0 && cbuf[turn_count*2+1]!=0;
turn_count++, turn=alt(turn)){
if(turn_count==KisenFile::MaxMoves || cbuf[ turn_count *2 ] == 0 || cbuf[ turn_count * 2 + 1 ] == 0 ){ break; }
int c0=cbuf[turn_count*2], c1=cbuf[turn_count*2+1];
if (moves.empty() && c0 == 0xff && c1 == 0xff) // komaochi
break;
const Move move=KisenUtils::convertMove(state,c0,c1);
if (move.isInvalid())
break;
moves.push_back(move);
state.makeMove(move);
assert(state.isConsistent( true ) );
}
return moves;
}
#ifndef MINIMAL
std::string osl::record::KisenFile::ipxFileName(const std::string& filename)
{
namespace bf = boost::filesystem;
const bf::path ipxfilename = bf::path(filename).replace_extension(".ipx");
return misc::file_string(ipxfilename);
}
osl::record::KisenIpxFile::KisenIpxFile(const std::string& filename)
:ifs(filename), file_name(filename)
{
if (! ifs)
throw CsaIOError("KisenIpxFile not found "+filename);
ifs.seekg(0,std::ios::end);
assert((ifs.tellg() % 256)==0);
number_of_games=ifs.tellg()/256;
}
std::string osl::record::KisenIpxFile::player(size_t index,Player pl)
{
assert(index<size());
ifs.seekg(index*256,std::ios::beg);
CArray<unsigned char, 256> cbuf;
ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
int startIndex=0;
if(pl==WHITE)startIndex=14;
CArray<char,15> buf;
buf[14]='\0';
strncpy(&buf[0],reinterpret_cast<char *>(&cbuf[startIndex]),14);
return misc::sjis2euc(std::string(&buf[0]));
}
unsigned int osl::record::KisenIpxFile::rating(size_t index,Player pl)
{
assert(index<size());
ifs.seekg(index*256,std::ios::beg);
CArray<unsigned char, 256> cbuf;
ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
int startIndex=0324;
if(pl==WHITE)startIndex=0326;
return cbuf[startIndex]+256*cbuf[startIndex+1];
}
unsigned int osl::record::KisenIpxFile::result(size_t index)
{
assert(index<size());
ifs.seekg(index*256,std::ios::beg);
CArray<unsigned char, 256> cbuf;
ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
return cbuf[64+48+6];
}
std::string osl::record::KisenIpxFile::title(size_t index,Player pl)
{
assert(index<size());
ifs.seekg(index*256,std::ios::beg);
CArray<unsigned char, 256> cbuf;
ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
int startIndex=28;
if(pl==WHITE)startIndex+=8;
CArray<char,9> buf;
buf[8]='\0';
strncpy(&buf[0],reinterpret_cast<const char*>(&cbuf[startIndex]),8);
return misc::sjis2euc(std::string(&buf[0]));
}
boost::gregorian::date osl::record::KisenIpxFile::startDate(size_t index)
{
assert(index<size());
ifs.seekg(index*256,std::ios::beg);
CArray<unsigned char, 256> cbuf;
ifs.read(reinterpret_cast<char *>(&cbuf[0]),256);
const int startIndex=84;
const unsigned int year = cbuf[startIndex] + 256*cbuf[startIndex+1];
const unsigned int month = cbuf[startIndex+2];
const unsigned int day = cbuf[startIndex+3];
try {
const boost::gregorian::date d = boost::gregorian::date(year, month, day);
return d;
} catch (std::out_of_range& e) {
std::cerr << e.what() << ": ["
<< index << "] " << year << "-" << month << "-" << day << "\n";
return boost::gregorian::date(boost::gregorian::not_a_date_time);
}
}
osl::record::KisenPlusFile::KisenPlusFile(const std::string& filename)
:ifs(filename)
{
if (! ifs)
throw CsaIOError("KisenPlusFile not found");
ifs.seekg(0,std::ios::end);
assert((ifs.tellg() % 2048)==0);
number_of_games=ifs.tellg()/2048;
}
std::vector<osl::Move> osl::record::KisenPlusFile::moves(size_t index)
{
std::vector<Move> moves;
std::vector<int> times;
load(index, moves, times);
return moves;
}
void osl::record::KisenPlusFile::load(size_t index,
std::vector<Move>& moves, std::vector<int>& times)
{
assert(index<size());
// std::cerr << "Game[" << index << "]" << std::endl;
ifs.seekg(index*2048,std::ios::beg);
CArray<unsigned char, 2048> cbuf;
ifs.read(reinterpret_cast<char *>(&cbuf[0]),2048);
NumEffectState state;
for (size_t i = 0;
i < 2048 && cbuf[i]!=0 && cbuf[i+1]!=0;
i += 8)
{
int c0 = cbuf[i];
int c1 = cbuf[i + 1];
bool is_promote = false;
Move move;
if (c0 > 100)
{
is_promote = true;
c0 = 256 - c0;
}
Square to(c0 % 10, c0 / 10);
if (c1 < 10)
{
// drop
move = Move(to,
PieceStand::order[c1 - 1],
state.turn());
}
else
{
Square from(c1 % 10, c1 / 10);
Ptype type = state.pieceAt(from).ptype();
if (is_promote)
type = promote(type);
move = Move(from, to,
type, state.pieceAt(to).ptype(),
is_promote, state.turn());
}
moves.push_back(move);
times.push_back(cbuf[i + 7] * 60 + cbuf[i + 6]);
state.makeMove(move);
assert(state.isConsistent( true ) );
}
}
#endif
osl::record::
KisenFile::~KisenFile()
{
}
#ifndef MINIMAL
osl::record::
KisenIpxFile::~KisenIpxFile()
{
}
void osl::record::
KisenWriter::save(const RecordMinimal& record)
{
if (!(record.initial_state == NumEffectState()))
{
std::cerr << "Can not save non-HIRATE record" << std::endl;
return;
}
NumEffectState state;
const int max_length = std::min(256, static_cast<int>(record.moves.size()));
for (int i = 0; i < max_length; ++i)
{
const Move move = record.moves[i];
if (!move.isDrop())
{
int from = KisenUtils::convertSquare(move.from());
int to = KisenUtils::convertSquare(move.to());
if (move.isPromotion())
{
to += 100;
}
os << static_cast<char>(to) << static_cast<char>(from);
}
else
{
int to = KisenUtils::convertSquare(move.to());
int count = 1;
for (Ptype ptype: PieceStand::order) {
if (ptype == move.ptype())
{
break;
}
count += state.countPiecesOnStand(move.player(), ptype);
}
count += 100;
os << static_cast<char>(to) << static_cast<char>(count);
}
state.makeMove(record.moves[i]);
}
for (int i = max_length; i < 256; ++i)
{
os << '\0' << '\0';
}
}
void osl::record::
KisenIpxWriter::writeString(const std::string &name, size_t length)
{
for (size_t i = 0; i < length; ++i)
{
if (i < name.length())
{
os << name[i];
}
else
{
os << '\0';
}
}
}
void osl::record::
KisenIpxWriter::writeRating(int rating)
{
int high = rating / 256;
int low = rating % 256;
os << static_cast<char>(low) << static_cast<char>(high);
}
void osl::record::
KisenIpxWriter::writeStartDate(int year, int month, int day, int hour, int min)
{
const int high_year = year / 256;
const int low_year = year % 256;
os << static_cast<char>(low_year)
<< static_cast<char>(high_year)
<< static_cast<char>(month)
<< static_cast<char>(day)
<< static_cast<char>(hour)
<< static_cast<char>(min);
}
void osl::record::
KisenIpxWriter::save(const Record &record,
int black_rating, int white_rating,
const std::string &black_title,
const std::string &white_title)
{
// total 256 bytes
// Player name: 14 bytes each
#ifndef _WIN32
writeString(IconvConvert::convert("EUC-JP", "SJIS", record.player[BLACK]), 14);
writeString(IconvConvert::convert("EUC-JP", "SJIS", record.player[WHITE]), 14);
writeString(IconvConvert::convert("EUC-JP", "SJIS", black_title), 8);
writeString(IconvConvert::convert("EUC-JP", "SJIS", white_title), 8);
#else
writeString("", 14);
writeString("", 14);
writeString("", 8);
writeString("", 8);
#endif
for (int i = 44; i < 84; ++i)
{
os << '\0';
}
const boost::gregorian::date start_date = record.start_date;
if (!start_date.is_special()) {
// time is fixed with 9am
writeStartDate(start_date.year(), start_date.month(), start_date.day(), 9, 0);
} else {
for (int i = 84; i < 90; ++i)
{
os << '\0';
}
}
for (int i = 90; i < 118; ++i)
{
os << '\0';
}
std::vector<Move> moves = record.moves();
std::vector<int> time = record.times;
// TODO: sennichite, jishogi
if (moves.size() <= 256)
{
if (moves.size() % 2 == 0)
os << static_cast<char>(KisenIpxFile::WHITE_WIN);
else
os << static_cast<char>(KisenIpxFile::BLACK_WIN);
}
else
{
if (moves.size() % 2 == 0)
os << static_cast<char>(KisenIpxFile::WHITE_WIN_256);
else
os << static_cast<char>(KisenIpxFile::BLACK_WIN_256);
}
for (int i = 119; i < 212; ++i)
{
os << '\0';
}
writeRating(black_rating);
writeRating(white_rating);
for (int i = 216; i < 256; ++i)
{
os << '\0';
}
}
#endif
// ;;; Local Variables:
// ;;; mode:c++
// ;;; c-basic-offset:2
// ;;; End:
osl::CArray
Definition container.h:20
osl::CArray::size
static size_t size()
Definition container.h:76
osl::Move
圧縮していない moveの表現 .
Definition basic_type.h:1052
osl::Move::INVALID
static const Move INVALID()
Definition basic_type.h:1095
osl::Move::isInvalid
bool isInvalid() const
state に apply 可能でない場合にtrue
Definition basic_type.h:1202
osl::Move::isPromotion
bool isPromotion() const
Definition basic_type.h:1147
osl::Move::ptype
Ptype ptype() const
Definition basic_type.h:1155
osl::Move::player
Player player() const
Definition basic_type.h:1195
osl::Move::isDrop
bool isDrop() const
Definition basic_type.h:1150
osl::Move::to
const Square to() const
Definition basic_type.h:1132
osl::Move::from
const Square from() const
Definition basic_type.h:1125
osl::NumEffectState
利きを持つ局面
Definition numEffectState.h:34
osl::NumEffectState::makeMove
void makeMove(Move move)
Definition numEffectState.cc:201
osl::NumEffectState::isConsistent
bool isConsistent(bool showError=true) const
Definition numEffectState.cc:663
osl::PieceStand::order
static const CArray< Ptype, 7 > order
持駒の表示で良く使われる順番.
Definition bits/pieceStand.h:41
osl::Piece
駒.
Definition basic_type.h:788
osl::Piece::ptype
Ptype ptype() const
Definition basic_type.h:821
osl::Piece::isEmpty
bool isEmpty() const
Definition basic_type.h:913
osl::Piece::owner
Player owner() const
Definition basic_type.h:963
osl::Piece::isPiece
bool isPiece() const
Definition basic_type.h:953
osl::SimpleState
Definition simpleState.h:35
osl::SimpleState::pieceOnBoard
const Piece pieceOnBoard(Square sq) const
Definition simpleState.h:170
osl::SimpleState::isValidMove
bool isValidMove(Move move, bool show_error=true) const
合法手かどうかを検査する． isValidMoveByRule, isAlmostValidMove をおこなう． 玉の素抜きや王手を防いでいるか， 千日手，打歩詰かどうかは検査しない．
Definition simpleState.cc:435
osl::SimpleState::turn
Player turn() const
Definition simpleState.h:220
osl::SimpleState::countPiecesOnStand
int countPiecesOnStand(Player pl, Ptype ptype) const
持駒の枚数を数える
Definition simpleState.h:182
osl::SimpleState::pieceAt
const Piece pieceAt(Square sq) const
Definition simpleState.h:167
osl::Square
Definition basic_type.h:532
osl::Square::y
int y() const
将棋としてのY座標を返す.
Definition basic_type.h:567
osl::Square::x
int x() const
将棋としてのX座標を返す.
Definition basic_type.h:563
osl::record::KisenFile::MaxMoves
static const size_t MaxMoves
Definition kisen.h:31
osl::record::KisenFile::number_of_games
size_t number_of_games
Definition kisen.h:28
osl::record::KisenFile::size
size_t size() const
Definition kisen.h:35
osl::record::KisenFile::moves
std::vector< Move > moves(size_t index)
Definition kisen.cc:94
osl::record::KisenFile::filename
const std::string filename
Definition kisen.h:29
osl::record::KisenFile::~KisenFile
~KisenFile()
Definition kisen.cc:273
osl::record::KisenFile::KisenFile
KisenFile(const std::string &filename)
Definition kisen.cc:84
osl::record::KisenFile::ipxFileName
std::string ipxFileName() const
Definition kisen.h:39
osl::record::KisenFile::ifs
std::ifstream ifs
Definition kisen.h:27
osl::record::KisenIpxFile::startDate
boost::gregorian::date startDate(size_t index)
開始日の年月日を返す
Definition kisen.cc:183
osl::record::KisenIpxFile::ifs
std::ifstream ifs
Definition kisen.h:68
osl::record::KisenIpxFile::size
size_t size() const
Definition kisen.h:86
osl::record::KisenIpxFile::player
std::string player(size_t index, Player pl)
Definition kisen.cc:139
osl::record::KisenIpxFile::title
std::string title(size_t index, Player pl)
Definition kisen.cc:170
osl::record::KisenIpxFile::number_of_games
size_t number_of_games
Definition kisen.h:69
osl::record::KisenIpxFile::rating
unsigned int rating(size_t index, Player pl)
Definition kisen.cc:152
osl::record::KisenIpxFile::KisenIpxFile
KisenIpxFile(std::string const &filename)
Definition kisen.cc:130
osl::record::KisenIpxFile::BLACK_WIN
@ BLACK_WIN
Definition kisen.h:74
osl::record::KisenIpxFile::WHITE_WIN_256
@ WHITE_WIN_256
Definition kisen.h:79
osl::record::KisenIpxFile::WHITE_WIN
@ WHITE_WIN
Definition kisen.h:75
osl::record::KisenIpxFile::BLACK_WIN_256
@ BLACK_WIN_256
Definition kisen.h:78
osl::record::KisenIpxFile::~KisenIpxFile
~KisenIpxFile()
Definition kisen.cc:278
osl::record::KisenIpxFile::result
unsigned int result(size_t index)
Definition kisen.cc:162
osl::record::KisenIpxFile::file_name
const std::string file_name
Definition kisen.h:70
osl::record::KisenIpxWriter::save
void save(const Record &, int black_rating, int white_rating, const std::string &black_title, const std::string &white_title)
Definition kisen.cc:365
osl::record::KisenIpxWriter::writeStartDate
void writeStartDate(int year, int month, int day, int hour, int min)
Definition kisen.cc:352
osl::record::KisenIpxWriter::os
std::ostream & os
Definition kisen.h:142
osl::record::KisenIpxWriter::writeRating
void writeRating(int rating)
Definition kisen.cc:344
osl::record::KisenIpxWriter::writeString
void writeString(const std::string &name, size_t length)
Definition kisen.cc:328
osl::record::KisenPlusFile::load
void load(size_t index, std::vector< Move > &, std::vector< int > &)
Definition kisen.cc:221
osl::record::KisenPlusFile::ifs
std::ifstream ifs
Definition kisen.h:104
osl::record::KisenPlusFile::moves
std::vector< Move > moves(size_t index)
Definition kisen.cc:213
osl::record::KisenPlusFile::KisenPlusFile
KisenPlusFile(const std::string &fileName)
Definition kisen.cc:203
osl::record::KisenPlusFile::size
size_t size() const
Definition kisen.h:109
osl::record::KisenPlusFile::number_of_games
size_t number_of_games
Definition kisen.h:105
osl::record::KisenUtils::convertMove
static Move convertMove(SimpleState const &state, int c0, int c1)
Definition kisen.cc:18
osl::record::KisenUtils::convertSquare
static Square convertSquare(int pos)
Definition kisen.cc:8
osl::record::KisenWriter::os
std::ostream & os
Definition kisen.h:121
osl::record::KisenWriter::save
void save(const RecordMinimal &)
Definition kisen.cc:283
filePath.h
iconvConvert.h
kisen.h
osl::misc::sjis2euc
std::string sjis2euc(const std::string &str)
Convert character encoding from Shift_JIS to EUC-JP.
Definition sjis2euc.cc:9
osl::misc::file_string
std::string file_string(const boost::filesystem::path &path)
Definition filePath.cc:6
osl::rating
Definition construct.h:18
osl::record
棋譜関係
Definition checkDuplicate.h:15
osl::Ptype
Ptype
駒の種類を4ビットでコード化する
Definition basic_type.h:84
osl::ROOK
@ ROOK
Definition basic_type.h:100
osl::BISHOP
@ BISHOP
Definition basic_type.h:99
osl::PAWN
@ PAWN
Definition basic_type.h:95
osl::KING
@ KING
Definition basic_type.h:93
osl::KNIGHT
@ KNIGHT
Definition basic_type.h:97
osl::PTYPE_EMPTY
@ PTYPE_EMPTY
Definition basic_type.h:85
osl::SILVER
@ SILVER
Definition basic_type.h:98
osl::GOLD
@ GOLD
Definition basic_type.h:94
osl::LANCE
@ LANCE
Definition basic_type.h:96
osl::Player
Player
Definition basic_type.h:8
osl::WHITE
@ WHITE
Definition basic_type.h:10
osl::BLACK
@ BLACK
Definition basic_type.h:9
osl::alt
constexpr Player alt(Player player)
Definition basic_type.h:13
osl::promote
Ptype promote(Ptype ptype)
promote可能なptypeに対して，promote後の型を返す promote不可のptypeを与えてはいけない．
Definition basic_type.h:173
osl::captured
PtypeO captured(PtypeO ptypeO)
unpromoteすると共に，ownerを反転する．
Definition basic_type.h:264
sjis2euc.h
osl::IconvConvert::convert
static std::string convert(const std::string &fromcode, const std::string &tocode, const std::string &src)
Definition iconvConvert.cc:60
osl::RecordMinimal
Definition csa.h:43
osl::csa::CsaIOError
Definition csa.h:18
osl::record::Record
Definition record.h:15