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 #include "units/types.hpp"
10 #include "units/unit.hpp"
11 
12 namespace wfl {
13 
14 namespace gamestate {
15 
16 DEFINE_WFL_FUNCTION(adjacent_locs, 1, 1)
17 {
18  const map_location loc = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "adjacent_locs:location")).convert_to<location_callable>()->loc();
19  map_location adj[6];
20  get_adjacent_tiles(loc, adj);
21 
22  std::vector<variant> v;
23  for(int n = 0; n != 6; ++n) {
24  if(resources::gameboard->map().on_board(adj[n])) {
25  v.emplace_back(std::make_shared<location_callable>(adj[n]));
26  }
27  }
28 
29  return variant(v);
30 }
31 
32 DEFINE_WFL_FUNCTION(locations_in_radius, 2, 2)
33 {
34  const map_location loc = args()[0]->evaluate(variables, fdb).convert_to<location_callable>()->loc();
35 
36  int range = args()[1]->evaluate(variables, fdb).as_int();
37 
38  if(range < 0) {
39  return variant();
40  }
41 
42  if(!range) {
43  return variant(std::make_shared<location_callable>(loc));
44  }
45 
46  std::vector<map_location> res;
47 
48  get_tiles_in_radius(loc, range, res);
49 
50  std::vector<variant> v;
51  v.reserve(res.size() + 1);
52  v.emplace_back(std::make_shared<location_callable>(loc));
53 
54  for(size_t n = 0; n != res.size(); ++n) {
55  if(resources::gameboard->map().on_board(res[n])) {
56  v.emplace_back(std::make_shared<location_callable>(res[n]));
57  }
58  }
59 
60  return variant(v);
61 }
62 
64 {
65  const std::string type = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "get_unit_type:name")).as_string();
66 
67  const unit_type *ut = unit_types.find(type);
68  if(ut) {
69  return variant(std::make_shared<unit_type_callable>(*ut));
70  }
71 
72  return variant();
73 }
74 
75 DEFINE_WFL_FUNCTION(unit_at, 1, 1)
76 {
77  variant loc_var = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "unit_at:location"));
78  if(loc_var.is_null()) {
79  return variant();
80  }
81  auto loc = loc_var.convert_to<location_callable>();
83  if(i != resources::gameboard->units().end()) {
84  return variant(std::make_shared<unit_callable>(*i));
85  } else {
86  return variant();
87  }
88 }
89 
90 DEFINE_WFL_FUNCTION(defense_on, 2, 2)
91 {
92  variant u = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "defense_on:unit"));
93  variant loc_var = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "defense_on:location"));
94  if(u.is_null() || loc_var.is_null()) {
95  return variant();
96  }
97 
98  auto u_call = u.try_convert<unit_callable>();
99  auto u_type = u.try_convert<unit_type_callable>();
100  const map_location& loc = loc_var.convert_to<location_callable>()->loc();
101 
102  if(u_call) {
103  const unit& un = u_call->get_unit();
104 
105  if(un.total_movement() < un.movement_cost((resources::gameboard->map())[loc]))
106  return variant();
107 
108  if(!resources::gameboard->map().on_board(loc)) {
109  return variant();
110  }
111 
112  return variant(100 - un.defense_modifier((resources::gameboard->map())[loc]));
113  }
114 
115  if(u_type) {
116  const unit_type& un = u_type->get_unit_type();
117 
118  if(un.movement() < un.movement_type().movement_cost((resources::gameboard->map())[loc]))
119  return variant();
120 
121  if(!resources::gameboard->map().on_board(loc)) {
122  return variant();
123  }
124 
125  return variant(100 - un.movement_type().defense_modifier((resources::gameboard->map())[loc]));
126  }
127 
128  return variant();
129 }
130 
131 DEFINE_WFL_FUNCTION(chance_to_hit, 2, 2)
132 {
133  variant u = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "chance_to_hit:unit"));
134  variant loc_var = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "chance_to_hit: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(!resources::gameboard->map().on_board(loc)) {
147  return variant();
148  }
149 
150  return variant(un.defense_modifier((resources::gameboard->map())[loc]));
151  }
152 
153  if(u_type) {
154  const unit_type& un = u_type->get_unit_type();
155 
156  if(!resources::gameboard->map().on_board(loc)) {
157  return variant();
158  }
159 
160  return variant(un.movement_type().defense_modifier((resources::gameboard->map())[loc]));
161  }
162 
163  return variant();
164 }
165 
166 DEFINE_WFL_FUNCTION(movement_cost, 2, 2)
167 {
168  variant u = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "movement_cost:unit"));
169  variant loc_var = args()[1]->evaluate(variables, add_debug_info(fdb, 0, "movement_cost:location"));
170  if(u.is_null() || loc_var.is_null()) {
171  return variant();
172  }
173  //we can pass to this function either unit_callable or unit_type callable
174  auto u_call = u.try_convert<unit_callable>();
175  auto u_type = u.try_convert<unit_type_callable>();
176  const map_location& loc = loc_var.convert_to<location_callable>()->loc();
177 
178  if(u_call) {
179  const unit& un = u_call->get_unit();
180 
181  if(!resources::gameboard->map().on_board(loc)) {
182  return variant();
183  }
184 
185  return variant(un.movement_cost((resources::gameboard->map())[loc]));
186  }
187 
188  if(u_type) {
189  const unit_type& un = u_type->get_unit_type();
190 
191  if(!resources::gameboard->map().on_board(loc)) {
192  return variant();
193  }
194 
195  return variant(un.movement_type().movement_cost((resources::gameboard->map())[loc]));
196  }
197 
198  return variant();
199 }
200 
201 DEFINE_WFL_FUNCTION(enemy_of, 2, 2)
202 {
203  variant self_v = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "enemy_of:self"));
204  variant other_v = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "enemy_of:other"));
205  int self, other;
206 
207  if(auto uc = self_v.try_convert<unit_callable>()) {
208  // For some obscure, bizarre reason, the unit callable returns a 0-indexed side. :|
209  self = uc->get_value("side").as_int() + 1;
210  } else if(auto tc = self_v.try_convert<team_callable>()) {
211  self = tc->get_value("side").as_int();
212  } else {
213  self = self_v.as_int();
214  }
215 
216  if(auto uc = other_v.try_convert<unit_callable>()) {
217  // For some obscure, bizarre reason, the unit callable returns a 0-indexed side. :|
218  other = uc->get_value("side").as_int() + 1;
219  } else if(auto tc = other_v.try_convert<team_callable>()) {
220  other = tc->get_value("side").as_int();
221  } else {
222  other = other_v.as_int();
223  }
224 
225  int num_teams = resources::gameboard->teams().size();
226  if(self < 1 || self > num_teams || other < 1 || other > num_teams) {
227  return variant(0);
228  }
229  return variant(resources::gameboard->get_team(self).is_enemy(other) ? 1 : 0);
230 }
231 
232 } // namespace gamestate
233 
234 gamestate_function_symbol_table::gamestate_function_symbol_table(std::shared_ptr<function_symbol_table> parent) : function_symbol_table(parent) {
235  using namespace gamestate;
236  function_symbol_table& functions_table = *this;
238  DECLARE_WFL_FUNCTION(unit_at);
239  DECLARE_WFL_FUNCTION(defense_on);
240  DECLARE_WFL_FUNCTION(chance_to_hit);
241  DECLARE_WFL_FUNCTION(movement_cost);
242  DECLARE_WFL_FUNCTION(adjacent_locs); // This is deliberately duplicated here; this form excludes off-map locations, while the core form does not
243  DECLARE_WFL_FUNCTION(locations_in_radius);
244  DECLARE_WFL_FUNCTION(enemy_of);
245 }
246 
247 }
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:1057
virtual const unit_map & units() const
Definition: game_board.hpp:97
unit_iterator end()
Definition: map.hpp:415
std::vector< char_t > string
This class represents a single unit of a specific type.
Definition: unit.hpp:100
int movement() const
Definition: types.hpp:153
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
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
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:1538
Encapsulates the map of the game.
Definition: location.hpp:40
DEFINE_WFL_FUNCTION(adjacent_locs, 1, 1)
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
Definition: unit.hpp:1224
size_t i
Definition: function.cpp:933
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:47
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
static map_location::DIRECTION n
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