My Project
kanjiMove.cc
Go to the documentation of this file.
1 #include "osl/record/kanjiMove.h"
2 #include "osl/record/kanjiCode.h"
4 #include "osl/misc/eucToLang.h"
5 #include <algorithm>
6 #include <iterator>
7 #include <iostream>
8 
9 namespace
10 {
11 int moveFromX(const osl::Move& move)
12 {
13  const osl::Square& p = move.from();
14  return p.x();
15 }
16 
17 int moveFromY(const osl::Move& move)
18 {
19  const osl::Square& p = move.from();
20  return p.y();
21 }
22 
23 struct 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 
34 struct 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 
45 struct 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 
56 struct 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 
67 struct 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 
82 struct 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 
97 struct 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 
112 struct 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 
127 struct 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 
142 struct 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 
157 struct 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 
172 struct 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 
187 struct 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 
202 struct 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  }
231  str2piece[K_PAWN] = PAWN;
239  str2piece[K_GOLD] = GOLD;
242  str2piece[K_ROOK] = ROOK;
245  str2piece[K_KING] = KING;
247 
248  // pieces in kakinoki-style board specification
252 }
253 
256 {
257 }
258 
260 KanjiMove::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 
269 KanjiMove::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 
361 KanjiMove::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の表現 .
Definition: basic_type.h:1052
static const Move INVALID()
Definition: basic_type.h:1095
bool isPromotion() const
Definition: basic_type.h:1147
bool isDrop() const
Definition: basic_type.h:1150
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 generateWithFullUnpromotions(MoveVector &) const
打歩詰め絡み以外では有利にはならない手も含め, 全ての合法手を生成す る(Move::ignoredUnpromoteも生成する).
Player turn() const
Definition: simpleState.h:220
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
int max(Player p, int v1, int v2)
Definition: evalTraits.h:84
int min(Player p, int v1, int v2)
Definition: evalTraits.h:92
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:146
static const CArray< std::string, 10 > suji
筋の文字。駒の文字幅に合わせる必要がある。
Definition: kanjiPrint.h:148