My Project
kanjiMove.cc
Go to the documentation of this file.
5#include <algorithm>
6#include <iterator>
7#include <iostream>
8
9namespace
10{
11int moveFromX(const osl::Move& move)
12{
13 const osl::Square& p = move.from();
14 return p.x();
15}
16
17int moveFromY(const osl::Move& move)
18{
19 const osl::Square& p = move.from();
20 return p.y();
21}
22
23struct SortMoveFromX :
24 public std::binary_function<osl::Move, osl::Move, bool>
25{
26 bool operator()(const osl::Move& a, const osl::Move& b) const
27 {
28 const osl::Square& a_p = a.from();
29 const osl::Square& b_p = b.from();
30 return a_p.x() < b_p.x();
31 }
32};
33
34struct SortMoveFromXDesc :
35 public std::binary_function<osl::Move, osl::Move, bool>
36{
37 bool operator()(const osl::Move& a, const osl::Move& b) const
38 {
39 const osl::Square& a_p = a.from();
40 const osl::Square& b_p = b.from();
41 return a_p.x() > b_p.x();
42 }
43};
44
45struct SortMoveFromY :
46 public std::binary_function<osl::Move, osl::Move, bool>
47{
48 bool operator()(const osl::Move& a, const osl::Move& b) const
49 {
50 const osl::Square& a_p = a.from();
51 const osl::Square& b_p = b.from();
52 return a_p.y() < b_p.y();
53 }
54};
55
56struct SortMoveFromYDesc :
57 public std::binary_function<osl::Move, osl::Move, bool>
58{
59 bool operator()(const osl::Move& a, const osl::Move& b) const
60 {
61 const osl::Square& a_p = a.from();
62 const osl::Square& b_p = b.from();
63 return a_p.y() > b_p.y();
64 }
65};
66
67struct RemoveMoveFromXOver :
68 public std::unary_function<osl::Move, bool>
69{
70 const int min_x;
71 RemoveMoveFromXOver(const int min_x)
72 : min_x(min_x)
73 {}
74
75 bool operator()(const osl::Move& m) const
76 {
77 const osl::Square& p = m.from();
78 return p.x() > min_x;
79 }
80};
81
82struct RemoveMoveFromXGTE :
83 public std::unary_function<osl::Move, bool>
84{
85 const int min_x;
86 RemoveMoveFromXGTE(const int min_x)
87 : min_x(min_x)
88 {}
89
90 bool operator()(const osl::Move& m) const
91 {
92 const osl::Square& p = m.from();
93 return p.x() >= min_x;
94 }
95};
96
97struct RemoveMoveFromYOver :
98 public std::unary_function<osl::Move, bool>
99{
100 const int min_y;
101 RemoveMoveFromYOver(const int min_y)
102 : min_y(min_y)
103 {}
104
105 bool operator()(const osl::Move& m) const
106 {
107 const osl::Square& p = m.from();
108 return p.y() > min_y;
109 }
110};
111
112struct RemoveMoveFromYGTE :
113 public std::unary_function<osl::Move, bool>
114{
115 const int min_y;
116 RemoveMoveFromYGTE(const int min_y)
117 : min_y(min_y)
118 {}
119
120 bool operator()(const osl::Move& m) const
121 {
122 const osl::Square& p = m.from();
123 return p.y() >= min_y;
124 }
125};
126
127struct RemoveMoveFromXUnder :
128 public std::unary_function<osl::Move, bool>
129{
130 const int max_x;
131 RemoveMoveFromXUnder(const int max_x)
132 : max_x(max_x)
133 {}
134
135 bool operator()(const osl::Move& m) const
136 {
137 const osl::Square& p = m.from();
138 return p.x() < max_x;
139 }
140};
141
142struct RemoveMoveFromXLTE :
143 public std::unary_function<osl::Move, bool>
144{
145 const int max_x;
146 RemoveMoveFromXLTE(const int max_x)
147 : max_x(max_x)
148 {}
149
150 bool operator()(const osl::Move& m) const
151 {
152 const osl::Square& p = m.from();
153 return p.x() <= max_x;
154 }
155};
156
157struct RemoveMoveFromYUnder :
158 public std::unary_function<osl::Move, bool>
159{
160 const int max_y;
161 RemoveMoveFromYUnder(const int max_y)
162 : max_y(max_y)
163 {}
164
165 bool operator()(const osl::Move& m) const
166 {
167 const osl::Square& p = m.from();
168 return p.y() < max_y;
169 }
170};
171
172struct RemoveMoveFromYLTE :
173 public std::unary_function<osl::Move, bool>
174{
175 const int max_y;
176 RemoveMoveFromYLTE(const int max_y)
177 : max_y(max_y)
178 {}
179
180 bool operator()(const osl::Move& m) const
181 {
182 const osl::Square& p = m.from();
183 return p.y() <= max_y;
184 }
185};
186
187struct RemoveMoveFromXEqual :
188 public std::unary_function<osl::Move, bool>
189{
190 const int x;
191 RemoveMoveFromXEqual(const int x)
192 : x(x)
193 {}
194
195 bool operator()(const osl::Move& m) const
196 {
197 const osl::Square& p = m.from();
198 return p.x() == x;
199 }
200};
201
202struct RemoveMoveFromYEqual :
203 public std::unary_function<osl::Move, bool>
204{
205 const int y;
206 RemoveMoveFromYEqual(const int y)
207 : y(y)
208 {}
209
210 bool operator()(const osl::Move& m) const
211 {
212 const osl::Square& p = m.from();
213 return p.y() == y;
214 }
215};
216} // anonymous namespace
217
220 : verbose(false)
221{
222 for (size_t x=1; x<=9; ++x)
223 {
224 for (size_t y=1; y<=9; ++y)
225 {
226 const std::string str = StandardCharacters::suji[x] +
228 str2position[str] = Square(x,y);
229 }
230 }
247
248 // pieces in kakinoki-style board specification
252}
253
258
260KanjiMove::toSquare(const std::string& s) const
261{
262 str2position_t::const_iterator p=str2position.find(s);
263 if (p == str2position.end())
264 return Square();
265 return p->second;
266}
267
269KanjiMove::toPtype(const std::string& s) const
270{
271 str2piece_t::const_iterator p=str2piece.find(s);
272 if (p == str2piece.end())
273 return Ptype();
274 return p->second;
275}
276
279 std::string& str,
280 const osl::Square& to_pos,
281 const osl::Player& player) const
282{
283 assert(!str.empty());
284 assert(found.size() >= 2);
285
286 if ( (str.substr(0,2) == K_MIGI && player == BLACK) ||
287 (str.substr(0,2) == K_HIDARI && player == WHITE) )
288 {
289 found.sort([](Move l, Move r){ return moveFromX(l) < moveFromX(r); });
290 const osl::Move min = found.front();
291 found.remove_if( RemoveMoveFromXOver(min.from().x()) ); // list really removes
292 }
293 else if ( (str.substr(0,2) == K_HIDARI && player == BLACK) ||
294 (str.substr(0,2) == K_MIGI && player == WHITE) )
295 {
296 found.sort([](Move l, Move r){ return moveFromX(l) < moveFromX(r); });
297 const Move max = found.back();
298 found.remove_if( RemoveMoveFromXUnder(max.from().x()) ); // list really removes
299 }
300 else if ( (str.substr(0,2) == K_SHITA && player == BLACK) ||
301 (str.substr(0,2) == K_UE && player == WHITE) )
302 {
303 found.sort([](Move l, Move r){ return moveFromY(l) < moveFromY(r); });
304 const Move min = found.front();
305 found.remove_if( RemoveMoveFromYOver(min.from().y()) ); // list really removes
306 }
307 else if ( (str.substr(0,2) == K_UE && player == BLACK) ||
308 (str.substr(0,2) == K_SHITA && player == WHITE) )
309 {
310 found.sort([](Move l, Move r){ return moveFromY(l) > moveFromY(r); });
311 const Move max = found.front();
312 found.remove_if( RemoveMoveFromYUnder(max.from().y()) ); // list really removes
313 }
314 else if (str.substr(0,2) == K_YORU)
315 {
316 found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y())) ); // list really removes
317 }
318 else if (str.substr(0,2) == K_SUGU && player == WHITE)
319 {
320 found.remove_if( std::not1(RemoveMoveFromXEqual(to_pos.x())) ); // or
321 found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()-1)) ); // list really removes
322 }
323 else if (str.substr(0,2) == K_SUGU && player == BLACK)
324
325 {
326 found.remove_if( std::not1(RemoveMoveFromXEqual(to_pos.x())) ); // or
327 found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()+1)) ); // list really removes
328 }
329 else if (str.substr(0,2) == K_HIKU && player == BLACK)
330 {
331 found.remove_if( RemoveMoveFromYGTE(to_pos.y()) ); // list really removes
332 }
333 else if (str.substr(0,2) == K_HIKU && player == WHITE)
334 {
335 found.remove_if( RemoveMoveFromYLTE(to_pos.y()) ); // list really removes
336 }
337 else if (str.substr(0,2) == K_YUKU && player == BLACK)
338 {
339 found.remove_if( RemoveMoveFromYLTE(to_pos.y()) ); // list really removes
340 }
341 else if (str.substr(0,2) == K_YUKU && player == WHITE)
342 {
343 found.remove_if( RemoveMoveFromYGTE(to_pos.y()) ); // list really removes
344 }
345
346 str.erase(0,2);
347 assert(!found.empty());
348
349 if (found.size() > 1)
350 {
351 assert(!str.empty());
352 selectCandidates(found, str, to_pos, player);
353 }
354
355 assert(found.size() == 1);
356 if (!str.empty())
357 std::cerr << "WARNING: A single candidate is selected, but the input string still has some characters: " << misc::eucToLang(str) << std::endl;
358}
359
361KanjiMove::strToMove(const std::string& orig,
362 const osl::NumEffectState& state,
363 const osl::Move& last_move) const
364{
365 std::string str(orig);
366 if (str.find(K_RESIGN) != str.npos)
367 return Move();
368 assert(str.size() >= 4*2
369 || (str.size() >= 3*2
370 && (str.substr(2,2) == K_ONAZI
371 || (isdigit(str[2]) && isdigit(str[3])))));
372 const Player player = str.substr(0,2) == K_BLACK_SIGN ? BLACK : WHITE;
373 assert(player == state.turn());
374 str.erase(0,2);
375
376 Square to_pos;
377 if (str.substr(0,2) == K_ONAZI)
378 {
379 to_pos = last_move.to();
380 str.erase(0,2);
381 if (str.substr(0,2) == K_SPACE)
382 str.erase(0,2);
383 }
384 else if (isdigit(str[0]) && isdigit(str[1]))
385 {
386 to_pos = Square(str[0]-'0', str[1]-'0');
387 str.erase(0,2);
388 }
389 else
390 {
391 to_pos = toSquare(str.substr(0,4));
392 str.erase(0,4);
393 }
394
395 Ptype ptype;
396 if (str.substr(0,2) == K_NARU) // PLANCE, PKIGHT, PSILVER
397 {
398 ptype = toPtype(str.substr(0,4));
399 str.erase(0,4);
400 }
401 else
402 {
403 ptype = toPtype(str.substr(0,2));
404 str.erase(0,2);
405 }
406
407 // promote or not
408 bool is_promote = false;
409 if (str.size() >= 4 && str.substr(0,4) == K_FUNARI)
410 str.erase(0,4);
411 else if (str.size() >= 4 && str.substr(str.size()-4,4) == K_FUNARI)
412 str.erase(str.size()-4,4);
413 else if (str.size() >= 2 && str.substr(0,2) == K_NARU)
414 {
415 is_promote = true;
416 str.erase(0,2);
417 }
418 else if (str.size() >= 2 && str.substr(str.size()-2,2) == K_NARU)
419 {
420 is_promote = true;
421 str.erase(str.size()-2,2);
422 }
423
424 MoveVector moves;
425 state.generateWithFullUnpromotions(moves);
426 found_moves_t found;
427 for (Move move: moves)
428 {
429 if (move.oldPtype() == ptype &&
430 move.to() == to_pos &&
431 move.isPromotion() == is_promote)
432 {
434 if (std::find(found.begin(), found.end(), move) == found.end())
435 found.push_back(move);
436 }
437 }
438 if (verbose)
439 {
440 std::cerr << "\n" << orig << "\n" << state;
441 std::cerr << "remain: " << str << " (" << str.size() << " bytes)\n";
442 std::cerr << "promote: " << is_promote << "\n";
443 std::cerr << "ptype: " << ptype << "\n";
444 std::cerr << "to_position: " << to_pos << "\n";
445 std::cerr << "candidates: " << found.size() << std::endl;
446 if (found.size() >=2) {
447 for (const Move move: found) {
448 std::cerr << " " << move << std::endl;
449 }
450 }
451 }
452 if (found.empty()) {
453 // there is no leagal move
454 return Move::INVALID();
455 }
456 assert(!found.empty());
457
458 // Single candidate
459 if (found.size() == 1)
460 return found.front();
461
462 // Multiple candidates
463 assert(found.size() >= 2);
464
465 // drop
466 if (str.substr(0,2) == K_UTSU)
467 {
468 found_moves_t::iterator it =
469 std::find_if(found.begin(), found.end(), [](Move m){ return m.isDrop(); });
470 str.erase(0,2);
471 assert(str.empty());
472 assert(it != found.end());
473 return *it;
474 }
475 else
476 {
477 found.remove_if([](Move m){ return m.isDrop(); }); // list really removes
478 if (found.size() == 1)
479 return found.front();
480 }
481
482 // Multiple candidates
483 assert(found.size() >= 2);
484 if (str.empty())
485 return Move();
486 assert(!str.empty());
487 selectCandidates(found, str, to_pos, player);
488 assert(found.size() == 1);
489 return found.front();
490}
491
494{
495 static const KanjiMove Kanji_Move;
496 return Kanji_Move;
497}
498
499// ;;; Local Variables:
500// ;;; mode:c++
501// ;;; c-basic-offset:2
502// ;;; End:
圧縮していない moveの表現 .
static const Move INVALID()
bool isPromotion() const
bool isDrop() const
Ptype oldPtype() const
移動前のPtype, i.e., 成る手だった場合成る前
const Square to() const
const Square from() const
利きを持つ局面
void generateWithFullUnpromotions(MoveVector &) const
打歩詰め絡み以外では有利にはならない手も含め, 全ての合法手を生成す る(Move::ignoredUnpromoteも生成する).
Player turn() const
int y() const
将棋としてのY座標を返す.
Definition basic_type.h:567
int x() const
将棋としてのX座標を返す.
Definition basic_type.h:563
Parse kanji records such as "7六歩", the style of which is generally used to write Shogi records in Jap...
Definition kanjiMove.h:20
str2position_t str2position
Definition kanjiMove.h:45
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
static const KanjiMove & instance()
Definition kanjiMove.cc:493
Square toSquare(const std::string &) const
Definition kanjiMove.cc:260
str2piece_t str2piece
Definition kanjiMove.h:47
std::list< Move > found_moves_t
Definition kanjiMove.h:38
Ptype toPtype(const std::string &) const
Definition kanjiMove.cc:269
void selectCandidates(found_moves_t &found, std::string &str, const Square &to_pos, const Player &player) const
Definition kanjiMove.cc:278
#define K_PSILVER
Definition kanjiCode.h:74
#define K_KNIGHT
Definition kanjiCode.h:67
#define K_NARU
Definition kanjiCode.h:54
#define K_PSILVER_D
Definition kanjiCode.h:76
#define K_PKNIGHT_D
Definition kanjiCode.h:71
#define K_PROOK2
Definition kanjiCode.h:86
#define K_KING2
Definition kanjiCode.h:89
#define K_PLANCE
Definition kanjiCode.h:64
#define K_GOLD
Definition kanjiCode.h:77
#define K_LANCE
Definition kanjiCode.h:62
#define K_RESIGN
Definition kanjiCode.h:118
#define K_SPACE
Definition kanjiCode.h:15
#define K_ROOK
Definition kanjiCode.h:83
#define K_YORU
Definition kanjiCode.h:50
#define K_SHITA
Definition kanjiCode.h:48
#define K_KING
Definition kanjiCode.h:88
#define K_PAWN
Definition kanjiCode.h:58
#define K_ONAZI
Definition kanjiCode.h:53
#define K_PPAWN
Definition kanjiCode.h:60
#define K_UTSU
Definition kanjiCode.h:56
#define K_BISHOP
Definition kanjiCode.h:79
#define K_FUNARI
Definition kanjiCode.h:55
#define K_PBISHOP
Definition kanjiCode.h:81
#define K_HIKU
Definition kanjiCode.h:51
#define K_PKNIGHT
Definition kanjiCode.h:69
#define K_MIGI
Definition kanjiCode.h:45
#define K_SILVER
Definition kanjiCode.h:72
#define K_PROOK
Definition kanjiCode.h:85
#define K_SUGU
Definition kanjiCode.h:49
#define K_HIDARI
Definition kanjiCode.h:46
#define K_PLANCE_D
Definition kanjiCode.h:66
#define K_BLACK_SIGN
Define Kanji characters by using EUC-JP codes.
Definition kanjiCode.h:13
#define K_UE
Definition kanjiCode.h:47
#define K_YUKU
Definition kanjiCode.h:52
std::string eucToLang(const std::string &src)
Definition eucToLang.cc:14
Ptype
駒の種類を4ビットでコード化する
Definition basic_type.h:84
@ ROOK
Definition basic_type.h:100
@ PPAWN
Definition basic_type.h:87
@ BISHOP
Definition basic_type.h:99
@ PROOK
Definition basic_type.h:92
@ PAWN
Definition basic_type.h:95
@ KING
Definition basic_type.h:93
@ KNIGHT
Definition basic_type.h:97
@ SILVER
Definition basic_type.h:98
@ PKNIGHT
Definition basic_type.h:89
@ GOLD
Definition basic_type.h:94
@ PLANCE
Definition basic_type.h:88
@ PBISHOP
Definition basic_type.h:91
@ LANCE
Definition basic_type.h:96
@ PSILVER
Definition basic_type.h:90
Player
Definition basic_type.h:8
@ WHITE
Definition basic_type.h:10
@ BLACK
Definition basic_type.h:9
static const CArray< std::string, 10 > dan
段数の文字
Definition kanjiPrint.h:111
static const CArray< std::string, 10 > suji
筋の文字。駒の文字幅に合わせる必要がある。
Definition kanjiPrint.h:113