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