Go to the documentation of this file.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/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
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()
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 || 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;
00097 if (state.longEffectAt(p.square(), attacker).any())
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
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;
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
00174
00175
00176