ntesukiMoveGenerator.cc
Go to the documentation of this file.
00001 /* ntesukiMoveGenerator.cc
00002  */
00003 #include "osl/ntesuki/ntesukiMoveGenerator.h"
00004 #include "osl/ntesuki/ntesukiRecord.h"
00005 #include "osl/state/numEffectState.h"
00006 #include "osl/effect_util/neighboring8Effect.h"
00007 #include "osl/effect_util/neighboring25Direct.h"
00008 #include "osl/move_generator/escape_.h"
00009 #include "osl/move_generator/addEffect_.h"
00010 #include "osl/move_classifier/canAttackInNMoves.h"
00011 #include "osl/move_classifier/moveAdaptor.h"
00012 #include "osl/move_classifier/safeMove.h"
00013 #include "osl/move_generator/allMoves.h"
00014 #include "osl/move_action/store.h"
00015 #include "osl/move_action/safeFilter.h"
00016 #include "osl/effect_util/effectUtil.h"
00017 #include <iostream>
00018 #ifdef NDEBUG
00019 # include "osl/move_generator/escape_.tcc"
00020 # include "osl/move_generator/capture_.tcc"
00021 #endif
00022 
00023 #include "osl/move_action/store.h"
00024 
00025 namespace osl
00026 {
00027   namespace ntesuki
00028   {
00029   }
00030 }
00031 
00032 /*
00033  * n 手すき探索で用いる move generator.
00034  */
00035 
00036 namespace osl
00037 {
00038   namespace ntesuki
00039   {
00040     /* ----------------------------------------------------------------------
00041      * Utility
00042      * ----------------------------------------------------------------------
00043      */
00044     inline
00045     bool
00046     hasEffectByBigPieces (const NumEffectState& state,
00047                           const Player player,
00048                           const Square pos)
00049     {
00050 #if OSL_WORDSIZE == 64
00051       const PieceMask bigPieceMask (container::PieceMaskBase(
00052                                       PieceMask::numToMask (PtypeTraits<ROOK>::indexMin)
00053                                       | PieceMask::numToMask (PtypeTraits<ROOK>::indexMin + 1)
00054                                       | PieceMask::numToMask (PtypeTraits<BISHOP>::indexMin)
00055                                       | PieceMask::numToMask (PtypeTraits<BISHOP>::indexMin + 1)));
00056       
00057       const PieceMask pieceMask = (state.piecesOnBoard (player)
00058                                    & state.effectAt (pos)
00059                                    & bigPieceMask);
00060       return pieceMask.any();
00061 #elif OSL_WORDSIZE == 32
00062       // TODO: 多分このコードで64bit 環境と共通にできると思うんだけど
00063       // 締切まではそのままに
00064       PieceMask bigPieceMask;
00065       bigPieceMask.set(PtypeTraits<ROOK>::indexMin);
00066       bigPieceMask.set(PtypeTraits<ROOK>::indexMin + 1);
00067       bigPieceMask.set(PtypeTraits<BISHOP>::indexMin);
00068       bigPieceMask.set(PtypeTraits<BISHOP>::indexMin + 1);
00069       const PieceMask pieceMask = (state.piecesOnBoard (player)
00070                                    & state.effectAt (pos)
00071                                    & bigPieceMask);
00072       return pieceMask.any();
00073 #endif
00074     }
00075 
00076     template <Player P>
00077     struct CaptureHelper
00078     {
00079       CaptureHelper(const NumEffectState& state,
00080                     move_action::Store& action)
00081         : state(state), action(action)
00082       {
00083       }
00084 
00085       void operator()(Piece p)
00086       {
00087         move_generator::GenerateCapture::generate(P,state, p.square(), action);
00088       }
00089     private:
00090       const NumEffectState& state;
00091       move_action::Store& action;
00092     };
00093 
00094     template <Player P, Ptype T>
00095     static
00096     void
00097     capture(const NumEffectState& state, move_action::Store action)
00098     {
00099       CaptureHelper<P> captureHelper(state, action);
00100       state.forEachOnBoard<PlayerTraits<P>::opponent, T, CaptureHelper<P> >(captureHelper);
00101     }
00102 
00103 
00104     /* NtesukiMoveGenerator
00105      */
00106     NtesukiMoveGenerator::NtesukiMoveGenerator(bool verbose)
00107       :verbose(verbose) {}
00108     NtesukiMoveGenerator::~NtesukiMoveGenerator() {}
00109 
00110     template <osl::Player T>
00111     static void
00112     generate_all_moves(const NumEffectState& state,
00113                        MoveVector& moves)
00114     {
00115       if (state.inCheck(T))
00116       {
00117         // 王手がかかっている時は防ぐ手のみを生成
00118         GenerateEscapeKing::generate(state, moves);
00119       }
00120       else
00121       {
00122         MoveVector all_moves;
00123         // そうでなければ全ての手を生成
00124         GenerateAllMoves::generate(T, state, all_moves);
00125         // この指手は,玉の素抜きがあったり,打歩詰の可能性があるので
00126         // 確認が必要
00127         using namespace osl::move_classifier;
00128         for (unsigned int i=0; i<all_moves.size(); ++i)
00129         {
00130           const Move m = all_moves[i];
00131           if (m.isDrop()
00132               || PlayerMoveAdaptor<SafeMove>::isMember(state, m))
00133           {
00134             moves.push_back(m);
00135           }
00136         }
00137       }
00138 
00139     }
00140     template <Player T>
00141     void NtesukiMoveGenerator::
00142     generateWithRzone(const NumEffectState& state,
00143                       NtesukiRecord *record,
00144                       int pass_left,
00145                       NtesukiMoveList& moves)
00146     {
00147       /* 攻め方の手番で, rzone を使っての手生成. */
00148       ntesuki_assert(record->turn() == T);
00149       const Player O = PlayerTraits<T>::opponent;
00150 
00151       const Square targetKing
00152         = state.kingSquare<O>();
00153       if (state.inCheck(T))
00154       {
00155         /* 自玉に王手がかかっている場合は,全合法手を生成 */
00156         MoveVector move_candidates;
00157         GenerateEscapeKing::generate(state, move_candidates);
00158         moves = NtesukiMoveList(state, move_candidates);
00159 
00160         setOrder<T>(state, moves);
00161       }
00162       else if (pass_left == 0)
00163       {
00164         /* 詰み探索の場合には,王手のみ生成 */
00165         MoveVector move_candidates;
00166         {
00167           move_action::Store store(move_candidates);
00168           move_action::SafeFilter<T, move_action::Store>
00169             store_safe(state, store);
00170           move_generator::AddEffect<T, true>::generate(state,
00171                                                        targetKing,
00172                                                        store_safe);
00173         }
00174         moves = NtesukiMoveList(state, move_candidates);
00175 
00176         for (NtesukiMoveList::iterator move_it = moves.begin();
00177              move_it != moves.end(); move_it++)
00178         {
00179           /* 大駒のただ捨ては遅らせる */
00180           const Move m = move_it->getMove();
00181           const Square to = m.to();
00182           const Piece atTo = state.pieceOnBoard(to);
00183           if (m.isDrop() &&
00184               isMajor(m.ptype()) &&
00185               state.countEffect2(O, to) == 1)
00186           {
00187             move_it->setOrder(1);
00188           }
00189           else
00190           {
00191             move_it->setOrder(0);
00192           }
00193         }
00194 
00195         moves.push_front(NtesukiMove(Move::PASS(T)));
00196         moves.front().setOrder(0);
00197       }
00198       else if (!record->rzone_move_generation)
00199       {
00200         return generate<T>(state, moves);
00201       }
00202       else
00203       {
00204         int rzone_order = pass_left - 1;
00205         Rzone rzone_cur = record->rzone<T>()[rzone_order];
00206         ntesuki_assert(rzone_cur.any());
00207         
00208         /* 取る手を生成 */
00209         MoveVector captures;
00210         {
00211           move_action::Store store(captures);
00212         
00213           capture<T, ROOK>(state, store);
00214           capture<T, BISHOP>(state, store);
00215           capture<T, GOLD>(state, store);
00216           capture<T, SILVER>(state, store);
00217           capture<T, KNIGHT>(state, store);
00218           capture<T, LANCE>(state, store);
00219         }
00220         for (size_t i = 0; i < captures.size(); ++i)
00221         {
00222           const Move m = captures[i];
00223           if (move_classifier::SafeMove<T>::isMember(state,
00224                                                      m.ptype(),
00225                                                      m.from(),
00226                                                      m.to()))
00227           {
00228             moves.add(m);
00229           }
00230         }
00231         
00232         /* 玉が逃げそうな位置に利きをつける手を生成 */
00233         for (int x = 1; x <=9; ++x)
00234         {
00235           for (int y = 1; y <=9; ++y)
00236           {
00237             bool close_to_target = false;
00238             const Square pos(x,y);
00239             if (NtesukiRecord::use_9rzone == true)
00240             {
00241               for (int dx = -1; dx <=1; dx++)
00242               {
00243                 for (int dy = -1; dy <=1; dy++)
00244                 {
00245                   int xx = x + dx;
00246                   int yy = y + dy;
00247                   if (xx > 0 && xx < 10 && yy > 0 && yy < 10)
00248                   {
00249                     ntesuki_assert(xx >= 1 && xx <= 9);
00250                     ntesuki_assert(yy >= 1 && yy <= 9);
00251                     const Square pos2(xx,yy);
00252                     close_to_target |= rzone_cur.test(pos2);
00253                   }
00254                 }
00255               }
00256             }
00257             else
00258             {
00259               close_to_target = rzone_cur.test(pos);
00260             }
00261             if (close_to_target)
00262             {
00263               MoveVector king_blocks;
00264               {
00265                 move_action::Store store2(king_blocks);
00266                 move_action::SafeFilter<T, move_action::Store>
00267                   store_safe(state, store2);
00268                 move_generator::AddEffect<T, false>::generate(state, pos, store_safe);
00269               }
00270               for (size_t i = 0; i < king_blocks.size(); ++i)
00271               {
00272                 const Move m = king_blocks[i];
00273                 moves.add(m);
00274               }
00275             }
00276           }
00277         }
00278 
00279         setOrder<T>(state, moves);
00280         moves.push_front(NtesukiMove(Move::PASS(T)));
00281         moves.front().setOrder(0);
00282       }
00283     }
00284 
00285 
00286     template <Player T>
00287     void NtesukiMoveGenerator::
00288     generate(const NumEffectState& state,
00289              NtesukiMoveList& moves)
00290     {
00291       MoveVector all_moves;
00292       generate_all_moves<T>(state, all_moves);
00293       moves = NtesukiMoveList(state, all_moves);
00294 
00295       setOrder<T>(state, moves);
00296 
00297       if (!state.inCheck(T))
00298       {
00299         moves.push_front(NtesukiMove(Move::PASS(T)));
00300         moves.front().setOrder(0);
00301       }
00302     }//generate
00303 
00304     template <Player T>
00305     void NtesukiMoveGenerator::
00306     setOrder(const NumEffectState& state,
00307              NtesukiMoveList& moves)
00308     {
00309       const Square opKingSquare =
00310         state.kingSquare (alt(state.turn ()));
00311 
00312       for (NtesukiMoveList::iterator move_it = moves.begin();
00313            move_it != moves.end(); move_it++)
00314       {
00315         if (!opKingSquare.isOnBoard())
00316         {
00317           move_it->setOrder(3);
00318           continue;
00319         }
00320         const Move m = move_it->getMove();
00321         const Square from = m.from();
00322         const Square to = m.to();
00323         const Piece atTo = state.pieceOnBoard (to);
00324 
00325         /* order == 0 : 王手 */
00326         if (move_it->isCheck())
00327         {
00328           move_it->setOrder(0);
00329         }
00330         /* order == 1 : 王の近傍への利き, 大駒の道, 小駒以外を取る */
00331         else if (Neighboring8Effect::hasEffect(state, m.ptypeO(), to,
00332                                                opKingSquare))
00333         {
00334           move_it->setOrder(1);
00335         }
00336         else if (hasEffectByBigPieces (state, state.turn (), from))
00337         {
00338           move_it->setOrder(1);
00339         }
00340         else if ((atTo.isPiece()) &&
00341                  (atTo.owner() == alt (state.turn ()))&&
00342                  (atTo.ptype() != PAWN))
00343         {
00344           move_it->setOrder(1);
00345         }
00346         /* order == 2 : 王の25近傍,小駒を取る */
00347         else if (Neighboring25Direct::hasEffect(state, m.ptypeO(), to,
00348                                                 opKingSquare))
00349         {
00350           move_it->setOrder(2);
00351         }
00352         else if ((atTo.isPiece()) &&
00353                  (atTo.owner() == alt (state.turn ())))
00354         {
00355           move_it->setOrder(2);
00356         }
00357         /* order > 2 : それ以外の手 */
00358         else
00359         {
00360           move_it->setOrder(3);
00361         }
00362       }
00363     }
00364 
00365     template void NtesukiMoveGenerator::generate<BLACK>(const NumEffectState& state,
00366                                                         NtesukiMoveList& moves);
00367     template void NtesukiMoveGenerator::generate<WHITE>(const NumEffectState& state,
00368                                                         NtesukiMoveList& moves);
00369 
00370     template void NtesukiMoveGenerator::generateWithRzone<BLACK>(const NumEffectState& state,
00371                                                                  NtesukiRecord* record,
00372                                                                  int pass_left,
00373                                                                  NtesukiMoveList& moves);
00374     template void NtesukiMoveGenerator::generateWithRzone<WHITE>(const NumEffectState& state,
00375                                                                  NtesukiRecord* record,
00376                                                                  int pass_left,
00377                                                                  NtesukiMoveList& moves);
00378 
00379   }//ntesuki
00380 }//osl
00381 
00382 
00383 // ;;; Local Variables:
00384 // ;;; mode:c++
00385 // ;;; c-basic-offset:2
00386 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines