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の表現 .
Definition: basic_type.h:1052
bool isValid() const
Definition: basic_type.cc:246
bool isInvalid() const
state に apply 可能でない場合にtrue
Definition: basic_type.h:1202
bool isPromotion() const
Definition: basic_type.h:1147
Player player() const
Definition: basic_type.h:1195
bool isPass() const
Definition: basic_type.h:1092
bool isNormal() const
INVALID でも PASS でもない.
Definition: basic_type.h:1088
Ptype oldPtype() const
移動前のPtype, i.e., 成る手だった場合成る前
Definition: basic_type.h:1174
const Square to() const
Definition: basic_type.h:1132
const Square from() const
Definition: basic_type.h:1125
利きを持つ局面
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
Definition: simpleState.h:167
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
GeneralMask< mask_int_t > mask_t
Definition: mask.h:351
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