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