20 #define GETTEXT_DOMAIN "wesnoth-lib" 31 #define ERR_G LOG_STREAM(err, lg::general()) 32 #define WRN_G LOG_STREAM(warn, lg::general()) 160 base(string_to_layer_(b)),
overlay(o)
164 base(string_to_layer_(b)),
overlay(string_to_layer_(o))
183 mask.resize(terrain.size());
186 for(std::size_t
i = 0;
i < terrain.size();
i++) {
199 mask.resize(terrain.size());
202 for(std::size_t
i = 0;
i < terrain.size();
i++) {
227 std::size_t offset = 0;
228 while(offset < str.length()) {
231 const std::string separators =
",";
232 const size_t pos_separator = str.find_first_of(separators, offset);
233 std::string_view terrain = str.substr(offset, pos_separator - offset);
239 result.push_back(tile);
242 if(pos_separator == std::string_view::npos) {
243 offset = str.length();
245 offset = pos_separator + 1;
254 std::stringstream result;
256 ter_list::const_iterator itor = list.begin();
257 for( ; itor != list.end(); ++itor) {
258 if(itor == list.begin()) {
268 static std::pair<int, int>
get_map_size(
const char* begin,
const char* end)
272 for (
const char* it = begin; it != end;) {
277 for (;it != end && (*it !=
'\n' && *it !=
'\r'); ++it) {
282 w = std::max(w, cur_w);
284 while (it != end && (*it ==
'\n' || *it ==
'\r')) {
294 std::size_t offset = 0;
295 int x = 0, y = 0, width = 0;
299 str.remove_prefix(1);
303 if(str.length() <= 1) {
307 auto map_size =
get_map_size(&str[0], &str[0] + str.size());
308 ter_map result(map_size.first, map_size.second);
310 while(offset < str.length()) {
313 const std::string separators =
",\n\r";
314 const std::size_t pos_separator = str.find_first_of(separators, offset);
315 std::string_view terrain = str.substr(offset, pos_separator - offset);
318 std::vector<std::string>
sp;
323 for(
const auto& starting_position : sp) {
324 if (starting_positions.left.find(starting_position) != starting_positions.left.end()) {
325 WRN_G <<
"Starting position " << starting_position <<
" is redefined." << std::endl;
327 starting_positions.insert(starting_positions::value_type(starting_position,
coordinate(x - border_offset.
x, y - border_offset.
y)));
330 if(result.w <= x || result.h <= y) {
331 throw error(
"Map not a rectangle.");
335 result.get(x, y) = tile;
338 if(pos_separator == std::string::npos ||
utils::isnewline(str[pos_separator])) {
344 if((x + 1) != width ) {
345 ERR_G <<
"Map not a rectangle error occurred at line offset " << y <<
" position offset " << x << std::endl;
346 throw error(
"Map not a rectangle.");
350 throw error(
"Map height limit exceeded.");
359 if(pos_separator == std::string::npos) {
360 offset = str.length();
364 offset = pos_separator + 1;
373 offset = pos_separator + 1;
376 throw error(
"Map width limit exceeded.");
382 if(x != 0 && (x + 1) != width) {
383 ERR_G <<
"Map not a rectangle error occurred at the end" << std::endl;
384 throw error(
"Map not a rectangle.");
392 std::stringstream str;
394 for(
int y = 0; y < map.
h; ++y) {
395 for(
int x = 0; x < map.
w; ++x) {
401 std::vector<std::string>
sp;
403 for(
const auto& pair : starting_positions.right.equal_range(
coordinate(x - border_offset.
x, y - border_offset.
y))) {
404 sp.push_back(pair.second);
437 std::cerr << std::hex <<
"src = " << src.
base <<
"^" << src.
overlay <<
"\t" 438 << src_mask.base <<
"^" << src_mask.overlay <<
"\t" 439 << masked_src.base <<
"^" << masked_src.overlay <<
"\t" 440 << src_has_wildcard <<
"\n";
444 ter_list::const_iterator itor = dest.begin();
447 for(; itor != dest.end(); ++itor) {
470 std::cerr << std::hex <<
"dest= " 471 << itor->base <<
"^" << itor->overlay <<
"\t" 472 << dest_mask.
base <<
"^" << dest_mask.
overlay <<
"\t" 473 << masked_dest.
base <<
"^" << masked_dest.
overlay <<
"\t" 474 << dest_has_wildcard <<
"\n";
476 if(dest_has_wildcard &&
522 ter_list::const_iterator end = dest.
terrain.end();
523 for(ter_list::const_iterator terrain_itor = dest.
terrain.begin();
525 ++
i, ++terrain_itor) {
528 if(*terrain_itor == STAR) {
533 if(*terrain_itor == NOT) {
539 if(*terrain_itor == src) {
589 ter_list::const_iterator itor = list.begin();
590 for(; itor != list.end(); ++itor) {
602 std::size_t offset = 0;
608 if((offset + 1) >= str.length()) {
612 auto map_size =
get_map_size(&str[offset], str.c_str() + str.size());
616 while(offset < str.length()) {
619 const std::string separators =
",\n\r";
620 const std::size_t pos_separator = str.find_first_of(separators, offset);
621 std::string terrain =
"";
624 if(pos_separator != offset) {
625 terrain = str.substr(offset, pos_separator - offset);
632 if (result.h <= x || result.w <= y) {
633 throw error(
"Map not a rectangle.");
637 result.get(y, x) = tile;
640 if(pos_separator == std::string::npos) {
646 offset = str.length();
652 offset = pos_separator + 1;
660 offset = pos_separator + 1;
679 if((terrain & 0xFF000000) == 0x2A000000)
return 0x00000000;
680 if((terrain & 0x00FF0000) == 0x002A0000)
return 0xFF000000;
681 if((terrain & 0x0000FF00) == 0x00002A00)
return 0xFFFF0000;
682 if((terrain & 0x000000FF) == 0x0000002A)
return 0xFFFFFF00;
712 VALIDATE(str.size() <= 4,
_(
"A terrain with a string with more " 713 "than 4 characters has been found, the affected terrain is:") + std::string(str));
720 for(std::size_t
i = 0;
i < 4; ++
i) {
721 const unsigned char c = (
i < str.size()) ? str[
i] : 0;
735 std::vector<std::string>
dummy;
751 std::size_t offset = str.find(
' ', 0);
752 while(offset != std::string::npos) {
753 start_positions.push_back(std::string(str.substr(0, offset)));
754 str.remove_prefix(offset + 1);
755 offset = str.find(
' ', 0);
758 offset = str.find(
'^', 0);
759 if(offset != std::string::npos) {
777 std::string result =
"";
780 for (
const std::string& str : start_positions) {
781 result = str +
" " + result;
789 unsigned char tcode[9] {0};
791 tcode[0] = ((terrain.
base & 0xFF000000) >> 24);
792 tcode[1] = ((terrain.
base & 0x00FF0000) >> 16);
793 tcode[2] = ((terrain.
base & 0x0000FF00) >> 8);
794 tcode[3] = (terrain.
base & 0x000000FF);
798 tcode[5] = ((terrain.
overlay & 0xFF000000) >> 24);
799 tcode[6] = ((terrain.
overlay & 0x00FF0000) >> 16);
800 tcode[7] = ((terrain.
overlay & 0x0000FF00) >> 8);
801 tcode[8] = (terrain.
overlay & 0x000000FF);
808 for(
int i = 0;
i < 9; ++
i) {
809 if(tcode[
i] != 0 && tcode[
i] != 0xFF) {
812 if(
i == 4 && tcode[
i] == 0) {
824 const std::string& whitespace =
" \t";
825 str.erase(0, str.find_first_not_of(whitespace));
827 str.erase(str.find_last_not_of(whitespace) + 1);
852 int main(
int argc,
char** argv)
856 if(std::string(argv[1]) ==
"match" && argc == 4) {
862 std::cout <<
"Match\n" ;
864 std::cout <<
"No match\n";
const terrain_code FOREST
boost::bimaps::bimap< boost::bimaps::set_of< std::string >, boost::bimaps::multiset_of< coordinate > > starting_positions
const terrain_code DWARVEN_KEEP
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
bool terrain_matches(const terrain_code &src, const terrain_code &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
static l_noret error(LoadState *S, const char *why)
New lexcical_cast header.
To lexical_cast_default(From value, To fallback=To())
Lexical cast converts one type to another with a fallback.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
ter_map read_game_map(std::string_view str, starting_positions &starting_positions, coordinate border_offset)
Reads a gamemap string into a 2D vector.
const terrain_code HUMAN_KEEP
static std::string _(const char *str)
const ter_match ALL_MOUNTAINS("!,*^V*,!,M*")
int main(int argc, char **argv)
terrain_code read_terrain_code(std::string_view str, const ter_layer filler)
Reads a single terrain from a string.
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
static std::string number_to_string_(terrain_code terrain, const std::vector< std::string > &start_position=std::vector< std::string >())
Converts a terrain number to a string.
int max_map_size()
Return the maximum allowed map size (in either dimension), the maximum map area is, therefore, this value squared.
const terrain_code MOUNTAIN
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
const terrain_code FOGGED
const terrain_code DWARVEN_CASTLE
const ter_match ALL_HILLS("!,*^V*,!,H*")
const terrain_code OFF_MAP_USER
static terrain_code string_to_builder_number_(std::string str)
Converts a terrain string to a number for the builder.
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
const terrain_code HUMAN_CASTLE
static ter_layer string_to_layer_(std::string_view str)
Encapsulates the map of the game.
static ter_layer get_layer_mask_(ter_layer terrain)
Get the mask for a single layer.
const ter_match ALL_SWAMPS("!,*^V*,*^B*,!,S*")
static terrain_code string_to_number_(std::string_view str, std::vector< std::string > &start_positions, const ter_layer filler)
Converts a terrain string to a number.
ter_map read_builder_map(const std::string &str)
Reads a builder map.
std::string write_list(const ter_list &list)
Writes a list of terrains to a string, only writes the new format.
static std::pair< int, int > get_map_size(const char *begin, const char *end)
const terrain_code CAVE_WALL
bool has_wildcard(const terrain_code &tcode)
Tests whether a terrain code contains a wildcard.
bool isnewline(const char c)
std::string write_game_map(const ter_map &map, const starting_positions &starting_positions, coordinate border_offset)
Write a gamemap in to a vector string.
const terrain_code DEEP_WATER
const ter_match ALL_OFF_MAP
const terrain_code UNDERGROUND_VILLAGE
Standard logging facilities (interface).
std::vector< terrain_code > ter_list
static terrain_code get_mask_(const terrain_code &terrain)
Gets a mask for a terrain, this mask is used for wildcard matching.
void trim(std::string_view &s)
const terrain_code SHALLOW_WATER
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
This structure can be used for matching terrain strings.
const terrain_code GRASS_LAND
ter_list read_list(std::string_view str, const ter_layer filler)
Reads a list of terrains from a string, when reading the.
const ter_match ALL_FORESTS