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