fixedDepthSearcher.tcc
Go to the documentation of this file.
00001 /* fixedDepthSearcher.tcc
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   // depth >= 3 では PawnCheckmateの際にunpromoteを試す必要あり
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   // multiple checkなので,pawn dropではない
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     // this is better approximation than naive enumeration of blocking moves,
00205     // for counting of disproof number in df-pn,
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       // move
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 /*attack_from*/, Square /*defense_king*/) 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;             // maybe PawnCheckmate
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   // depth >= 2 では unprmote も試す必要あり
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 /* OSL_CHECKMATE_FIXED_DEPTH_SERCHER_TCC */
00474 // ;;; Local Variables:
00475 // ;;; mode:c++
00476 // ;;; c-basic-offset:2
00477 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines