00001
00002
00003 #ifndef OSL_CHECKMATE_FIXED_DEPTH_SERCHER2_TCC
00004 #define OSL_CHECKMATE_FIXED_DEPTH_SERCHER2_TCC
00005 #include "osl/checkmate/fixedDepthSearcher2.h"
00006 #include "osl/checkmate/immediateCheckmate.h"
00007 #include "osl/checkmate/proofPieces.h"
00008 #include "osl/checkmate/proofNumberTable.h"
00009 #include "osl/state/numEffectState.h"
00010 #include "osl/container/moveVector.h"
00011 #include "osl/move_action/store.h"
00012 #include "osl/move_action/count.h"
00013 #include "osl/move_generator/addEffectWithEffect.h"
00014 #include "osl/move_generator/addEffectWithEffect.tcc"
00015 #include "osl/move_generator/escape_.h"
00016 #include "osl/move_classifier/check_.h"
00017 #include "osl/effect_util/effectUtil.h"
00018 #include "osl/apply_move/applyMove.h"
00019 #include "osl/neighboring8.h"
00020 #include "osl/stat/ratio.h"
00021 #include <boost/foreach.hpp>
00022
00023 template <osl::Player P, bool SetPieces, bool HasGuide>
00024 const osl::checkmate::ProofDisproof
00025 osl::checkmate::FixedDepthSearcher2::
00026 attackMayUnsafe(int depth, Move& best_move, PieceStand& proof_pieces)
00027 {
00028 NumEffectState* state= &states[depth];
00029 assert(state->getTurn() == P);
00030 const Position target_king
00031 = state->template getKingPosition<PlayerTraits<P>::opponent>();
00032 if (state->hasEffectBy<P>(target_king))
00033 return ProofDisproof::NoEscape();
00034 return attack<P,SetPieces,HasGuide>(depth, best_move, proof_pieces);
00035 }
00036
00037 template <osl::Player P, bool SetPieces, bool HasGuide>
00038 const osl::checkmate::ProofDisproof
00039 osl::checkmate::FixedDepthSearcher2::
00040 attack(int depth, Move& best_move, PieceStand& proof_pieces)
00041 {
00042 NumEffectState* state= &states[depth];
00043 assert(state->getTurn() == P);
00044 assert ((! HasGuide)
00045 || (state->isAlmostValidMove(best_move)
00046 && move_classifier::
00047 Check<P>::isMember(*state, best_move.ptype(), best_move.from(),
00048 best_move.to())));
00049 addCount();
00050 const Position target_king
00051 = state->template getKingPosition<PlayerTraits<P>::opponent>();
00052 assert(! state->hasEffectBy<P>(target_king));
00053 const King8Info info(state->Iking8Info(alt(P)));
00054 if ((! state->inCheck())
00055 && ImmediateCheckmate::hasCheckmateMove<P>(*state, info, target_king,
00056 best_move))
00057 {
00058 if (SetPieces)
00059 {
00060 proof_pieces = PieceStand();
00061 if (best_move.isDrop())
00062 proof_pieces.add(best_move.ptype());
00063 }
00064 return ProofDisproof::Checkmate();
00065 }
00066 if (depth <= 0)
00067 {
00068 return Proof_Number_Table.attackEstimation(*state, P, info, target_king);
00069 }
00070
00071 ProofDisproof pdp;
00072 int minProof = ProofDisproof::PROOF_MAX;
00073 int sumDisproof=0;
00074 if (HasGuide)
00075 {
00076 copyState(&states[depth-1],&states[depth]);
00077 ApplyMoveOfTurn::doMove(states[depth-1],best_move);
00078 pdp=defense<P,SetPieces>(best_move,depth-1,proof_pieces);
00079 if (pdp.isCheckmateSuccess())
00080 {
00081 if (SetPieces)
00082 proof_pieces = ProofPieces::attack(proof_pieces, best_move, PieceStand(P,*state));
00083 return ProofDisproof::Checkmate();
00084 }
00085 minProof = pdp.proof();
00086 sumDisproof += pdp.disproof();
00087 }
00088
00089 const Position targetKing
00090 = state->template getKingPosition<PlayerTraits<P>::opponent>();
00091 MoveVector moves;
00092 bool has_pawn_checkmate=false;
00093 move_generator::GenerateAddEffectWithEffect::generate<true>
00094 (P,*state,targetKing,moves,has_pawn_checkmate);
00095
00096 if (moves.size()==0){
00097 if(has_pawn_checkmate)
00098 return ProofDisproof::PawnCheckmate();
00099 else
00100 return ProofDisproof::NoCheckmate();
00101 }
00102 if(has_pawn_checkmate)
00103 minProof=std::min(minProof,(int)ProofDisproof::PAWN_CHECK_MATE_PROOF);
00104 BOOST_FOREACH(Move move, moves) {
00105 if (HasGuide && move == best_move)
00106 continue;
00107 copyState(&states[depth-1],&states[depth]);
00108 ApplyMoveOfTurn::doMove(states[depth-1],move);
00109 pdp=defense<P,SetPieces>(move,depth-1,proof_pieces);
00110 int proof=pdp.proof();
00111 if (proof<minProof){
00112 if (proof==0){
00113 best_move=move;
00114 if (SetPieces)
00115 {
00116 proof_pieces = ProofPieces::attack(proof_pieces, best_move, PieceStand(P,*state));
00117 }
00118 return ProofDisproof::Checkmate();
00119 }
00120 minProof=proof;
00121 }
00122 sumDisproof+=pdp.disproof();
00123 }
00124
00125 return ProofDisproof(minProof,sumDisproof);
00126 }
00127
00128 template <osl::Player P, bool SetPieces>
00129 inline
00130 const osl::checkmate::ProofDisproof
00131 osl::checkmate::FixedDepthSearcher2::
00132 defenseEstimation(int depth,Move last_move, PieceStand& proof_pieces,
00133 Piece attacker_piece, Position target_position) const
00134 {
00135 const NumEffectState* state= &states[depth];
00136 assert(state->getTurn() == alt(P));
00137 const Player Opponent = PlayerTraits<P>::opponent;
00138 int count=King8Info(state->Iking8Info(Opponent)).libertyCount();
00139
00140 if (attacker_piece.isEmpty())
00141 {
00142 if (count>0){
00143 return ProofDisproof(count,1);
00144 }
00145 return ProofDisproof::NoEscape();
00146 }
00147 const Position attack_from=attacker_piece.position();
00148 count += state->countEffect(alt(P), attack_from);
00149 if (Neighboring8::isNeighboring8(attack_from, target_position))
00150 --count;
00151 const EffectContent effect
00152 = Ptype_Table.getEffect(attacker_piece.ptypeO(),
00153 attack_from, target_position);
00154 if (! effect.hasUnblockableEffect())
00155 {
00156
00157
00158 ++count;
00159 }
00160
00161 if (count==0){
00162 if (last_move.isValid() && last_move.isDrop() && last_move.ptype()==PAWN)
00163 return ProofDisproof::PawnCheckmate();
00164 if (SetPieces)
00165 {
00166 proof_pieces = ProofPieces::leaf(*state, P, PieceStand(P,*state));
00167 }
00168 return ProofDisproof::NoEscape();
00169 }
00170 return ProofDisproof(count, 1);
00171 }
00172
00173 template <osl::Player Defense>
00174 void osl::checkmate::FixedDepthSearcher2::
00175 generateBlockingWhenLiberty0(int depth,Piece defense_king, Position attack_from,
00176 MoveVector& moves) const
00177 {
00178 const NumEffectState* state= &states[depth];
00179 assert(state->getKingPiece(Defense) == defense_king);
00180 using namespace move_generator;
00181 using namespace move_action;
00182 MoveVector all_moves;
00183 {
00184 Store store(all_moves);
00185 Escape<Store>::
00186 generateBlockingKing<Defense,false>(*state, defense_king, attack_from,store);
00187 }
00188 BOOST_FOREACH(Move move, all_moves)
00189 {
00190 if (move.isDrop())
00191 {
00192 if (! state->hasEffectBy<Defense>(move.to()))
00193 continue;
00194 }
00195 else
00196 {
00197
00198 if (! Neighboring8::isNeighboring8(move.from(), defense_king.position()))
00199 {
00200 if (! state->hasMultipleEffectBy(Defense, move.to()))
00201 continue;
00202 }
00203 }
00204 moves.push_back(move);
00205 }
00206 }
00207
00208 template <osl::Player Defense> inline
00209 int osl::checkmate::FixedDepthSearcher2::
00210 blockEstimation(Position , Position ) const
00211 {
00212
00213 return 1;
00214 }
00215
00216 template <osl::Player P, bool SetPieces>
00217 const osl::checkmate::ProofDisproof
00218 osl::checkmate::FixedDepthSearcher2::
00219 defense(Move last_move, int depth, PieceStand& proof_pieces)
00220 {
00221 NumEffectState* state= &states[depth];
00222 assert(state->getTurn() == alt(P));
00223 addCount();
00224 const Player Defense = PlayerTraits<P>::opponent;
00225 const Position attackerKing
00226 = state->template getKingPosition<P>();
00230 if (attackerKing.isOnBoard() && state->hasEffectBy<Defense>(attackerKing))
00231 return ProofDisproof::NoCheckmate();
00232 const Piece target_king
00233 = state->template getKingPiece<Defense>();
00234 const Position target_position = target_king.position();
00235 assert(state->hasEffectBy<P>(target_position));
00236 Piece attacker_piece;
00237 state->template findCheckPiece<Defense>(attacker_piece);
00238 if (depth <= 0)
00239 {
00240 return defenseEstimation<P, SetPieces>
00241 (depth,last_move, proof_pieces, attacker_piece, target_position);
00242 }
00243
00244 assert(depth > 0);
00245 MoveVector moves;
00246 bool blockable_check = false;
00247 int nonblock_moves;
00248 {
00249 using namespace move_generator;
00250 using namespace move_action;
00251 if (attacker_piece.isEmpty()) {
00252 {
00253 move_action::Store store(moves);
00254 Escape<Store>::template
00255 generateEscape<Defense,KING>(*state,target_king,store);
00256 }
00257 nonblock_moves = moves.size();
00258 }
00259 else {
00260 const Position attack_from=attacker_piece.position();
00261 {
00262 move_action::Store store(moves);
00263 Escape<Store>::
00264 generateCaptureKing<Defense>(*state, target_king, attack_from,store);
00265 }
00266 const int num_captures = moves.size();
00267 {
00268 move_action::Store store(moves);
00269 Escape<Store>::template
00270 generateEscape<Defense,KING>(*state, target_king, store);
00271 }
00272 nonblock_moves = moves.size();
00273 blockable_check =
00274 ! effect_util::UnblockableCheck::isMember(alt(P), *state);
00275 if ((depth <= 1) && num_captures && (nonblock_moves > 2))
00276 {
00277 if (nonblock_moves > 3)
00278 {
00279 const int block_estimate = blockable_check
00280 ? blockEstimation<Defense>(attack_from, target_position)
00281 : 0;
00282 return ProofDisproof(nonblock_moves + block_estimate, 1);
00283 }
00284 }
00285 if (moves.empty())
00286 generateBlockingWhenLiberty0<Defense>(depth,target_king, attack_from, moves);
00287 }
00288 }
00289
00290 if (moves.empty()) {
00291 if (last_move.isValid() && last_move.isDrop() && last_move.ptype()==PAWN)
00292 return ProofDisproof::PawnCheckmate();
00293 if (SetPieces)
00294 {
00295 proof_pieces = ProofPieces::leaf(*state, P, PieceStand(P,*state));
00296 }
00297 return ProofDisproof::NoEscape();
00298 }
00299 const bool cut_candidate = (depth <= 1)
00300 && (nonblock_moves - (state->hasPieceOnStand<GOLD>(P)
00301 || state->hasPieceOnStand<SILVER>(P)) > 4);
00302 if (cut_candidate)
00303 return ProofDisproof(nonblock_moves, 1);
00304
00305 if (SetPieces)
00306 proof_pieces = PieceStand();
00307 PieceStand child_proof;
00308 ProofDisproof pdp;
00309 int minDisproof = ProofDisproof::DISPROOF_MAX;
00310 int sumProof = 0;
00311 size_t i=0;
00312 start_examine:
00313 for (;i<moves.size();i++){
00314 copyState(&states[depth-1],&states[depth]);
00315 ApplyMoveOfTurn::doMove(states[depth-1],moves[i]);
00316 pdp=attack<P,SetPieces,false>(depth-1, moves[i], child_proof);
00317 const int disproof=pdp.disproof();
00318 if (disproof<minDisproof){
00319 if (disproof==0)
00320 {
00321 return pdp;
00322 }
00323 minDisproof=disproof;
00324 }
00325 sumProof+=pdp.proof();
00326 if (sumProof == 0)
00327 {
00328 if (SetPieces)
00329 proof_pieces = proof_pieces.max(child_proof);
00330 }
00331 else
00332 {
00333 if (i+1 < moves.size())
00334 {
00335 minDisproof = 1;
00336 if ((int)i < nonblock_moves)
00337 sumProof += nonblock_moves - (i+1);
00338 if (blockable_check)
00339 ++sumProof;
00340 }
00341 return ProofDisproof(sumProof,minDisproof);
00342 }
00343 }
00344 if ((sumProof == 0) && blockable_check
00345 && ((int)moves.size() == nonblock_moves))
00346 {
00347 using namespace move_generator;
00348 using namespace move_action;
00349 const Position attack_from=attacker_piece.position();
00350 {
00351 move_action::Store store(moves);
00352 Escape<Store>::
00353 generateBlockingKing<Defense,false>(*state, target_king, attack_from,store);
00354 }
00355 if ((int)moves.size() > nonblock_moves)
00356 goto start_examine;
00357 }
00358
00359 if (SetPieces && (sumProof == 0) && blockable_check)
00360 {
00361 ProofPiecesUtil::addMonopolizedPieces(*state, P, PieceStand(P,*state), proof_pieces);
00362 }
00363
00364 return ProofDisproof(sumProof,minDisproof);
00365 }
00366
00367 template <osl::Player P>
00368 const osl::checkmate::ProofDisproof
00369 osl::checkmate::FixedDepthSearcher2::
00370 hasEscapeByMove(Move next_move, int depth, Move& check_move,
00371 PieceStand& proof_pieces)
00372 {
00373 proof_pieces = PieceStand();
00374 ProofDisproof pdp;
00375 copyState(&states[depth-1],&states[depth]);
00376 ApplyMoveOfTurn::doMove(states[depth-1],next_move);
00377 pdp=attackMayUnsafe<P,true,false>(depth-1, check_move, proof_pieces);
00378 return pdp;
00379 }
00380
00381 template <osl::Player P>
00382 const osl::checkmate::ProofDisproof
00383 osl::checkmate::FixedDepthSearcher2::
00384 hasEscapeByMove(Move next_move, int depth)
00385 {
00386 PieceStand proof_pieces;
00387 ProofDisproof pdp;
00388 copyState(&states[depth-1],&states[depth]);
00389 ApplyMoveOfTurn::doMove(states[depth-1],next_move);
00390 pdp=attack<P,false,false>(depth-1, next_move, proof_pieces);
00391 return pdp;
00392 }
00393
00394 template <osl::Player P>
00395 const osl::checkmate::ProofDisproof
00396 osl::checkmate::FixedDepthSearcher2::
00397 hasCheckmateWithGuide(int depth, Move& guide, PieceStand& proof_pieces)
00398 {
00399 NumEffectState* state= &states[depth];
00400 assert(guide.isNormal());
00401 if (! guide.isDrop())
00402 {
00403 const Piece p=state->getPieceOnBoard(guide.to());
00404 if (!p.isPtype<KING>())
00405 guide=guide.newCapture(p);
00406 }
00407 if (state->template isAlmostValidMove<false>(guide)
00408 && move_classifier::Check<P>
00409 ::isMember(*state, guide.ptype(), guide.from(), guide.to()))
00410 return attack<P,true,true>(depth, guide, proof_pieces);
00411 return attack<P,true,false>(depth, guide, proof_pieces);
00412 }
00413
00414 #endif
00415
00416
00417
00418