checkmateIfCapture.cc
Go to the documentation of this file.
00001 /* checkmateIfCapture.cc
00002  */
00003 #include "osl/checkmate/checkmateIfCapture.h"
00004 #include "osl/checkmate/fixedDepthSearcher.h"
00005 #include "osl/checkmate/king8Info.h"
00006 #include "osl/checkmate/immediateCheckmate.h"
00007 #include "osl/effect_util/effectUtil.h"
00008 #include "osl/effect_util/neighboring8Direct.h"
00009 #include "osl/move_generator/capture_.h"
00010 #include "osl/move_action/store.h"
00011 #include "osl/move_classifier/moveAdaptor.h"
00012 #include "osl/move_classifier/openCheck.h"
00013 #include "osl/neighboring8.h"
00014 
00015 struct osl::checkmate::CheckmateIfCapture::CallDefense
00016 {
00017   NumEffectState *state;
00018   int depth;
00019   bool result;
00020   void operator()(Square last_to)
00021   {
00022     result = cannotCapture(*state, last_to, depth);
00023   }
00024 };
00025 
00026 bool osl::checkmate::
00027 CheckmateIfCapture::effectiveAttackCandidate0(const NumEffectState& state, Move move)
00028 {
00029   using namespace move_classifier;
00030   // depth 0 専用の枝刈
00031   const Player attacker = state.turn();
00032   const Player defender = alt(attacker);
00033   const Square king = state.kingSquare(defender);
00034   PieceMask pieces = state.effectSetAt(move.to())
00035     & state.piecesOnBoard(defender);
00036   if (pieces.none())
00037     return false;
00038   if (Neighboring8::isNeighboring8(move.to(), king))
00039     return true;
00040   const Piece captured = state.pieceOnBoard(move.to());
00041   if (move.isCapture()) {
00042     if (Neighboring8Direct::hasEffect(state, captured.ptypeO(), 
00043                                       move.to(), king))
00044       return true;
00045   }
00046   if (! move.isDrop()
00047       && (state.longEffectAt(move.from(), attacker).any() // todo: refinement 開き王手pinとか8近傍くらい?
00048           || (Neighboring8::isNeighboring8(move.from(), king)
00049               && state.hasEffectAt(attacker, move.from()))))
00050     return true;
00051 
00052   const King8Info info = state.king8Info(defender);
00053   const CArray<Square,2> knight_position = {{
00054       Board_Table.nextSquare(defender, king, UUR),
00055       Board_Table.nextSquare(defender, king, UUL)
00056     }};
00057   if (state.inCheck()
00058       && (info.dropCandidate() || info.moveCandidate2()
00059           || /* only when has knight or knight effect */info.liberty() == 0))
00060     return true;
00061   if (move.isCapture()) {
00062     if (info.dropCandidate())
00063       return true;
00064     if (info.liberty() == 0) {
00065       for (int i=0; i<2; ++i) {
00066         const Square kp = knight_position[i];
00067         const Piece kpp = state.pieceAt(kp);
00068         if (kpp.isEdge() || state.hasEffectNotBy(defender, captured, kp))
00069           continue;
00070         if (kpp.isEmpty()
00071             && unpromote(move.capturePtype()) == KNIGHT)
00072           return true;
00073         if (state.hasEffectByPiece(captured, kp)
00074             && (unpromote(move.capturePtype()) == KNIGHT
00075                 || state.hasPieceOnStand<KNIGHT>(attacker)
00076                 || state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp)))
00077           return true;
00078       }
00079     }
00080   } else if (info.liberty() == 0 && state.hasPieceOnStand<KNIGHT>(attacker)) {
00081       for (int i=0; i<2; ++i) {
00082         const Square kp = knight_position[i];
00083         const Piece kpp = state.pieceAt(kp);
00084         if (! kpp.isOnBoardByOwner(defender))
00085           continue;
00086         if (state.hasEffectByPiece(kpp, move.to()))
00087           return true;
00088       }
00089   }
00090   // テストでは出てこないが焦点もあるか?
00091   while (pieces.any())
00092   {
00093     const Piece p=state.pieceOf(pieces.takeOneBit());
00094     if (Neighboring8Direct::hasEffectOrAdditional(state, p.ptypeO(), p.square(), king)
00095         || Neighboring8::isNeighboring8(p.square(), king))
00096       continue;         // i.e., need analyses
00097     if (state.longEffectAt(p.square(), attacker).any()) // todo: refinement
00098       continue;
00099     if (info.liberty() == 0) {
00100       int i=0;
00101       for (; i<2; ++i) {
00102         const Square kp = knight_position[i];
00103         const Piece kpp = state.pieceAt(kp);
00104         if (kpp.isEdge() || state.hasEffectNotBy(defender, p, kp))
00105           continue;
00106         if (p.square() == kp
00107             && state.hasPieceOnStand<KNIGHT>(attacker))
00108           break;
00109         if (state.countEffect(defender, kp) == 1)
00110           if ((kpp.canMoveOn(attacker)
00111                && state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp))
00112               || (kpp.isEmpty()
00113                   && state.hasPieceOnStand<KNIGHT>(attacker)))
00114             break;
00115       }
00116       if (i<2)
00117         continue;
00118     }
00119     // now we have safe takeback
00120     return false;
00121   }
00122   return true;
00123 }
00124 
00125 bool osl::checkmate::
00126 CheckmateIfCapture::effectiveAttack(NumEffectState& state, Move move, int depth)
00127 {
00128   assert(move.player() == state.turn());
00129   CallDefense defense = { &state, depth, false };
00130   state.makeUnmakeMove(move, defense);
00131 #ifdef OSL_DEBUG
00132   if (defense.result && ! effectiveAttackCandidate0(state, move))
00133     std::cerr << state << move << "\n", assert(0);
00134 #endif
00135   return defense.result;
00136 }
00137 
00138 bool osl::checkmate::
00139 CheckmateIfCapture::cannotCapture(NumEffectState& state, 
00140                                   Square last_to, int depth)
00141 {
00142   if (state.inCheck(alt(state.turn())))
00143     return false;               // 前の手が自殺
00144 
00145   using namespace move_generator;
00146   using namespace move_action;
00147   MoveVector moves;             // may contain unsafe move
00148   GenerateCapture::generate(state, last_to, moves);
00149 
00150   if (moves.empty())
00151     return false;
00152 
00153   FixedDepthSearcher searcher(state);
00154   const Square king = state.kingSquare(state.turn());
00155   for (MoveVector::const_iterator p=moves.begin(); p!=moves.end(); ++p)
00156   {
00157     if (state.inCheck()) {
00158       if (state.countEffect(alt(state.turn()), king) > 1
00159           || ! state.hasEffectByPiece(state.pieceOnBoard(last_to), king))
00160         if (p->ptype() != KING)
00161           continue;
00162     }
00163     const bool checkmate
00164       = searcher.hasEscapeByMoveOfTurn(*p, depth).isCheckmateSuccess();
00165     if (! checkmate)
00166       return false;
00167   }
00168 
00169   return true;
00170 }
00171 
00172 /* ------------------------------------------------------------------------- */
00173 // ;;; Local Variables:
00174 // ;;; mode:c++
00175 // ;;; c-basic-offset:2
00176 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines