Skip to content

Commit

Permalink
Add on_board and on_border map methods
Browse files Browse the repository at this point in the history
  • Loading branch information
CelticMinstrel committed Feb 21, 2021
1 parent 679529b commit 63fb96d
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/scripting/game_lua_kernel.cpp
Expand Up @@ -4136,6 +4136,9 @@ game_lua_kernel::game_lua_kernel(game_state & gs, play_controller & pc, reports
static luaL_Reg const map_callbacks[] {
// Map methods
{"terrain_mask", &intf_terrain_mask},
{"on_board", &intf_on_board},
{"on_border", &intf_on_border},
{"iter", &intf_terrainmap_iter},
// Shroud operations
{"place_shroud", &dispatch2<&game_lua_kernel::intf_shroud_op, true>},
{"remove_shroud", &dispatch2<&game_lua_kernel::intf_shroud_op, false>},
Expand Down
93 changes: 93 additions & 0 deletions src/scripting/lua_terrainmap.cpp
Expand Up @@ -345,6 +345,99 @@ static int impl_terrainmap_set(lua_State *L)
return luaL_argerror(L, 2, err_msg.c_str());
}

/*
The map iterator, when called with false as its parameter
is roughly equivalent to the following Lua function:
function map_iter()
local map, x, y = wesnoth.map.get(), 0, 1
return function()
if x == map.playable_width then
if y == map.playable_height then
return nil
else
x, y = 1, y + 1
end
else
x = x + 1
end
return x, y, map[{x, y}]
end
end
*/

template<bool with_border>
static int impl_terrainmap_iter(lua_State* L)
{
// Retrieve the upvalues stored with the function
gamemap_base& tm = luaW_checkterrainmap(L, lua_upvalueindex(1));
map_location prev_loc = luaW_checklocation(L, lua_upvalueindex(2));
int w = with_border ? tm.total_width() - 1 : tm.w();
int h = with_border ? tm.total_height() - 1 : tm.h();
int x, y;

// Given the previous location, determine the next one to be returned
if(prev_loc.wml_x() == w) {
if(prev_loc.wml_y() == h) {
lua_pushnil(L);
return 1;
} else {
x = with_border ? 0 : 1;
y = prev_loc.wml_y() + 1;
}
} else {
x = prev_loc.wml_x() + 1;
y = prev_loc.wml_y();
}

// Assign the upvalue representing the previous location
map_location next_loc(x, y, wml_loc{});
luaW_pushlocation(L, next_loc);
lua_replace(L, lua_upvalueindex(2));

// Return the new location and its terrain code
lua_pushinteger(L, x);
lua_pushinteger(L, y);
luaW_push_terrain(L, tm, next_loc);

return 3;
}

int intf_terrainmap_iter(lua_State* L)
{
gamemap_base& tm = luaW_checkterrainmap(L, 1);
bool with_border = lua_isboolean(L, 2) ? luaW_toboolean(L, 2) : false;
lua_settop(L, 1);
luaW_pushlocation(L, map_location(with_border ? -1 : 0, 1, wml_loc{}));

if(with_border) {
lua_pushcclosure(L, impl_terrainmap_iter<true>, 2);
} else {
lua_pushcclosure(L, impl_terrainmap_iter<false>, 2);
}
return 1;
}

int intf_on_board(lua_State* L)
{
gamemap_base& tm = luaW_checkterrainmap(L, 1);
map_location loc = luaW_checklocation(L, 2);
bool with_border = luaL_opt(L, luaW_toboolean, 3, false);

lua_pushboolean(L, with_border ? tm.on_board_with_border(loc) : tm.on_board(loc));
return 1;
}

int intf_on_border(lua_State* L)
{
gamemap_base& tm = luaW_checkterrainmap(L, 1);
map_location loc = luaW_checklocation(L, 2);

lua_pushboolean(L, tm.on_board_with_border(loc) && !tm.on_board(loc));
return 1;
}

static std::vector<gamemap::overlay_rule> read_rules_vector(lua_State *L, int index)
{
std::vector<gamemap::overlay_rule> rules;
Expand Down
3 changes: 3 additions & 0 deletions src/scripting/lua_terrainmap.hpp
Expand Up @@ -58,6 +58,9 @@ int intf_terrainmap_create(lua_State *L);
int intf_terrainmap_get(lua_State *L);

int intf_replace_if_failed(lua_State* L);
int intf_terrainmap_iter(lua_State* L);
int intf_on_board(lua_State* L);
int intf_on_border(lua_State* L);

namespace lua_terrainmap {
std::string register_metatables(lua_State *L);
Expand Down

0 comments on commit 63fb96d

Please sign in to comment.