Some updates to Lua map location operations

* Rename the vector operations to hex_vector (to emphasize that they are NOT standard vector ops) and document them as official API
* Add new get_hexes_at_radius, which returns an unfilled ring (as opposed to get_hexes_in_radius which returns a filled circle)
* Expose the new cubic coordinate conversions
This commit is contained in:
Celtic Minstrel 2024-09-07 20:27:12 -04:00 committed by Celtic Minstrel
parent 6547d224e0
commit 2a26a68025
5 changed files with 157 additions and 5 deletions

View file

@ -461,6 +461,9 @@ if wesnoth.kernel_type() == "Mapgen Lua Kernel" then
wesnoth.map.get_tiles_radius = wesnoth.deprecate_api('map:get_tiles_radius', 'map:find_in_radius', 1, nil, function(map, locs, filter, radius)
return wesnoth.map.find_in_radius(map, locs, radius, filter)
end, 'The filter is now the last parameter, instead of the radius')
wesnoth.map.vector_sum = wesnoth.deprecate_api('wesnoth.map.vector_sum', 'wesnoth.map.hex_vector_sum', 1, nil, wesnoth.map.hex_vector_sum)
wesnoth.map.vector_diff = wesnoth.deprecate_api('wesnoth.map.vector_diff', 'wesnoth.map.hex_vector_dif', 1, nil, wesnoth.map.hex_vector_diff)
wesnoth.map.vector_negation = wesnoth.deprecate_api('wesnoth.map.vector_negation', 'wesnoth.map.hex_vector_negation', 1, nil, wesnoth.map.hex_vector_negation)
end
wesnoth.map.tiles_adjacent = wesnoth.deprecate_api('wesnoth.map.tiles_adjacent', 'wesnoth.map.are_hexes_adjacent', 1, nil, wesnoth.map.are_hexes_adjacent)

View file

