00001
00002
00003 #ifndef _FEATURE_H
00004 #define _FEATURE_H
00005
00006 #include "osl/rating/ratingEnv.h"
00007 #include "osl/state/numEffectState.h"
00008 #include "osl/effect_util/effectUtil.h"
00009 #include "osl/move_classifier/check_.h"
00010 #include "osl/move_classifier/moveAdaptor.h"
00011 #include <string>
00012
00013 namespace osl
00014 {
00015 namespace rating
00016 {
00017 class Feature
00018 {
00019 std::string my_name;
00020 public:
00021 Feature(const std::string& name) : my_name(name)
00022 {
00023 }
00024 virtual ~Feature();
00025 virtual bool match(const NumEffectState& state, Move, const RatingEnv&) const =0;
00026 virtual bool effectiveInCheck() const { return false; }
00027 const std::string& name() const { return my_name; }
00028 };
00029
00030 class TakeBack : public Feature
00031 {
00032 public:
00033 TakeBack() : Feature("TakeBack")
00034 {
00035 }
00036 bool match(const NumEffectState&, Move move, const RatingEnv& env) const
00037 {
00038 return env.history.hasLastMove() && move.to() == env.history.lastMove().to();
00039 }
00040 virtual bool effectiveInCheck() const { return true; }
00041 };
00042
00043 class TakeBack2 : public Feature
00044 {
00045 public:
00046 TakeBack2() : Feature("TakeBack2")
00047 {
00048 }
00049 bool match(const NumEffectState&, Move move, const RatingEnv& env) const
00050 {
00051 return env.history.hasLastMove(2)
00052 && move.to() == env.history.lastMove().to()
00053 && move.to() == env.history.lastMove(2).to();
00054 }
00055 bool effectiveInCheck() const { return true; }
00056 };
00057
00058
00059 class Check : public Feature
00060 {
00061 int property;
00062 public:
00063 Check(int p);
00064 static bool openLong(const NumEffectState& state, Move move)
00065 {
00066 if (move.isDrop())
00067 return false;
00068 return state.hasEffectByPtype<LANCE>(move.player(), move.from())
00069 || state.hasEffectByPtype<BISHOP>(move.player(), move.from())
00070 || state.hasEffectByPtype<ROOK>(move.player(), move.from());
00071 }
00072 bool match(const NumEffectState& state, Move move, const RatingEnv&) const;
00073 static const CArray<const char*,4> check_property;
00074 bool effectiveInCheck() const { return true; }
00075 };
00076
00077 class SendOff : public Feature
00078 {
00079 bool capture;
00080 public:
00081 SendOff(bool c) : Feature("SO"), capture(c) {}
00082 bool match(const NumEffectState& state, Move move, const RatingEnv& env) const
00083 {
00084 return env.sendoffs.isMember(move.to()) && (move.capturePtype() !=PTYPE_EMPTY) == capture;
00085 }
00086 };
00087
00088 class Block : public Feature
00089 {
00090 int self, opponent;
00091 public:
00092 static const std::string name(int self, int opponent);
00093 Block(int s, int o) : Feature(name(s, o)), self(s), opponent(o) {}
00094 static int count(const NumEffectState& state, Position position, Player player)
00095 {
00096 return (state.effectPtype<LANCE>(player, position).ptype() == LANCE)
00097 + state.hasEffectByPtype<BISHOP>(player, position)
00098 + state.hasEffectByPtype<ROOK>(player, position);
00099 }
00100 bool match(const NumEffectState& state, Move move, const RatingEnv&) const
00101 {
00102 return count(state, move.to(), state.getTurn()) == self
00103 && count(state, move.to(), alt(state.getTurn())) == opponent;
00104 }
00105 bool effectiveInCheck() const { return true; }
00106 };
00107
00108
00109 struct CountOpen
00110 {
00111 static int index(const NumEffectState& state, Player player, Position from)
00112 {
00113 if (from.isPieceStand())
00114 return -1;
00115 const bool vertical = state.hasEffectByPtype<LANCE>(player, from)
00116 || state.hasEffectByPtype<ROOK>(player, from);
00117 const bool diagonal = state.hasEffectByPtype<BISHOP>(player, from);
00118 return diagonal*2+vertical;
00119 }
00120 };
00121
00122 class Open : public Feature
00123 {
00124 int property;
00125 public:
00126 Open(int p) : Feature(name(p)), property(p) {}
00127 static int index(const NumEffectState& state, Move move)
00128 {
00129 if (move.isDrop())
00130 return -1;
00131 return CountOpen::index(state, move.player(), move.from())*4
00132 + CountOpen::index(state, alt(move.player()), move.from());
00133 }
00134 bool match(const NumEffectState& state, Move move, const RatingEnv&) const
00135 {
00136 return index(state, move) == property;
00137 }
00138 static const std::string name(int property);
00139 bool effectiveInCheck() const { return true; }
00140 };
00141
00142 class Chase : public Feature
00143 {
00144 public:
00145 enum OpponentType { CAPTURE, DROP, ESCAPE, OTHER, };
00146 private:
00147 Ptype self, target;
00148 bool drop;
00149 OpponentType opponent_type;
00150 public:
00151 Chase(Ptype s, Ptype t, bool d, OpponentType o)
00152 : Feature(name(s,t,d,o)), self(s), target(t), drop(d), opponent_type(o) {}
00153 bool match(const NumEffectState& state, Move move, const RatingEnv& env) const
00154 {
00155 const Move last_move = env.history.lastMove();
00156 if (! last_move.isNormal())
00157 return false;
00158 if (! (move.ptype() == self && last_move.ptype() == target
00159 && drop == move.isDrop()))
00160 return false;
00161 switch (opponent_type) {
00162 case CAPTURE:
00163 if (last_move.capturePtype() == PTYPE_EMPTY)
00164 return false;
00165 break;
00166 case DROP:
00167 if (! last_move.isDrop())
00168 return false;
00169 break;
00170 case ESCAPE:
00171 if (last_move.isDrop() || last_move.capturePtype() != PTYPE_EMPTY
00172 || ! state.hasEffectBy(state.getTurn(), last_move.from()))
00173 return false;
00174 break;
00175 case OTHER:
00176 if (last_move.isDrop() || last_move.capturePtype() != PTYPE_EMPTY)
00177 return false;
00178 break;
00179 }
00180 return state.hasEffectFromTo(move.ptypeO(), move.to(), last_move.to());
00181 }
00182 static const std::string name(Ptype, Ptype, bool, OpponentType);
00183 };
00184
00185 class ImmediateAddSupport : public Feature
00186 {
00187 class Test;
00188 Ptype self, attack;
00189 public:
00190 ImmediateAddSupport(Ptype self, Ptype attack);
00191 bool match(const NumEffectState& state, Move move, const RatingEnv& env) const;
00192 bool effectiveInCheck() const { return true; }
00193 static int index(const NumEffectState& state, Move move, const RatingEnv& env);
00194 };
00195
00196 class RookDefense : public Feature
00197 {
00198 public:
00199 RookDefense() : Feature("RookDefense")
00200 {
00201 }
00202 bool match(const NumEffectState& state, Move move, const RatingEnv& env) const
00203 {
00204 if (move.isDrop() || env.progress.value() > 8)
00205 return false;
00206 Piece rook1 = state.getPieceOf(PtypeTraits<ROOK>::indexMin);
00207 Piece rook2 = state.getPieceOf(PtypeTraits<ROOK>::indexMin + 1);
00208 if (move.from() == rook2.position())
00209 std::swap(rook1, rook2);
00210 if (move.from() != rook1.position()
00211 || rook2.position().isPieceStand()
00212 || rook2.owner() == move.player()
00213 || rook2.position().x() != move.to().x())
00214 return false;
00215 return (move.to().y() - rook2.position().y())*playerToMul(move.player()) > 0;
00216 }
00217 };
00218
00219 class BadLance : public Feature
00220 {
00221 bool has_effect;
00222 public:
00223 explicit BadLance(bool h) : Feature(h ? "StrongBadLance" : "WeakBadLance"), has_effect(h)
00224 {
00225 }
00226 static bool basicMatch(const NumEffectState& state, Move move, Position front)
00227 {
00228 if (! (move.isDrop() && move.ptype() == LANCE))
00229 return false;
00230 return state.getPieceOnBoard(front).isEmpty()
00231 && state.hasPieceOnStand(alt(move.player()), PAWN)
00232 && !state.isPawnMaskSet(alt(move.player()), front.x());
00233 }
00234 bool match(const NumEffectState& state, Move move, const RatingEnv&) const
00235 {
00236 const Position front = Board_Table.nextPosition(move.player(), move.to(), U);
00237 return basicMatch(state, move, front)
00238 && ((!has_effect) ^ state.hasEffectBy(alt(move.player()), front));
00239 }
00240 };
00241
00242 class PawnAttack : public Feature
00243 {
00244 public:
00245 PawnAttack() : Feature("PA")
00246 {
00247 }
00248 bool match(const NumEffectState& state, Move move, const RatingEnv& env) const
00249 {
00250 if (! (move.isDrop() && move.ptype() == PAWN))
00251 return false;
00252 const Move last_move = env.history.lastMove();
00253 if (! last_move.isNormal() || last_move.capturePtype() == PTYPE_EMPTY)
00254 return false;
00255 return last_move.capturePtype() == PAWN && last_move.to().x() == move.to().x();
00256 }
00257 };
00258
00259 }
00260 }
00261
00262
00263 #endif
00264
00265
00266
00267