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