ki2.cc
Go to the documentation of this file.
#include "osl/record/ki2.h"
#include "osl/record/kanjiCode.h"
#include "osl/record/kanjiPrint.h"
#include "osl/record/ki2IOError.h"
#include "osl/misc/sjis2euc.h"
#include "osl/bits/ptypeTable.h"
#include <boost/algorithm/string/trim.hpp>
#include <fstream>
#include <iostream>
osl::ki2::Ki2File::ParseResult
osl::ki2::Ki2File::parseLine(NumEffectState& state, Record& record, KanjiMove& kmove,
std::string line)
{
boost::algorithm::trim(line);
if (line.empty() || line.at(0) == '*')
return OK;
else if (line.size() > 10 && line.substr(0,10) == (K_KAISHI K_NICHIJI K_COLON))
{
std::string date_str(line.substr(10)); // this may or may not include HH:MM
const static std::string spaces[] = {" ", K_SPACE};
for (const auto& space: spaces) {
const std::string::size_type pos_space = date_str.find(space);
if (pos_space != std::string::npos)
date_str = date_str.substr(0, pos_space);
}
record.setDate(date_str);
// an invalid date_str results in an invalid boost::gregorian::date value
// you can check it date.is_special()
return OK;
}
else if (line.size() > 6 && line.substr(0,6) == (K_BLACK K_COLON))
{
const std::string player_name(line.substr(6));
record.player[BLACK] = player_name;
return OK;
}
else if (line.size() > 6 && line.substr(0,6) == (K_WHITE K_COLON))
{
const std::string player_name(line.substr(6));
record.player[WHITE] = player_name;
return OK;
}
else if (line.size() > 6 && line.substr(0,6) == (K_KISEN K_COLON))
{
record.tournament_name = line.substr(6);
return OK;
}
else if (line.size() > 8 && line.substr(0,8) == (K_TEAIWARI K_COLON))
return Komaochi;
else if (line.substr(0,2) != K_BLACK_SIGN && line.substr(0,2) != K_WHITE_SIGN)
return OK;
std::string move_str;
for (size_t i = 0; ; ) {
if (i < line.size() &&
(line.at(i) == ' ' || line.at(i) == '\t'))
{
++i;
continue;
}
if ( (line.substr(i,2) == K_BLACK_SIGN ||
line.substr(i,2) == K_WHITE_SIGN ||
i+1 >= line.size())
&& !move_str.empty())
{
// apply move_str
Move last_move;
if (record.moves().size() > 0)
last_move = record.moves().back();
const Move move = kmove.strToMove(move_str, state, last_move);
if (!move.isValid()) {
if (move_str.find(K_RESIGN) != move_str.npos)
return OK;
return Illegal;
}
record.record.moves.push_back(move);
state.makeMove(move);
move_str.clear();
}
if (i+1 >= line.size())
return OK;
move_str.append(line.substr(i,2));
i += 2;
} // for
}
osl::ki2::
Ki2File::Ki2File(const std::string& filename, bool v)
: verbose(v)
{
std::ifstream is(filename);
if (! is)
{
const std::string msg = "Ki2File::Ki2File file cannot read ";
std::cerr << msg << filename << "\n";
throw Ki2IOError(msg + filename);
}
KanjiMove kmove;
kmove.setVerbose(verbose);
NumEffectState work;
record.record.initial_state = work;
std::string line;
while (std::getline(is, line))
{
line = misc::sjis2euc(line);
const ParseResult result = parseLine(work, record, kmove, line);
switch (result)
{
case OK:
continue;
case Komaochi:
{
const std::string msg = "ERROR: Komaochi (handicapped game) records are not available: ";
std::cerr << msg << "\n";
throw Ki2IOError(msg);
}
case Illegal:
{
const std::string msg = "ERROR: An illegal move found in a record.";
throw Ki2IOError(msg);
}
default:
assert(false);
}
}
}
const std::string osl::ki2::show(Square position)
{
using namespace record;
if (position.isPieceStand())
return "";
const int x = position.x(), y = position.y();
return StandardCharacters::suji[x] + StandardCharacters::dan[y];
}
const std::string osl::ki2::show(Ptype ptype)
{
using namespace record;
switch (ptype)
{
case PSILVER: case PKNIGHT: case PLANCE:
return K_NARU + StandardCharacters().kanji(unpromote(ptype));
default:
;
}
return StandardCharacters().kanji(ptype);
}
const std::string osl::ki2::showPromote(bool promote)
{
return promote ? K_NARU : K_FUNARI;
}
const std::string osl::ki2::show(Square cur, Square prev)
{
if (cur == prev)
return K_ONAZI;
return show(cur);
}
const std::string osl::ki2::show(Move m, const NumEffectState& state,
Move prev)
{
std::string ret = (m.player() == BLACK) ? K_BLACK_SIGN : K_WHITE_SIGN;
if (m.isPass()) {
ret += K_PASS;
return ret;
}
const Square from = m.from(), to = m.to();
const Ptype ptype = m.oldPtype();
const Player player = m.player();
mask_t pieces = state.allEffectAt(player, ptype, to);
const mask_t promoted = state.promotedPieces().getMask(Ptype_Table.getIndex(ptype));
if (isPromoted(ptype))
pieces &= promoted;
else
pieces &= ~promoted;
if (from.isPieceStand()) {
ret += show(to) + show(ptype);
int has_effect = 0;
while (pieces.any()) {
const Piece p = state.pieceOf(pieces.takeOneBit());
if (p.ptype() == ptype)
++has_effect;
}
if (has_effect)
ret += K_UTSU;
return ret;
}
ret += prev.isNormal() && (to == prev.to())
? K_ONAZI : show(to);
ret += show(m.oldPtype());
const int count = pieces.countBit();
if (count >= 2) {
CArray<int,3> x_count = {{ 0 }}, y_count = {{ 0 }};
int my_x = 0, my_y = 0;
while (pieces.any()) {
const int n = pieces.takeOneBit() + Ptype_Table.getIndex(ptype)*32;
const Piece p = state.pieceOf(n);
if (p.ptype() != ptype)
continue;
int index_x = 1, index_y = 1;
if (p.square().x() != to.x())
index_x = ((p.square().x() - to.x()) * sign(player) > 0)
? 2 : 0;
if (p.square().y() != to.y())
index_y = ((p.square().y() - to.y()) * sign(player) > 0)
? 2 : 0;
if (p.square() == from)
my_x = index_x, my_y = index_y;
x_count[index_x]++;
y_count[index_y]++;
}
if (y_count[my_y] == 1) {
if (from.y() == to.y())
ret += K_YORU;
else if ((to.y() - from.y())*sign(player) > 0)
ret += K_HIKU;
else
ret += K_UE;
}
else if (x_count[my_x] == 1) {
if (from.x() == to.x()) {
if (isPromoted(ptype) && isMajor(ptype)) {
const Piece l = state.pieceAt
(Square(from.x() - sign(player), from.y()));
if (l.isOnBoardByOwner(player) && l.ptype() == ptype)
ret += K_HIDARI;
else
ret += K_MIGI;
}
else
ret += K_SUGU;
}
else if ((to.x() - from.x())*sign(player) > 0)
ret += K_MIGI;
else
ret += K_HIDARI;
}
else if (from.x() == to.x()) {
if ((to.y() - from.y())*sign(player) > 0)
ret += K_HIKU;
else
ret += K_SUGU;
}
else {
if ((to.x() - from.x())*sign(player) > 0)
ret += K_MIGI;
else
ret += K_HIDARI;
if ((to.y() - from.y())*sign(player) > 0)
ret += K_HIKU;
else
ret += K_UE;
}
}
if (canPromote(m.oldPtype()))
if (m.isPromotion()
|| to.canPromote(player) || from.canPromote(player)) {
ret += showPromote(m.isPromotion());
}
return ret;
}
const std::string osl::
ki2::show(const Move *first, const Move *last,
const char *threatmate_first, const char *threatmate_last,
const NumEffectState& initial, Move prev)
{
if (first == last || first->isInvalid())
return "";
NumEffectState state(initial);
std::string ret = show(*first, state, prev);
if (threatmate_first != threatmate_last
&& *threatmate_first++)
ret += "(" K_TSUMERO ")";
for (; first+1 != last; ++first) {
if (first->isInvalid())
break;
state.makeMove(*first);
ret += show(*(first+1), state, *first);
if (threatmate_first != threatmate_last
&& *threatmate_first++)
ret += "(" K_TSUMERO ")";
}
return ret;
}
const std::string osl::
ki2::show(const Move *first, const Move *last, const NumEffectState& initial, Move prev)
{
std::vector<char> threatmate(last-first, false);
return show(first, last, &*threatmate.begin(), &*threatmate.end(), initial, prev);
}
// ;;; Local Variables:
// ;;; mode:c++
// ;;; c-basic-offset:2
// ;;; End:
osl::CArray
Definition container.h:20
osl::Move
圧縮していない moveの表現 .
Definition basic_type.h:1052
osl::Move::isValid
bool isValid() const
Definition basic_type.cc:246
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::player
Player player() const
Definition basic_type.h:1195
osl::Move::isPass
bool isPass() const
Definition basic_type.h:1092
osl::Move::isNormal
bool isNormal() const
INVALID でも PASS でもない.
Definition basic_type.h:1088
osl::Move::oldPtype
Ptype oldPtype() const
移動前のPtype, i.e., 成る手だった場合成る前
Definition basic_type.h:1174
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::promotedPieces
const PieceMask promotedPieces() const
Definition numEffectState.h:64
osl::NumEffectState::allEffectAt
const mask_t allEffectAt(Player P, Square target) const
Definition numEffectState.h:293
osl::PieceMask::getMask
const mask_t getMask(int num) const
Definition pieceMask.h:59
osl::Piece
駒.
Definition basic_type.h:788
osl::Piece::ptype
Ptype ptype() const
Definition basic_type.h:821
osl::Piece::square
const Square square() const
Definition basic_type.h:832
osl::Piece::isOnBoardByOwner
bool isOnBoardByOwner() const
piece がプレイヤーPの持ち物でかつボード上にある駒の場合は true.
Definition basic_type.h:852
osl::SimpleState::pieceOf
const Piece pieceOf(int num) const
Definition simpleState.h:76
osl::SimpleState::pieceAt
const Piece pieceAt(Square sq) const
Definition simpleState.h:167
osl::Square
Definition basic_type.h:532
osl::Square::isPieceStand
bool isPieceStand() const
Definition basic_type.h:576
osl::Square::y
int y() const
将棋としてのY座標を返す.
Definition basic_type.h:567
osl::Square::canPromote
bool canPromote() const
Definition basic_type.h:659
osl::Square::x
int x() const
将棋としてのX座標を返す.
Definition basic_type.h:563
osl::ki2::Ki2File::verbose
bool verbose
Definition ki2.h:24
osl::ki2::Ki2File::parseLine
static ParseResult parseLine(NumEffectState &, Record &, KanjiMove &, std::string element)
Definition ki2.cc:12
osl::ki2::Ki2File::Ki2File
Ki2File(const std::string &filename, bool verbose=false)
Definition ki2.cc:92
osl::ki2::Ki2File::ParseResult
ParseResult
Definition ki2.h:28
osl::ki2::Ki2File::Komaochi
@ Komaochi
Definition ki2.h:29
osl::ki2::Ki2File::Illegal
@ Illegal
Definition ki2.h:29
osl::ki2::Ki2File::OK
@ OK
Definition ki2.h:29
osl::misc::GeneralMask::any
bool any() const
Definition mask.h:298
osl::misc::GeneralMask::countBit
int countBit() const
mask にセットされているビットの数を数える． あまり速くない．
Definition mask.h:290
osl::misc::GeneralMask::takeOneBit
int takeOneBit()
non-zeroのmaskのsetされているビットをLSBから探し，その番号を返す 副作用としてmaskの対応するビットをクリアする
Definition mask.h:265
osl::record::KanjiMove
Parse kanji records such as "７六歩", the style of which is generally used to write Shogi records in Jap...
Definition kanjiMove.h:20
osl::record::KanjiMove::strToMove
const Move strToMove(const std::string &, const NumEffectState &state, const Move &last_move) const
Convert a Japanese string (one token) to a move object.
Definition kanjiMove.cc:361
osl::record::KanjiMove::setVerbose
void setVerbose(bool verbose)
Definition kanjiMove.h:31
osl::record::RecordFile::record
Record record
Definition record.h:66
kanjiCode.h
K_KAISHI
#define K_KAISHI
Definition kanjiCode.h:106
K_NARU
#define K_NARU
Definition kanjiCode.h:54
K_RESIGN
#define K_RESIGN
Definition kanjiCode.h:118
K_PASS
#define K_PASS
Definition kanjiCode.h:98
K_SPACE
#define K_SPACE
Definition kanjiCode.h:15
K_YORU
#define K_YORU
Definition kanjiCode.h:50
K_TEAIWARI
#define K_TEAIWARI
Definition kanjiCode.h:97
K_TSUMERO
#define K_TSUMERO
Definition kanjiCode.h:105
K_ONAZI
#define K_ONAZI
Definition kanjiCode.h:53
K_UTSU
#define K_UTSU
Definition kanjiCode.h:56
K_BLACK
#define K_BLACK
Definition kanjiCode.h:92
K_FUNARI
#define K_FUNARI
Definition kanjiCode.h:55
K_HIKU
#define K_HIKU
Definition kanjiCode.h:51
K_NICHIJI
#define K_NICHIJI
Definition kanjiCode.h:107
K_WHITE
#define K_WHITE
Definition kanjiCode.h:93
K_MIGI
#define K_MIGI
Definition kanjiCode.h:45
K_COLON
#define K_COLON
Definition kanjiCode.h:17
K_WHITE_SIGN
#define K_WHITE_SIGN
Definition kanjiCode.h:14
K_SUGU
#define K_SUGU
Definition kanjiCode.h:49
K_HIDARI
#define K_HIDARI
Definition kanjiCode.h:46
K_KISEN
#define K_KISEN
Definition kanjiCode.h:103
K_BLACK_SIGN
#define K_BLACK_SIGN
Define Kanji characters by using EUC-JP codes.
Definition kanjiCode.h:13
K_UE
#define K_UE
Definition kanjiCode.h:47
kanjiPrint.h
ki2IOError.h
ki2.h
osl::ki2::showPromote
const std::string showPromote(bool)
Definition ki2.cc:155
osl::ki2::show
const std::string show(Square)
Definition ki2.cc:133
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::mask_t
GeneralMask< mask_int_t > mask_t
Definition mask.h:351
osl::record
棋譜関係
Definition checkDuplicate.h:15
osl::Ptype
Ptype
駒の種類を4ビットでコード化する
Definition basic_type.h:84
osl::PKNIGHT
@ PKNIGHT
Definition basic_type.h:89
osl::PLANCE
@ PLANCE
Definition basic_type.h:88
osl::PSILVER
@ PSILVER
Definition basic_type.h:90
osl::Ptype_Table
const PtypeTable Ptype_Table
Definition tables.cc:97
osl::canPromote
bool canPromote(Ptype ptype)
ptypeがpromote可能な型かどうかのチェック promote済みの場合はfalseを返す
Definition basic_type.h:147
osl::unpromote
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に，promote前の型を返す． promoteしていない型の時はそのまま返す
Definition basic_type.h:157
osl::isPromoted
bool isPromoted(Ptype ptype)
ptypeがpromote後の型かどうかのチェック
Definition basic_type.h:137
osl::sign
constexpr int sign(Player player)
Definition basic_type.h:23
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::isMajor
bool isMajor(Ptype ptype)
Definition basic_type.h:185
osl::promote
Ptype promote(Ptype ptype)
promote可能なptypeに対して，promote後の型を返す promote不可のptypeを与えてはいけない．
Definition basic_type.h:173
ptypeTable.h
sjis2euc.h
osl::record::Record
Definition record.h:15
osl::record::ki2::Ki2IOError
Definition ki2IOError.h:16