SimulationCraft
SimulationCraft is a tool to explore combat mechanics in the popular MMO RPG World of Warcraft (tm).
expressions.hpp
1 // ==========================================================================
2 // Dedmonwakeen's Raid DPS/TPS Simulator.
3 // Send questions to [email protected]
4 // ==========================================================================
5 
6 #pragma once
7 
8 #include "config.hpp"
9 #include <string>
10 #include <vector>
11 #include <functional>
12 #include <memory>
13 
14 #include "util/timespan.hpp"
15 #include "util/span.hpp"
16 #include "util/string_view.hpp"
17 
18 struct action_t;
19 struct sim_t;
20 struct player_t;
21 struct expr_t;
22 
23 // Expressions ==============================================================
24 
25 namespace expression
26 {
27 enum token_e
28 {
29  TOK_UNKNOWN = 0,
30  TOK_PLUS,
31  TOK_MINUS,
32  TOK_MULT,
33  TOK_DIV,
34  TOK_MOD,
35  TOK_ADD,
36  TOK_SUB,
37  TOK_AND,
38  TOK_OR,
39  TOK_XOR,
40  TOK_NOT,
41  TOK_EQ,
42  TOK_NOTEQ,
43  TOK_LT,
44  TOK_LTEQ,
45  TOK_GT,
46  TOK_GTEQ,
47  TOK_LPAR,
48  TOK_RPAR,
49  TOK_IN,
50  TOK_NOTIN,
51  TOK_NUM,
52  TOK_STR,
53  TOK_ABS,
54  TOK_SPELL_LIST,
55  TOK_FLOOR,
56  TOK_CEIL,
57  TOK_MAX,
58  TOK_MIN,
59  TOK_EOF, // "end of stream"
60 };
61 
63 {
64  token_e type;
65  std::string label;
66 };
67 
68 bool is_unary( token_e );
69 bool is_binary( token_e );
70 std::vector<expr_token_t> parse_tokens( action_t* action, util::string_view expr_str );
71 void print_tokens( util::span<const expr_token_t> tokens, sim_t* sim );
72 bool convert_to_rpn( std::vector<expr_token_t>& tokens );
73 std::unique_ptr<expr_t> build_player_expression_tree(
74  player_t& player, std::vector<expression::expr_token_t>& tokens,
75  bool optimize );
76 }
77 
79 struct expr_t
80 {
81 protected:
82  expr_t( util::string_view name, expression::token_e op = expression::TOK_UNKNOWN )
83  : op_( op )
84 #if !defined( NDEBUG )
85  ,
86  id_( get_global_id() ),
87  name_(name)
88 #endif
89  {
90  (void)name;
91  }
92 
93 public:
94  virtual ~expr_t() = default;
95 
96  const char* name() const
97  {
98 #if !defined( NDEBUG )
99  return name_.c_str();
100 #else
101  return "anonymous expression";
102 #endif
103  }
104  int id() const
105  {
106 #if !defined( NDEBUG )
107  return id_;
108 #else
109  return -1;
110 #endif
111  }
112 
113  double eval()
114  {
115  return evaluate();
116  }
117  bool success()
118  {
119  return eval() != 0;
120  }
121  bool always_true()
122  {
123  return is_constant() && evaluate() != 0.0;
124  }
125  bool always_false()
126  {
127  return is_constant() && evaluate() == 0.0;
128  }
129  static double coerce( timespan_t t )
130  {
131  return t.total_seconds();
132  }
133  template <typename T>
134  static double coerce( T t )
135  {
136  return static_cast<double>( t );
137  }
138 
139  static std::unique_ptr<expr_t> parse( action_t*, util::string_view expr_str,
140  bool optimize = false );
141  template<class T>
142  static std::unique_ptr<expr_t> create_constant( util::string_view name, T value );
143 
144  static void optimize_expression(std::unique_ptr<expr_t>& expression, bool analyze_further = false, int spacing = 0);
145 
146  static void optimize_expression(std::unique_ptr<expr_t>& expression, sim_t& sim);
147 
148  virtual double evaluate() = 0;
149 
150  virtual bool is_constant()
151  {
152  return false;
153  }
154 
155  virtual bool is_analyze_expression()
156  {
157  return false;
158  }
159 
160  expression::token_e op_;
161 
162 private:
163  /* Attempts to create a optimized version of the expression.
164  Should return null if no improved version can be built.
165  */
166  virtual std::unique_ptr<expr_t> build_optimized_expression( bool /* analyze_further */, int /* spacing */ )
167  {
168  return {};
169  }
170 #if !defined( NDEBUG )
171  int id_;
172  std::string name_;
173 
174  int get_global_id();
175 #endif
176 };
177 
178 class const_expr_t : public expr_t
179 {
180  double value;
181 
182 public:
183  const_expr_t( util::string_view name, double value_ )
184  : expr_t( name, expression::TOK_NUM ), value( value_ )
185  {
186  }
187 
188  double evaluate() override // override
189  {
190  return value;
191  }
192 
193  bool is_constant() override // override
194  {
195  return true;
196  }
197 };
198 
199 // Reference Expression - ref_expr_t
200 // Class Template to create a expression with a reference ( ref ) of arbitrary
201 // type T, and evaluate that reference
202 template <typename T>
203 struct ref_expr_t : public expr_t
204 {
205 public:
206  ref_expr_t( util::string_view name, const T& t_ ) : expr_t( name ), t( t_ )
207  {
208  }
209 
210 private:
211  const T& t;
212  double evaluate() override
213  {
214  return coerce( t );
215  }
216 };
217 
218 // Template to return a reference expression
219 template <typename T>
220 inline std::unique_ptr<expr_t> make_ref_expr( util::string_view name, T& t )
221 {
222  return std::make_unique<ref_expr_t<T>>( name, const_cast<const T&>( t ) );
223 }
224 
225 // Function Expression - fn_expr_t
226 // Class Template to create a function ( fn ) expression with arbitrary functor
227 // f, which gets evaluated
228 template <typename F>
229 struct fn_expr_t : public expr_t
230 {
231 public:
232  template <typename U = F>
233  fn_expr_t( util::string_view name, U&& f_ ) : expr_t( name ), f( std::forward<U>( f_ ) )
234  { }
235 
236 private:
237  F f;
238 
239  double evaluate() override
240  {
241  return coerce( f() );
242  }
243 };
244 
246 {
247  action_t& action;
248  std::vector<std::unique_ptr<expr_t>> proxy_expr;
249  std::string suffix_expr_str;
250 
251  // Inlined
252  target_wrapper_expr_t( action_t& a, util::string_view name_str,
253  util::string_view expr_str );
254  virtual player_t* target() const;
255  double evaluate() override;
256 };
257 
258 // Template to return a function expression
259 template <typename F>
260 inline std::unique_ptr<expr_t> make_fn_expr( util::string_view name, F&& f )
261 {
262  return std::make_unique<fn_expr_t<std::decay_t<F>>>( name, std::forward<F>( f ) );
263 }
264 
265 // Make member function expression - make_mem_fn_expr
266 // Template to return function expression that calls a member ( mem ) function (
267 // fn ) f on reference t.
268 template <typename F, typename T>
269 inline std::unique_ptr<expr_t> make_mem_fn_expr( util::string_view name, T& t, F f )
270 {
271  return make_fn_expr( name, std::bind( std::mem_fn( f ), &t ) );
272 }
273 
274 template<class T>
275 inline std::unique_ptr<expr_t> expr_t::create_constant( util::string_view name, T value )
276 {
277  return std::make_unique<const_expr_t>( name, coerce(value) );
278 }
279 
Definition: expressions.cpp:12
Definition: expressions.hpp:229
Definition: expressions.hpp:62
Definition: expressions.hpp:245
Definition: action.hpp:47
Definition: expressions.hpp:178
Class for representing InGame time.
Definition: timespan.hpp:37
Definition: player.hpp:109
Action expression.
Definition: expressions.hpp:79
Definition: expressions.hpp:203
Definition: core.h:1208
Simulation engine.
Definition: sim.hpp:61