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