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 int moveFromX(const osl::Move& move)
00017 {
00018   const osl::Square& p = move.from();
00019   return p.x();
00020 }
00021 
00022 int moveFromY(const osl::Move& move)
00023 {
00024   const osl::Square& 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::Square& a_p = a.from();
00034     const osl::Square& 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::Square& a_p = a.from();
00045     const osl::Square& 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::Square& a_p = a.from();
00056     const osl::Square& 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::Square& a_p = a.from();
00067     const osl::Square& 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::Square& 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::Square& 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::Square& 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::Square& 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::Square& 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::Square& 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::Square& 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::Square& 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::Square& 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::Square& 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::Square(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::Square osl::record::
00258 KanjiMove::toSquare(const std::string& s) const
00259 {
00260   str2position_t::const_iterator p=str2position.find(s);
00261   if (p == str2position.end())
00262     return Square();
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::Square& 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()) ); // list really removes
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()) ); // list really removes
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()) ); // list really removes
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()) ); // list really removes
00311   }
00312   else if (str.substr(0,2) == K_YORU)
00313   {
00314     found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y())) ); // list really removes
00315   }
00316   else if (str.substr(0,2) == K_SUGU && player == osl::WHITE)
00317   {
00318     found.remove_if( std::not1(RemoveMoveFromXEqual(to_pos.x())) ); // or
00319     found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()-1)) ); // list really removes
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())) ); // or
00325     found.remove_if( std::not1(RemoveMoveFromYEqual(to_pos.y()+1)) ); // list really removes
00326   }
00327   else if (str.substr(0,2) == K_HIKU && player == osl::BLACK)
00328   {
00329     found.remove_if( RemoveMoveFromYGTE(to_pos.y()) ); // list really removes
00330   }
00331   else if (str.substr(0,2) == K_HIKU && player == osl::WHITE)
00332   {
00333     found.remove_if( RemoveMoveFromYLTE(to_pos.y()) ); // list really removes
00334   }   
00335   else if (str.substr(0,2) == K_YUKU && player == osl::BLACK)
00336   {
00337     found.remove_if( RemoveMoveFromYLTE(to_pos.y()) ); // list really removes
00338   }
00339   else if (str.substr(0,2) == K_YUKU && player == osl::WHITE)
00340   {
00341     found.remove_if( RemoveMoveFromYGTE(to_pos.y()) ); // list really removes
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.turn());
00367   str.erase(0,2);
00368 
00369   Square 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 = toSquare(str.substr(0,4));
00380     str.erase(0,4);
00381   }
00382 
00383   Ptype ptype;
00384   if (str.substr(0,2) == K_NARU) // PLANCE, PKIGHT, PSILVER
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   // promote or not
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.isPromotion() == is_promote)
00420     {
00422       if (std::find(found.begin(), found.end(), move) == found.end())
00423         found.push_back(move);
00424     }
00425   }
00426   if (verbose)
00427   {
00428     std::cerr << "\n" << orig << "\n" << state;
00429     std::cerr << "remain: " << str  << " (" << str.size() << " bytes)\n";
00430     std::cerr << "promote: " << is_promote << "\n";
00431     std::cerr << "ptype: " << ptype << "\n";
00432     std::cerr << "to_position: " << to_pos << "\n";
00433     std::cerr << "candidates: " << found.size() << std::endl;
00434     if (found.size() >=2) {
00435       BOOST_FOREACH(const Move move, found) {
00436         std::cerr << "            " << move << std::endl;
00437       }
00438     }
00439   }
00440   if (found.empty()) {
00441     // there is no leagal move
00442     return Move::INVALID();
00443   }
00444   assert(!found.empty());
00445 
00446   // Single candidate
00447   if (found.size() == 1)
00448     return found.front();
00449 
00450   // Multiple candidates
00451   assert(found.size() >= 2);
00452 
00453   // drop
00454   if (str.substr(0,2) == K_UTSU)
00455   {
00456     found_moves_t::iterator it = 
00457       std::find_if(found.begin(), found.end(),
00458         bind(boost::mem_fn(&Move::isDrop), boost::lambda::_1)
00459       );
00460     str.erase(0,2);
00461     assert(str.empty());
00462     assert(it != found.end());
00463     return *it;
00464   }
00465   else
00466   {
00467     found.remove_if(
00468       bind(boost::mem_fn(&Move::isDrop), boost::lambda::_1)
00469     ); // list really removes
00470     if (found.size() == 1)
00471       return found.front();
00472   }
00473 
00474   // Multiple candidates
00475   assert(found.size() >= 2);
00476   assert(!str.empty());
00477   selectCandidates(found, str, to_pos, player);
00478   assert(found.size() == 1);
00479   return found.front();
00480 }
00481 
00482 // ;;; Local Variables:
00483 // ;;; mode:c++
00484 // ;;; c-basic-offset:2
00485 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines