From 63fb96d88c886974dc862b1beaad414d4f232116 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Wed, 17 Feb 2021 13:31:53 -0500 Subject: [PATCH] Add on_board and on_border map methods --- src/scripting/game_lua_kernel.cpp | 3 + src/scripting/lua_terrainmap.cpp | 93 +++++++++++++++++++++++++++++++ src/scripting/lua_terrainmap.hpp | 3 + 3 files changed, 99 insertions(+) diff --git a/src/scripting/game_lua_kernel.cpp b/src/scripting/game_lua_kernel.cpp index 7b9d9873a6b1b..6808be2c8e95e 100644 --- a/src/scripting/game_lua_kernel.cpp +++ b/src/scripting/game_lua_kernel.cpp @@ -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>}, diff --git a/src/scripting/lua_terrainmap.cpp b/src/scripting/lua_terrainmap.cpp index 6c0c10f7b5966..6d3cda3cf8d76 100644 --- a/src/scripting/lua_terrainmap.cpp +++ b/src/scripting/lua_terrainmap.cpp @@ -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 +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, 2); + } else { + lua_pushcclosure(L, impl_terrainmap_iter, 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 read_rules_vector(lua_State *L, int index) { std::vector rules; diff --git a/src/scripting/lua_terrainmap.hpp b/src/scripting/lua_terrainmap.hpp index fe2093bd2f9bb..7e41044487ea9 100644 --- a/src/scripting/lua_terrainmap.hpp +++ b/src/scripting/lua_terrainmap.hpp @@ -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);