32 #define ERR_NG LOG_STREAM(err, log_engine) 33 #define WRN_NG LOG_STREAM(warn, log_engine) 60 bool parity = (me.
x & 1) != 0;
63 if((a.
x > 0) && (a.
x % 2) && parity)
65 if((a.
x < 0) && (a.
x % 2) && !parity)
94 , global_image(global_image)
104 , images_foreground()
105 , images_background()
106 , last_tod(
"invalid_tod")
107 , sorted_images(false)
124 bool is_background = ri->is_background();
131 bool has_flag_match =
true;
132 for(
const std::string&
s : variant.
has_flag) {
135 has_flag_match =
false;
140 if(!has_flag_match) {
145 if(!variant.
tods.empty() && variant.
tods.find(tod) == variant.
tods.end())
150 unsigned int rnd = ri.rand / 7919;
153 bool is_empty =
true;
164 img_list.push_back(anim);
169 img_list.back().set_animation_time(ri.rand % img_list.back().get_animation_duration());
171 img_list.back().set_animation_time(ri.rand % variant.
random_start);
174 img_list.back().pause_animation();
178 log->emplace_back(&ri, &variant);
198 unsigned int a = (loc.
x + 92872973) ^ 918273;
199 unsigned int b = (loc.
y + 1672517) ^ 128123;
200 unsigned int c = (index + 127390) ^ 13923787;
201 unsigned int abc = a * b * c + a * b + b * c + a * c + a + b +
c;
215 std::vector<terrain_builder::tile> new_tiles((x + 4) * (y + 4));
216 tiles_.swap(new_tiles);
222 if(loc.
x < -2 || loc.
y < -2 || loc.
x > (x_ + 1) || loc.
y > (y_ + 1)) {
233 return tiles_[(loc.
x + 2) + (loc.
y + 2) * (x_ + 4)];
240 return tiles_[(loc.
x + 2) + (loc.
y + 2) * (x_ + 4)];
271 for(
int x = -2; x <=
map().
w(); ++x) {
272 for(
int y = -2; y <=
map().
h(); ++y) {
326 if(!img_list.empty()) {
338 bool changed =
false;
366 if(!filename.empty()) {
374 if(
map().get_terrain_info(loc).is_combined()) {
377 if(!filename_ovl.empty()) {
396 bool precached = name.find(
"..") == std::string::npos;
407 static std::vector<std::string>
get_variations(
const std::string& base,
const std::string& variations)
410 std::vector<std::string> res;
411 if(variations.empty()) {
415 std::string::size_type pos = base.find(
"@V", 0);
416 if(pos == std::string::npos) {
420 std::vector<std::string> vars =
utils::split(variations,
';', 0);
422 for(
const std::string& v : vars) {
425 while((pos = res.back().find(
"@V", pos)) != std::string::npos) {
426 res.back().replace(pos, 2, v);
445 for(
const std::string& var : var_strings) {
450 for(
const std::string& frame : frames) {
452 const std::string& str = items.front();
454 const std::size_t tilde = str.find(
'~');
455 bool has_tilde = tilde != std::string::npos;
456 const std::string filename =
"terrain/" + (has_tilde ? str.substr(0, tilde) : str);
462 const std::string modif = (has_tilde ? str.substr(tilde + 1) :
"");
465 if(items.size() > 1) {
467 time = std::stoi(items.back());
468 }
catch(
const std::invalid_argument&) {
469 ERR_NG <<
"Invalid 'time' value in terrain image builder: " << items.back();
484 variant.
images.push_back(std::move(res));
486 if(variant.
images.empty())
503 } rotations[6] {{1, 0, 0, 1}, {1, 1, -1, 0}, {0, 1, -1, -1}, {-1, 0, 0, -1}, {-1, -1, 1, 0}, {0, -1, 1, 1}};
540 { 1./2. , -3./4., 1., 1./2. },
541 { -1./2., -3./4., 1, -1./2.},
542 { -1. , 0., 0., -1. },
543 { -1./2., 3./4., -1., -1./2.},
544 { 1./2. , 3./4., -1., 1./2. },
555 int ri = rotations[angle].ii * vi + rotations[angle].ij * vj;
556 int rj = rotations[angle].ji * vi + rotations[angle].jj * vj;
559 ret.
loc.
y = ri + (rj >= 0 ? rj / 2 : (rj - 1) / 2);
562 double vx, vy, rx, ry;
564 vx =
static_cast<double>(itor->basex) - static_cast<double>(
tilewidth_) / 2;
565 vy =
static_cast<double>(itor->basey) - static_cast<double>(
tilewidth_) / 2;
567 rx = xyrotations[angle].xx * vx + xyrotations[angle].xy * vy;
568 ry = xyrotations[angle].yx * vx + xyrotations[angle].yy * vy;
570 itor->basex =
static_cast<int>(rx +
tilewidth_ / 2);
571 itor->basey =
static_cast<int>(ry +
tilewidth_ / 2);
577 std::string::size_type pos = 0;
578 while((pos = s.find(
"@R", pos)) != std::string::npos) {
579 if(pos + 2 >= s.size())
581 unsigned i = s[pos + 2] -
'0' + angle;
588 const std::string& r = replacement[
i];
589 s.replace(pos, 3, r);
602 rule_imagelist& list,
int angle,
const std::vector<std::string>& replacement)
616 for(std::string& flag : cons.
no_flag) {
619 for(std::string& flag : cons.
has_flag) {
630 if(rot.size() != 6) {
631 ERR_NG <<
"invalid rotations";
644 minx = std::min<int>(cons.
loc.
x, minx);
645 miny = std::min<int>(2 * cons.
loc.
y + (cons.
loc.
x & 1), miny);
648 if((miny & 1) && (minx & 1) && (minx < 0))
650 if(!(miny & 1) && (minx & 1) && (minx > 0))
661 const std::string& variations,
662 const std::string& tod,
663 const std::string& has_flag,
665 : image_string(image_string)
666 , variations(variations)
670 , random_start(random_start)
672 if(!has_flag.empty()) {
676 const std::vector<std::string> tod_list =
utils::split(tod);
677 tods.insert(tod_list.begin(), tod_list.end());
684 int layer = img[
"layer"];
689 if(base.size() >= 2) {
691 basex = std::stoi(base[0]);
692 basey = std::stoi(base[1]);
693 }
catch(
const std::invalid_argument&) {
694 ERR_NG <<
"Invalid 'base' value in terrain image builder: " << base[0] <<
", " << base[1];
699 int center_x = -1, center_y = -1;
701 std::vector<std::string> center =
utils::split(*center_);
702 if(center.size() >= 2) {
704 center_x = std::stoi(center[0]);
705 center_y = std::stoi(center[1]);
706 }
catch(
const std::invalid_argument&) {
707 ERR_NG <<
"Invalid 'center' value in terrain image builder: " << center[0] <<
", " << center[1];
712 bool is_water = img[
"is_water"].to_bool();
714 images.push_back(
rule_image(layer, basex - dx, basey - dy, global, center_x, center_y, is_water));
718 const std::string& name = variant[
"name"];
719 const std::string&
variations = img[
"variations"];
720 const std::string& tod = variant[
"tod"];
721 const std::string&
has_flag = variant[
"has_flag"];
724 int random_start = variant[
"random_start"].to_bool(
true) ? variant[
"random_start"].to_int(-1) : 0;
726 images.back().variants.emplace_back(name, variations, tod, has_flag, random_start);
731 const std::string& name = img[
"name"];
732 const std::string&
variations = img[
"variations"];
734 int random_start = img[
"random_start"].to_bool(
true) ? img[
"random_start"].to_int(-1) : 0;
736 images.back().variants.emplace_back(name, variations, random_start);
743 const config& global_images)
755 constraints.emplace_back(loc);
756 cons = &constraints.back();
773 const config& global_images)
780 constraint.
set_flag.insert(constraint.
set_flag.end(), item_string.begin(), item_string.end());
783 constraint.
has_flag.insert(constraint.
has_flag.end(), item_string.begin(), item_string.end());
786 constraint.
no_flag.insert(constraint.
no_flag.end(), item_string.begin(), item_string.end());
789 constraint.
set_flag.insert(constraint.
set_flag.end(), item_string.begin(), item_string.end());
790 constraint.
no_flag.insert(constraint.
no_flag.end(), item_string.begin(), item_string.end());
792 constraint.
no_draw = cfg[
"no_draw"].to_bool(
false);
805 if(map.
data.empty()) {
812 for(
int y_off = 0; y_off < map.
w; ++y_off) {
813 for(
int x_off = x; x_off < map.
h; ++x_off) {
819 }
else if(terrain.
overlay != 0) {
831 if(lineno % 2 == 1) {
850 if(rotations.empty()) {
855 const std::vector<std::string>& rot =
utils::split(rotations,
',');
857 for(std::size_t angle = 0; angle < rot.size(); ++angle) {
866 if(rot.at(angle) ==
"skip") {
884 log_scope(
"terrain_builder::parse_config");
922 if(anchors.find(pos) == anchors.end()) {
923 WRN_NG <<
"Invalid anchor!";
927 std::pair<anchormap::const_iterator, anchormap::const_iterator> range = anchors.equal_range(pos);
929 for(; range.first != range.second; ++range.first) {
930 loc = range.first->second;
936 const std::vector<std::string> global_set_flag =
utils::split(br[
"set_flag"]);
937 const std::vector<std::string> global_no_flag =
utils::split(br[
"no_flag"]);
938 const std::vector<std::string> global_has_flag =
utils::split(br[
"has_flag"]);
939 const std::vector<std::string> global_set_no_flag =
utils::split(br[
"set_no_flag"]);
942 constraint.
set_flag.insert(constraint.
set_flag.end(), global_set_flag.begin(), global_set_flag.end());
943 constraint.
no_flag.insert(constraint.
no_flag.end(), global_no_flag.begin(), global_no_flag.end());
944 constraint.
has_flag.insert(constraint.
has_flag.end(), global_has_flag.begin(), global_has_flag.end());
945 constraint.
set_flag.insert(constraint.
set_flag.end(), global_set_no_flag.begin(), global_set_no_flag.end());
946 constraint.
no_flag.insert(constraint.
no_flag.end(), global_set_no_flag.begin(), global_set_no_flag.end());
950 const std::string& rotations = br[
"rotations"];
966 building_ruleset::const_iterator rule;
968 PLAIN_LOG <<
">> New rule: image_background = " 969 <<
"\n>> Location " << rule->second.location_constraints
970 <<
"\n>> Probability " << rule->second.probability
972 for(constraint_set::const_iterator constraint = rule->second.constraints.begin();
973 constraint != rule->second.constraints.end(); ++constraint) {
975 PLAIN_LOG <<
">>>> New constraint: location = (" << constraint->second.loc
978 std::vector<std::string>::const_iterator
flag;
980 for(flag = constraint->second.set_flag.begin(); flag != constraint->second.set_flag.end(); ++
flag) {
984 for(flag = constraint->second.no_flag.begin(); flag != constraint->second.no_flag.end(); ++
flag) {
1006 tile_image[
"layer"] = -1000;
1007 tile_image[
"name"] = image;
1009 item[
"probability"] = 100;
1010 item[
"no_flag"] =
"base";
1011 item[
"set_flag"] =
"base";
1035 if(random > static_cast<unsigned int>(rule.
probability)) {
1055 const std::set<std::string>& flags =
tile_map_[tloc].flags;
1057 for(
const std::string&
s : cons.
no_flag) {
1059 if(flags.find(s) != flags.end()) {
1063 for(
const std::string& s : cons.
has_flag) {
1065 if(flags.find(s) == flags.end()) {
1088 btile.
images.emplace_back(&img, rand_seed);
1094 btile.
flags.insert(flag);
1105 for(std::string::const_iterator it = str.begin(), it_end = str.end(); it != it_end; ++it)
1106 h = ((h << 9) | (h >> (
sizeof(int) * 8 - 9))) ^ (*it);
1116 for(
const rule_image& ri : constraint.images) {
1133 log_scope(
"terrain_builder::build_terrains");
1136 for(
int x = -2; x <=
map().
w(); ++x) {
1137 for(
int y = -2; y <=
map().
h(); ++y) {
1167 std::size_t constraint_size = 0;
1173 const std::size_t match_size = type_it->second.size();
1174 constraint_size += match_size;
1175 if(constraint_size >= min_size) {
1178 matching_types.push_back(t);
1182 if(constraint_size < min_size) {
1183 min_size = constraint_size;
1184 min_types = matching_types;
1185 min_constraint = &constraint;
1194 assert(min_constraint !=
nullptr);
1197 for(t_translation::ter_list::const_iterator
t = min_types.begin();
t != min_types.end(); ++
t) {
1200 for(std::vector<map_location>::const_iterator itor = locations->begin(); itor != locations->end(); ++itor) {
void rebuild_terrain(const map_location &loc)
Performs a "quick-rebuild" of the terrain in a given location.
void reload_map()
Updates internals that cache map size.
std::size_t get_frames_count() const
The in-memory representation of a [terrain_graphics] WML rule.
void precache_file_existence(const std::string &subdir)
Precache the existence of files in a binary path subdirectory (e.g.
terrain_by_type_map terrain_by_type_
A map representing all locations whose terrain is of a given type.
tile * get_tile(const map_location &loc)
static const game_config_view * rules_cfg_
Config used to parse global terrain rules.
const terrain_code NONE_TERRAIN
map_location modulo_constraints
Used to constrain locations to ones with coordinates that are multiples of the "mod_x" and "mod_y" pa...
void reset()
Resets the whole tile map.
The in-memory representation of a [tile] WML rule inside of a [terrain_graphics] WML rule...
void add_rule(building_ruleset &rules, building_rule &rule)
Adds a rule to a ruleset.
tile & operator[](const map_location &loc)
Returns a reference to the tile which is at the position pointed by loc.
Variant for storing WML attributes.
bool no_draw
Whether to actually draw the images onto this hex or not.
bool precached_file_exists(const std::string &file)
void add_off_map_rule(const std::string &image)
Adds a builder rule for the _off^_usr tile, this tile only has 1 image.
static game_config_view wrap(const config &cfg)
config_array_view child_range(config_key_type key) const
bool load_images(building_rule &rule)
Load images and tests for validity of a rule.
std::vector< terrain_constraint > constraint_set
The list of constraints attached to a terrain_graphics WML rule.
child_itors child_range(config_key_type key)
Represent a rule_image applied with a random seed.
terrain_constraint & add_constraints(constraint_set &constraints, const map_location &loc, const t_translation::ter_match &type, const config &global_images)
Creates a rule constraint object which matches a given list of terrains, and adds it to the list of c...
imagelist images_background
The list of images which are behind the unit sprites, attached to this tile.
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
int precedence
Ordering relation between the rules.
std::multimap< int, map_location > anchormap
static building_ruleset building_rules_
Parsed terrain rules.
const std::vector< std::string > items
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
std::vector< terrain_code > data
const int tilewidth_
The tile width used when using basex and basey.
static map_location & legacy_sum_assign(map_location &me, const map_location &a)
static map_location legacy_difference(const map_location &me, const map_location &a)
static lg::log_domain log_engine("engine")
t_translation::ter_match terrain_types_match
void add_rotated_rules(building_ruleset &rules, building_rule &tpl, const std::string &rotations)
Adds a set of rules to a ruleset, from a template rule which spans 6 rotations (or less if some of th...
void add_frame(int duration, const T &value, bool force_change=false)
Adds a frame to an animation.
int random_start
Specify the allowed amount of random shift (in milliseconds) applied to the animation start time...
void apply_rule(const building_rule &rule, const map_location &loc)
Applies a rule at a given location: applies the result of a matching rule at a given location: attach...
static unsigned int get_noise(const map_location &loc, unsigned int index)
void rebuild_all()
Performs a complete rebuild of the list of terrain graphics attached to a map.
static const unsigned int DUMMY_HASH
void rebuild_cache(const std::string &tod, logs *log=nullptr)
Rebuilds the whole image cache, for a given time-of-day.
void replace_rotate_tokens(std::string &s, int angle, const std::vector< std::string > &replacement)
Replaces, in a given string, rotation tokens with their values.
int probability
The probability of this rule to match, when all conditions are met.
Represents a tile of the game map, with all associated builder-specific parameters: flags...
void change_map(const gamemap *m)
int get_animation_duration() const
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
rule_image_variant(const std::string &image_string, const std::string &variations, int random_start=-1)
Constructor for the normal default case.
const gamemap * map_
A pointer to the gamemap class used in the current level.
int w() const
Effective map width.
const T & get_frame(std::size_t n) const
bool rule_matches(const building_rule &rule, const map_location &loc, const terrain_constraint *type_checked) const
Checks whether a rule matches a given location in the map.
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
tilemap tile_map_
The tile_map_ for the current level, which is filled by the build_terrains_ method to contain "tiles"...
static bool image_exists(const std::string &name)
Encapsulates the map of the game.
std::set< std::string > tods
The Time of Day associated to this variant (if any)
TERRAIN_TYPE
Used as a parameter for the get_terrain_at function.
std::vector< rule_image_variant > variants
A list of variants for this image.
std::vector< rule_image_rand > images
The list of rule_images and random seeds associated to this tile.
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
std::vector< log_details > logs
bool local
Indicate if the rule is only for this scenario.
const terrain_code OFF_MAP_USER
Generic locator abstracting the location of an image.
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
bool terrain_matches(const t_translation::terrain_code &tcode, const t_translation::ter_list &terrains) const
Checks whether a terrain code matches a given list of terrain codes.
Encapsulates the map of the game.
void rotate_rule(building_rule &rule, int angle, const std::vector< std::string > &angle_name)
Rotates a template rule to a given angle.
bool update_animation(const map_location &loc)
Updates the animation at a given tile.
bool global_image
Set to true if the image was defined as a child of the [terrain_graphics] tag, set to false if it was...
std::string last_tod
The time-of-day to which the image caches correspond.
void rotate(terrain_constraint &constraint, int angle)
"Rotates" a constraint from a rule.
std::vector< std::string > set_flag
Game configuration data as global variables.
void update_last_draw_time(double acceleration=0)
static map_location::DIRECTION s
std::set< std::string > flags
The list of flags present in this tile.
rule_image(int layer, int x, int y, bool global_image=false, int center_x=-1, int center_y=-1, bool is_water=false)
This file holds the terrain_builder implementation.
std::vector< rule_image > rule_imagelist
A shorthand notation for a vector of rule_images.
ter_map read_builder_map(const std::string &str)
Reads a builder map.
void start_animation(int start_time, bool cycles=false)
Starts an animation cycle.
#define log_scope(description)
void parse_mapstring(const std::string &mapstring, struct building_rule &br, anchormap &anchors, const config &global_images)
Parses a map string (the map= element of a [terrain_graphics] rule, and adds constraints from this ma...
const std::string & minimap_image() const
std::string write_list(const ter_list &list)
Writes a list of terrains to a string, only writes the new format.
bool on_map(const map_location &loc) const
Tests if a location is on the map.
std::vector< std::string > has_flag
Definitions for the terrain builder.
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.
int center_x
The position where the center of the image base should be.
void reload(int x, int y)
Rebuilds the map to a new set of dimensions.
Represents terrains which are to be drawn behind unit sprites.
Each terrain_graphics rule is associated a set of images, which are applied on the terrain if the rul...
std::vector< std::string > has_flag
terrain_code & get(int x, int y)
config & add_child(config_key_type key)
static map_location legacy_negation(const map_location &me)
These legacy map_location functions moved here from map_location.
std::vector< animated< image::locator > > imagelist
A shorthand typedef for a list of animated image locators, the base data type returned by the get_ter...
void build_terrains()
Calculates the list of terrains, and fills the tile_map_ member, from the gamemap and the building_ru...
tile()
Constructor for the tile() structure.
std::multiset< building_rule > building_ruleset
A set of building rules.
terrain_builder(const config &level, const gamemap *map, const std::string &offmap_image, bool draw_border)
Constructor for the terrain_builder class.
constraint_set constraints
The set of [tile] constraints of this rule.
void parse_global_config(const game_config_view &cfg)
bool sorted_images
Indicates if 'images' is sorted.
std::vector< std::string > split(const config_attribute_value &val)
void add_images_from_config(rule_imagelist &images, const config &cfg, bool global, int dx=0, int dy=0)
Parses a "config" object, which should contains [image] children, and adds the corresponding parsed r...
bool is_empty_hex(const locator &i_locator)
Checks if an image is empty after hex masking.
const gamemap & map() const
map_location location_constraints
The location on which this map may match.
std::vector< animated< image::locator > > images
An animated image locator built according to the image string.
Functions to load and save images from/to disk.
Standard logging facilities (interface).
std::vector< terrain_code > ter_list
std::string image_string
A string representing either the filename for an image, or a list of images, with an optional timing ...
std::string variations
A semi-solon separated list of string used to replace.
void parse_config(const config &cfg, bool local=true)
Parses a configuration object containing [terrain_graphics] rules, and fills the building_rules_ memb...
unsigned int get_hash() const
static unsigned int hash_str(const std::string &str)
static map_location legacy_sum(const map_location &me, const map_location &a)
imagelist images_foreground
The list of images which are in front of the unit sprites, attached to this tile. ...
A config object defines a single node in a WML file, with access to child nodes.
static void set_terrain_rules_cfg(const game_config_view &cfg)
Set the config where we will parse the global terrain rules.
void clear()
Clears all data in this tile, and resets the cache.
static std::vector< std::string > get_variations(const std::string &base, const std::string &variations)
static map_location::DIRECTION n
int h() const
Effective map height.
const std::string & minimap_image_overlay() const
This structure can be used for matching terrain strings.
bool draw_border_
Whether the map border should be drawn.
std::vector< std::string > no_flag
std::string::const_iterator iterator
std::vector< std::string > square_parenthetical_split(const std::string &val, const char separator, const std::string &left, const std::string &right, const int flags)
Similar to parenthetical_split, but also expands embedded square brackets.
std::pair< std::string, unsigned > item
const imagelist * get_terrain_at(const map_location &loc, const std::string &tod, TERRAIN_TYPE const terrain_type)
Returns a vector of strings representing the images to load & blit together to get the built content ...