The Battle for Wesnoth  1.19.5+dev
lua_map_location_ops.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
3  by Chris Beck <render787@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
17 #include "scripting/lua_common.hpp"
18 #include "scripting/push_check.hpp"
19 
20 #include "map/location.hpp"
21 #include "pathutils.hpp"
22 
23 #include <string>
24 #include <utility>
25 
26 static bool luaW_tocubeloc(lua_State* L, int idx, cubic_location& out) {
27  if(!lua_istable(L, idx)) {
28  return false;
29  }
30  int n = lua_absindex(L, -1);
31  if(!luaW_tableget(L, n, "q")) {
32  return false;
33  }
34  out.q = luaL_checkinteger(L, -1);
35  if(!luaW_tableget(L, n, "r")) {
36  return false;
37  }
38  out.r = luaL_checkinteger(L, -1);
39  if(luaW_tableget(L, n, "s")) {
40  out.s = luaL_checkinteger(L, -1);
41  } else {
42  out.s = -out.q - out.r;
43  }
44  if(out.q + out.s + out.r != 0) {
45  return false;
46  }
47  return true;
48 }
49 
50 static cubic_location luaW_checkcubeloc(lua_State* L, int idx) {
51  cubic_location loc;
52  if(!luaW_tocubeloc(L, idx, loc)) {
53  luaL_argerror(L, idx, "expected cubic location");
54  }
55  return loc;
56 }
57 
58 static void luaW_pushcubeloc(lua_State* L, cubic_location loc) {
59  luaW_push_namedtuple(L, {"q", "r", "s"});
60  lua_pushinteger(L, loc.q);
61  lua_rawseti(L, -2, 1);
62  lua_pushinteger(L, loc.r);
63  lua_rawseti(L, -2, 2);
64  lua_pushinteger(L, loc.s);
65  lua_rawseti(L, -2, 3);
66 }
67 
68 namespace lua_map_location {
69 
70 /**
71  * Expose map_location::get_direction function to lua
72  * Arg 1: a location
73  * Arg 2: a direction
74  * Arg 3: (optional) number of steps
75  */
76 int intf_get_direction(lua_State* L)
77 {
78  map_location l;
79  if(!luaW_tolocation(L, 1, l)) {
80  return luaL_argerror(L, 1, "get_direction: first argument(S) must be a location");
81  }
82  int nargs = lua_gettop(L);
83  if (nargs < 2) {
84  luaL_error(L, "get_direction: not missing direction argument");
85  return 0;
86  }
87 
88  int n = 1;
89  if (nargs == 3) {
90  n = luaL_checkinteger(L, -1);
91  lua_pop(L,1);
92  }
93 
95  if (lua_isstring(L, -1)) {
96  d = map_location::parse_direction(luaL_checkstring(L,-1));
97  lua_pop(L,1);
98  } else {
99  std::string msg("get_direction: second argument should be a direction string, instead found a ");
100  msg += lua_typename(L, lua_type(L, -1));
101  return luaL_argerror(L, -1, msg.c_str());
102  }
103 
104  map_location result = l.get_direction(d, n);
105  luaW_pushlocation(L, result);
106  return 1;
107 }
108 
109 /**
110  * Expose map_location::vector_sum to lua
111  */
112 int intf_vector_sum(lua_State* L)
113 {
114  map_location l1, l2;
115  if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
116  lua_pushstring(L, "vector_sum: requires two locations");
117  return lua_error(L);
118  }
119 
121  return 1;
122 }
123 
124 /**
125  * Expose map_location::vector_difference to lua
126  */
127 int intf_vector_diff(lua_State* L)
128 {
129  map_location l1, l2;
130  if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
131  lua_pushstring(L, "vector_diff: requires two locations");
132  return lua_error(L);
133  }
134 
136  return 1;
137 }
138 
139 /**
140  * Expose map_location::vector_negation to lua
141  * - Arg 1: Location
142  * - Ret: Negated vector
143  */
144 int intf_vector_negation(lua_State* L)
145 {
146  map_location l1;
147  if(!luaW_tolocation(L, 1, l1)) {
148  return luaL_argerror(L, 1, "expected a location");
149  }
150 
152  return 1;
153 }
154 
155 /**
156  * Expose map_location::rotate_right_around_center to lua
157  */
159 {
160  int k = luaL_checkinteger(L, -1);
161  lua_pop(L,1);
162  map_location center, loc;
163  if(!luaW_tolocation(L, 1, loc) || !luaW_tolocation(L, 2, center)) {
164  lua_pushstring(L, "rotate_right_around_center: requires two locations");
165  return lua_error(L);
166  }
167 
169  return 1;
170 }
171 
172 /**
173  * Expose map_location tiles_adjacent
174  * - Args 1, 2: Two locations
175  * - Ret: True if the locations are adjacent
176  */
177 int intf_tiles_adjacent(lua_State* L)
178 {
179  map_location l1, l2;
180  if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
181  lua_pushstring(L, "tiles_adjacent: requires two locations");
182  return lua_error(L);
183  }
184 
185  lua_pushboolean(L, tiles_adjacent(l1,l2));
186  return 1;
187 }
188 
189 /**
190  * Expose map_location get_adjacent_tiles
191  * - Arg 1: A location
192  * - Ret 1 - 6: The adjacent locations
193  */
194 int intf_get_adjacent_tiles(lua_State* L)
195 {
196  map_location l1;
197  if(!luaW_tolocation(L, 1, l1)) {
198  return luaL_argerror(L, 1, "expected a location");
199  }
200 
201  for(const map_location& adj : get_adjacent_tiles(l1)) {
202  luaW_pushlocation(L, adj);
203  }
204 
205  return 6;
206 }
207 
208 /**
209  * Expose map_location get_tile_ring
210  * - Arg 1: A location
211  * - Arg 2: A radius
212  * - Ret: The locations
213  */
214 int intf_get_tile_ring(lua_State* L)
215 {
216  map_location l1;
217  if(!luaW_tolocation(L, 1, l1)) {
218  return luaL_argerror(L, 1, "expected a location");
219  }
220  int radius = luaL_checkinteger(L, 2);
221 
222  std::vector<map_location> locs;
223  get_tile_ring(l1, radius, locs);
224  lua_push(L, locs);
225 
226  return 1;
227 }
228 
229 /**
230 * Expose map_location get_tiles_in_radius
231 * - Arg 1: A location
232 * - Arg 2: A radius
233 * - Ret: The locations
234 */
235 int intf_get_tiles_in_radius(lua_State* L)
236 {
237  map_location l1;
238  if(!luaW_tolocation(L, 1, l1)) {
239  return luaL_argerror(L, 1, "expected a location");
240  }
241  int radius = luaL_checkinteger(L, 2);
242 
243  std::vector<map_location> locs;
244  get_tiles_in_radius(l1, radius, locs);
245  lua_push(L, locs);
246 
247  return 1;
248 }
249 
250 /**
251  * Expose map_location distance_between
252  * - Args 1, 2: Two locations
253  * - Ret: The distance between the two locations
254  */
255 int intf_distance_between(lua_State* L)
256 {
257  map_location l1, l2;
258  if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
259  lua_pushstring(L, "distance_between: requires two locations");
260  return lua_error(L);
261  }
262 
263  lua_pushinteger(L, distance_between(l1,l2));
264  return 1;
265 }
266 
267 /**
268  * Expose map_location to_cubic
269  * - Arg: Location
270  * - Ret: Location in cubic coordinates
271  */
272 int intf_get_in_cubic(lua_State* L)
273 {
274  map_location l1;
275  if(!luaW_tolocation(L, 1, l1)) {
276  return luaL_argerror(L, 1, "expected a location");
277  }
278  cubic_location h = l1.to_cubic();
279  // Due to the way that locations in Lua have are 1 more on each coordinate
280  // compared to the C++ coordinates, the output here also needs to be adjusted.
281  h.q++;
282  h.s--;
283  luaW_pushcubeloc(L, h);
284  return 1;
285 }
286 
287 /**
288  * Expose map_location from_cubic
289  * - Arg: Location in cubic coordinates
290  * - Ret: Location
291  */
292 int intf_get_from_cubic(lua_State* L)
293 {
295  // Adjust it from the WML location system
296  h.q--;
297  h.s++;
299  luaW_pushlocation(L, l);
300  return 1;
301 }
302 
303 /**
304  * Expose map_location get_relative_dir
305  * - Args 1, 2: Two locations
306  * - Ret: The direction of location 2 from location 1
307  */
308 int intf_get_relative_dir(lua_State* L)
309 {
310  map_location l1, l2;
311  if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
312  lua_pushstring(L, "get_relative_dir: requires two locations");
313  return lua_error(L);
314  }
315 
316  const std::string dir = map_location::write_direction(l1.get_relative_dir(l2));
317  lua_pushlstring(L, dir.c_str(), dir.length());
318  return 1;
319 }
320 
321 } // end namespace lua_map_location
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.cpp:479
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition: location.cpp:550
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.cpp:507
void luaW_push_namedtuple(lua_State *L, const std::vector< std::string > &names)
Push an empty "named tuple" onto the stack.
Definition: lua_common.cpp:712
void luaW_pushlocation(lua_State *L, const map_location &ml)
Converts a map location object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:740
bool luaW_tableget(lua_State *L, int index, const char *key)
bool luaW_tolocation(lua_State *L, int index, map_location &loc)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:751
static void luaW_pushcubeloc(lua_State *L, cubic_location loc)
static cubic_location luaW_checkcubeloc(lua_State *L, int idx)
static bool luaW_tocubeloc(lua_State *L, int idx, cubic_location &out)
int intf_get_relative_dir(lua_State *L)
Expose map_location get_relative_dir.
int intf_vector_negation(lua_State *L)
Expose map_location::vector_negation to lua.
int intf_distance_between(lua_State *L)
Expose map_location distance_between.
int intf_get_in_cubic(lua_State *L)
Expose map_location to_cubic.
int intf_tiles_adjacent(lua_State *L)
Expose map_location tiles_adjacent.
int intf_vector_diff(lua_State *L)
Expose map_location::vector_difference to lua.
int intf_get_from_cubic(lua_State *L)
Expose map_location from_cubic.
int intf_vector_sum(lua_State *L)
Expose map_location::vector_sum to lua.
int intf_get_tile_ring(lua_State *L)
Expose map_location get_tile_ring.
int intf_rotate_right_around_center(lua_State *L)
Expose map_location::rotate_right_around_center to lua.
int intf_get_tiles_in_radius(lua_State *L)
Expose map_location get_tiles_in_radius.
int intf_get_adjacent_tiles(lua_State *L)
Expose map_location get_adjacent_tiles.
int intf_get_direction(lua_State *L)
Expose map_location::get_direction function to lua Arg 1: a location Arg 2: a direction Arg 3: (optio...
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
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:56
void get_tile_ring(const map_location &center, const int radius, std::vector< map_location > &result)
Function that will add to result all locations exactly radius tiles from center (or nothing if radius...
Definition: pathutils.cpp:32
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:425
Represents a map location in cubic hexagonal coordinates.
Definition: location.hpp:33
Encapsulates the map of the game.
Definition: location.hpp:45
map_location & vector_sum_assign(const map_location &a)
Definition: location.hpp:142
map_location & vector_difference_assign(const map_location &a)
Definition: location.hpp:150
static map_location from_cubic(cubic_location h)
Definition: location.hpp:172
static std::string write_direction(direction dir)
Definition: location.cpp:154
map_location vector_negation() const
Definition: location.hpp:132
map_location get_direction(direction dir, unsigned int n=1u) const
Definition: location.cpp:364
map_location rotate_right_around_center(const map_location &center, int k) const
Definition: location.cpp:301
cubic_location to_cubic() const
Definition: location.hpp:166
direction
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:47
direction get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
Definition: location.cpp:240
static direction parse_direction(const std::string &str)
Definition: location.cpp:79
static map_location::direction n
#define d
#define h