The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
function_gamestate.cpp
Go to the documentation of this file.
1 
3 #include "formula/callable_objects.hpp"
4 
5 #include "resources.hpp"
6 #include "game_board.hpp"
7 #include "map/map.hpp"
8 #include "pathutils.hpp"
9 
10 namespace wfl {
11 
12 namespace gamestate {
13 
15 {
16 public:
18  : function_expression("adjacent_locs", args, 1, 1)
19  {}
20 
21 private:
22  variant execute(const formula_callable& variables, formula_debugger *fdb) const
23  {
24  const map_location loc = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "adjacent_locs:location")).convert_to<location_callable>()->loc();
25  map_location adj[6];
26  get_adjacent_tiles(loc, adj);
27 
28  std::vector<variant> v;
29  for(int n = 0; n != 6; ++n) {
30  if(resources::gameboard->map().on_board(adj[n])) {
31  v.emplace_back(std::make_shared<location_callable>(adj[n]));
32  }
33  }
34 
35  return variant(v);
36  }
37 };
38 
40 {
41 public:
43  : function_expression("locations_in_radius", args, 2, 2)
44  {}
45 
46 private:
47  variant execute(const formula_callable& variables, formula_debugger *fdb) const
48  {
49  const map_location loc = args()[0]->evaluate(variables, fdb).convert_to<location_callable>()->loc();
50 
51  int range = args()[1]->evaluate(variables, fdb).as_int();
52 
53  if(range < 0) {
54  return variant();
55  }
56 
57  if(!range) {
58  return variant(std::make_shared<location_callable>(loc));
59  }
60 
61  std::vector<map_location> res;
62 
63  get_tiles_in_radius(loc, range, res);
64 
65  std::vector<variant> v;
66  v.reserve(res.size() + 1);
67  v.emplace_back(std::make_shared<location_callable>(loc));
68 
69  for(size_t n = 0; n != res.size(); ++n) {
70  if(resources::gameboard->map().on_board(res[n])) {
71  v.emplace_back(std::make_shared<location_callable>(res[n]));
72  }
73  }
74 
75  return variant(v);
76  }
77 };
78 
80 {
81 public:
83  : function_expression("get_unit_type", args, 1, 1)
84  {}
85 private:
86  variant execute(const formula_callable& variables, formula_debugger *fdb) const
87  {
88  const std::string type = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "get_unit_type:name")).as_string();
89 
90  const unit_type *ut = unit_types.find(type);
91  if(ut) {
92  return variant(std::make_shared<unit_type_callable>(*ut));
93  }
94 
95  return variant();
96  }
97 };
98 
99 
101 {
102 public:
104  : function_expression("unit_at", args, 1, 1)
105  {}
106 private:
107  variant execute(const formula_callable& variables, formula_debugger *fdb) const
108  {
109  variant loc_var = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "unit_at:location"));
110  if(loc_var.is_null()) {
111  return variant();
112  }
113  auto loc = loc_var.convert_to<location_callable>();
115  if(i != resources::gameboard->units().end()) {
116  return variant(std::make_shared<unit_callable>(*i));
117  } else {
118  return variant();
119  }
120  }
121 };
122 
123 
125 {
126 public:
128  : function_expression("defense_on", args, 2, 2)
129  {}
130 private:
131  variant execute(const formula_callable& variables, formula_debugger *fdb) const
132  {
133  variant u = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "defense_on:unit"));
134  variant loc_var = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "defense_on:location"));
135  if(u.is_null() || loc_var.is_null()) {
136  return variant();
137  }
138 
139  auto u_call = u.try_convert<unit_callable>();
140  auto u_type = u.try_convert<unit_type_callable>();
141  const map_location& loc = loc_var.convert_to<location_callable>()->loc();
142 
143  if(u_call) {
144  const unit& un = u_call->get_unit();
145 
146  if(un.total_movement() < un.movement_cost((resources::gameboard->map())[loc]))
147  return variant();
148 
149  if(!resources::gameboard->map().on_board(loc)) {
150  return variant();
151  }
152 
153  return variant(100 - un.defense_modifier((resources::gameboard->map())[loc]));
154  }
155 
156  if(u_type) {
157  const unit_type& un = u_type->get_unit_type();
158 
159  if(un.movement() < un.movement_type().movement_cost((resources::gameboard->map())[loc]))
160  return variant();
161 
162  if(!resources::gameboard->map().on_board(loc)) {
163  return variant();
164  }
165 
166  return variant(100 - un.movement_type().defense_modifier((resources::gameboard->map())[loc]));
167  }
168 
169  return variant();
170  }
171 };
172 
173 
175 {
176 public:
178  : function_expression("chance_to_hit", args, 2, 2)
179  {}
180 private:
181  variant execute(const formula_callable& variables, formula_debugger *fdb) const
182  {
183  variant u = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "chance_to_hit:unit"));
184  variant loc_var = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "chance_to_hit:location"));
185  if(u.is_null() || loc_var.is_null()) {
186  return variant();
187  }
188 
189  auto u_call = u.try_convert<unit_callable>();
190  auto u_type = u.try_convert<unit_type_callable>();
191  const map_location& loc = loc_var.convert_to<location_callable>()->loc();
192 
193  if(u_call) {
194  const unit& un = u_call->get_unit();
195 
196  if(!resources::gameboard->map().on_board(loc)) {
197  return variant();
198  }
199 
200  return variant(un.defense_modifier((resources::gameboard->map())[loc]));
201  }
202 
203  if(u_type) {
204  const unit_type& un = u_type->get_unit_type();
205 
206  if(!resources::gameboard->map().on_board(loc)) {
207  return variant();
208  }
209 
210  return variant(un.movement_type().defense_modifier((resources::gameboard->map())[loc]));
211  }
212 
213  return variant();
214  }
215 };
216 
217 
219 {
220 public:
222  : function_expression("movement_cost", args, 2, 2)
223  {}
224 private:
225  variant execute(const formula_callable& variables, formula_debugger *fdb) const
226  {
227  variant u = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "movement_cost:unit"));
228  variant loc_var = args()[1]->evaluate(variables, add_debug_info(fdb, 0, "movement_cost:location"));
229  if(u.is_null() || loc_var.is_null()) {
230  return variant();
231  }
232  //we can pass to this function either unit_callable or unit_type callable
233  auto u_call = u.try_convert<unit_callable>();
234  auto u_type = u.try_convert<unit_type_callable>();
235  const map_location& loc = loc_var.convert_to<location_callable>()->loc();
236 
237  if(u_call) {
238  const unit& un = u_call->get_unit();
239 
240  if(!resources::gameboard->map().on_board(loc)) {
241  return variant();
242  }
243 
244  return variant(un.movement_cost((resources::gameboard->map())[loc]));
245  }
246 
247  if(u_type) {
248  const unit_type& un = u_type->get_unit_type();
249 
250  if(!resources::gameboard->map().on_board(loc)) {
251  return variant();
252  }
253 
254  return variant(un.movement_type().movement_cost((resources::gameboard->map())[loc]));
255  }
256 
257  return variant();
258  }
259 };
260 
261 
263 {
264 public:
266  : function_expression("enemy_of", args, 2, 2)
267  {}
268 private:
269  variant execute(const formula_callable& variables, formula_debugger *fdb) const
270  {
271  variant self_v = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "enemy_of:self"));
272  variant other_v = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "enemy_of:other"));
273  int self, other;
274 
275  if(auto uc = self_v.try_convert<unit_callable>()) {
276  // For some obscure, bizarre reason, the unit callable returns a 0-indexed side. :|
277  self = uc->get_value("side").as_int() + 1;
278  } else if(auto tc = self_v.try_convert<team_callable>()) {
279  self = tc->get_value("side").as_int();
280  } else {
281  self = self_v.as_int();
282  }
283 
284  if(auto uc = other_v.try_convert<unit_callable>()) {
285  // For some obscure, bizarre reason, the unit callable returns a 0-indexed side. :|
286  other = uc->get_value("side").as_int() + 1;
287  } else if(auto tc = other_v.try_convert<team_callable>()) {
288  other = tc->get_value("side").as_int();
289  } else {
290  other = other_v.as_int();
291  }
292 
293  int num_teams = resources::gameboard->teams().size();
294  if(self < 1 || self > num_teams || other < 1 || other > num_teams) {
295  return variant(0);
296  }
297  return variant(resources::gameboard->get_team(self).is_enemy(other) ? 1 : 0);
298  }
299 };
300 
301 } // namespace gamestate
302 
303 gamestate_function_symbol_table::gamestate_function_symbol_table(std::shared_ptr<function_symbol_table> parent) : function_symbol_table(parent) {
304  using namespace gamestate;
305  function_symbol_table& functions_table = *this;
307  DECLARE_WFL_FUNCTION(unit_at);
308  DECLARE_WFL_FUNCTION(defense_on);
309  DECLARE_WFL_FUNCTION(chance_to_hit);
310  DECLARE_WFL_FUNCTION(movement_cost);
311  DECLARE_WFL_FUNCTION(adjacent_locs); // This is deliberately duplicated here; this form excludes off-map locations, while the core form does not
312  DECLARE_WFL_FUNCTION(locations_in_radius);
313  DECLARE_WFL_FUNCTION(enemy_of);
314 }
315 
316 }
variant execute(const formula_callable &variables, formula_debugger *fdb) const
variant execute(const formula_callable &variables, formula_debugger *fdb) const
int movement_cost(const t_translation::terrain_code &terrain, bool slowed=false) const
Returns the cost to move through the indicated terrain.
Definition: movetype.hpp:197
int total_movement() const
The maximum moves this unit has.
Definition: unit.hpp:1058
virtual const unit_map & units() const
Definition: game_board.hpp:97
unit_iterator end()
Definition: map.hpp:415
std::vector< char_t > string
variant execute(const formula_callable &variables, formula_debugger *fdb) const
This class represents a single unit of a specific type.
Definition: unit.hpp:101
int movement() const
Definition: types.hpp:153
std::vector< expression_ptr > args_list
Definition: function.hpp:57
variant execute(const formula_callable &variables, formula_debugger *fdb) const
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.hpp:299
int as_int() const
Definition: variant.cpp:298
formula_debugger * add_debug_info(formula_debugger *fdb, int arg_number, const std::string &f_name)
void get_tiles_in_radius(const map_location &center, const int radius, std::vector< map_location > &result)
Function that will add to result all locations within radius tiles of center (excluding center itself...
Definition: pathutils.cpp:54
const movetype & movement_type() const
Definition: types.hpp:175
variant execute(const formula_callable &variables, formula_debugger *fdb) const
unit_type_data unit_types
Definition: types.cpp:1455
virtual const std::vector< team > & teams() const
Definition: game_board.hpp:92
A single unit type that the player may recruit.
Definition: types.hpp:43
variant execute(const formula_callable &variables, formula_debugger *fdb) const
enemy_of_function(const args_list &args)
game_board * gameboard
Definition: resources.cpp:20
std::shared_ptr< T > try_convert() const
Definition: variant.hpp:86
int defense_modifier(const t_translation::terrain_code &terrain) const
The unit's defense on a given terrain.
Definition: unit.cpp:1535
Encapsulates the map of the game.
Definition: location.hpp:40
const args_list & args() const
Definition: function.hpp:74
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
Definition: unit.hpp:1225
#define i
unit_at_function(const args_list &args)
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:58
#define DECLARE_WFL_FUNCTION(name)
Declares a function name in the local function table functions_table.
Definition: function.hpp:162
virtual const gamemap & map() const
Definition: game_board.hpp:96
static const unit_type & get_unit_type(const std::string &type_id)
Converts a string ID to a unit_type.
Definition: unit.cpp:198
Definition: contexts.hpp:42
gamestate_function_symbol_table(std::shared_ptr< function_symbol_table > parent=nullptr)
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition: types.cpp:1273
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:96
unit_iterator find(size_t id)
Definition: map.cpp:311
variant execute(const formula_callable &variables, formula_debugger *fdb) const
static map_location::DIRECTION n
variant execute(const formula_callable &variables, formula_debugger *fdb) const
unit_map * units
Definition: resources.cpp:34
int defense_modifier(const t_translation::terrain_code &terrain) const
Returns the defensive value of the indicated terrain.
Definition: movetype.hpp:207