The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
lua_map_location_ops.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2014 - 2025
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
19
20#include "map/location.hpp"
21#include "pathutils.hpp"
22
23#include <string>
24#include <utility>
25
26static 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
50static cubic_location luaW_checkcubeloc(lua_State* L, int idx) {
52 if(!luaW_tocubeloc(L, idx, loc)) {
53 luaL_argerror(L, idx, "expected cubic location");
54 }
55 return loc;
56}
57
58static void luaW_pushcubeloc(lua_State* L, cubic_location loc) {
59 static const lua_named_tuple_builder tuple_builder{ {"q", "r", "s"} };
60 tuple_builder.push(L);
61 lua_pushinteger(L, loc.q);
62 lua_rawseti(L, -2, 1);
63 lua_pushinteger(L, loc.r);
64 lua_rawseti(L, -2, 2);
65 lua_pushinteger(L, loc.s);
66 lua_rawseti(L, -2, 3);
67}
68
70
71/**
72 * Expose map_location::get_direction function to lua
73 * Arg 1: a location
74 * Arg 2: a direction
75 * Arg 3: (optional) number of steps
76 */
77int intf_get_direction(lua_State* L)
78{
80 if(!luaW_tolocation(L, 1, l)) {
81 return luaL_argerror(L, 1, "get_direction: first argument(S) must be a location");
82 }
83 int nargs = lua_gettop(L);
84 if (nargs < 2) {
85 luaL_error(L, "get_direction: not missing direction argument");
86 return 0;
87 }
88
89 int n = 1;
90 if (nargs == 3) {
91 n = luaL_checkinteger(L, -1);
92 lua_pop(L,1);
93 }
94
96 if (lua_isstring(L, -1)) {
97 d = map_location::parse_direction(luaL_checkstring(L,-1));
98 lua_pop(L,1);
99 } else {
100 std::string msg("get_direction: second argument should be a direction string, instead found a ");
101 msg += lua_typename(L, lua_type(L, -1));
102 return luaL_argerror(L, -1, msg.c_str());
103 }
104
105 map_location result = l.get_direction(d, n);
106 luaW_pushlocation(L, result);
107 return 1;
108}
109
110/**
111 * Expose map_location::vector_sum to lua
112 */
113int intf_vector_sum(lua_State* L)
114{
115 map_location l1, l2;
116 if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
117 lua_pushstring(L, "vector_sum: requires two locations");
118 return lua_error(L);
119 }
120
122 return 1;
123}
124
125/**
126 * Expose map_location::vector_difference to lua
127 */
128int intf_vector_diff(lua_State* L)
129{
130 map_location l1, l2;
131 if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
132 lua_pushstring(L, "vector_diff: requires two locations");
133 return lua_error(L);
134 }
135
137 return 1;
138}
139
140/**
141 * Expose map_location::vector_negation to lua
142 * - Arg 1: Location
143 * - Ret: Negated vector
144 */
145int intf_vector_negation(lua_State* L)
146{
147 map_location l1;
148 if(!luaW_tolocation(L, 1, l1)) {
149 return luaL_argerror(L, 1, "expected a location");
150 }
151
153 return 1;
154}
155
156/**
157 * Expose map_location::rotate_right_around_center to lua
158 */
160{
161 int k = luaL_checkinteger(L, -1);
162 lua_pop(L,1);
163 map_location center, loc;
164 if(!luaW_tolocation(L, 1, loc) || !luaW_tolocation(L, 2, center)) {
165 lua_pushstring(L, "rotate_right_around_center: requires two locations");
166 return lua_error(L);
167 }
168
170 return 1;
171}
172
173/**
174 * Expose map_location tiles_adjacent
175 * - Args 1, 2: Two locations
176 * - Ret: True if the locations are adjacent
177 */
178int intf_tiles_adjacent(lua_State* L)
179{
180 map_location l1, l2;
181 if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
182 lua_pushstring(L, "tiles_adjacent: requires two locations");
183 return lua_error(L);
184 }
185
186 lua_pushboolean(L, tiles_adjacent(l1,l2));
187 return 1;
188}
189
190/**
191 * Expose map_location get_adjacent_tiles
192 * - Arg 1: A location
193 * - Ret 1 - 6: The adjacent locations
194 */
195int intf_get_adjacent_tiles(lua_State* L)
196{
197 map_location l1;
198 if(!luaW_tolocation(L, 1, l1)) {
199 return luaL_argerror(L, 1, "expected a location");
200 }
201
202 for(const map_location& adj : get_adjacent_tiles(l1)) {
203 luaW_pushlocation(L, adj);
204 }
205
206 return 6;
207}
208
209/**
210 * Expose map_location get_tile_ring
211 * - Arg 1: A location
212 * - Arg 2: A radius
213 * - Ret: The locations
214 */
215int intf_get_tile_ring(lua_State* L)
216{
217 map_location l1;
218 if(!luaW_tolocation(L, 1, l1)) {
219 return luaL_argerror(L, 1, "expected a location");
220 }
221 int radius = luaL_checkinteger(L, 2);
222
223 std::vector<map_location> locs;
224 get_tile_ring(l1, radius, locs);
225 lua_push(L, locs);
226
227 return 1;
228}
229
230/**
231* Expose map_location get_tiles_in_radius
232* - Arg 1: A location
233* - Arg 2: A radius
234* - Ret: The locations
235*/
237{
238 map_location l1;
239 if(!luaW_tolocation(L, 1, l1)) {
240 return luaL_argerror(L, 1, "expected a location");
241 }
242 int radius = luaL_checkinteger(L, 2);
243
244 std::vector<map_location> locs;
245 get_tiles_in_radius(l1, radius, locs);
246 lua_push(L, locs);
247
248 return 1;
249}
250
251/**
252 * Expose map_location distance_between
253 * - Args 1, 2: Two locations
254 * - Ret: The distance between the two locations
255 */
256int intf_distance_between(lua_State* L)
257{
258 map_location l1, l2;
259 if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
260 lua_pushstring(L, "distance_between: requires two locations");
261 return lua_error(L);
262 }
263
264 lua_pushinteger(L, distance_between(l1,l2));
265 return 1;
266}
267
268/**
269 * Expose map_location to_cubic
270 * - Arg: Location
271 * - Ret: Location in cubic coordinates
272 */
273int intf_get_in_cubic(lua_State* L)
274{
275 map_location l1;
276 if(!luaW_tolocation(L, 1, l1)) {
277 return luaL_argerror(L, 1, "expected a location");
278 }
280 // Due to the way that locations in Lua have are 1 more on each coordinate
281 // compared to the C++ coordinates, the output here also needs to be adjusted.
282 h.q++;
283 h.s--;
285 return 1;
286}
287
288/**
289 * Expose map_location from_cubic
290 * - Arg: Location in cubic coordinates
291 * - Ret: Location
292 */
293int intf_get_from_cubic(lua_State* L)
294{
296 // Adjust it from the WML location system
297 h.q--;
298 h.s++;
300 luaW_pushlocation(L, l);
301 return 1;
302}
303
304/**
305 * Expose map_location get_relative_dir
306 * - Args 1, 2: Two locations
307 * - Ret: The direction of location 2 from location 1
308 */
309int intf_get_relative_dir(lua_State* L)
310{
311 map_location l1, l2;
312 if(!luaW_tolocation(L, 1, l1) || !luaW_tolocation(L, 2, l2)) {
313 lua_pushstring(L, "get_relative_dir: requires two locations");
314 return lua_error(L);
315 }
316
317 const std::string dir = map_location::write_direction(l1.get_relative_dir(l2));
318 lua_pushlstring(L, dir.c_str(), dir.length());
319 return 1;
320}
321
322} // end namespace lua_map_location
map_location loc
Definition move.cpp:172
Efficiently creates new LUA "named tuples" with the specified field names.
void push(lua_State *L) const
Push an empty "named tuple" onto the stack.
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:584
void get_adjacent_tiles(const map_location &a, utils::span< map_location, 6 > res)
Function which, given a location, will place all adjacent locations in res.
Definition location.cpp:513
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition location.cpp:541
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.
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.
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...
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)
Represents a map location in cubic hexagonal coordinates.
Definition location.hpp:34
Encapsulates the map of the game.
Definition location.hpp:46
static map_location from_cubic(cubic_location h)
Definition location.hpp:173
map_location & vector_sum_assign(const map_location &a)
Definition location.hpp:143
static std::string write_direction(direction dir)
Definition location.cpp:154
map_location vector_negation() const
Definition location.hpp:133
map_location get_direction(direction dir, unsigned int n=1u) const
Definition location.cpp:362
map_location rotate_right_around_center(const map_location &center, int k) const
Definition location.cpp:299
cubic_location to_cubic() const
Definition location.hpp:167
direction
Valid directions which can be moved in our hexagonal world.
Definition location.hpp:48
direction get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
Definition location.cpp:238
static direction parse_direction(const std::string &str)
Definition location.cpp:79
map_location & vector_difference_assign(const map_location &a)
Definition location.hpp:151
static map_location::direction n
#define d
#define h