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