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