説明を見る。00001
00002
00003 #include "osl/rating/feature/checkmate.h"
00004 #include "osl/bits/king8Info.h"
00005 #include "osl/effect_util/neighboring8Direct.h"
00006
00007 struct osl::rating::Threatmate::Helper
00008 {
00009 bool *result;
00010 NumEffectState *state;
00011 void operator()(Square)
00012 {
00013 if (state->inCheck(state->turn())
00014 || state->inCheck(alt(state->turn()))) {
00015 *result = false;
00016 return;
00017 }
00018 state->changeTurn();
00019 *result = ImmediateCheckmate::hasCheckmateMove(state->turn(), *state);
00020 state->changeTurn();
00021 }
00022 };
00023
00024 bool osl::rating::
00025 Threatmate::knight2Step(const NumEffectState& state, Move move, Square king)
00026 {
00027 if (move.ptype() != KNIGHT)
00028 return false;
00029 const int y = king.y() + sign(state.turn())*4;
00030 if (y != move.to().y())
00031 return false;
00032 const int x = move.to().x();
00033 return (x == king.x() || abs(king.x() - x) == 2);
00034 }
00035 bool osl::rating::
00036 Threatmate::captureForKnightCheck(const NumEffectState& state, Move move, Square king)
00037 {
00038 const Player defender = alt(state.turn());
00039 const CArray<Square,2> knight_position = {{
00040 Board_Table.nextSquare(defender, king, UUR),
00041 Board_Table.nextSquare(defender, king, UUL)
00042 }};
00043 const Piece captured = state.pieceOnBoard(move.to());
00044 assert(captured.isPiece());
00045 for (int i=0; i<2; ++i) {
00046 const Square kp = knight_position[i];
00047 const Piece p = state.pieceAt(kp);
00048 if (state.hasEffectNotBy(defender, captured, kp))
00049 continue;
00050 if (p.isEmpty()
00051 && (unpromote(move.capturePtype()) == KNIGHT
00052 || state.hasPieceOnStand<KNIGHT>(state.turn())))
00053 return true;
00054 if (p.canMoveOn(state.turn())
00055 && state.hasEffectByPtypeStrict<KNIGHT>(state.turn(), kp))
00056 return true;
00057 }
00058 return false;
00059 }
00060
00061 bool osl::rating::Threatmate::isCandidate(const NumEffectState& state, Move move)
00062 {
00063 const Player defender = alt(state.turn());
00064 const Square king = state.kingSquare(defender);
00065 if (Neighboring8Direct::hasEffectOrAdditional(state, move.ptypeO(), move.to(), king)
00066 || move.to().isNeighboring8(king)
00067 || state.longEffectAt(move.to(), alt(state.turn())).any()
00068 || (! move.isDrop() && state.longEffectAt(move.from(), state.turn()).any())
00069 )
00070 return true;
00071 if (move.capturePtype() != PTYPE_EMPTY
00072 && Neighboring8Direct::hasEffectOrAdditional(state, move.capturePtypeO(), move.to(), king))
00073 return true;
00074
00075 const King8Info info(state.king8Info(defender));
00076 if (move.capturePtype() != PTYPE_EMPTY
00077 && (info.dropCandidate()
00078 || (info.liberty() == 0 && captureForKnightCheck(state, move, king))))
00079 return true;
00080 if (state.inCheck()
00081 && (info.dropCandidate() || info.moveCandidate2()
00082 || info.liberty() == 0))
00083 return true;
00084 if (info.liberty() == 0
00085 && (knight2Step(state, move, king)
00086 || (! move.isDrop()
00087 && ((state.hasPieceOnStand<KNIGHT>(state.turn())
00088 && state.hasEffectIf(newPtypeO(state.turn(),KNIGHT), move.from(), king))
00089 || state.hasEffectByPtypeStrict<KNIGHT>(state.turn(), move.from())))))
00090 return true;
00091 return false;
00092 }
00093
00094 bool osl::rating::Threatmate::match(const NumEffectState& cstate, Move move,
00095 const RatingEnv&) const
00096 {
00097 NumEffectState& state = const_cast<NumEffectState&>(cstate);
00098 if (! isCandidate(cstate, move))
00099 return false;
00100 bool result = false;
00101 Helper helper = { &result, &state };
00102 state.makeUnmakeMove(move, helper);
00103 #ifdef OSL_DEBUG
00104 if (result && ! isCandidate(cstate, move))
00105 std::cerr << cstate << move << "\n", assert(0);
00106 #endif
00107 return result;
00108 }
00109
00110
00111
00112
00113
00114