The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
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"
22#include "resources.hpp"
23#include "game_board.hpp"
24#include "play_controller.hpp"
25
26
27static 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
31static const char terrainmapKey[] = "terrain map";
32static const char maplocationKey[] = "special locations";
33static const char mapReplaceIfFailedKey[] = "replace_if_failed terrain code";
34
36 enum {CODE = 1, MODE = 2};
37}
38
39using std::string_view;
40
41//////// SPECIAL LOCATION ////////
42
43static 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
57static 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
67static 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
91static 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
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 }
161private:
162 std::unique_ptr<gamemap_base> owned_map;
163 gamemap_base* map_ptr; // either owned or unowned
164};
165
166bool 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
172gamemap_base* luaW_toterrainmap(lua_State *L, int index)
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
180gamemap_base& luaW_checkterrainmap(lua_State *L, int index)
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*/
197int 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
212int 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 */
222static 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
229static 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
235static 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 */
278static 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 */
314static 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/*
332The map iterator, when called with false as its parameter
333is roughly equivalent to the following Lua function:
334
335function 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
349end
350
351*/
352
353template<bool with_border>
354static 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
390int intf_terrainmap_iter(lua_State* L)
391{
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
405int 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
415int 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
424static 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*/
482int intf_terrain_mask(lua_State *L)
483{
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 {
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
535int 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
558static 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
569namespace 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
virtual const std::vector< team > & teams() const override
bool change_terrain(const map_location &loc, const std::string &t, const std::string &mode, bool replace_if_failed)
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:265
int w() const
Effective map width.
Definition map.hpp:50
location_map & special_locations()
Definition map.hpp:105
void set_special_location(const std::string &id, const map_location &loc)
Definition map.cpp:325
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:177
map_location special_location(const std::string &id) const
Definition map.cpp:274
int total_width() const
Real width of the map, including borders.
Definition map.hpp:59
std::string to_string() const
Definition map.cpp:442
bool on_board_with_border(const map_location &loc) const
Definition map.cpp:352
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.
terrain_map & tiles()
Definition map.hpp:161
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:347
Encapsulates the map of the game.
Definition map.hpp:176
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
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.
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.
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
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)
#define return_int_attrib(name, accessor)
static int impl_slocs_get(lua_State *L)
static std::vector< gamemap::overlay_rule > read_rules_vector(lua_State *L, int index)
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[]
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).
gamemap_base & luaW_checkterrainmap(lua_State *L, int index)
int intf_on_board(lua_State *L)
int intf_terrainmap_iter(lua_State *L)
static int impl_slocs_set(lua_State *L)
gamemap_base * luaW_toterrainmap(lua_State *L, int index)
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)
static const char mapReplaceIfFailedKey[]
bool luaW_isterrainmap(lua_State *L, int index)
int intf_replace_if_failed(lua_State *L)
constexpr bool is_odd(T num)
Definition math.hpp:34
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
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.
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...
std::unique_ptr< gamemap_base > owned_map
lua_map_ref(int w, int h, const t_translation::terrain_code &ter)
lua_map_ref(string_view data)
gamemap_base * map_ptr
lua_map_ref(gamemap_base &ref)
gamemap_base & get_map()
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)
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
static map_location::direction s
#define i
#define h