kanjiMove.cc
Go to the documentation of this file.
#include "osl/record/kanjiMove.h"
#include "osl/record/kanjiCode.h"
#include "osl/record/kanjiPrint.h"
#include "osl/misc/eucToLang.h"
#include <algorithm>
#include <iterator>
#include <iostream>
namespace
{
int moveFromX(const osl::Move& move)
{
const osl::Square& p = move.from();
return p.x();
}
int moveFromY(const osl::Move& move)
{
const osl::Square& p = move.from();
return p.y();
}
struct SortMoveFromX :
public std::binary_function<osl::Move, osl::Move, bool>
{
bool operator()(const osl::Move& a, const osl::Move& b) const
{
const osl::Square& a_p = a.from();
const osl::Square& b_p = b.from();
return a_p.x() < b_p.x();
}
};
struct SortMoveFromXDesc :
public std::binary_function<osl::Move, osl::Move, bool>
{
bool operator()(const osl::Move& a, const osl::Move& b) const
{
const osl::Square& a_p = a.from();
const osl::Square& b_p = b.from();
return a_p.x() > b_p.x();
}
};
struct SortMoveFromY :
public std::binary_function<osl::Move, osl::Move, bool>
{
bool operator()(const osl::Move& a, const osl::Move& b) const
{
const osl::Square& a_p = a.from();
const osl::Square& b_p = b.from();
return a_p.y() < b_p.y();
}
};
struct SortMoveFromYDesc :
public std::binary_function<osl::Move, osl::Move, bool>
{
bool operator()(const osl::Move& a, const osl::Move& b) const
{
const osl::Square& a_p = a.from();
const osl::Square& b_p = b.from();
return a_p.y() > b_p.y();
}
};
struct RemoveMoveFromXOver :
public std::unary_function<osl::Move, bool>
{
const int min_x;
RemoveMoveFromXOver(const int min_x)
: min_x(min_x)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.x() > min_x;
}
};
struct RemoveMoveFromXGTE :
public std::unary_function<osl::Move, bool>
{
const int min_x;
RemoveMoveFromXGTE(const int min_x)
: min_x(min_x)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.x() >= min_x;
}
};
struct RemoveMoveFromYOver :
public std::unary_function<osl::Move, bool>
{
const int min_y;
RemoveMoveFromYOver(const int min_y)
: min_y(min_y)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.y() > min_y;
}
};
struct RemoveMoveFromYGTE :
public std::unary_function<osl::Move, bool>
{
const int min_y;
RemoveMoveFromYGTE(const int min_y)
: min_y(min_y)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.y() >= min_y;
}
};
struct RemoveMoveFromXUnder :
public std::unary_function<osl::Move, bool>
{
const int max_x;
RemoveMoveFromXUnder(const int max_x)
: max_x(max_x)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.x() < max_x;
}
};
struct RemoveMoveFromXLTE :
public std::unary_function<osl::Move, bool>
{
const int max_x;
RemoveMoveFromXLTE(const int max_x)
: max_x(max_x)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.x() <= max_x;
}
};
struct RemoveMoveFromYUnder :
public std::unary_function<osl::Move, bool>
{
const int max_y;
RemoveMoveFromYUnder(const int max_y)
: max_y(max_y)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.y() < max_y;
}
};
struct RemoveMoveFromYLTE :
public std::unary_function<osl::Move, bool>
{
const int max_y;
RemoveMoveFromYLTE(const int max_y)
: max_y(max_y)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.y() <= max_y;
}
};
struct RemoveMoveFromXEqual :
public std::unary_function<osl::Move, bool>
{
const int x;
RemoveMoveFromXEqual(const int x)
: x(x)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.x() == x;
}
};
struct RemoveMoveFromYEqual :
public std::unary_function<osl::Move, bool>
{
const int y;
RemoveMoveFromYEqual(const int y)
: y(y)
{}
bool operator()(const osl::Move& m) const
{
const osl::Square& p = m.from();
return p.y() == y;
}
};
} // anonymous namespace
osl::record::
KanjiMove::KanjiMove()
: verbose(false)
{
for (size_t x=1; x<=9; ++x)
{
for (size_t y=1; y<=9; ++y)
{
const std::string str = StandardCharacters::suji[x] +
StandardCharacters::dan[y];
str2position[str] = Square(x,y);
}
}
str2piece[K_PAWN] = PAWN;
str2piece[K_PPAWN] = PPAWN;
str2piece[K_LANCE] = LANCE;
str2piece[K_PLANCE_D] = PLANCE;
str2piece[K_KNIGHT] = KNIGHT;
str2piece[K_PKNIGHT_D] = PKNIGHT;
str2piece[K_SILVER] = SILVER;
str2piece[K_PSILVER_D] = PSILVER;
str2piece[K_GOLD] = GOLD;
str2piece[K_BISHOP] = BISHOP;
str2piece[K_PBISHOP] = PBISHOP;
str2piece[K_ROOK] = ROOK;
str2piece[K_PROOK] = PROOK;
str2piece[K_PROOK2] = PROOK;
str2piece[K_KING] = KING;
str2piece[K_KING2] = KING;
// pieces in kakinoki-style board specification
str2piece[K_PLANCE] = PLANCE;
str2piece[K_PKNIGHT] = PKNIGHT;
str2piece[K_PSILVER] = PSILVER;
}
osl::record::
KanjiMove::~KanjiMove()
{
}
osl::Square osl::record::
KanjiMove::toSquare(const std::string& s) const
{
str2position_t::const_iterator p=str2position.find(s);
if (p == str2position.end())
return Square();
return p->second;
}
osl::Ptype osl::record::
KanjiMove::toPtype(const std::string& s) const
{
str2piece_t::const_iterator p=str2piece.find(s);
if (p == str2piece.end())
return Ptype();
return p->second;
}
void osl::record::
KanjiMove::selectCandidates(found_moves_t& found,
std::string& str,
const osl::Square& to_pos,
const osl::Player& player) const
{
assert(!str.empty());
assert(found.size() >= 2);
if ( (str.substr(0,2) == K_MIGI && player == BLACK) ||
(str.substr(0,2) == K_HIDARI && player == WHITE) )
{
found.sort([](Move l, Move r){ return moveFromX(l) < moveFromX(r); });
const osl::Move min = found.front();
found.remove_if( RemoveMoveFromXOver(min.from().x()) ); // list really removes
}
else if ( (str.substr(0,2) == K_HIDARI && player == BLACK) ||
(str.substr(0,2) == K_MIGI && player == WHITE) )
{
found.sort([](Move l, Move r){ return moveFromX(l) < moveFromX(r); });
const Move max = found.back();
found.remove_if( RemoveMoveFromXUnder(max.from().x()) ); // list really removes
}
else if ( (str.substr(0,2) == K_SHITA && player == BLACK) ||
(str.substr(0,2) == K_UE && player == WHITE) )
{
found.sort([](Move l, Move r){ return moveFromY(l) < moveFromY(r); });
const Move min = found.front();
found.remove_if( RemoveMoveFromYOver(min.from().y()) ); // list really removes
}
else if ( (str.substr(0,2) == K_UE && player == BLACK) ||
(str.substr(0,2) == K_SHITA && player == WHITE) )
{
found.sort([](Move l, Move r){ return moveFromY(l) > moveFromY(r); });
const Move max = found.front();
found.remove_if( RemoveMoveFromYUnder(max.from().y()) ); // list really removes
}
else if (str.substr(0,2) == K_YORU)
{
found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y())) ); // list really removes
}
else if (str.substr(0,2) == K_SUGU && player == WHITE)
{
found.remove_if( std::not1(RemoveMoveFromXEqual(to_pos.x())) ); // or
found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()-1)) ); // list really removes
}
else if (str.substr(0,2) == K_SUGU && player == BLACK)
{
found.remove_if( std::not1(RemoveMoveFromXEqual(to_pos.x())) ); // or
found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()+1)) ); // list really removes
}
else if (str.substr(0,2) == K_HIKU && player == BLACK)
{
found.remove_if( RemoveMoveFromYGTE(to_pos.y()) ); // list really removes
}
else if (str.substr(0,2) == K_HIKU && player == WHITE)
{
found.remove_if( RemoveMoveFromYLTE(to_pos.y()) ); // list really removes
}
else if (str.substr(0,2) == K_YUKU && player == BLACK)
{
found.remove_if( RemoveMoveFromYLTE(to_pos.y()) ); // list really removes
}
else if (str.substr(0,2) == K_YUKU && player == WHITE)
{
found.remove_if( RemoveMoveFromYGTE(to_pos.y()) ); // list really removes
}
str.erase(0,2);
assert(!found.empty());
if (found.size() > 1)
{
assert(!str.empty());
selectCandidates(found, str, to_pos, player);
}
assert(found.size() == 1);
if (!str.empty())
std::cerr << "WARNING: A single candidate is selected, but the input string still has some characters: " << misc::eucToLang(str) << std::endl;
}
const osl::Move osl::record::
KanjiMove::strToMove(const std::string& orig,
const osl::NumEffectState& state,
const osl::Move& last_move) const
{
std::string str(orig);
if (str.find(K_RESIGN) != str.npos)
return Move();
assert(str.size() >= 4*2
|| (str.size() >= 3*2
&& (str.substr(2,2) == K_ONAZI
|| (isdigit(str[2]) && isdigit(str[3])))));
const Player player = str.substr(0,2) == K_BLACK_SIGN ? BLACK : WHITE;
assert(player == state.turn());
str.erase(0,2);
Square to_pos;
if (str.substr(0,2) == K_ONAZI)
{
to_pos = last_move.to();
str.erase(0,2);
if (str.substr(0,2) == K_SPACE)
str.erase(0,2);
}
else if (isdigit(str[0]) && isdigit(str[1]))
{
to_pos = Square(str[0]-'0', str[1]-'0');
str.erase(0,2);
}
else
{
to_pos = toSquare(str.substr(0,4));
str.erase(0,4);
}
Ptype ptype;
if (str.substr(0,2) == K_NARU) // PLANCE, PKIGHT, PSILVER
{
ptype = toPtype(str.substr(0,4));
str.erase(0,4);
}
else
{
ptype = toPtype(str.substr(0,2));
str.erase(0,2);
}
// promote or not
bool is_promote = false;
if (str.size() >= 4 && str.substr(0,4) == K_FUNARI)
str.erase(0,4);
else if (str.size() >= 4 && str.substr(str.size()-4,4) == K_FUNARI)
str.erase(str.size()-4,4);
else if (str.size() >= 2 && str.substr(0,2) == K_NARU)
{
is_promote = true;
str.erase(0,2);
}
else if (str.size() >= 2 && str.substr(str.size()-2,2) == K_NARU)
{
is_promote = true;
str.erase(str.size()-2,2);
}
MoveVector moves;
state.generateWithFullUnpromotions(moves);
found_moves_t found;
for (Move move: moves)
{
if (move.oldPtype() == ptype &&
move.to() == to_pos &&
move.isPromotion() == is_promote)
{
if (std::find(found.begin(), found.end(), move) == found.end())
found.push_back(move);
}
}
if (verbose)
{
std::cerr << "\n" << orig << "\n" << state;
std::cerr << "remain: " << str << " (" << str.size() << " bytes)\n";
std::cerr << "promote: " << is_promote << "\n";
std::cerr << "ptype: " << ptype << "\n";
std::cerr << "to_position: " << to_pos << "\n";
std::cerr << "candidates: " << found.size() << std::endl;
if (found.size() >=2) {
for (const Move move: found) {
std::cerr << " " << move << std::endl;
}
}
}
if (found.empty()) {
// there is no leagal move
return Move::INVALID();
}
assert(!found.empty());
// Single candidate
if (found.size() == 1)
return found.front();
// Multiple candidates
assert(found.size() >= 2);
// drop
if (str.substr(0,2) == K_UTSU)
{
found_moves_t::iterator it =
std::find_if(found.begin(), found.end(), [](Move m){ return m.isDrop(); });
str.erase(0,2);
assert(str.empty());
assert(it != found.end());
return *it;
}
else
{
found.remove_if([](Move m){ return m.isDrop(); }); // list really removes
if (found.size() == 1)
return found.front();
}
// Multiple candidates
assert(found.size() >= 2);
if (str.empty())
return Move();
assert(!str.empty());
selectCandidates(found, str, to_pos, player);
assert(found.size() == 1);
return found.front();
}
const osl::record::KanjiMove& osl::record::
KanjiMove::instance()
{
static const KanjiMove Kanji_Move;
return Kanji_Move;
}
// ;;; Local Variables:
// ;;; mode:c++
// ;;; c-basic-offset:2
// ;;; End:
osl::MoveVector
Definition container.h:293
osl::Move
圧縮していない moveの表現 .
Definition basic_type.h:1052
osl::Move::INVALID
static const Move INVALID()
Definition basic_type.h:1095
osl::Move::isPromotion
bool isPromotion() const
Definition basic_type.h:1147
osl::Move::isDrop
bool isDrop() const
Definition basic_type.h:1150
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::generateWithFullUnpromotions
void generateWithFullUnpromotions(MoveVector &) const
打歩詰め絡み以外では有利にはならない手も含め, 全ての合法手を生成す る（Move::ignoredUnpromoteも生成する）.
Definition numEffectState.cc:1105
osl::SimpleState::turn
Player turn() const
Definition simpleState.h:220
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::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::KanjiMove
KanjiMove()
Definition kanjiMove.cc:219
osl::record::KanjiMove::verbose
bool verbose
Definition kanjiMove.h:48
osl::record::KanjiMove::str2position
str2position_t str2position
Definition kanjiMove.h:45
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::instance
static const KanjiMove & instance()
Definition kanjiMove.cc:493
osl::record::KanjiMove::toSquare
Square toSquare(const std::string &) const
Definition kanjiMove.cc:260
osl::record::KanjiMove::str2piece
str2piece_t str2piece
Definition kanjiMove.h:47
osl::record::KanjiMove::found_moves_t
std::list< Move > found_moves_t
Definition kanjiMove.h:38
osl::record::KanjiMove::~KanjiMove
~KanjiMove()
Definition kanjiMove.cc:255
osl::record::KanjiMove::toPtype
Ptype toPtype(const std::string &) const
Definition kanjiMove.cc:269
osl::record::KanjiMove::selectCandidates
void selectCandidates(found_moves_t &found, std::string &str, const Square &to_pos, const Player &player) const
Definition kanjiMove.cc:278
eucToLang.h
kanjiCode.h
K_PSILVER
#define K_PSILVER
Definition kanjiCode.h:74
K_KNIGHT
#define K_KNIGHT
Definition kanjiCode.h:67
K_NARU
#define K_NARU
Definition kanjiCode.h:54
K_PSILVER_D
#define K_PSILVER_D
Definition kanjiCode.h:76
K_PKNIGHT_D
#define K_PKNIGHT_D
Definition kanjiCode.h:71
K_PROOK2
#define K_PROOK2
Definition kanjiCode.h:86
K_KING2
#define K_KING2
Definition kanjiCode.h:89
K_PLANCE
#define K_PLANCE
Definition kanjiCode.h:64
K_GOLD
#define K_GOLD
Definition kanjiCode.h:77
K_LANCE
#define K_LANCE
Definition kanjiCode.h:62
K_RESIGN
#define K_RESIGN
Definition kanjiCode.h:118
K_SPACE
#define K_SPACE
Definition kanjiCode.h:15
K_ROOK
#define K_ROOK
Definition kanjiCode.h:83
K_YORU
#define K_YORU
Definition kanjiCode.h:50
K_SHITA
#define K_SHITA
Definition kanjiCode.h:48
K_KING
#define K_KING
Definition kanjiCode.h:88
K_PAWN
#define K_PAWN
Definition kanjiCode.h:58
K_ONAZI
#define K_ONAZI
Definition kanjiCode.h:53
K_PPAWN
#define K_PPAWN
Definition kanjiCode.h:60
K_UTSU
#define K_UTSU
Definition kanjiCode.h:56
K_BISHOP
#define K_BISHOP
Definition kanjiCode.h:79
K_FUNARI
#define K_FUNARI
Definition kanjiCode.h:55
K_PBISHOP
#define K_PBISHOP
Definition kanjiCode.h:81
K_HIKU
#define K_HIKU
Definition kanjiCode.h:51
K_PKNIGHT
#define K_PKNIGHT
Definition kanjiCode.h:69
K_MIGI
#define K_MIGI
Definition kanjiCode.h:45
K_SILVER
#define K_SILVER
Definition kanjiCode.h:72
K_PROOK
#define K_PROOK
Definition kanjiCode.h:85
K_SUGU
#define K_SUGU
Definition kanjiCode.h:49
K_HIDARI
#define K_HIDARI
Definition kanjiCode.h:46
K_PLANCE_D
#define K_PLANCE_D
Definition kanjiCode.h:66
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
K_YUKU
#define K_YUKU
Definition kanjiCode.h:52
kanjiMove.h
kanjiPrint.h
osl::misc::eucToLang
std::string eucToLang(const std::string &src)
Definition eucToLang.cc:14
osl::Ptype
Ptype
駒の種類を4ビットでコード化する
Definition basic_type.h:84
osl::ROOK
@ ROOK
Definition basic_type.h:100
osl::PPAWN
@ PPAWN
Definition basic_type.h:87
osl::BISHOP
@ BISHOP
Definition basic_type.h:99
osl::PROOK
@ PROOK
Definition basic_type.h:92
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::SILVER
@ SILVER
Definition basic_type.h:98
osl::PKNIGHT
@ PKNIGHT
Definition basic_type.h:89
osl::GOLD
@ GOLD
Definition basic_type.h:94
osl::PLANCE
@ PLANCE
Definition basic_type.h:88
osl::PBISHOP
@ PBISHOP
Definition basic_type.h:91
osl::LANCE
@ LANCE
Definition basic_type.h:96
osl::PSILVER
@ PSILVER
Definition basic_type.h:90
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::record::StandardCharacters::dan
static const CArray< std::string, 10 > dan
段数の文字
Definition kanjiPrint.h:111
osl::record::StandardCharacters::suji
static const CArray< std::string, 10 > suji
筋の文字。駒の文字幅に合わせる必要がある。
Definition kanjiPrint.h:113