00001
00002
00003 #include "osl/checkmate/oracleProverLight.h"
00004 #include "osl/checkmate/immediateCheckmate.h"
00005 #include "osl/checkmate/oracleAdjust.h"
00006 #include "osl/effect_util/effectUtil.h"
00007 #include "osl/container/moveVector.h"
00008 #include "osl/move_generator/escape_.h"
00009 #include "osl/move_action/store.h"
00010 #include "osl/apply_move/applyMove.h"
00011
00012 namespace osl
00013 {
00014 namespace checkmate
00015 {
00019 template <Player Attacker>
00020 struct OracleProverLightDefense
00021 {
00022 OracleProverLight<Attacker> *prover;
00023 ProofOracleDefense<Attacker> oracle;
00024 ProofDisproof result;
00025 void operator()(Position)
00026 {
00027 result = prover->defense(oracle);
00028 }
00029 };
00030
00034 template <Player Attacker>
00035 struct OracleProverLightAttack
00036 {
00037 OracleProverLight<Attacker> *prover;
00038 ProofOracleAttack<Attacker> oracle;
00039 ProofDisproof result;
00040 void operator()(Position)
00041 {
00042 result = prover->attack(oracle);
00043 }
00044 };
00045
00046 }
00047 }
00048
00049 template <osl::Player Attacker>
00050 bool osl::checkmate::OracleProverLight<Attacker>::
00051 proofWin(state_t& state, ProofOracleAttack<Attacker> oracle, Move& best_move)
00052 {
00053 check_assert(oracle.isValid());
00054 check_assert(state.getTurn() == Attacker);
00055 this->state = &state;
00056 fixed_searcher.setState(state);
00057 if ((! EffectUtil::isKingInCheck(Attacker, state))
00058 && ImmediateCheckmate::hasCheckmateMove<Attacker>(state, best_move)) {
00059 assert(state.isValidMove(best_move));
00060 return true;
00061 }
00062 if (oracle.guide->getBestMove()
00063 && oracle.guide->getBestMove()->flags.isSet(MoveFlags::ImmediateCheckmate))
00064 return fixed_searcher.hasCheckmateMove<Attacker>(2, best_move).isCheckmateSuccess();
00065 const ProofDisproof result = attack(oracle);
00066 if (! result.isCheckmateSuccess())
00067 return false;
00068 best_move = this->best_move;
00069 assert(state.isValidMove(best_move));
00070 return true;
00071 }
00072
00073 template <osl::Player Attacker>
00074 bool osl::checkmate::OracleProverLight<Attacker>::
00075 proofLose(state_t& state, ProofOracleDefense<Attacker> oracle, Move last_move)
00076 {
00077 check_assert(oracle.isValid());
00078 check_assert(state.getTurn() == alt(Attacker));
00079 this->state = &state;
00080 fixed_searcher.setState(state);
00081
00082 const ProofDisproof result = defense(oracle);
00083 if (result.isPawnDropFoul(last_move))
00084 return false;
00085 return result.isCheckmateSuccess();
00086 }
00087
00088 template <osl::Player Attacker>
00089 const osl::checkmate::ProofDisproof
00090 osl::checkmate::OracleProverLight<Attacker>::
00091 attack(ProofOracleAttack<Attacker> oracle)
00092 {
00093 ++node_count;
00094 check_assert(oracle.isValid());
00095 check_assert(state->getTurn() == Attacker);
00096 #if 0
00097 if ((! EffectUtil::isKingInCheck(Attacker, *state))
00098 && ImmediateCheckmate::hasCheckmateMove<Attacker>(*state, best_move))
00099 return ProofDisproof::Checkmate();
00100 if (oracle.guide->getBestMove()
00101 && oracle.guide->getBestMove()->flags.isSet(MoveFlags::ImmediateCheckmate))
00102 return fixed_searcher.hasCheckmateMove<Attacker>(2, best_move);
00103 #endif
00104 if (fixed_searcher.hasCheckmateMove<Attacker>(2, best_move).isCheckmateSuccess()) {
00105 state->isValidMove(best_move);
00106 return ProofDisproof::Checkmate();
00107 }
00108
00109 ProofOracleDefense<Attacker> new_oracle = oracle.expandOracle();
00110 if (! new_oracle.isValid())
00111 return ProofDisproof::Unknown();
00112 check_assert(oracle.oracle().player() == Attacker);
00113 Move check_move = OracleAdjust::attack(*state, oracle.oracle());
00114 if (! check_move.isNormal())
00115 return ProofDisproof::Unknown();
00116
00117 OracleProverLightDefense<Attacker> oracle_prover = {this, new_oracle,
00118 ProofDisproof::Unknown()};
00119 ApplyMove<Attacker>::doUndoMove(*state, check_move, oracle_prover);
00120 if (oracle_prover.result.isPawnDropFoul(check_move))
00121 return ProofDisproof::Unknown();
00122
00123 best_move = check_move;
00124 return oracle_prover.result;
00125 }
00126
00127 template <osl::Player Attacker>
00128 const osl::checkmate::ProofDisproof
00129 osl::checkmate::OracleProverLight<Attacker>::
00130 defense(ProofOracleDefense<Attacker> oracle)
00131 {
00132 ++node_count;
00133 check_assert(oracle.isValid());
00134 const Player Defense = PlayerTraits<Attacker>::opponent;
00135
00136 const bool illegal = EffectUtil::isKingInCheck(Attacker, *state);
00137 if (illegal)
00138 return ProofDisproof::NoCheckmate();
00139 const bool check = EffectUtil::isKingInCheck(Defense, *state);
00140 if (! check)
00141 return ProofDisproof::NoCheckmate();
00142
00143 MoveVector moves;
00144 {
00145 move_action::Store store(moves);
00146 const Piece king_piece=state->getKingPiece<Defense>();
00147 move_generator::Escape<Defense,NumEffectState,move_action::Store>::
00148 generateMoves(*state,king_piece,store);
00149 }
00150 if (moves.empty())
00151 return ProofDisproof::NoEscape();
00152 for (MoveVector::const_iterator p=moves.begin(); p!=moves.end(); ++p)
00153 {
00154 ProofOracleAttack<Attacker> new_oracle = oracle.expandOracle(*p);
00155 if (! new_oracle.isValid()) {
00156 const ProofDisproof pdp = fixed_searcher.hasEscapeMove<Attacker>(*p, 2);
00157 if (pdp.isCheckmateSuccess())
00158 return pdp;
00159 return ProofDisproof::Unknown();
00160 }
00161 OracleProverLightAttack<Attacker> oracle_prover = {this, new_oracle,
00162 ProofDisproof::Unknown()};
00163 ApplyMove<Defense>::doUndoMove(*state, *p, oracle_prover);
00164
00165 if (! oracle_prover.result.isCheckmateSuccess())
00166 return oracle_prover.result;
00167 }
00168 return ProofDisproof::Checkmate();
00169 }
00170 namespace osl
00171 {
00172 namespace checkmate
00173 {
00174 template class OracleProverLight<BLACK>;
00175 template class OracleProverLight<WHITE>;
00176 }
00177 }
00178
00179
00180
00181