The Battle for Wesnoth  1.19.1+dev
lua_terrainmap.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2018 - 2024
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);
61  map_location loc = luaW_checklocation(L, 3);
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 
137 void mapgen_gamemap::set_terrain(const map_location& loc, const terrain_code & terrain, const terrain_type_data::merge_mode mode, bool)
138 {
139  terrain_code old = get_terrain(loc);
140  terrain_code t = terrain;
141  simplemerge(old, t, mode);
142  tiles().get(loc.x + border_size(), loc.y + border_size()) = t;
143 }
144 
145 struct lua_map_ref {
147  : owned_map(new mapgen_gamemap(w, h, ter))
148  , map_ptr(owned_map.get())
149  {}
150  lua_map_ref(string_view data)
152  , map_ptr(owned_map.get())
153  {}
155  : map_ptr(&ref)
156  {}
158  return *map_ptr;
159  }
160 private:
161  std::unique_ptr<gamemap_base> owned_map;
162  gamemap_base* map_ptr; // either owned or unowned
163 };
164 
165 bool luaW_isterrainmap(lua_State* L, int index)
166 {
167  return luaL_testudata(L, index, terrainmapKey) != nullptr || luaL_testudata(L, index, maplocationKey) != nullptr;
168 }
169 
170 
172 {
173  if(luaW_isterrainmap(L, index)) {
174  return &static_cast<lua_map_ref*>(lua_touserdata(L, index))->get_map();
175  }
176  return nullptr;
177 }
178 
180 {
181  if(luaW_isterrainmap(L, index)) {
182  return static_cast<lua_map_ref*>(lua_touserdata(L, index))->get_map();
183  }
184  luaW_type_error(L, index, "terrainmap");
185  throw "luaW_type_error didn't throw";
186 }
187 
188 /**
189  * Create a map.
190  * - Arg 1: string describing the map data.
191  * - or:
192  * - Arg 1: int, width
193  * - Arg 2: int, height
194  * - Arg 3: string, terrain
195 */
196 int intf_terrainmap_create(lua_State *L)
197 {
198  if(lua_isnumber(L, 1) && lua_isnumber(L, 2)) {
199  int w = lua_tointeger(L, 1);
200  int h = lua_tointeger(L, 2);
201  auto terrain = t_translation::read_terrain_code(luaL_checkstring(L, 3));
202  new(L) lua_map_ref(w, h, terrain);
203  } else {
204  string_view data_str = luaL_checkstring(L, 1);
205  new(L) lua_map_ref(data_str);
206  }
207  luaL_setmetatable(L, terrainmapKey);
208  return 1;
209 }
210 
211 int intf_terrainmap_get(lua_State* L)
212 {
213  new(L) lua_map_ref(const_cast<gamemap&>(resources::gameboard->map()));
214  luaL_setmetatable(L, terrainmapKey);
215  return 1;
216 }
217 
218 /**
219  * Destroys a map object before it is collected (__gc metamethod).
220  */
221 static int impl_terrainmap_collect(lua_State *L)
222 {
223  lua_map_ref* m = static_cast<lua_map_ref*>(lua_touserdata(L, 1));
224  m->lua_map_ref::~lua_map_ref();
225  return 0;
226 }
227 
228 static void luaW_push_terrain(lua_State* L, gamemap_base& map, map_location loc)
229 {
230  auto t = map.get_terrain(loc);
231  lua_pushstring(L, t_translation::write_terrain_code(t).c_str());
232 }
233 
234 static void impl_merge_terrain(lua_State* L, gamemap_base& map, map_location loc)
235 {
236  auto mode = terrain_type_data::BOTH;
237  bool replace_if_failed = false;
238  string_view t_str;
239  if(luaL_testudata(L, 3, mapReplaceIfFailedKey)) {
240  replace_if_failed = true;
241  lua_getiuservalue(L, 3, replace_if_failed_idx::CODE);
242  t_str = luaL_checkstring(L, -1);
243  lua_getiuservalue(L, 3, replace_if_failed_idx::MODE);
244  mode = terrain_type_data::merge_mode(luaL_checkinteger(L, -1));
245  } else {
246  t_str = luaL_checkstring(L, 3);
247  if(t_str.front() == '^') {
249  } else if(t_str.back() == '^') {
251  }
252  }
253 
254  auto ter = t_translation::read_terrain_code(t_str);
255 
256  if(auto gm = dynamic_cast<gamemap*>(&map)) {
258  bool result = resources::gameboard->change_terrain(loc, ter, mode, replace_if_failed);
259 
260  for(team& t : resources::gameboard->teams()) {
261  t.fix_villages(*gm);
262  }
263 
266  }
267  }
268  } else map.set_terrain(loc, ter, mode, replace_if_failed);
269 }
270 
271 /**
272  * Gets some data on a map (__index metamethod).
273  * - Arg 1: full userdata containing the map.
274  * - Arg 2: string containing the name of the property.
275  * - Ret 1: something containing the attribute.
276  */
277 static int impl_terrainmap_get(lua_State *L)
278 {
280  map_location loc;
281  if(luaW_tolocation(L, 2, loc)) {
282  luaW_push_terrain(L, tm, loc);
283  return 1;
284  }
285 
286  char const *m = luaL_checkstring(L, 2);
287 
288  // Find the corresponding attribute.
289  return_int_attrib("width", tm.total_width());
290  return_int_attrib("height", tm.total_height());
291  return_int_attrib("playable_width", tm.w());
292  return_int_attrib("playable_height", tm.h());
293  return_int_attrib("border_size", tm.border_size());
294  return_string_attrib("data", tm.to_string());
295 
296  if(strcmp(m, "special_locations") == 0) {
297  new(L) lua_map_ref(tm);
298  luaL_setmetatable(L, maplocationKey);
299  return 1;
300  }
301  if(luaW_getglobal(L, "wesnoth", "map", m)) {
302  return 1;
303  }
304  return 0;
305 }
306 
307 /**
308  * Sets some data on a map (__newindex metamethod).
309  * - Arg 1: full userdata containing the map.
310  * - Arg 2: string containing the name of the property.
311  * - Arg 3: something containing the attribute.
312  */
313 static int impl_terrainmap_set(lua_State *L)
314 {
316  map_location loc;
317  // The extra check that value (arg 3) isn't a number is because without it,
318  // map[4] = 5 would be interpreted as map[{4, 5}] = nil, due to the way
319  // luaW_tolocation modifies the stack if it finds a pair of numbers on it.
320  if(lua_type(L, 3) != LUA_TNUMBER && luaW_tolocation(L, 2, loc)) {
321  impl_merge_terrain(L, tm, loc);
322  return 0;
323  }
324  char const *m = luaL_checkstring(L, 2);
325  std::string err_msg = "unknown modifiable property of map: ";
326  err_msg += m;
327  return luaL_argerror(L, 2, err_msg.c_str());
328 }
329 
330 /*
331 The map iterator, when called with false as its parameter
332 is roughly equivalent to the following Lua function:
333 
334 function map_iter()
335  local map, x, y = wesnoth.current.map, 0, 1
336  return function()
337  if x == map.playable_width then
338  if y == map.playable_height then
339  return nil
340  else
341  x, y = 1, y + 1
342  end
343  else
344  x = x + 1
345  end
346  return x, y, map[{x, y}]
347  end
348 end
349 
350 */
351 
352 template<bool with_border>
353 static int impl_terrainmap_iter(lua_State* L)
354 {
355  // Retrieve the upvalues stored with the function
356  gamemap_base& tm = luaW_checkterrainmap(L, lua_upvalueindex(1));
357  map_location prev_loc = luaW_checklocation(L, lua_upvalueindex(2));
358  int w = with_border ? tm.total_width() - 1 : tm.w();
359  int h = with_border ? tm.total_height() - 1 : tm.h();
360  int x, y;
361 
362  // Given the previous location, determine the next one to be returned
363  if(prev_loc.wml_x() == w) {
364  if(prev_loc.wml_y() == h) {
365  lua_pushnil(L);
366  return 1;
367  } else {
368  x = with_border ? 0 : 1;
369  y = prev_loc.wml_y() + 1;
370  }
371  } else {
372  x = prev_loc.wml_x() + 1;
373  y = prev_loc.wml_y();
374  }
375 
376  // Assign the upvalue representing the previous location
377  map_location next_loc(x, y, wml_loc{});
378  luaW_pushlocation(L, next_loc);
379  lua_replace(L, lua_upvalueindex(2));
380 
381  // Return the new location and its terrain code
382  lua_pushinteger(L, x);
383  lua_pushinteger(L, y);
384  luaW_push_terrain(L, tm, next_loc);
385 
386  return 3;
387 }
388 
389 int intf_terrainmap_iter(lua_State* L)
390 {
391  luaW_checkterrainmap(L, 1);
392  bool with_border = lua_isboolean(L, 2) ? luaW_toboolean(L, 2) : false;
393  lua_settop(L, 1);
394  luaW_pushlocation(L, map_location(with_border ? -1 : 0, 1, wml_loc{}));
395 
396  if(with_border) {
397  lua_pushcclosure(L, impl_terrainmap_iter<true>, 2);
398  } else {
399  lua_pushcclosure(L, impl_terrainmap_iter<false>, 2);
400  }
401  return 1;
402 }
403 
404 int intf_on_board(lua_State* L)
405 {
407  map_location loc = luaW_checklocation(L, 2);
408  bool with_border = luaL_opt(L, luaW_toboolean, 3, false);
409 
410  lua_pushboolean(L, with_border ? tm.on_board_with_border(loc) : tm.on_board(loc));
411  return 1;
412 }
413 
414 int intf_on_border(lua_State* L)
415 {
417  map_location loc = luaW_checklocation(L, 2);
418 
419  lua_pushboolean(L, tm.on_board_with_border(loc) && !tm.on_board(loc));
420  return 1;
421 }
422 
423 static std::vector<gamemap::overlay_rule> read_rules_vector(lua_State *L, int index)
424 {
425  std::vector<gamemap::overlay_rule> rules;
426  for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i)
427  {
428  lua_rawgeti(L, index, i);
429  if(!lua_istable(L, -1)) {
430  luaL_argerror(L, index, "rules must be a table of tables");
431  }
432  rules.push_back(gamemap::overlay_rule());
433  auto& rule = rules.back();
434  if(luaW_tableget(L, -1, "old")) {
435  rule.old_ = t_translation::read_list(luaW_tostring(L, -1));
436  lua_pop(L, 1);
437  }
438 
439  if(luaW_tableget(L, -1, "new")) {
440  rule.new_ = t_translation::read_list(luaW_tostring(L, -1));
441  lua_pop(L, 1);
442  }
443 
444  if(luaW_tableget(L, -1, "layer")) {
445  auto str = luaW_tostring(L, -1);
446  rule.mode_ = str == "base" ? terrain_type_data::BASE : (str == "overlay" ? terrain_type_data::OVERLAY : terrain_type_data::BOTH);
447  lua_pop(L, 1);
448  }
449 
450  if(luaW_tableget(L, -1, "terrain")) {
452  if(!terrain.empty()) {
453  rule.terrain_ = terrain[0];
454  }
455  lua_pop(L, 1);
456  }
457 
458  if(luaW_tableget(L, -1, "use_old")) {
459  rule.use_old_ = luaW_toboolean(L, -1);
460  lua_pop(L, 1);
461  }
462 
463  if(luaW_tableget(L, -1, "replace_if_failed")) {
464  rule.replace_if_failed_ = luaW_toboolean(L, -1);
465  lua_pop(L, 1);
466  }
467 
468  lua_pop(L, 1);
469  }
470  return rules;
471 }
472 /**
473  * Replaces part of the map.
474  * - Arg 1: map location.
475  * - Arg 2: map data string.
476  * - Arg 3: table for optional named arguments
477  * - is_odd: boolean, if Arg2 has the odd map format (as if it was cut from a odd map location)
478  * - ignore_special_locations: boolean
479  * - rules: table of tables
480 */
481 int intf_terrain_mask(lua_State *L)
482 {
483  gamemap_base& map = luaW_checkterrainmap(L, 1);
484  map_location loc = luaW_checklocation(L, 2);
485 
486  bool is_odd = false;
487  bool ignore_special_locations = false;
488  std::vector<gamemap::overlay_rule> rules;
489 
490  if(lua_istable(L, 4)) {
491  is_odd = luaW_table_get_def(L, 4, "is_odd", false);
492  ignore_special_locations = luaW_table_get_def(L, 4, "ignore_special_locations", false);
493 
494  if(luaW_tableget(L, 4, "rules")) {
495  if(!lua_istable(L, -1)) {
496  return luaL_argerror(L, 4, "rules must be a table");
497  }
498  rules = read_rules_vector(L, -1);
499  lua_pop(L, 1);
500  }
501  }
502 
503  if(lua_isstring(L, 3)) {
504  const std::string t_str = luaL_checkstring(L, 3);
505  std::unique_ptr<gamemap_base> mask;
506  if(dynamic_cast<gamemap*>(&map)) {
507  auto mask_ptr = new gamemap("");
508  mask_ptr->read(t_str, false);
509  mask.reset(mask_ptr);
510  } else {
511  mask.reset(new mapgen_gamemap(t_str));
512  }
513  map.overlay(*mask, loc, rules, is_odd, ignore_special_locations);
514  } else {
515  gamemap_base& mask = luaW_checkterrainmap(L, 3);
516  map.overlay(mask, loc, rules, is_odd, ignore_special_locations);
517  }
518 
520  if(auto gmap = dynamic_cast<gamemap*>(&map)) {
521  for(team& t : resources::gameboard->teams()) {
522  t.fix_villages(*gmap);
523  }
524  }
525  }
526 
529  }
530 
531  return 0;
532 }
533 
534 int intf_replace_if_failed(lua_State* L)
535 {
536  auto mode = terrain_type_data::BOTH;
537  if(!lua_isnoneornil(L, 2)) {
538  string_view mode_str = luaL_checkstring(L, 2);
539  if(mode_str == "base") {
541  } else if(mode_str == "overlay") {
543  } else if(mode_str != "both") {
544  return luaL_argerror(L, 2, "must be one of 'base', 'overlay', or 'both'");
545  }
546  }
547 
548  lua_newuserdatauv(L, 0, 2);
549  lua_pushinteger(L, int(mode));
550  lua_setiuservalue(L, -2, replace_if_failed_idx::MODE);
551  lua_pushvalue(L, 1);
552  lua_setiuservalue(L, -2, replace_if_failed_idx::CODE);
553  luaL_setmetatable(L, mapReplaceIfFailedKey);
554  return 1;
555 }
556 
557 static int impl_replace_if_failed_tostring(lua_State* L)
558 {
559  static const char* mode_strs[] = {"base", "overlay", "both"};
560  lua_getiuservalue(L, 1, replace_if_failed_idx::CODE);
561  string_view t_str = luaL_checkstring(L, -1);
562  lua_getiuservalue(L, 1, replace_if_failed_idx::MODE);
563  int mode = luaL_checkinteger(L, -1);
564  lua_pushfstring(L, "replace_if_failed('%s', '%s')", t_str.data(), mode_strs[mode]);
565  return 1;
566 }
567 
568 namespace lua_terrainmap {
569  std::string register_metatables(lua_State* L)
570  {
571  std::ostringstream cmd_out;
572 
573  cmd_out << "Adding terrain map metatable...\n";
574 
575  luaL_newmetatable(L, terrainmapKey);
576  lua_pushcfunction(L, impl_terrainmap_collect);
577  lua_setfield(L, -2, "__gc");
578  lua_pushcfunction(L, impl_terrainmap_get);
579  lua_setfield(L, -2, "__index");
580  lua_pushcfunction(L, impl_terrainmap_set);
581  lua_setfield(L, -2, "__newindex");
582  lua_pushstring(L, terrainmapKey);
583  lua_setfield(L, -2, "__metatable");
584 
585  luaL_newmetatable(L, mapReplaceIfFailedKey);
586  lua_pushcfunction(L, impl_replace_if_failed_tostring);
587  lua_setfield(L, -2, "__tostring");
588  lua_pushstring(L, mapReplaceIfFailedKey);
589  lua_setfield(L, -2, "__metatable");
590 
591  cmd_out << "Adding special locations metatable...\n";
592 
593  luaL_newmetatable(L, maplocationKey);
594  lua_pushcfunction(L, impl_slocs_get);
595  lua_setfield(L, -2, "__index");
596  lua_pushcfunction(L, impl_slocs_set);
597  lua_setfield(L, -2, "__newindex");
598  lua_pushcfunction(L, impl_slocs_iter);
599  lua_setfield(L, -2, "__pairs");
600  lua_pushstring(L, maplocationKey);
601  lua_setfield(L, -2, "__metatable");
602 
603  return cmd_out.str();
604  }
605 }
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:327
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:301
int w() const
Effective map width.
Definition: map.hpp:50
terrain_map & tiles()
Definition: map.hpp:157
void set_special_location(const std::string &id, const map_location &loc)
Definition: map.cpp:362
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:214
map_location special_location(const std::string &id) const
Definition: map.cpp:311
virtual void 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 total_width() const
Real width of the map, including borders.
Definition: map.hpp:59
std::string to_string() const
Definition: map.cpp:469
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:389
int total_height() const
Real height of the map, including borders.
Definition: map.hpp:62
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:384
location_map & special_locations()
Definition: map.hpp:90
Encapsulates the map of the game.
Definition: map.hpp:172
void 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:968
int w
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:727
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:985
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:738
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:787
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.
Definition: lua_common.cpp:966
#define return_string_attrib(name, accessor)
Definition: lua_common.hpp:256
#define return_int_attrib(name, accessor)
Definition: lua_common.hpp:267
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:36
CURSOR_TYPE get()
Definition: cursor.cpp:216
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(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
std::string_view data
Definition: picture.cpp:194
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:383
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:38
int wml_y() const
Definition: location.hpp:154
int wml_x() const
Definition: location.hpp:153
terrain_code & get(int x, int y)
Definition: translation.hpp:89
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