The Battle for Wesnoth  1.19.18+dev
lua_terrainmap.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2018 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 
17 #include "log.hpp"
18 #include "map/location.hpp"
19 #include "map/map.hpp"
20 #include "scripting/lua_common.hpp"
21 #include "scripting/push_check.hpp"
22 #include "resources.hpp"
23 #include "game_board.hpp"
24 #include "play_controller.hpp"
25 
26 
27 static lg::log_domain log_scripting_lua("scripting/lua");
28 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
29 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
30 
31 static const char terrainmapKey[] = "terrain map";
32 static const char maplocationKey[] = "special locations";
33 static const char mapReplaceIfFailedKey[] = "replace_if_failed terrain code";
34 
36  enum {CODE = 1, MODE = 2};
37 }
38 
39 using std::string_view;
40 
41 //////// SPECIAL LOCATION ////////
42 
43 static int impl_slocs_get(lua_State* L)
44 {
46  string_view id = luaL_checkstring(L, 2);
47  auto res = m.special_location(std::string(id));
48  if(res.valid()) {
49  luaW_pushlocation(L, res);
50  } else {
51  //functions with variable return numbers have been causing problem in the past
52  lua_pushnil(L);
53  }
54  return 1;
55 }
56 
57 static int impl_slocs_set(lua_State* L)
58 {
60  string_view id = luaL_checkstring(L, 2);
62 
63  m.set_special_location(std::string(id), loc);
64  return 0;
65 }
66 
67 static int impl_slocs_next(lua_State *L)
68 {
69  gamemap_base& m = luaW_checkterrainmap(L, lua_upvalueindex(1));
70  const t_translation::starting_positions::left_map& left = m.special_locations().left;
71 
72  t_translation::starting_positions::left_const_iterator it;
73  if (lua_isnoneornil(L, 2)) {
74  it = left.begin();
75  }
76  else {
77  it = left.find(luaL_checkstring(L, 2));
78  if (it == left.end()) {
79  return 0;
80  }
81  ++it;
82  }
83  if (it == left.end()) {
84  return 0;
85  }
86  lua_pushstring(L, it->first.c_str());
87  luaW_pushlocation(L, it->second);
88  return 2;
89 }
90 
91 static int impl_slocs_iter(lua_State *L)
92 {
93  lua_settop(L, 1);
94  lua_pushvalue(L, 1);
95  lua_pushcclosure(L, &impl_slocs_next, 1);
96  lua_pushvalue(L, 1);
97  lua_pushnil(L);
98  return 3;
99 }
100 
101 //////// MAP ////////
102 
104 {
105  if(s.empty()) {
106  return;
107  }
108  //throws t_translation::error
109  //todo: make read_game_map take a string_view
111 }
112 
114  : gamemap_base(w, h, t)
115 {
116 
117 }
118 
119 // This can produce invalid combinations in rare case
120 // where an overlay doesn't have an independent terrain definition,
121 // or if you set an overlay with no base and merge mode other than OVERLAY.
123 {
124  switch(mode) {
126  new_t = t_translation::terrain_code(old_t.base, new_t.overlay);
127  break;
129  new_t = t_translation::terrain_code(new_t.base, old_t.overlay);
130  break;
132  new_t = t_translation::terrain_code(new_t.base, new_t.overlay);
133  break;
134  }
135 }
136 
138 {
140  terrain_code t = terrain;
141  simplemerge(old, t, mode);
142  tiles().get(loc.x + border_size(), loc.y + border_size()) = t;
143  return {t}; // We don't track village changes here
144 }
145 
146 struct lua_map_ref {
148  : owned_map(new mapgen_gamemap(w, h, ter))
149  , map_ptr(owned_map.get())
150  {}
151  lua_map_ref(string_view data)
153  , map_ptr(owned_map.get())
154  {}
156  : map_ptr(&ref)
157  {}
159  return *map_ptr;
160  }
161 private:
162  std::unique_ptr<gamemap_base> owned_map;
163  gamemap_base* map_ptr; // either owned or unowned
164 };
165 
166 bool luaW_isterrainmap(lua_State* L, int index)
167 {
168  return luaL_testudata(L, index, terrainmapKey) != nullptr || luaL_testudata(L, index, maplocationKey) != nullptr;
169 }
170 
171 
173 {
174  if(luaW_isterrainmap(L, index)) {
175  return &static_cast<lua_map_ref*>(lua_touserdata(L, index))->get_map();
176  }
177  return nullptr;
178 }
179 
181 {
182  if(luaW_isterrainmap(L, index)) {
183  return static_cast<lua_map_ref*>(lua_touserdata(L, index))->get_map();
184  }
185  luaW_type_error(L, index, "terrainmap");
186  throw "luaW_type_error didn't throw";
187 }
188 
189 /**
190  * Create a map.
191  * - Arg 1: string describing the map data.
192  * - or:
193  * - Arg 1: int, width
194  * - Arg 2: int, height
195  * - Arg 3: string, terrain
196 */
197 int intf_terrainmap_create(lua_State *L)
198 {
199  if(lua_isnumber(L, 1) && lua_isnumber(L, 2)) {
200  int w = lua_tointeger(L, 1);
201  int h = lua_tointeger(L, 2);
202  auto terrain = t_translation::read_terrain_code(luaL_checkstring(L, 3));
203  new(L) lua_map_ref(w, h, terrain);
204  } else {
205  string_view data_str = luaL_checkstring(L, 1);
206  new(L) lua_map_ref(data_str);
207  }
208  luaL_setmetatable(L, terrainmapKey);
209  return 1;
210 }
211 
212 int intf_terrainmap_get(lua_State* L)
213 {
214  new(L) lua_map_ref(const_cast<gamemap&>(resources::gameboard->map()));
215  luaL_setmetatable(L, terrainmapKey);
216  return 1;
217 }
218 
219 /**
220  * Destroys a map object before it is collected (__gc metamethod).
221  */
222 static int impl_terrainmap_collect(lua_State *L)
223 {
224  lua_map_ref* m = static_cast<lua_map_ref*>(lua_touserdata(L, 1));
225  m->lua_map_ref::~lua_map_ref();
226  return 0;
227 }
228 
229 static void luaW_push_terrain(lua_State* L, gamemap_base& map, map_location loc)
230 {
231  auto t = map.get_terrain(loc);
232  lua_pushstring(L, t_translation::write_terrain_code(t).c_str());
233 }
234 
235 static void impl_merge_terrain(lua_State* L, gamemap_base& map, map_location loc)
236 {
237  auto mode = terrain_type_data::BOTH;
238  bool replace_if_failed = false;
239  string_view t_str;
240  if(luaL_testudata(L, 3, mapReplaceIfFailedKey)) {
241  replace_if_failed = true;
242  lua_getiuservalue(L, 3, replace_if_failed_idx::CODE);
243  t_str = luaL_checkstring(L, -1);
244  lua_getiuservalue(L, 3, replace_if_failed_idx::MODE);
245  mode = terrain_type_data::merge_mode(luaL_checkinteger(L, -1));
246  } else {
247  t_str = luaL_checkstring(L, 3);
248  if(t_str.front() == '^') {
250  } else if(t_str.back() == '^') {
252  }
253  }
254 
255  auto ter = t_translation::read_terrain_code(t_str);
256 
257  if(auto gm = dynamic_cast<gamemap*>(&map)) {
259  bool result = resources::gameboard->change_terrain(loc, ter, mode, replace_if_failed);
260 
261  for(team& t : resources::gameboard->teams()) {
262  t.fix_villages(*gm);
263  }
264 
267  }
268  }
269  } else map.set_terrain(loc, ter, mode, replace_if_failed);
270 }
271 
272 /**
273  * Gets some data on a map (__index metamethod).
274  * - Arg 1: full userdata containing the map.
275  * - Arg 2: string containing the name of the property.
276  * - Ret 1: something containing the attribute.
277  */
278 static int impl_terrainmap_get(lua_State *L)
279 {
282  if(luaW_tolocation(L, 2, loc)) {
283  luaW_push_terrain(L, tm, loc);
284  return 1;
285  }
286 
287  char const *m = luaL_checkstring(L, 2);
288 
289  // Find the corresponding attribute.
290  return_int_attrib("width", tm.total_width());
291  return_int_attrib("height", tm.total_height());
292  return_int_attrib("playable_width", tm.w());
293  return_int_attrib("playable_height", tm.h());
294  return_int_attrib("border_size", tm.border_size());
295  return_string_attrib("data", tm.to_string());
296 
297  if(strcmp(m, "special_locations") == 0) {
298  new(L) lua_map_ref(tm);
299  luaL_setmetatable(L, maplocationKey);
300  return 1;
301  }
302  if(luaW_getglobal(L, "wesnoth", "map", m)) {
303  return 1;
304  }
305  return 0;
306 }
307 
308 /**
309  * Sets some data on a map (__newindex metamethod).
310  * - Arg 1: full userdata containing the map.
311  * - Arg 2: string containing the name of the property.
312  * - Arg 3: something containing the attribute.
313  */
314 static int impl_terrainmap_set(lua_State *L)
315 {
318  // The extra check that value (arg 3) isn't a number is because without it,
319  // map[4] = 5 would be interpreted as map[{4, 5}] = nil, due to the way
320  // luaW_tolocation modifies the stack if it finds a pair of numbers on it.
321  if(lua_type(L, 3) != LUA_TNUMBER && luaW_tolocation(L, 2, loc)) {
322  impl_merge_terrain(L, tm, loc);
323  return 0;
324  }
325  char const *m = luaL_checkstring(L, 2);
326  std::string err_msg = "unknown modifiable property of map: ";
327  err_msg += m;
328  return luaL_argerror(L, 2, err_msg.c_str());
329 }
330 
331 /*
332 The map iterator, when called with false as its parameter
333 is roughly equivalent to the following Lua function:
334 
335 function map_iter()
336  local map, x, y = wesnoth.current.map, 0, 1
337  return function()
338  if x == map.playable_width then
339  if y == map.playable_height then
340  return nil
341  else
342  x, y = 1, y + 1
343  end
344  else
345  x = x + 1
346  end
347  return x, y, map[{x, y}]
348  end
349 end
350 
351 */
352 
353 template<bool with_border>
354 static int impl_terrainmap_iter(lua_State* L)
355 {
356  // Retrieve the upvalues stored with the function
357  gamemap_base& tm = luaW_checkterrainmap(L, lua_upvalueindex(1));
358  map_location prev_loc = luaW_checklocation(L, lua_upvalueindex(2));
359  int w = with_border ? tm.total_width() - 1 : tm.w();
360  int h = with_border ? tm.total_height() - 1 : tm.h();
361  int x, y;
362 
363  // Given the previous location, determine the next one to be returned
364  if(prev_loc.wml_x() == w) {
365  if(prev_loc.wml_y() == h) {
366  lua_pushnil(L);
367  return 1;
368  } else {
369  x = with_border ? 0 : 1;
370  y = prev_loc.wml_y() + 1;
371  }
372  } else {
373  x = prev_loc.wml_x() + 1;
374  y = prev_loc.wml_y();
375  }
376 
377  // Assign the upvalue representing the previous location
378  map_location next_loc(x, y, wml_loc{});
379  luaW_pushlocation(L, next_loc);
380  lua_replace(L, lua_upvalueindex(2));
381 
382  // Return the new location and its terrain code
383  lua_pushinteger(L, x);
384  lua_pushinteger(L, y);
385  luaW_push_terrain(L, tm, next_loc);
386 
387  return 3;
388 }
389 
390 int intf_terrainmap_iter(lua_State* L)
391 {
392  luaW_checkterrainmap(L, 1);
393  bool with_border = lua_isboolean(L, 2) ? luaW_toboolean(L, 2) : false;
394  lua_settop(L, 1);
395  luaW_pushlocation(L, map_location(with_border ? -1 : 0, 1, wml_loc{}));
396 
397  if(with_border) {
398  lua_pushcclosure(L, impl_terrainmap_iter<true>, 2);
399  } else {
400  lua_pushcclosure(L, impl_terrainmap_iter<false>, 2);
401  }
402  return 1;
403 }
404 
405 int intf_on_board(lua_State* L)
406 {
409  bool with_border = luaL_opt(L, luaW_toboolean, 3, false);
410 
411  lua_pushboolean(L, with_border ? tm.on_board_with_border(loc) : tm.on_board(loc));
412  return 1;
413 }
414 
415 int intf_on_border(lua_State* L)
416 {
419 
420  lua_pushboolean(L, tm.on_board_with_border(loc) && !tm.on_board(loc));
421  return 1;
422 }
423 
424 static std::vector<gamemap::overlay_rule> read_rules_vector(lua_State *L, int index)
425 {
426  std::vector<gamemap::overlay_rule> rules;
427  for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i)
428  {
429  lua_rawgeti(L, index, i);
430  if(!lua_istable(L, -1)) {
431  luaL_argerror(L, index, "rules must be a table of tables");
432  }
433  rules.push_back(gamemap::overlay_rule());
434  auto& rule = rules.back();
435  if(luaW_tableget(L, -1, "old")) {
436  rule.old_ = t_translation::read_list(luaW_tostring(L, -1));
437  lua_pop(L, 1);
438  }
439 
440  if(luaW_tableget(L, -1, "new")) {
441  rule.new_ = t_translation::read_list(luaW_tostring(L, -1));
442  lua_pop(L, 1);
443  }
444 
445  if(luaW_tableget(L, -1, "layer")) {
446  auto str = luaW_tostring(L, -1);
447  rule.mode_ = str == "base" ? terrain_type_data::BASE : (str == "overlay" ? terrain_type_data::OVERLAY : terrain_type_data::BOTH);
448  lua_pop(L, 1);
449  }
450 
451  if(luaW_tableget(L, -1, "terrain")) {
453  if(!terrain.empty()) {
454  rule.terrain_ = terrain[0];
455  }
456  lua_pop(L, 1);
457  }
458 
459  if(luaW_tableget(L, -1, "use_old")) {
460  rule.use_old_ = luaW_toboolean(L, -1);
461  lua_pop(L, 1);
462  }
463 
464  if(luaW_tableget(L, -1, "replace_if_failed")) {
465  rule.replace_if_failed_ = luaW_toboolean(L, -1);
466  lua_pop(L, 1);
467  }
468 
469  lua_pop(L, 1);
470  }
471  return rules;
472 }
473 /**
474  * Replaces part of the map.
475  * - Arg 1: map location.
476  * - Arg 2: map data string.
477  * - Arg 3: table for optional named arguments
478  * - is_odd: boolean, if Arg2 has the odd map format (as if it was cut from a odd map location)
479  * - ignore_special_locations: boolean
480  * - rules: table of tables
481 */
482 int intf_terrain_mask(lua_State *L)
483 {
484  gamemap_base& map = luaW_checkterrainmap(L, 1);
486 
487  bool is_odd = false;
488  bool ignore_special_locations = false;
489  std::vector<gamemap::overlay_rule> rules;
490 
491  if(lua_istable(L, 4)) {
492  is_odd = luaW_table_get_def(L, 4, "is_odd", false);
493  ignore_special_locations = luaW_table_get_def(L, 4, "ignore_special_locations", false);
494 
495  if(luaW_tableget(L, 4, "rules")) {
496  if(!lua_istable(L, -1)) {
497  return luaL_argerror(L, 4, "rules must be a table");
498  }
499  rules = read_rules_vector(L, -1);
500  lua_pop(L, 1);
501  }
502  }
503 
504  if(lua_isstring(L, 3)) {
505  const std::string t_str = luaL_checkstring(L, 3);
506  std::unique_ptr<gamemap_base> mask;
507  if(dynamic_cast<gamemap*>(&map)) {
508  auto mask_ptr = new gamemap("");
509  mask_ptr->read(t_str, false);
510  mask.reset(mask_ptr);
511  } else {
512  mask.reset(new mapgen_gamemap(t_str));
513  }
514  map.overlay(*mask, loc, rules, is_odd, ignore_special_locations);
515  } else {
516  gamemap_base& mask = luaW_checkterrainmap(L, 3);
517  map.overlay(mask, loc, rules, is_odd, ignore_special_locations);
518  }
519 
521  if(auto gmap = dynamic_cast<gamemap*>(&map)) {
522  for(team& t : resources::gameboard->teams()) {
523  t.fix_villages(*gmap);
524  }
525  }
526  }
527 
530  }
531 
532  return 0;
533 }
534 
535 int intf_replace_if_failed(lua_State* L)
536 {
537  auto mode = terrain_type_data::BOTH;
538  if(!lua_isnoneornil(L, 2)) {
539  string_view mode_str = luaL_checkstring(L, 2);
540  if(mode_str == "base") {
542  } else if(mode_str == "overlay") {
544  } else if(mode_str != "both") {
545  return luaL_argerror(L, 2, "must be one of 'base', 'overlay', or 'both'");
546  }
547  }
548 
549  lua_newuserdatauv(L, 0, 2);
550  lua_pushinteger(L, int(mode));
551  lua_setiuservalue(L, -2, replace_if_failed_idx::MODE);
552  lua_pushvalue(L, 1);
553  lua_setiuservalue(L, -2, replace_if_failed_idx::CODE);
554  luaL_setmetatable(L, mapReplaceIfFailedKey);
555  return 1;
556 }
557 
558 static int impl_replace_if_failed_tostring(lua_State* L)
559 {
560  static const char* mode_strs[] = {"base", "overlay", "both"};
561  lua_getiuservalue(L, 1, replace_if_failed_idx::CODE);
562  string_view t_str = luaL_checkstring(L, -1);
563  lua_getiuservalue(L, 1, replace_if_failed_idx::MODE);
564  int mode = luaL_checkinteger(L, -1);
565  lua_pushfstring(L, "replace_if_failed('%s', '%s')", t_str.data(), mode_strs[mode]);
566  return 1;
567 }
568 
569 namespace lua_terrainmap {
570  std::string register_metatables(lua_State* L)
571  {
572  std::ostringstream cmd_out;
573 
574  cmd_out << "Adding terrain map metatable...\n";
575 
576  luaL_newmetatable(L, terrainmapKey);
577  lua_pushcfunction(L, impl_terrainmap_collect);
578  lua_setfield(L, -2, "__gc");
579  lua_pushcfunction(L, impl_terrainmap_get);
580  lua_setfield(L, -2, "__index");
581  lua_pushcfunction(L, impl_terrainmap_set);
582  lua_setfield(L, -2, "__newindex");
583  lua_pushstring(L, terrainmapKey);
584  lua_setfield(L, -2, "__metatable");
585 
586  luaL_newmetatable(L, mapReplaceIfFailedKey);
587  lua_pushcfunction(L, impl_replace_if_failed_tostring);
588  lua_setfield(L, -2, "__tostring");
589  lua_pushstring(L, mapReplaceIfFailedKey);
590  lua_setfield(L, -2, "__metatable");
591 
592  cmd_out << "Adding special locations metatable...\n";
593 
594  luaL_newmetatable(L, maplocationKey);
595  lua_pushcfunction(L, impl_slocs_get);
596  lua_setfield(L, -2, "__index");
597  lua_pushcfunction(L, impl_slocs_set);
598  lua_setfield(L, -2, "__newindex");
599  lua_pushcfunction(L, impl_slocs_iter);
600  lua_setfield(L, -2, "__pairs");
601  lua_pushstring(L, maplocationKey);
602  lua_setfield(L, -2, "__metatable");
603 
604  return cmd_out.str();
605  }
606 }
map_location loc
Definition: move.cpp:172
double t
Definition: astarsearch.cpp:63
bool change_terrain(const map_location &loc, const std::string &t, const std::string &mode, bool replace_if_failed)
Definition: game_board.cpp:317
void needs_rebuild(bool b)
Sets whether the screen (map visuals) needs to be rebuilt.
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:271
int w() const
Effective map width.
Definition: map.hpp:50
terrain_map & tiles()
Definition: map.hpp:158
void set_special_location(const std::string &id, const map_location &loc)
Definition: map.cpp:331
int h() const
Effective map height.
Definition: map.hpp:53
void overlay(const gamemap_base &m, map_location loc, const std::vector< overlay_rule > &rules=std::vector< overlay_rule >(), bool is_odd=false, bool ignore_special_locations=false)
Overlays another map onto this one at the given position.
Definition: map.cpp:183
map_location special_location(const std::string &id) const
Definition: map.cpp:280
int total_width() const
Real width of the map, including borders.
Definition: map.hpp:59
std::string to_string() const
Definition: map.cpp:448
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:358
int total_height() const
Real height of the map, including borders.
Definition: map.hpp:62
virtual set_terrain_result set_terrain(const map_location &loc, const terrain_code &terrain, const terrain_type_data::merge_mode mode=terrain_type_data::BOTH, bool replace_if_failed=false)=0
Clobbers over the terrain at location 'loc', with the given terrain.
int border_size() const
Size of the map border.
Definition: map.hpp:56
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:353
location_map & special_locations()
Definition: map.hpp:102
Encapsulates the map of the game.
Definition: map.hpp:173
gamemap_base::set_terrain_result set_terrain(const map_location &loc, const terrain_code &terrain, const terrain_type_data::merge_mode mode=terrain_type_data::BOTH, bool replace_if_failed=false) override
Clobbers over the terrain at location 'loc', with the given terrain.
mapgen_gamemap(std::string_view data)
game_display & get_display() override
Get a reference to a display member a derived class uses.
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:74
std::size_t i
Definition: function.cpp:1032
Standard logging facilities (interface).
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.
Definition: lua_common.cpp:825
bool luaW_toboolean(lua_State *L, int n)
int luaW_type_error(lua_State *L, int narg, const char *tname)
std::string_view luaW_tostring(lua_State *L, int index)
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.
Definition: lua_common.cpp:836
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:885
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil.
#define return_string_attrib(name, accessor)
Definition: lua_common.hpp:288
#define return_int_attrib(name, accessor)
Definition: lua_common.hpp:299
static int impl_slocs_get(lua_State *L)
static const char terrainmapKey[]
static void luaW_push_terrain(lua_State *L, gamemap_base &map, map_location loc)
static lg::log_domain log_scripting_lua("scripting/lua")
static const char maplocationKey[]
static std::vector< gamemap::overlay_rule > read_rules_vector(lua_State *L, int index)
int intf_terrainmap_create(lua_State *L)
Create a map.
static int impl_terrainmap_get(lua_State *L)
Gets some data on a map (__index metamethod).
int intf_terrain_mask(lua_State *L)
Replaces part of the map.
static int impl_replace_if_failed_tostring(lua_State *L)
static void impl_merge_terrain(lua_State *L, gamemap_base &map, map_location loc)
static int impl_slocs_iter(lua_State *L)
int intf_on_border(lua_State *L)
static int impl_terrainmap_set(lua_State *L)
Sets some data on a map (__newindex metamethod).
int intf_on_board(lua_State *L)
int intf_terrainmap_iter(lua_State *L)
static int impl_slocs_set(lua_State *L)
static int impl_terrainmap_iter(lua_State *L)
int intf_terrainmap_get(lua_State *L)
static int impl_terrainmap_collect(lua_State *L)
Destroys a map object before it is collected (__gc metamethod).
static int impl_slocs_next(lua_State *L)
static void simplemerge(t_translation::terrain_code old_t, t_translation::terrain_code &new_t, const terrain_type_data::merge_mode mode)
gamemap_base & luaW_checkterrainmap(lua_State *L, int index)
static const char mapReplaceIfFailedKey[]
bool luaW_isterrainmap(lua_State *L, int index)
int intf_replace_if_failed(lua_State *L)
gamemap_base * luaW_toterrainmap(lua_State *L, int index)
constexpr bool is_odd(T num)
Definition: math.hpp:34
CURSOR_TYPE get()
Definition: cursor.cpp:218
std::string register_metatables(lua_State *L)
game_board * gameboard
Definition: resources.cpp:20
play_controller * controller
Definition: resources.cpp:21
terrain_code read_terrain_code(std::string_view str, const ter_layer filler)
Reads a single terrain from a string.
ter_map read_game_map(std::string_view str, starting_positions &starting_positions, coordinate border_offset)
Reads a gamemap string into a 2D vector.
std::vector< terrain_code > ter_list
Definition: translation.hpp:77
ter_list read_list(std::string_view str, const ter_layer filler)
Reads a list of terrains from a string, when reading the.
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
int w
Definition: pathfind.cpp:188
std::string_view data
Definition: picture.cpp:188
std::decay_t< T > luaW_table_get_def(lua_State *L, int index, std::string_view k, const T &def)
returns t[k] where k is the table at index index and k is k or def if it is not convertible to the co...
Definition: push_check.hpp:435
std::unique_ptr< gamemap_base > owned_map
lua_map_ref(int w, int h, const t_translation::terrain_code &ter)
gamemap_base & get_map()
lua_map_ref(string_view data)
gamemap_base * map_ptr
lua_map_ref(gamemap_base &ref)
Encapsulates the map of the game.
Definition: location.hpp:46
int wml_y() const
Definition: location.hpp:187
int wml_x() const
Definition: location.hpp:186
terrain_code & get(int x, int y)
Definition: translation.hpp:83
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
static map_location::direction s
#define h