oracleProverLight.tcc
Go to the documentation of this file.
00001 /* oracleProverLight.tcc
00002  */
00003 #include "osl/ntesuki/oracleProverLight.h"
00004 #include "osl/ntesuki/ntesukiRecord.h"
00005 #include "osl/ntesuki/ntesukiMoveGenerator.h"
00006 #include "osl/checkmate/fixedDepthSearcher.h"
00007 #include "osl/checkmate/fixedDepthSearcher.tcc"
00008 #include "osl/move_classifier/safeMove.h"
00009 #include "osl/apply_move/applyMoveWithPath.h"
00010 #include "osl/checkmate/immediateCheckmate.h"
00011 #include "osl/effect_util/effectUtil.h"
00012 #ifdef NDEBUG
00013 # include "osl/ntesuki/ntesukiMove.tcc"
00014 # include "osl/ntesuki/ntesukiRecord.tcc"
00015 //# include "osl/move_generator/escape.tcc"
00016 #endif
00017 
00018 using namespace osl;
00019 using namespace osl::ntesuki;
00020 
00021 /* Helper classes
00022  */
00023 template <class Searcher, Player P>
00024 class
00025 OracleProverLight::
00026 AttackHelper
00027 {
00028   Searcher* searcher;
00029   const NtesukiRecord *record_orig;
00030   unsigned int pass_left;
00031 public:
00032   bool result;
00033 
00034   AttackHelper(Searcher* searcher,
00035                const NtesukiRecord* record_orig,
00036                unsigned int pass_left)
00037     : searcher(searcher), record_orig(record_orig), pass_left(pass_left)
00038   {}
00039 
00040   void operator()(Square p)
00041   {
00042     const Player O = PlayerTraits<P>::opponent;
00043     result = (*searcher).template defense<O>(record_orig, pass_left);
00044   }
00045 };
00046       
00047 template <class Searcher, Player P>
00048 class OracleProverLight::
00049 DefenseHelper
00050 {
00051   Searcher* searcher;
00052   const NtesukiRecord *record_orig;
00053   unsigned int pass_left;
00054 
00055 public:
00056   bool result;
00057 
00058   DefenseHelper(Searcher* searcher,
00059                 const NtesukiRecord* record_orig,
00060                 unsigned int pass_left)
00061     : searcher(searcher), record_orig(record_orig), pass_left(pass_left)
00062   {}
00063 
00064   void operator()(Square p)
00065   {
00066     const Player O = PlayerTraits<P>::opponent;
00067     result = (*searcher).template attack<O>(record_orig, pass_left);
00068   }
00069 };
00070 
00071 /* Utility
00072  */
00073 
00074 /* Still cannot see if is safe move */
00075 template <Player P>
00076 static bool
00077 is_safe_move(const osl::ntesuki::OracleProverLight::state_t state,
00078              const osl::Move& m,
00079              int pass_left)
00080 {
00081   if (!m.isValid()) return false;
00082   if (!state.isValidMove(m, false)) return false;
00083   if (m.isDrop()) return true;
00084   return move_classifier::SafeMove<P>::isMember(state, m.ptype(), m.from(), m.to());
00085 }
00086 
00087 /* adjust the captuer ptype of a move */
00088 template <Player P>
00089 static osl::Move
00090 adjustMove(const osl::ntesuki::OracleProverLight::state_t state,
00091            osl::Move candidate)
00092 {
00093   if (! candidate.isDrop())
00094   {
00095     const osl::Piece p = state.pieceOnBoard(candidate.to());
00096     candidate=setCapture(candidate,p);
00097   }
00098   return candidate;
00099 }
00100 
00101 
00102 /* The worker
00103  */
00104 
00105 /* attack */
00106 template <Player P>
00107 bool
00108 OracleProverLight::
00109 attack(const NtesukiRecord* record_orig,
00110        const unsigned int pass_left)
00111 {
00112   const Player attacker = P;
00113   ntesuki_assert(P == state.turn());
00114 
00115   if (!record_orig ||
00116       !record_orig->getValue<attacker>(pass_left)
00117       .isCheckmateSuccess() ||
00118       !record_orig->getBestMove<attacker>(pass_left).isValid())
00119   {
00120     return false;
00121   }
00122 
00123   Move check_move;
00124   FixedDepthSearcher fixed_searcher(state);
00125 
00126   if (!state.inCheck(P) &&
00127       fixed_searcher.hasCheckmateMove<P>(NtesukiRecord::fixed_search_depth,
00128                                          check_move).isCheckmateSuccess())
00129   {
00130     /* Immediate Checkmate */
00131     return true;
00132   }
00133 
00134   /* Simulation 元が immediate checkmate ならこの先は simulate できない */
00135   const NtesukiMove best_move_orig = record_orig->getBestMove<attacker>(pass_left);
00136   if (best_move_orig.isImmediateCheckmate())
00137   {
00138     return false;
00139   }
00140 
00141   /* n が少ないときの結果を参照 */
00142   if ((pass_left > 0) && 
00143       record_orig->getValue<attacker>(pass_left - 1).isCheckmateSuccess())
00144   {
00145     return attack<P>(record_orig, pass_left - 1);
00146   }
00147 
00148   const Move move = adjustMove<P>(state, best_move_orig.move());
00149 
00150   /* invalid move となってしまった */
00151   if (!is_safe_move<P>(state, move, pass_left))
00152   {
00153     return false;
00154   }
00155   const bool move_is_check = (move_classifier::PlayerMoveAdaptor<move_classifier::Check>::
00156 			      isMember(state, move));
00157   /* 即詰探索中は王手のみ読む */
00158   if(0 == pass_left && !move_is_check)
00159   {
00160     return false;
00161   }
00162 
00163   /* 以前は check だったのが今は違ってしまった・その逆 */
00164   if (best_move_orig.isCheck() != move_is_check)
00165   {
00166     return false;
00167   }
00168 
00169   /* 以前の bestMove を実行 */
00170   const NtesukiRecord* record_child_orig = table.findWithMoveConst(record_orig,
00171                                                                    best_move_orig);
00172   if (!record_child_orig)
00173   {
00174     //ntesuki_assert (record_orig->isBySimulation());
00175     return false;
00176   }
00177   //ntesuki_assert(record_child_orig);
00178 
00179   AttackHelper<OracleProverLight, P> helper(this,
00180                                             record_child_orig,
00181                                             pass_left);
00182   TRY_DFPN;
00183   ApplyMoveWithPath<P>::doUndoMove(state, path, move, helper);
00184   CATCH_DFPN;
00185 
00186   return helper.result;
00187 }
00188 
00189 /* defense */
00190 template <Player P>
00191 bool OracleProverLight::
00192 defense(const NtesukiRecord* record_orig,
00193         const unsigned int pass_left)
00194 {
00195   const Player attacker = PlayerTraits<P>::opponent;
00196 
00197   ntesuki_assert(P == state.turn());
00198   if (!record_orig ||
00199       !record_orig->getValue<attacker>(pass_left)
00200       .isCheckmateSuccess())
00201   {
00202     return false;
00203   }
00204 
00205   /* 攻撃側に王手がかかっていないか調べる */
00206   if (state.inCheck(attacker))
00207   {
00208     return false;
00209   }
00210 
00211   /* 現在王手になっているかどうか */
00212   if ((pass_left == 0) &&
00213       !state.inCheck(P))
00214   {
00215     return false;
00216   }
00217 
00218   /* n が少ないときの結果を参照 */
00219   if (pass_left > 0 &&
00220       record_orig->getValue<attacker>(pass_left - 1).isCheckmateSuccess())
00221   {
00222     return defense<P>(record_orig, pass_left - 1);
00223   }
00224 
00225   /* 手の生成 */
00226   NtesukiMoveList moves;
00227   mg->generateSlow(P, state, moves);
00228   if (moves.empty()) return true;
00229 
00230   /* 受ける手の実行 */
00231   for (NtesukiMoveList::iterator move_it = moves.begin();
00232        move_it != moves.end(); move_it++)
00233   {
00234     NtesukiMove& move = *move_it;
00235     if (isscheme != NtesukiRecord::normal_is &&
00236         isscheme != NtesukiRecord::delay_is &&
00237         move.isCheck() && pass_left > 0) continue;
00238 
00239     ntesuki_assert(move.isPass() || move.isNormal());
00240 
00241     const NtesukiRecord *record_child_orig = table.findWithMoveConst(record_orig, move);
00242     if (!record_child_orig ||
00243         !record_child_orig->getValue<attacker>(pass_left).isCheckmateSuccess())
00244     {
00245       return false;
00246     }
00247 
00248     int pass_left_child = pass_left;
00249     if (move.isPass()) --pass_left_child;
00250     DefenseHelper<OracleProverLight, P> helper(this, record_child_orig, pass_left_child);
00251     TRY_DFPN;
00252     ApplyMoveWithPath<P>::doUndoMoveOrPass(state, path, move.move(), helper);
00253     CATCH_DFPN;
00254     if (false == helper.result) return false;
00255   }
00256 
00257   return true;
00258 }
00259 
00260 /* Publice interface
00261  */
00262 template <Player P>
00263 bool
00264 OracleProverLight::
00265 startFromAttack(NtesukiRecord* record,
00266                 const NtesukiRecord* record_orig,
00267                 const unsigned int pass_left)
00268 {
00269   const Player attacker = P;
00270   if (!record || !record_orig) return false;
00271   
00272   if (!record->getPieceStand<attacker>().isSuperiorOrEqualTo
00273       (record_orig->getPDPieces<attacker>(pass_left)))
00274   {
00275     return false;
00276   }
00277 
00278   ntesuki_assert(record_orig->getValue<attacker>(pass_left).isCheckmateSuccess());
00279 
00280   if (attack<P>(record_orig, pass_left))
00281   {
00282 #ifndef NDEBUG
00283     const NtesukiMove m = (record_orig->getBestMove<attacker>(pass_left));
00284     ntesuki_assert(m.isValid());
00285     ntesuki_assert(!m.isImmediateCheckmate());
00286 #endif
00287 
00288     TRY_DFPN;
00289     const PieceStand ps = record->getPieceStand<attacker>();
00290     record->setResult<attacker>(pass_left, ProofDisproof::Checkmate(),
00291                                 record_orig->getBestMove<attacker>(pass_left),
00292                                 true, &ps);
00293     CATCH_DFPN;
00294     return true;
00295   }
00296   return false;
00297 }
00298 
00299 template <Player P>
00300 bool
00301 OracleProverLight::
00302 startFromDefense(NtesukiRecord* record,
00303                  const NtesukiRecord* record_orig,
00304                  const unsigned int pass_left)
00305 {
00306   const Player attacker = PlayerTraits<P>::opponent;
00307   if (!record || !record_orig) return false;
00308 
00309   if (!record->getPieceStand<attacker>().isSuperiorOrEqualTo
00310       (record_orig->getPDPieces<attacker>(pass_left)))
00311   {
00312     return false;
00313   }
00314 
00315   ntesuki_assert(record_orig->getValue<attacker>(pass_left).isCheckmateSuccess());
00316 
00317   if (defense<P>(record_orig, pass_left))
00318   {
00319     TRY_DFPN;
00320     const PieceStand ps = record->getPieceStand<attacker>();
00321     record->setResult<attacker>(pass_left, ProofDisproof::Checkmate(),
00322                                 record_orig->getBestMove<attacker>(pass_left),
00323                                 true, &ps);
00324     CATCH_DFPN;
00325     return true;
00326   }
00327   return false;
00328 }
00329 
00330 // ;;; Local Variables:
00331 // ;;; mode:c++
00332 // ;;; c-basic-offset:2
00333 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines