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