csa.cc
Go to the documentation of this file.
#include "osl/csa.h"
#include "osl/simpleState.h"
#include "osl/bits/pieceTable.h"
#include "osl/oslConfig.h"
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <cassert>
#include <string>
#include <fstream>
#include <array>
/* ------------------------------------------------------------------------- */
osl::Player osl::csa::
charToPlayer(char c)
{
if(c=='+')
return BLACK;
if(c=='-')
return WHITE;
throw CsaIOError("not a csa PlayerCharacter "+std::string(1,c));
}
const osl::Square osl::csa::
strToPos(const std::string& s)
{
int x=s.at(0)-'0';
int y=s.at(1)-'0';
if(x==0 && y==0)
return Square::STAND();
return Square(x,y);
}
osl::Ptype osl::csa::
strToPtype(const std::string& s)
{
for(int i=0;i<16;i++){
if(s == Ptype_Table.getCsaName(static_cast<Ptype>(i)))
return static_cast<Ptype>(i);
}
throw CsaIOError("unknown std::string in csa::strToPtype "+s);
}
const osl::Move osl::csa::
strToMove(const std::string& s,const SimpleState& state)
{
if (s == "%KACHI")
return Move::DeclareWin();
if (s == "%TORYO")
return Move::INVALID();
if (s == "%PASS") // FIXME: not in CSA protocol
return Move::PASS(state.turn());
Player pl=csa::charToPlayer(s.at(0));
Square fromPos=csa::strToPos(s.substr(1,2));
Square toPos=csa::strToPos(s.substr(3,2));
Ptype ptype=csa::strToPtype(s.substr(5,2));
if(fromPos==Square::STAND()){
if (isPromoted(ptype))
throw CsaIOError("drop with promote ?! in csa::strToMove "+s);
return Move(toPos,ptype,pl);
}
else{
Piece p0=state.pieceAt(fromPos);
Piece p1=state.pieceAt(toPos);
Ptype capturePtype=p1.ptype();
bool isPromote=(p0.ptype()!=ptype);
if (! ((p0.ptype()==ptype)||(p0.ptype()==unpromote(ptype))))
throw CsaIOError("bad promotion in csa::strToMove "+s);
return Move(fromPos,toPos,ptype,
capturePtype,isPromote,pl);
}
}
/* ------------------------------------------------------------------------- */
const std::string osl::csa::
show(Player player, std::string& buf, size_t offset)
{
assert(buf.size() >= offset+1);
buf[offset] = (player==BLACK) ? '+' : '-';
return buf;
}
const std::string osl::csa::
show(Move move, std::string& buf)
{
assert(buf.capacity() >= 7);
buf.resize(7);
if (move == Move::DeclareWin())
return buf = "%KACHI";
if (move.isInvalid())
return buf = "%TORYO";
if (move.isPass())
return buf = "%PASS"; // FIXME: not in CSA protocol
show(move.player(), buf);
show(move.from(), buf, 1);
show(move.to(), buf, 3);
show(move.ptype(), buf, 5);
return buf;
}
const std::string osl::csa::
show(Square pos, std::string& buf, size_t offset)
{
assert(buf.size() >= offset+2);
if (pos.isPieceStand())
{
buf[0+offset] = '0';
buf[1+offset] = '0';
return buf;
}
const int x = pos.x();
const int y = pos.y();
buf[offset+0] = x + '0';
buf[offset+1] = y + '0';
return buf;
}
const std::string osl::csa::
show(Ptype ptype, std::string& buf, size_t offset)
{
assert(buf.size() >= offset+2);
const char *name = Ptype_Table.getCsaName(ptype);
buf[0+offset] = name[0];
buf[1+offset] = name[1];
return buf;
}
const std::string osl::csa::
show(Move move)
{
// NOTE: copy コピーを返すので dangling pointer ではない
std::string buf("+7776FU");
return show(move, buf);
}
const std::string osl::csa::
fancyShow(Move move)
{
std::string ret = show(move);
if (move.isNormal()) {
if (move.capturePtype() != PTYPE_EMPTY)
ret += "x" + show(move.capturePtype());
if (move.isPromotion())
ret += '+';
}
return ret;
}
const std::string osl::csa::
show(Player player)
{
std::string buf("+");
return show(player, buf);
}
const std::string osl::csa::
show(Square position)
{
std::string buf("00");
return show(position, buf);
}
const std::string osl::csa::
show(Ptype ptype)
{
std::string buf("OU");
return show(ptype, buf);
}
const std::string osl::csa::
show(Piece piece)
{
if (piece.isEdge())
return " ";
if (piece.isEmpty())
return " * ";
assert(piece.isPiece() && isPiece(piece.ptype()));
assert(unpromote(piece.ptype()) == Piece_Table.getPtypeOf(piece.number()));
return show(piece.owner())
+ show(piece.ptype());
}
const std::string osl::csa::
show(const Move *first, const Move *last)
{
std::ostringstream out;
for (; first != last; ++first) {
if (first->isInvalid())
break;
out << show(*first);
}
return out.str();
}
/* ------------------------------------------------------------------------- */
osl::csa::CsaFileMinimal::CsaFileMinimal(const std::string& filename)
{
std::ifstream is(filename);
if (! is) {
const std::string msg = "CsaFileMinimal::CsaFileMinimal file open failed ";
std::cerr << msg << filename << "\n";
throw CsaIOError(msg + filename);
}
load(is);
}
osl::csa::CsaFileMinimal::CsaFileMinimal(std::istream& is)
{
load(is);
}
osl::csa::CsaFileMinimal::~CsaFileMinimal()
{
}
void osl::csa::CsaFileMinimal::load(std::istream& is)
{
SimpleState work;
work.init();
std::string line;
CArray<bool, 9> board_parsed = {{ false }};
while (std::getline(is, line))
{
// quick hack for \r
if ((! line.empty())
&& (line[line.size()-1] == 13))
line.erase(line.size()-1);
std::vector<std::string> elements;
boost::algorithm::split(elements, line, boost::algorithm::is_any_of(","));
for (auto& e: elements) {
boost::algorithm::trim(e);
boost::algorithm::trim_left(e);
parseLine(work, record, e, board_parsed);
}
}
if (*std::min_element(board_parsed.begin(), board_parsed.end()) == false)
throw CsaIOError("incomplete position description in csaParseLine");
assert(record.initial_state.isConsistent());
}
bool osl::csa::
CsaFileMinimal::parseLine(SimpleState& state, RecordMinimal& record, std::string s,
CArray<bool,9>& board_parsed)
{
while (! s.empty() && isspace(s[s.size()-1])) // ignore trailing garbage
s.resize(s.size()-1);
if (s.length()==0)
return true;
switch(s.at(0)){
case 'P': /* 開始盤面 */
switch(s.at(1)){
case 'I': /* 平手初期配置 */
board_parsed.fill(true);
state.init(HIRATE);
break;
case '+': /* 先手の駒 */
case '-':{ /* 後手の駒 */
Player pl=csa::charToPlayer(s.at(1));
for(int i=2;i<=(int)s.length()-4;i+=4){
Square pos=csa::strToPos(s.substr(i,2));
if(s.substr(i+2,2) == "AL"){
state.setPieceAll(pl);
}
else{
Ptype ptype=csa::strToPtype(s.substr(i+2,2));
state.setPiece(pl,pos,ptype);
}
}
break;
}
default:
if(isdigit(s.at(1))){
const int y=s.at(1)-'0';
board_parsed[y-1] = true;
for(unsigned int x=9,i=2;i<s.length();i+=3,x--){
if (s.at(i) != '+' && s.at(i) != '-' && s.find(" *",i)!=i) {
if (OslConfig::inUnitTest())
throw CsaIOError("parse board error " + s);
else
std::cerr << "possible typo for empty square " << s << "\n";
}
if (s.at(i) != '+' && s.at(i) != '-') continue;
Player pl=csa::charToPlayer(s.at(i));
Square pos(x,y);
Ptype ptype=csa::strToPtype(s.substr(i+1,2));
state.setPiece(pl,pos,ptype);
}
}
}
break;
case '+':
case '-':{
Player pl=csa::charToPlayer(s.at(0));
if(s.length()==1){
state.setTurn(pl);
state.initPawnMask();
record.initial_state = NumEffectState(state);
}
else{ // actual moves
const Move m = csa::strToMove(s,state);
if (! state.isValidMove(m))
{
std::cerr << "Illegal move " << m << std::endl;
throw CsaIOError("illegal move "+s);
}
record.moves.push_back(m);
NumEffectState copy(state);
copy.makeMove(m);
state = copy;
}
break;
}
default:
return false; // there are unhandled contents
}
return true;
}
/* ------------------------------------------------------------------------- */
osl::csa::CsaString::CsaString(const std::string& s)
{
std::istringstream is(s);
load(is);
}
/* ------------------------------------------------------------------------- */
// ;;; Local Variables:
// ;;; mode:c++
// ;;; c-basic-offset:2
// ;;; End:
osl::CArray
Definition container.h:20
osl::CArray::fill
void fill(const T_simple &value=T_simple())
Definition container.h:67
osl::CArray::end
iterator end()
Definition container.h:65
osl::CArray::begin
iterator begin()
Definition container.h:64
osl::Move
圧縮していない moveの表現 .
Definition basic_type.h:1052
osl::Move::PASS
static const Move PASS(Player P)
Definition basic_type.h:1094
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::DeclareWin
static const Move DeclareWin()
Definition basic_type.h:1096
osl::Move::isPass
bool isPass() const
Definition basic_type.h:1092
osl::Move::capturePtype
Ptype capturePtype() const
Definition basic_type.h:1180
osl::Move::isNormal
bool isNormal() const
INVALID でも PASS でもない.
Definition basic_type.h:1088
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::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::isEdge
bool isEdge() const
Definition basic_type.h:919
osl::Piece::owner
Player owner() const
Definition basic_type.h:963
osl::Piece::isPiece
bool isPiece() const
Definition basic_type.h:953
osl::Piece::number
int number() const
Definition basic_type.h:828
osl::SimpleState
Definition simpleState.h:35
osl::SimpleState::isValidMove
bool isValidMove(Move move, bool show_error=true) const
合法手かどうかを検査する． isValidMoveByRule, isAlmostValidMove をおこなう． 玉の素抜きや王手を防いでいるか， 千日手，打歩詰かどうかは検査しない．
Definition simpleState.cc:435
osl::SimpleState::setTurn
void setTurn(Player player)
Definition simpleState.h:217
osl::SimpleState::init
void init()
盤面が空の状態に初期化
Definition simpleState.cc:44
osl::SimpleState::turn
Player turn() const
Definition simpleState.h:220
osl::SimpleState::setPieceAll
void setPieceAll(Player player)
Definition simpleState.cc:139
osl::SimpleState::initPawnMask
void initPawnMask()
Definition simpleState.cc:20
osl::SimpleState::setPiece
void setPiece(Player player, Square sq, Ptype ptype)
Definition simpleState.cc:114
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::STAND
static const Square STAND()
Definition basic_type.h:548
osl::Square::x
int x() const
将棋としてのX座標を返す.
Definition basic_type.h:563
osl::csa::CsaFileMinimal::parseLine
static bool parseLine(SimpleState &, RecordMinimal &, std::string element, CArray< bool, 9 > &)
Definition csa.cc:247
osl::csa::CsaFileMinimal::~CsaFileMinimal
virtual ~CsaFileMinimal()
Definition csa.cc:216
osl::csa::CsaFileMinimal::CsaFileMinimal
CsaFileMinimal()
Definition csa.h:62
osl::csa::CsaFileMinimal::record
RecordMinimal record
Definition csa.h:53
osl::csa::CsaFileMinimal::load
RecordMinimal load() const
Definition csa.h:58
osl::csa::CsaString::CsaString
CsaString(const std::string &)
Definition csa.cc:325
csa.h
osl::csa::strToPos
const Square strToPos(const std::string &s)
Definition csa.cc:28
osl::csa::strToPtype
Ptype strToPtype(const std::string &s)
Definition csa.cc:38
osl::csa::show
const std::string show(Move)
Definition csa.cc:133
osl::csa::charToPlayer
Player charToPlayer(char c)
Definition csa.cc:18
osl::csa::strToMove
const Move strToMove(const std::string &s, const SimpleState &st)
Definition csa.cc:48
osl::csa::fancyShow
const std::string fancyShow(Move)
Definition csa.cc:141
osl::Ptype
Ptype
駒の種類を4ビットでコード化する
Definition basic_type.h:84
osl::PTYPE_EMPTY
@ PTYPE_EMPTY
Definition basic_type.h:85
osl::Ptype_Table
const PtypeTable Ptype_Table
Definition tables.cc:97
osl::Piece_Table
const PieceTable Piece_Table
Definition tables.cc:94
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::Player
Player
Definition basic_type.h:8
osl::WHITE
@ WHITE
Definition basic_type.h:10
osl::BLACK
@ BLACK
Definition basic_type.h:9
osl::isPiece
constexpr bool isPiece(Ptype ptype)
ptypeが空白やEDGEでないかのチェック
Definition basic_type.h:120
osl::HIRATE
@ HIRATE
Definition simpleState.h:21
oslConfig.h
pieceTable.h
simpleState.h
osl::OslConfig::inUnitTest
static int inUnitTest()
Definition oslConfig.h:87
osl::RecordMinimal
Definition csa.h:43
osl::csa::CsaIOError
Definition csa.h:18