My Project
ki2.cc
Go to the documentation of this file.
1#include "osl/record/ki2.h"
5#include "osl/misc/sjis2euc.h"
7#include <boost/algorithm/string/trim.hpp>
8#include <fstream>
9#include <iostream>
10
13 std::string line)
14{
15 boost::algorithm::trim(line);
16
17 if (line.empty() || line.at(0) == '*')
18 return OK;
19 else if (line.size() > 10 && line.substr(0,10) == (K_KAISHI K_NICHIJI K_COLON))
20 {
21 std::string date_str(line.substr(10)); // this may or may not include HH:MM
23 const static std::string spaces[] = {" ", K_SPACE};
24 for (const auto& space: spaces) {
25 const std::string::size_type pos_space = date_str.find(space);
26 if (pos_space != std::string::npos)
27 date_str = date_str.substr(0, pos_space);
28 }
29 record.setDate(date_str);
30 // an invalid date_str results in an invalid boost::gregorian::date value
31 // you can check it date.is_special()
32 return OK;
33 }
34 else if (line.size() > 6 && line.substr(0,6) == (K_BLACK K_COLON))
35 {
36 const std::string player_name(line.substr(6));
37 record.player[BLACK] = player_name;
38 return OK;
39 }
40 else if (line.size() > 6 && line.substr(0,6) == (K_WHITE K_COLON))
41 {
42 const std::string player_name(line.substr(6));
43 record.player[WHITE] = player_name;
44 return OK;
45 }
46 else if (line.size() > 6 && line.substr(0,6) == (K_KISEN K_COLON))
47 {
48 record.tournament_name = line.substr(6);
49 return OK;
50 }
51 else if (line.size() > 8 && line.substr(0,8) == (K_TEAIWARI K_COLON))
52 return Komaochi;
53 else if (line.substr(0,2) != K_BLACK_SIGN && line.substr(0,2) != K_WHITE_SIGN)
54 return OK;
55
56 std::string move_str;
57 for (size_t i = 0; ; ) {
58 if (i < line.size() &&
59 (line.at(i) == ' ' || line.at(i) == '\t'))
60 {
61 ++i;
62 continue;
63 }
64
65 if ( (line.substr(i,2) == K_BLACK_SIGN ||
66 line.substr(i,2) == K_WHITE_SIGN ||
67 i+1 >= line.size())
68 && !move_str.empty())
69 {
70 // apply move_str
71 Move last_move;
72 if (record.moves().size() > 0)
73 last_move = record.moves().back();
74 const Move move = kmove.strToMove(move_str, state, last_move);
75 if (!move.isValid()) {
76 if (move_str.find(K_RESIGN) != move_str.npos)
77 return OK;
78 return Illegal;
79 }
80 record.record.moves.push_back(move);
81 state.makeMove(move);
82 move_str.clear();
83 }
84 if (i+1 >= line.size())
85 return OK;
86 move_str.append(line.substr(i,2));
87 i += 2;
88 } // for
89}
90
92Ki2File::Ki2File(const std::string& filename, bool v)
93 : verbose(v)
94{
95 std::ifstream is(filename);
96 if (! is)
97 {
98 const std::string msg = "Ki2File::Ki2File file cannot read ";
99 std::cerr << msg << filename << "\n";
100 throw Ki2IOError(msg + filename);
101 }
102 KanjiMove kmove;
103 kmove.setVerbose(verbose);
104
105 NumEffectState work;
107 std::string line;
108 while (std::getline(is, line))
109 {
110 line = misc::sjis2euc(line);
111 const ParseResult result = parseLine(work, record, kmove, line);
112 switch (result)
113 {
114 case OK:
115 continue;
116 case Komaochi:
117 {
118 const std::string msg = "ERROR: Komaochi (handicapped game) records are not available: ";
119 std::cerr << msg << "\n";
120 throw Ki2IOError(msg);
121 }
122 case Illegal:
123 {
124 const std::string msg = "ERROR: An illegal move found in a record.";
125 throw Ki2IOError(msg);
126 }
127 default:
128 assert(false);
129 }
130 }
131}
132
133const std::string osl::ki2::show(Square position)
134{
135 using namespace record;
136 if (position.isPieceStand())
137 return "";
138 const int x = position.x(), y = position.y();
139 return StandardCharacters::suji[x] + StandardCharacters::dan[y];
140}
141
142const std::string osl::ki2::show(Ptype ptype)
143{
144 using namespace record;
145 switch (ptype)
146 {
147 case PSILVER: case PKNIGHT: case PLANCE:
148 return K_NARU + StandardCharacters().kanji(unpromote(ptype));
149 default:
150 ;
151 }
152 return StandardCharacters().kanji(ptype);
153}
154
155const std::string osl::ki2::showPromote(bool promote)
156{
157 return promote ? K_NARU : K_FUNARI;
158}
159
160const std::string osl::ki2::show(Square cur, Square prev)
161{
162 if (cur == prev)
163 return K_ONAZI;
164 return show(cur);
165}
166
167const std::string osl::ki2::show(Move m, const NumEffectState& state,
168 Move prev)
169{
170 std::string ret = (m.player() == BLACK) ? K_BLACK_SIGN : K_WHITE_SIGN;
171 if (m.isPass()) {
172 ret += K_PASS;
173 return ret;
174 }
175 const Square from = m.from(), to = m.to();
176 const Ptype ptype = m.oldPtype();
177 const Player player = m.player();
178 mask_t pieces = state.allEffectAt(player, ptype, to);
179 const mask_t promoted = state.promotedPieces().getMask(Ptype_Table.getIndex(ptype));
180 if (isPromoted(ptype))
181 pieces &= promoted;
182 else
183 pieces &= ~promoted;
184 if (from.isPieceStand()) {
185 ret += show(to) + show(ptype);
186 int has_effect = 0;
187 while (pieces.any()) {
188 const Piece p = state.pieceOf(pieces.takeOneBit());
189 if (p.ptype() == ptype)
190 ++has_effect;
191 }
192 if (has_effect)
193 ret += K_UTSU;
194 return ret;
195 }
196 ret += prev.isNormal() && (to == prev.to())
197 ? K_ONAZI : show(to);
198 ret += show(m.oldPtype());
199 const int count = pieces.countBit();
200 if (count >= 2) {
201 CArray<int,3> x_count = {{ 0 }}, y_count = {{ 0 }};
202 int my_x = 0, my_y = 0;
203 while (pieces.any()) {
204 const int n = pieces.takeOneBit() + Ptype_Table.getIndex(ptype)*32;
205 const Piece p = state.pieceOf(n);
206 if (p.ptype() != ptype)
207 continue;
208 int index_x = 1, index_y = 1;
209 if (p.square().x() != to.x())
210 index_x = ((p.square().x() - to.x()) * sign(player) > 0)
211 ? 2 : 0;
212 if (p.square().y() != to.y())
213 index_y = ((p.square().y() - to.y()) * sign(player) > 0)
214 ? 2 : 0;
215 if (p.square() == from)
216 my_x = index_x, my_y = index_y;
217 x_count[index_x]++;
218 y_count[index_y]++;
219 }
220 if (y_count[my_y] == 1) {
221 if (from.y() == to.y())
222 ret += K_YORU;
223 else if ((to.y() - from.y())*sign(player) > 0)
224 ret += K_HIKU;
225 else
226 ret += K_UE;
227 }
228 else if (x_count[my_x] == 1) {
229 if (from.x() == to.x()) {
230 if (isPromoted(ptype) && isMajor(ptype)) {
231 const Piece l = state.pieceAt
232 (Square(from.x() - sign(player), from.y()));
233 if (l.isOnBoardByOwner(player) && l.ptype() == ptype)
234 ret += K_HIDARI;
235 else
236 ret += K_MIGI;
237 }
238 else
239 ret += K_SUGU;
240 }
241 else if ((to.x() - from.x())*sign(player) > 0)
242 ret += K_MIGI;
243 else
244 ret += K_HIDARI;
245 }
246 else if (from.x() == to.x()) {
247 if ((to.y() - from.y())*sign(player) > 0)
248 ret += K_HIKU;
249 else
250 ret += K_SUGU;
251 }
252 else {
253 if ((to.x() - from.x())*sign(player) > 0)
254 ret += K_MIGI;
255 else
256 ret += K_HIDARI;
257 if ((to.y() - from.y())*sign(player) > 0)
258 ret += K_HIKU;
259 else
260 ret += K_UE;
261 }
262 }
263 if (canPromote(m.oldPtype()))
264 if (m.isPromotion()
265 || to.canPromote(player) || from.canPromote(player)) {
266 ret += showPromote(m.isPromotion());
267 }
268 return ret;
269}
270
271const std::string osl::
272ki2::show(const Move *first, const Move *last,
273 const char *threatmate_first, const char *threatmate_last,
274 const NumEffectState& initial, Move prev)
275{
276 if (first == last || first->isInvalid())
277 return "";
278 NumEffectState state(initial);
279 std::string ret = show(*first, state, prev);
280 if (threatmate_first != threatmate_last
281 && *threatmate_first++)
282 ret += "(" K_TSUMERO ")";
283 for (; first+1 != last; ++first) {
284 if (first->isInvalid())
285 break;
286 state.makeMove(*first);
287 ret += show(*(first+1), state, *first);
288 if (threatmate_first != threatmate_last
289 && *threatmate_first++)
290 ret += "(" K_TSUMERO ")";
291 }
292 return ret;
293}
294
295const std::string osl::
296ki2::show(const Move *first, const Move *last, const NumEffectState& initial, Move prev)
297{
298 std::vector<char> threatmate(last-first, false);
299 return show(first, last, &*threatmate.begin(), &*threatmate.end(), initial, prev);
300}
301
302// ;;; Local Variables:
303// ;;; mode:c++
304// ;;; c-basic-offset:2
305// ;;; End:
圧縮していない moveの表現 .
bool isValid() const
bool isInvalid() const
state に apply 可能でない場合にtrue
bool isPromotion() const
Player player() const
bool isPass() const
bool isNormal() const
INVALID でも PASS でもない.
Ptype oldPtype() const
移動前のPtype, i.e., 成る手だった場合成る前
const Square to() const
const Square from() const
利きを持つ局面
void makeMove(Move move)
const PieceMask promotedPieces() const
const mask_t allEffectAt(Player P, Square target) const
const mask_t getMask(int num) const
Definition pieceMask.h:59
Ptype ptype() const
Definition basic_type.h:821
const Square square() const
Definition basic_type.h:832
bool isOnBoardByOwner() const
piece がプレイヤーPの持ち物でかつボード上にある駒の場合は true.
Definition basic_type.h:852
int getIndex(Ptype) const
Definition ptypeTable.h:50
const Piece pieceOf(int num) const
Definition simpleState.h:76
const Piece pieceAt(Square sq) const
bool isPieceStand() const
Definition basic_type.h:576
int y() const
将棋としてのY座標を返す.
Definition basic_type.h:567
bool canPromote() const
Definition basic_type.h:659
int x() const
将棋としてのX座標を返す.
Definition basic_type.h:563
bool verbose
Definition ki2.h:24
static ParseResult parseLine(NumEffectState &, Record &, KanjiMove &, std::string element)
Definition ki2.cc:12
Ki2File(const std::string &filename, bool verbose=false)
Definition ki2.cc:92
Parse kanji records such as "7六歩", the style of which is generally used to write Shogi records in Jap...
Definition kanjiMove.h:20
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
void setVerbose(bool verbose)
Definition kanjiMove.h:31
#define K_KAISHI
Definition kanjiCode.h:106
#define K_NARU
Definition kanjiCode.h:54
#define K_RESIGN
Definition kanjiCode.h:118
#define K_PASS
Definition kanjiCode.h:98
#define K_SPACE
Definition kanjiCode.h:15
#define K_YORU
Definition kanjiCode.h:50
#define K_TEAIWARI
Definition kanjiCode.h:97
#define K_TSUMERO
Definition kanjiCode.h:105
#define K_ONAZI
Definition kanjiCode.h:53
#define K_UTSU
Definition kanjiCode.h:56
#define K_BLACK
Definition kanjiCode.h:92
#define K_FUNARI
Definition kanjiCode.h:55
#define K_HIKU
Definition kanjiCode.h:51
#define K_NICHIJI
Definition kanjiCode.h:107
#define K_WHITE
Definition kanjiCode.h:93
#define K_MIGI
Definition kanjiCode.h:45
#define K_COLON
Definition kanjiCode.h:17
#define K_WHITE_SIGN
Definition kanjiCode.h:14
#define K_SUGU
Definition kanjiCode.h:49
#define K_HIDARI
Definition kanjiCode.h:46
#define K_KISEN
Definition kanjiCode.h:103
#define K_BLACK_SIGN
Define Kanji characters by using EUC-JP codes.
Definition kanjiCode.h:13
#define K_UE
Definition kanjiCode.h:47
const std::string showPromote(bool)
Definition ki2.cc:155
const std::string show(Square)
Definition ki2.cc:133
std::string sjis2euc(const std::string &str)
Convert character encoding from Shift_JIS to EUC-JP.
Definition sjis2euc.cc:9
Ptype
駒の種類を4ビットでコード化する
Definition basic_type.h:84
@ PKNIGHT
Definition basic_type.h:89
@ PLANCE
Definition basic_type.h:88
@ PSILVER
Definition basic_type.h:90
const PtypeTable Ptype_Table
Definition tables.cc:97
bool canPromote(Ptype ptype)
ptypeがpromote可能な型かどうかのチェック promote済みの場合はfalseを返す
Definition basic_type.h:147
Ptype unpromote(Ptype ptype)
ptypeがpromote後の型の時に,promote前の型を返す. promoteしていない型の時はそのまま返す
Definition basic_type.h:157
bool isPromoted(Ptype ptype)
ptypeがpromote後の型かどうかのチェック
Definition basic_type.h:137
constexpr int sign(Player player)
Definition basic_type.h:23
Player
Definition basic_type.h:8
@ WHITE
Definition basic_type.h:10
@ BLACK
Definition basic_type.h:9
bool isMajor(Ptype ptype)
Definition basic_type.h:185
Ptype promote(Ptype ptype)
promote可能なptypeに対して,promote後の型を返す promote不可のptypeを与えてはいけない.
Definition basic_type.h:173
NumEffectState initial_state
Definition csa.h:44
std::vector< Move > moves
Definition csa.h:45
std::string tournament_name
Definition record.h:28
RecordMinimal record
Definition record.h:16
std::vector< Move > moves() const
Definition record.h:41
void setDate(const std::string &date_str)
Definition record.cc:39
CArray< std::string, 2 > player
Definition record.h:29