00001
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/apply_move/applyMove.h"
00014 #include "osl/neighboring8.h"
00015
00016 struct osl::checkmate::CheckmateIfCapture::CallDefense
00017 {
00018 NumEffectState *state;
00019 int depth;
00020 bool result;
00021 void operator()(Position last_to)
00022 {
00023 result = cannotCapture(*state, last_to, depth);
00024 }
00025 };
00026
00027 bool osl::checkmate::
00028 CheckmateIfCapture::effectiveAttackCandidate0(const NumEffectState& state, Move move)
00029 {
00030 using namespace move_classifier;
00031
00032 const Player attacker = state.getTurn();
00033 const Player defender = alt(attacker);
00034 const Position king = state.getKingPosition(defender);
00035 PieceMask pieces = state.getEffect(move.to())
00036 & state.getOnBoardMask(defender);
00037 if (pieces.none())
00038 return false;
00039 if (Neighboring8::isNeighboring8(move.to(), king))
00040 return true;
00041 const Piece captured = state.getPieceOnBoard(move.to());
00042 if (move.capturePtype() != PTYPE_EMPTY) {
00043 if (Neighboring8Direct::hasEffect(state, captured.ptypeO(),
00044 move.to(), king))
00045 return true;
00046 }
00047 if (! move.isDrop()
00048 && (state.selectLong(move.from(), attacker).any()
00049 || (Neighboring8::isNeighboring8(move.from(), king)
00050 && state.hasEffectBy(attacker, move.from()))))
00051 return true;
00052
00053 const King8Info info = state.king8Info(defender);
00054 const CArray<Position,2> knight_position = {{
00055 Board_Table.nextPosition(defender, king, UUR),
00056 Board_Table.nextPosition(defender, king, UUL)
00057 }};
00058 if (state.inCheck()
00059 && (info.dropCandidate() || info.moveCandidate2()
00060 || info.liberty() == 0))
00061 return true;
00062 if (move.capturePtype() != PTYPE_EMPTY) {
00063 if (info.dropCandidate())
00064 return true;
00065 if (info.liberty() == 0) {
00066 for (int i=0; i<2; ++i) {
00067 const Position kp = knight_position[i];
00068 const Piece kpp = state.getPieceAt(kp);
00069 if (kpp.isEdge() || state.hasEffectNotBy(defender, captured, kp))
00070 continue;
00071 if (kpp.isEmpty()
00072 && unpromote(move.capturePtype()) == KNIGHT)
00073 return true;
00074 if (state.hasEffectByPiece(captured, kp)
00075 && (unpromote(move.capturePtype()) == KNIGHT
00076 || state.hasPieceOnStand<KNIGHT>(attacker)
00077 || state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp)))
00078 return true;
00079 }
00080 }
00081 }
00082
00083
00084 while (pieces.any())
00085 {
00086 const Piece p=state.getPieceOf(pieces.takeOneBit());
00087 if (Neighboring8Direct::hasEffectOrAdditional(state, p.ptypeO(), p.position(), king)
00088 || Neighboring8::isNeighboring8(p.position(), king))
00089 continue;
00090 if (state.selectLong(p.position(), attacker).any())
00091 continue;
00092 if (info.liberty() == 0) {
00093 int i=0;
00094 for (; i<2; ++i) {
00095 const Position kp = knight_position[i];
00096 const Piece kpp = state.getPieceAt(kp);
00097 if (kpp.isEdge() || state.hasEffectNotBy(defender, p, kp))
00098 continue;
00099 if (p.position() == kp
00100 && state.hasPieceOnStand<KNIGHT>(attacker))
00101 break;
00102 if (state.countEffect(defender, kp) == 1)
00103 if ((kpp.canMoveOn(attacker)
00104 && state.hasEffectByPtypeStrict<KNIGHT>(attacker, kp))
00105 || (kpp.isEmpty()
00106 && state.hasPieceOnStand<KNIGHT>(attacker)))
00107 break;
00108 }
00109 if (i<2)
00110 continue;
00111 }
00112
00113 return false;
00114 }
00115 return true;
00116 }
00117
00118 bool osl::checkmate::
00119 CheckmateIfCapture::effectiveAttack(NumEffectState& state, Move move, int depth)
00120 {
00121 assert(move.player() == state.getTurn());
00122 CallDefense defense = { &state, depth, false };
00123 ApplyMoveOfTurn::doUndoMove(state, move, defense);
00124 #ifdef OSL_DEBUG
00125 if (defense.result && ! effectiveAttackCandidate0(state, move))
00126 std::cerr << state << move << "\n", assert(0);
00127 #endif
00128 return defense.result;
00129 }
00130
00131 bool osl::checkmate::
00132 CheckmateIfCapture::cannotCapture(NumEffectState& state,
00133 Position last_to, int depth)
00134 {
00135 if (state.inCheck(alt(state.getTurn())))
00136 return false;
00137
00138 using namespace move_generator;
00139 using namespace move_action;
00140 MoveVector moves;
00141 GenerateCapture::generate(state, last_to, moves);
00142
00143 if (moves.empty())
00144 return false;
00145
00146 FixedDepthSearcher searcher(state);
00147 const Position king = state.getKingPosition(state.getTurn());
00148 for (MoveVector::const_iterator p=moves.begin(); p!=moves.end(); ++p)
00149 {
00150 if (state.inCheck()) {
00151 if (state.countEffect(alt(state.getTurn()), king) > 1
00152 || ! state.hasEffectByPiece(state.getPieceOnBoard(last_to), king))
00153 if (p->ptype() != KING)
00154 continue;
00155 }
00156 const bool checkmate
00157 = searcher.hasEscapeByMoveOfTurn(*p, depth).isCheckmateSuccess();
00158 if (! checkmate)
00159 return false;
00160 }
00161
00162 return true;
00163 }
00164
00165
00166
00167
00168
00169