@ -873,14 +873,17 @@ lua_kernel_base::lua_kernel_base()
static luaL_Reg const map_callbacks[] {
{ "get_direction", &lua_map_location::intf_get_direction },
{ "vector_sum", &lua_map_location::intf_vector_sum },
{ "vector_diff", &lua_map_location::intf_vector_diff },
{ "vector_negation", &lua_map_location::intf_vector_negation },
{ "hex_vector_sum", &lua_map_location::intf_vector_sum },
{ "hex_vector_diff", &lua_map_location::intf_vector_diff },
{ "hex_vector_negation", &lua_map_location::intf_vector_negation },
{ "rotate_right_around_center", &lua_map_location::intf_rotate_right_around_center },
{ "are_hexes_adjacent", &lua_map_location::intf_tiles_adjacent },
{ "get_adjacent_hexes", &lua_map_location::intf_get_adjacent_tiles },
{ "get_hexes_in_radius", &lua_map_location::intf_get_tiles_in_radius },
{ "get_hexes_at_radius", &lua_map_location::intf_get_tile_ring },
{ "distance_between", &lua_map_location::intf_distance_between },
{ "get_cubic", &lua_map_location::intf_get_in_cubic },
{ "from_cubic", &lua_map_location::intf_get_from_cubic },
{ "get_relative_dir", &lua_map_location::intf_get_relative_dir },
// Shroud bitmaps
{"parse_bitmap", intf_parse_shroud_bitmap},

View file

@ -23,6 +23,47 @@
#include <string>
#include <utility>
static bool luaW_tocubeloc(lua_State* L, int idx, cubic_location& out) {
if(!lua_istable(L, idx)) {
return false;
}
int n = lua_absindex(L, -1);
if(!luaW_tableget(L, n, "q")) {
return false;
}
out.q = luaL_checkinteger(L, -1);
if(!luaW_tableget(L, n, "r")) {
return false;
}
out.r = luaL_checkinteger(L, -1);
if(luaW_tableget(L, n, "s")) {
out.s = luaL_checkinteger(L, -1);
} else {
out.s = -out.q - out.r;
}
if(out.q + out.s + out.r != 0) {
return false;
}
return true;
}
static cubic_location luaW_checkcubeloc(lua_State* L, int idx) {
cubic_location loc;
if(!luaW_tocubeloc(L, idx, loc)) {
luaL_argerror(L, idx, "expected cubic location");
}
return loc;
}
static void luaW_pushcubeloc(lua_State* L, cubic_location loc) {
luaW_push_namedtuple(L, {"q", "r", "s"});
lua_pushinteger(L, loc.q);
lua_rawseti(L, -2, 1);
lua_pushinteger(L, loc.r);
lua_rawseti(L, -2, 2);
lua_pushinteger(L, loc.s);
lua_rawseti(L, -2, 3);
}
namespace lua_map_location {
@ -165,10 +206,32 @@ int intf_get_adjacent_tiles(lua_State* L)
}
/**
* Expose map_location get_tiles_in_radius
* Expose map_location get_tile_ring
* - Arg 1: A location
* - Arg 2: A radius
* - Ret: The locations
*/
int intf_get_tile_ring(lua_State* L)
{
map_location l1;
if(!luaW_tolocation(L, 1, l1)) {
return luaL_argerror(L, 1, "expected a location");
}
int radius = luaL_checkinteger(L, 2);
std::vector<map_location> locs;
get_tile_ring(l1, radius, locs);
lua_push(L, locs);
return 1;
}
/**
* Expose map_location get_tiles_in_radius
* - Arg 1: A location
* - Arg 2: A radius
* - Ret: The locations
*/
int intf_get_tiles_in_radius(lua_State* L)
{
map_location l1;
@ -201,6 +264,42 @@ int intf_distance_between(lua_State* L)
return 1;
}
/**
* Expose map_location to_cubic
* - Arg: Location
* - Ret: Location in cubic coordinates
*/
int intf_get_in_cubic(lua_State* L)
{
map_location l1;
if(!luaW_tolocation(L, 1, l1)) {
return luaL_argerror(L, 1, "expected a location");
}
cubic_location h = l1.to_cubic();
// Due to the way that locations in Lua have are 1 more on each coordinate
// compared to the C++ coordinates, the output here also needs to be adjusted.
h.q++;
h.s--;
luaW_pushcubeloc(L, h);
return 1;
}
/**
* Expose map_location from_cubic
* - Arg: Location in cubic coordinates
* - Ret: Location
*/
int intf_get_from_cubic(lua_State* L)
{
cubic_location h = luaW_checkcubeloc(L, 1);
// Adjust it from the WML location system
h.q--;
h.s++;
map_location l = map_location::from_cubic(h);
luaW_pushlocation(L, l);
return 1;
}
/**
* Expose map_location get_relative_dir
* - Args 1, 2: Two locations

View file

@ -31,8 +31,11 @@ int intf_vector_negation(lua_State*);
int intf_rotate_right_around_center(lua_State*);
int intf_tiles_adjacent(lua_State*);
int intf_get_adjacent_tiles(lua_State*);
int intf_get_tile_ring(lua_State*);
int intf_get_tiles_in_radius(lua_State*);
int intf_distance_between(lua_State*);
int intf_get_in_cubic(lua_State*);
int intf_get_from_cubic(lua_State*);
int intf_get_relative_dir(lua_State*);
} // end namespace lua_map_location

View file

@ -288,5 +288,49 @@ function wesnoth.map.are_hexes_adjacent(loc1, loc2) end
---@return integer
---@overload fun(x1:integer, y1:integer, loc2:location):integer
---@overload fun(loc1:location, x2:integer, y2:integer):integer
---@overload fun(x1:integer, y1:integer, x2:integer, y2:integer):integer``
---@overload fun(x1:integer, y1:integer, x2:integer, y2:integer):integer
function wesnoth.map.distance_between(loc1, loc2) end
---Represents a map location expressed in cubic coordinates.
---Each axis covers a "diagonal" direction on the hexagonal grid.
---To put it another way, it's the directions corresponding to
--- the hex's vertices, rather than the edges.
---@class location_cube
---@field q integer Horizontal (e/w) component
---@field r integer Positive diagonal (nne/ssw) component
---@field s integer Negative diagonal (nnw/sse) component
---Convert a hex location into cubic coordinates
---@param loc location
---@return location_cube
---@overload fun(x:integer, y:integer):location_cube
function wesnoth.map.get_cubic(loc) end
---Convert a cubic hex location back into standard hex coordinates
---@param vec location_cube
---@return location
function wesnoth.map.from_cubic(vec) end
---Add two hex vectors together
---@param v1 location
---@param v2 location
---@return location
---@overload fun(x1:integer, y1:integer, x2:integer, y2:integer):location
---@overload fun(loc1:location, x2:integer, y2:integer):location
---@overload fun(x1: integer, y1:integer, loc2:location):location
function wesnoth.map.hex_vector_sum(v1, v2) end
---Take the difference of two hex vectors
---@param v1 location
---@param v2 location
---@return location
---@overload fun(x1:integer, y1:integer, x2:integer, y2:integer):location
---@overload fun(loc1:location, x2:integer, y2:integer):location
---@overload fun(x1: integer, y1:integer, loc2:location):location
function wesnoth.map.hex_vector_diff(v1, v2) end
---Reverse the direction of a hex vector
---@param vec location
---@return location
---@overload fun(x:integer, y:integer):location
function wesnoth.map.hex_vector_negation(vec) end