00001 #include "osl/record/kanjiMove.h"
00002 #include "osl/record/kanjiCode.h"
00003 #include "osl/record/kanjiPrint.h"
00004 #include "osl/container/moveVector.h"
00005 #include "osl/move_generator/legalMoves.h"
00006 #include "osl/stl/copy_if.h"
00007 #include <boost/foreach.hpp>
00008 #include <boost/mem_fn.hpp>
00009 #include <boost/lambda/lambda.hpp>
00010 #include <boost/lambda/bind.hpp>
00011 #include <algorithm>
00012 #include <iterator>
00013 #include <iostream>
00014 using namespace boost::lambda;
00015
00016 int moveFromX(const osl::Move& move)
00017 {
00018 const osl::Position& p = move.from();
00019 return p.x();
00020 }
00021
00022 int moveFromY(const osl::Move& move)
00023 {
00024 const osl::Position& p = move.from();
00025 return p.y();
00026 }
00027
00028 struct SortMoveFromX :
00029 public std::binary_function<osl::Move, osl::Move, bool>
00030 {
00031 bool operator()(const osl::Move& a, const osl::Move& b) const
00032 {
00033 const osl::Position& a_p = a.from();
00034 const osl::Position& b_p = b.from();
00035 return a_p.x() < b_p.x();
00036 }
00037 };
00038
00039 struct SortMoveFromXDesc :
00040 public std::binary_function<osl::Move, osl::Move, bool>
00041 {
00042 bool operator()(const osl::Move& a, const osl::Move& b) const
00043 {
00044 const osl::Position& a_p = a.from();
00045 const osl::Position& b_p = b.from();
00046 return a_p.x() > b_p.x();
00047 }
00048 };
00049
00050 struct SortMoveFromY :
00051 public std::binary_function<osl::Move, osl::Move, bool>
00052 {
00053 bool operator()(const osl::Move& a, const osl::Move& b) const
00054 {
00055 const osl::Position& a_p = a.from();
00056 const osl::Position& b_p = b.from();
00057 return a_p.y() < b_p.y();
00058 }
00059 };
00060
00061 struct SortMoveFromYDesc :
00062 public std::binary_function<osl::Move, osl::Move, bool>
00063 {
00064 bool operator()(const osl::Move& a, const osl::Move& b) const
00065 {
00066 const osl::Position& a_p = a.from();
00067 const osl::Position& b_p = b.from();
00068 return a_p.y() > b_p.y();
00069 }
00070 };
00071
00072 struct RemoveMoveFromXOver :
00073 public std::unary_function<osl::Move, bool>
00074 {
00075 const int min_x;
00076 RemoveMoveFromXOver(const int min_x)
00077 : min_x(min_x)
00078 {}
00079
00080 bool operator()(const osl::Move& m) const
00081 {
00082 const osl::Position& p = m.from();
00083 return p.x() > min_x;
00084 }
00085 };
00086
00087 struct RemoveMoveFromXGTE :
00088 public std::unary_function<osl::Move, bool>
00089 {
00090 const int min_x;
00091 RemoveMoveFromXGTE(const int min_x)
00092 : min_x(min_x)
00093 {}
00094
00095 bool operator()(const osl::Move& m) const
00096 {
00097 const osl::Position& p = m.from();
00098 return p.x() >= min_x;
00099 }
00100 };
00101
00102 struct RemoveMoveFromYOver :
00103 public std::unary_function<osl::Move, bool>
00104 {
00105 const int min_y;
00106 RemoveMoveFromYOver(const int min_y)
00107 : min_y(min_y)
00108 {}
00109
00110 bool operator()(const osl::Move& m) const
00111 {
00112 const osl::Position& p = m.from();
00113 return p.y() > min_y;
00114 }
00115 };
00116
00117 struct RemoveMoveFromYGTE :
00118 public std::unary_function<osl::Move, bool>
00119 {
00120 const int min_y;
00121 RemoveMoveFromYGTE(const int min_y)
00122 : min_y(min_y)
00123 {}
00124
00125 bool operator()(const osl::Move& m) const
00126 {
00127 const osl::Position& p = m.from();
00128 return p.y() >= min_y;
00129 }
00130 };
00131
00132 struct RemoveMoveFromXUnder :
00133 public std::unary_function<osl::Move, bool>
00134 {
00135 const int max_x;
00136 RemoveMoveFromXUnder(const int max_x)
00137 : max_x(max_x)
00138 {}
00139
00140 bool operator()(const osl::Move& m) const
00141 {
00142 const osl::Position& p = m.from();
00143 return p.x() < max_x;
00144 }
00145 };
00146
00147 struct RemoveMoveFromXLTE :
00148 public std::unary_function<osl::Move, bool>
00149 {
00150 const int max_x;
00151 RemoveMoveFromXLTE(const int max_x)
00152 : max_x(max_x)
00153 {}
00154
00155 bool operator()(const osl::Move& m) const
00156 {
00157 const osl::Position& p = m.from();
00158 return p.x() <= max_x;
00159 }
00160 };
00161
00162 struct RemoveMoveFromYUnder :
00163 public std::unary_function<osl::Move, bool>
00164 {
00165 const int max_y;
00166 RemoveMoveFromYUnder(const int max_y)
00167 : max_y(max_y)
00168 {}
00169
00170 bool operator()(const osl::Move& m) const
00171 {
00172 const osl::Position& p = m.from();
00173 return p.y() < max_y;
00174 }
00175 };
00176
00177 struct RemoveMoveFromYLTE :
00178 public std::unary_function<osl::Move, bool>
00179 {
00180 const int max_y;
00181 RemoveMoveFromYLTE(const int max_y)
00182 : max_y(max_y)
00183 {}
00184
00185 bool operator()(const osl::Move& m) const
00186 {
00187 const osl::Position& p = m.from();
00188 return p.y() <= max_y;
00189 }
00190 };
00191
00192 struct RemoveMoveFromXEqual :
00193 public std::unary_function<osl::Move, bool>
00194 {
00195 const int x;
00196 RemoveMoveFromXEqual(const int x)
00197 : x(x)
00198 {}
00199
00200 bool operator()(const osl::Move& m) const
00201 {
00202 const osl::Position& p = m.from();
00203 return p.x() == x;
00204 }
00205 };
00206
00207 struct RemoveMoveFromYEqual :
00208 public std::unary_function<osl::Move, bool>
00209 {
00210 const int y;
00211 RemoveMoveFromYEqual(const int y)
00212 : y(y)
00213 {}
00214
00215 bool operator()(const osl::Move& m) const
00216 {
00217 const osl::Position& p = m.from();
00218 return p.y() == y;
00219 }
00220 };
00221
00222 osl::record::
00223 KanjiMove::KanjiMove()
00224 : verbose(false)
00225 {
00226 for (size_t x=1; x<=9; ++x)
00227 {
00228 for (size_t y=1; y<=9; ++y)
00229 {
00230 const std::string str = osl::record::StandardCharacters::suji[x] +
00231 osl::record::StandardCharacters::dan[y];
00232 str2position[str] = osl::Position(x,y);
00233 }
00234 }
00235 str2piece[K_PAWN] = osl::PAWN;
00236 str2piece[K_PPAWN] = osl::PPAWN;
00237 str2piece[K_LANCE] = osl::LANCE;
00238 str2piece[K_PLANCE_D] = osl::PLANCE;
00239 str2piece[K_KNIGHT] = osl::KNIGHT;
00240 str2piece[K_PKNIGHT_D] = osl::PKNIGHT;
00241 str2piece[K_SILVER] = osl::SILVER;
00242 str2piece[K_PSILVER_D] = osl::PSILVER;
00243 str2piece[K_GOLD] = osl::GOLD;
00244 str2piece[K_BISHOP] = osl::BISHOP;
00245 str2piece[K_PBISHOP] = osl::PBISHOP;
00246 str2piece[K_ROOK] = osl::ROOK;
00247 str2piece[K_PROOK] = osl::PROOK;
00248 str2piece[K_PROOK2] = osl::PROOK;
00249 str2piece[K_KING] = osl::KING;
00250 }
00251
00252 osl::record::
00253 KanjiMove::~KanjiMove()
00254 {
00255 }
00256
00257 osl::Position osl::record::
00258 KanjiMove::toPosition(const std::string& s) const
00259 {
00260 str2position_t::const_iterator p=str2position.find(s);
00261 if (p == str2position.end())
00262 return Position();
00263 return p->second;
00264 }
00265
00266 osl::Ptype osl::record::
00267 KanjiMove::toPtype(const std::string& s) const
00268 {
00269 str2piece_t::const_iterator p=str2piece.find(s);
00270 if (p == str2piece.end())
00271 return Ptype();
00272 return p->second;
00273 }
00274
00275 void osl::record::
00276 KanjiMove::selectCandidates(found_moves_t& found,
00277 std::string& str,
00278 const osl::Position& to_pos,
00279 const osl::Player& player) const
00280 {
00281 assert(!str.empty());
00282 assert(found.size() >= 2);
00283
00284 if ( (str.substr(0,2) == K_MIGI && player == osl::BLACK) ||
00285 (str.substr(0,2) == K_HIDARI && player == osl::WHITE) )
00286 {
00287 found.sort( bind(moveFromX, boost::lambda::_1) < bind(moveFromX, boost::lambda::_2) );
00288 const osl::Move min = found.front();
00289 found.remove_if( RemoveMoveFromXOver(min.from().x()) );
00290 }
00291 else if ( (str.substr(0,2) == K_HIDARI && player == osl::BLACK) ||
00292 (str.substr(0,2) == K_MIGI && player == osl::WHITE) )
00293 {
00294 found.sort( bind(moveFromX, boost::lambda::_1) < bind(moveFromX, boost::lambda::_2) );
00295 const osl::Move max = found.back();
00296 found.remove_if( RemoveMoveFromXUnder(max.from().x()) );
00297 }
00298 else if ( (str.substr(0,2) == K_SHITA && player == osl::BLACK) ||
00299 (str.substr(0,2) == K_UE && player == osl::WHITE) )
00300 {
00301 found.sort( bind(moveFromY, boost::lambda::_1) < bind(moveFromY, boost::lambda::_2) );
00302 const osl::Move min = found.front();
00303 found.remove_if( RemoveMoveFromYOver(min.from().y()) );
00304 }
00305 else if ( (str.substr(0,2) == K_UE && player == osl::BLACK) ||
00306 (str.substr(0,2) == K_SHITA && player == osl::WHITE) )
00307 {
00308 found.sort( bind(moveFromY, boost::lambda::_1) > bind(moveFromY, boost::lambda::_2) );
00309 const osl::Move max = found.front();
00310 found.remove_if( RemoveMoveFromYUnder(max.from().y()) );
00311 }
00312 else if (str.substr(0,2) == K_YORU)
00313 {
00314 found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y())) );
00315 }
00316 else if (str.substr(0,2) == K_SUGU && player == osl::WHITE)
00317 {
00318 found.remove_if( std::not1(RemoveMoveFromXEqual(to_pos.x())) );
00319 found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()-1)) );
00320 }
00321 else if (str.substr(0,2) == K_SUGU && player == osl::BLACK)
00322
00323 {
00324 found.remove_if( std::not1(RemoveMoveFromXEqual(to_pos.x())) );
00325 found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()+1)) );
00326 }
00327 else if (str.substr(0,2) == K_HIKU && player == osl::BLACK)
00328 {
00329 found.remove_if( RemoveMoveFromYGTE(to_pos.y()) );
00330 }
00331 else if (str.substr(0,2) == K_HIKU && player == osl::WHITE)
00332 {
00333 found.remove_if( RemoveMoveFromYLTE(to_pos.y()) );
00334 }
00335 else if (str.substr(0,2) == K_YUKU && player == osl::BLACK)
00336 {
00337 found.remove_if( RemoveMoveFromYLTE(to_pos.y()) );
00338 }
00339 else if (str.substr(0,2) == K_YUKU && player == osl::WHITE)
00340 {
00341 found.remove_if( RemoveMoveFromYGTE(to_pos.y()) );
00342 }
00343
00344 str.erase(0,2);
00345 assert(!found.empty());
00346
00347 if (found.size() > 1)
00348 {
00349 assert(!str.empty());
00350 selectCandidates(found, str, to_pos, player);
00351 }
00352
00353 assert(found.size() == 1);
00354 if (!str.empty())
00355 std::cerr << "WARNING: A single candidate is selected, but the input string still has some characters: " << str << std::endl;
00356 }
00357
00358 const osl::Move osl::record::
00359 KanjiMove::strToMove(const std::string& orig,
00360 const osl::NumEffectState& state,
00361 const osl::Move& last_move) const
00362 {
00363 std::string str(orig);
00364 assert(orig.size() >= 4*2 || (str.substr(2,2) == K_ONAZI && orig.size() >= 3*2));
00365 const osl::Player player = str.substr(0,2) == K_BLACK_SIGN ? osl::BLACK : osl::WHITE;
00366 assert(player == state.getTurn());
00367 str.erase(0,2);
00368
00369 Position to_pos;
00370 if (str.substr(0,2) == K_ONAZI)
00371 {
00372 to_pos = last_move.to();
00373 str.erase(0,2);
00374 if (str.substr(0,2) == K_SPACE)
00375 str.erase(0,2);
00376 }
00377 else
00378 {
00379 to_pos = toPosition(str.substr(0,4));
00380 str.erase(0,4);
00381 }
00382
00383 Ptype ptype;
00384 if (str.substr(0,2) == K_NARU)
00385 {
00386 ptype = toPtype(str.substr(0,4));
00387 str.erase(0,4);
00388 }
00389 else
00390 {
00391 ptype = toPtype(str.substr(0,2));
00392 str.erase(0,2);
00393 }
00394
00395
00396 bool is_promote = false;
00397 if (str.size() >= 4 && str.substr(0,4) == K_FUNARI)
00398 str.erase(0,4);
00399 else if (str.size() >= 4 && str.substr(str.size()-4,4) == K_FUNARI)
00400 str.erase(str.size()-4,4);
00401 else if (str.size() >= 2 && str.substr(0,2) == K_NARU)
00402 {
00403 is_promote = true;
00404 str.erase(0,2);
00405 }
00406 else if (str.size() >= 2 && str.substr(str.size()-2,2) == K_NARU)
00407 {
00408 is_promote = true;
00409 str.erase(str.size()-2,2);
00410 }
00411
00412 MoveVector moves;
00413 LegalMoves::generateWithFullUnpromotions(state, moves);
00414 found_moves_t found;
00415 BOOST_FOREACH(Move move, moves)
00416 {
00417 if (move.oldPtype() == ptype &&
00418 move.to() == to_pos &&
00419 move.isPromote() == is_promote)
00420 {
00421 found.push_back(move);
00422 }
00423 }
00424 if (verbose)
00425 {
00426 std::cerr << "\n" << orig << "\n" << state;
00427 std::cerr << "remain: " << str << " (" << str.size() << " bytes)\n";
00428 std::cerr << "promote: " << is_promote << "\n";
00429 std::cerr << "ptype: " << "\n";
00430 std::cerr << "to_position: " << to_pos << "\n";
00431 std::cerr << "candidates: " << found.size() << std::endl;
00432 }
00433 if (found.empty()) {
00434
00435 return Move::INVALID();
00436 }
00437 assert(!found.empty());
00438
00439
00440 if (found.size() == 1)
00441 return found.front();
00442
00443
00444 assert(found.size() >= 2);
00445
00446
00447 if (str.substr(0,2) == K_UTSU)
00448 {
00449 found_moves_t::iterator it =
00450 std::find_if(found.begin(), found.end(),
00451 bind(boost::mem_fn(&Move::isDrop), boost::lambda::_1)
00452 );
00453 str.erase(0,2);
00454 assert(str.empty());
00455 assert(it != found.end());
00456 return *it;
00457 }
00458 else
00459 {
00460 found.remove_if(
00461 bind(boost::mem_fn(&Move::isDrop), boost::lambda::_1)
00462 );
00463 if (found.size() == 1)
00464 return found.front();
00465 }
00466
00467
00468 assert(found.size() >= 2);
00469 assert(!str.empty());
00470 selectCandidates(found, str, to_pos, player);
00471 assert(found.size() == 1);
00472 return found.front();
00473 }
00474
00475
00476
00477
00478