Implement a map iterator
This commit is contained in:
parent
2054cf4acb
commit
9cea078f9b
3 changed files with 76 additions and 0 deletions
|
@ -4138,6 +4138,7 @@ game_lua_kernel::game_lua_kernel(game_state & gs, play_controller & pc, reports
|
|||
{"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>},
|
||||
|
|
|
@ -345,6 +345,80 @@ 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)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -58,6 +58,7 @@ 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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue