33 #define ERR_NG LOG_STREAM(err, log_engine)
34 #define WRN_NG LOG_STREAM(warn, log_engine)
61 bool parity = (me.
x & 1) != 0;
64 if((a.
x > 0) && (a.
x % 2) && parity)
66 if((a.
x < 0) && (a.
x % 2) && !parity)
103 bool is_background = ri->is_background();
104 bool animate = (!ri.ri->is_water ||
prefs::get().animate_water());
110 bool has_flag_match =
true;
111 for(
const std::string&
s : variant.
has_flag) {
114 has_flag_match =
false;
119 if(!has_flag_match) {
124 if(!variant.
tods.empty() && variant.
tods.find(tod) == variant.
tods.end())
129 unsigned int rnd = ri.rand / 7919;
132 bool is_empty =
true;
143 img_list.push_back(anim);
148 img_list.back().set_animation_time(ri.rand % img_list.back().get_animation_duration());
150 img_list.back().set_animation_time(ri.rand % variant.
random_start);
153 img_list.back().pause_animation();
157 log->emplace_back(&ri, &variant);
169 sorted_images =
false;
170 images_foreground.clear();
171 images_background.clear();
172 last_tod =
"invalid_tod";
177 unsigned int a = (loc.
x + 92872973) ^ 918273;
178 unsigned int b = (loc.
y + 1672517) ^ 128123;
179 unsigned int c = (
index + 127390) ^ 13923787;
180 unsigned int abc = a *
b *
c + a *
b +
b *
c + a *
c + a +
b +
c;
185 : tiles_((x + 4) * (y + 4))
202 std::vector<terrain_builder::tile> new_tiles(
static_cast<size_t>(x + 4) * (y + 4));
203 tiles_.swap(new_tiles);
209 if(loc.
x < -2 || loc.
y < -2 || loc.
x > (x_ + 1) || loc.
y > (y_ + 1)) {
220 return tiles_[(loc.
x + 2) + (loc.
y + 2) * (x_ + 4)];
227 return tiles_[(loc.
x + 2) + (loc.
y + 2) * (x_ + 4)];
258 for(
int x = -2; x <=
map().
w(); ++x) {
259 for(
int y = -2; y <=
map().
h(); ++y) {
313 if(!img_list.empty()) {
325 bool changed =
false;
361 if(
map().get_terrain_info(loc).is_combined()) {
364 if(!filename_ovl.empty()) {
383 bool precached = name.find(
"..") == std::string::npos;
394 static std::vector<std::string>
get_variations(
const std::string& base,
const std::string& variations)
397 std::vector<std::string> res;
398 if(variations.empty()) {
402 std::string::size_type pos = base.find(
"@V", 0);
403 if(pos == std::string::npos) {
407 std::vector<std::string> vars =
utils::split(variations,
';', 0);
409 for(
const std::string& v : vars) {
412 while((pos = res.back().find(
"@V", pos)) != std::string::npos) {
413 res.back().replace(pos, 2, v);
432 for(
const std::string& var : var_strings) {
437 for(
const std::string& frame : frames) {
438 const std::vector<std::string> items =
utils::split(frame,
':');
439 const std::string& str = items.front();
441 const std::size_t tilde = str.find(
'~');
442 bool has_tilde = tilde != std::string::npos;
443 const std::string
filename =
"terrain/" + (has_tilde ? str.substr(0, tilde) : str);
449 const std::string modif = (has_tilde ? str.substr(tilde + 1) :
"");
452 if(items.size() > 1) {
454 time = std::stoi(items.back());
455 }
catch(
const std::invalid_argument&) {
456 ERR_NG <<
"Invalid 'time' value in terrain image builder: " << items.back();
469 variant.
images.push_back(std::move(res));
471 if(variant.
images.empty())
488 } 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}};
525 { 1./2. , -3./4., 1., 1./2. },
526 { -1./2., -3./4., 1, -1./2.},
527 { -1. , 0., 0., -1. },
528 { -1./2., 3./4., -1., -1./2.},
529 { 1./2. , 3./4., -1., 1./2. },
540 int ri = rotations[angle].ii * vi + rotations[angle].ij * vj;
541 int rj = rotations[angle].ji * vi + rotations[angle].jj * vj;
544 ret.
loc.
y = ri + (rj >= 0 ? rj / 2 : (rj - 1) / 2);
547 double vx, vy, rx, ry;
549 vx =
static_cast<double>(itor->basex) -
static_cast<double>(
tilewidth_) / 2;
550 vy =
static_cast<double>(itor->basey) -
static_cast<double>(
tilewidth_) / 2;
552 rx = xyrotations[angle].xx * vx + xyrotations[angle].xy * vy;
553 ry = xyrotations[angle].yx * vx + xyrotations[angle].yy * vy;
555 itor->basex =
static_cast<int>(rx +
tilewidth_ / 2);
556 itor->basey =
static_cast<int>(ry +
tilewidth_ / 2);
562 std::string::size_type pos = 0;
563 while((pos =
s.find(
"@R", pos)) != std::string::npos) {
564 if(pos + 2 >=
s.size())
566 unsigned i =
s[pos + 2] -
'0' + angle;
573 const std::string& r = replacement[
i];
574 s.replace(pos, 3, r);
587 rule_imagelist& list,
int angle,
const std::vector<std::string>& replacement)
615 if(rot.size() != 6) {
616 ERR_NG <<
"invalid rotations";
625 int minx = std::numeric_limits<int>::max();
626 int miny = std::numeric_limits<int>::max();
629 minx = std::min<int>(cons.
loc.
x, minx);
630 miny = std::min<int>(2 * cons.
loc.
y + (cons.
loc.
x & 1), miny);
633 if((miny & 1) && (minx & 1) && (minx < 0))
635 if(!(miny & 1) && (minx & 1) && (minx > 0))
646 const std::string& variations,
648 : image_string(image_string)
649 , variations(variations)
653 , random_start(random_start)
658 const std::string& variations,
659 const std::string& tod,
660 const std::string& has_flag,
662 : image_string(image_string)
663 , variations(variations)
667 , random_start(random_start)
673 const std::vector<std::string> tod_list =
utils::split(tod);
674 tods.insert(tod_list.begin(), tod_list.end());
681 int layer =
img[
"layer"].to_int();
686 if(base.size() >= 2) {
688 basex = std::stoi(base[0]);
689 basey = std::stoi(base[1]);
690 }
catch(
const std::invalid_argument&) {
691 ERR_NG <<
"Invalid 'base' value in terrain image builder: " << base[0] <<
", " << base[1];
696 int center_x = -1, center_y = -1;
698 std::vector<std::string> center =
utils::split(*center_);
699 if(center.size() >= 2) {
701 center_x = std::stoi(center[0]);
702 center_y = std::stoi(center[1]);
703 }
catch(
const std::invalid_argument&) {
704 ERR_NG <<
"Invalid 'center' value in terrain image builder: " << center[0] <<
", " << center[1];
709 bool is_water =
img[
"is_water"].to_bool();
711 images.AGGREGATE_EMPLACE(layer, basex - dx, basey - dy, global, center_x, center_y, is_water);
714 for(
const config& variant :
img.child_range(
"variant")) {
715 const std::string& name = variant[
"name"];
716 const std::string& variations =
img[
"variations"];
717 const std::string& tod = variant[
"tod"];
718 const std::string& has_flag = variant[
"has_flag"];
721 int random_start = variant[
"random_start"].to_bool(
true) ? variant[
"random_start"].to_int(-1) : 0;
723 images.back().variants.emplace_back(name, variations, tod, has_flag, random_start);
728 const std::string& name =
img[
"name"];
729 const std::string& variations =
img[
"variations"];
731 int random_start =
img[
"random_start"].to_bool(
true) ?
img[
"random_start"].to_int(-1) : 0;
733 images.back().variants.emplace_back(name, variations, random_start);
740 const config& global_images)
752 constraints.AGGREGATE_EMPLACE(loc);
753 cons = &constraints.back();
756 if(!
type.terrain.empty()) {
770 const config& global_images)
777 constraint.
set_flag.insert(constraint.
set_flag.end(), item_string.begin(), item_string.end());
780 constraint.
has_flag.insert(constraint.
has_flag.end(), item_string.begin(), item_string.end());
783 constraint.
no_flag.insert(constraint.
no_flag.end(), item_string.begin(), item_string.end());
786 constraint.
set_flag.insert(constraint.
set_flag.end(), item_string.begin(), item_string.end());
787 constraint.
no_flag.insert(constraint.
no_flag.end(), item_string.begin(), item_string.end());
789 constraint.
no_draw = cfg[
"no_draw"].to_bool(
false);
809 for(
int y_off = 0; y_off <
map.
w; ++y_off) {
810 for(
int x_off = x; x_off <
map.
h; ++x_off) {
816 }
else if(terrain.
overlay != 0) {
828 if(lineno % 2 == 1) {
847 if(rotations.empty()) {
852 const std::vector<std::string>& rot =
utils::split(rotations,
',');
854 for(std::size_t angle = 0; angle < rot.size(); ++angle) {
863 if(rot.at(angle) ==
"skip") {
881 log_scope(
"terrain_builder::parse_config");
904 for(
const config& tc :
br.child_range(
"tile")) {
918 int pos = v->to_int();
919 if(anchors.find(pos) == anchors.end()) {
920 WRN_NG <<
"Invalid anchor!";
924 std::pair<anchormap::const_iterator, anchormap::const_iterator> range = anchors.equal_range(pos);
926 for(; range.first != range.second; ++range.first) {
927 loc = range.first->second;
933 const std::vector<std::string> global_set_flag =
utils::split(
br[
"set_flag"]);
934 const std::vector<std::string> global_no_flag =
utils::split(
br[
"no_flag"]);
935 const std::vector<std::string> global_has_flag =
utils::split(
br[
"has_flag"]);
936 const std::vector<std::string> global_set_no_flag =
utils::split(
br[
"set_no_flag"]);
939 constraint.
set_flag.insert(constraint.
set_flag.end(), global_set_flag.begin(), global_set_flag.end());
940 constraint.
no_flag.insert(constraint.
no_flag.end(), global_no_flag.begin(), global_no_flag.end());
941 constraint.
has_flag.insert(constraint.
has_flag.end(), global_has_flag.begin(), global_has_flag.end());
942 constraint.
set_flag.insert(constraint.
set_flag.end(), global_set_no_flag.begin(), global_set_no_flag.end());
943 constraint.
no_flag.insert(constraint.
no_flag.end(), global_set_no_flag.begin(), global_set_no_flag.end());
947 const std::string& rotations =
br[
"rotations"];
963 building_ruleset::const_iterator rule;
965 PLAIN_LOG <<
">> New rule: image_background = "
966 <<
"\n>> Location " << rule->second.location_constraints
967 <<
"\n>> Probability " << rule->second.probability
969 for(constraint_set::const_iterator constraint = rule->second.constraints.begin();
970 constraint != rule->second.constraints.end(); ++constraint) {
972 PLAIN_LOG <<
">>>> New constraint: location = (" << constraint->second.loc
975 std::vector<std::string>::const_iterator
flag;
977 for(
flag = constraint->second.set_flag.begin();
flag != constraint->second.set_flag.end(); ++
flag) {
981 for(
flag = constraint->second.no_flag.begin();
flag != constraint->second.no_flag.end(); ++
flag) {
1002 config& tile_image =
tile.add_child(
"image");
1003 tile_image[
"layer"] = -1000;
1004 tile_image[
"name"] =
image;
1006 item[
"probability"] = 100;
1007 item[
"no_flag"] =
"base";
1008 item[
"set_flag"] =
"base";
1032 if(random >
static_cast<unsigned int>(rule.
probability)) {
1052 const std::set<std::string>& flags =
tile_map_[tloc].flags;
1054 for(
const std::string&
s : cons.
no_flag) {
1056 if(flags.find(
s) != flags.end()) {
1060 for(
const std::string&
s : cons.
has_flag) {
1062 if(flags.find(
s) == flags.end()) {
1085 btile.
images.AGGREGATE_EMPLACE(&
img, rand_seed);
1102 for(std::string::const_iterator it = str.begin(), it_end = str.end(); it != it_end; ++it)
1103 h = ((
h << 9) | (
h >> (
sizeof(
int) * 8 - 9))) ^ (*it);
1113 for(
const rule_image& ri : constraint.images) {
1130 log_scope(
"terrain_builder::build_terrains");
1133 for(
int x = -2; x <=
map().
w(); ++x) {
1134 for(
int y = -2; y <=
map().
h(); ++y) {
1154 std::size_t
min_size = std::numeric_limits<int>::max();
1164 std::size_t constraint_size = 0;
1170 const std::size_t match_size = type_it->second.size();
1171 constraint_size += match_size;
1175 matching_types.push_back(
t);
1181 min_types = matching_types;
1182 min_constraint = &constraint;
1191 assert(min_constraint !=
nullptr);
1194 for(t_translation::ter_list::const_iterator
t = min_types.begin();
t != min_types.end(); ++
t) {
1197 for(std::vector<map_location>::const_iterator itor = locations->begin(); itor != locations->end(); ++itor) {
static map_location legacy_negation(const map_location &me)
These legacy map_location functions moved here from map_location.
static lg::log_domain log_engine("engine")
static std::vector< std::string > get_variations(const std::string &base, const std::string &variations)
static unsigned int hash_str(const std::string &str)
static unsigned int get_noise(const map_location &loc, unsigned int index)
static map_location & legacy_sum_assign(map_location &me, const map_location &a)
static map_location legacy_sum(const map_location &me, const map_location &a)
static bool image_exists(const std::string &name)
static map_location legacy_difference(const map_location &me, const map_location &a)
Definitions for the terrain builder.
const T & get_frame(std::size_t n) const
void update_last_draw_time(double acceleration=0)
void start_animation(int start_time, bool cycles=false)
Starts an animation cycle.
int get_animation_duration() const
std::size_t get_frames_count() const
void add_frame(int duration, const T &value, bool force_change=false)
Adds a frame to an animation.
Variant for storing WML attributes.
A config object defines a single node in a WML file, with access to child nodes.
child_itors child_range(config_key_type key)
config & add_child(config_key_type key)
A class grating read only view to a vector of config objects, viewed as one config with all children ...
static game_config_view wrap(const config &cfg)
config_array_view child_range(config_key_type key) const
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
int w() const
Effective map width.
int h() const
Effective map height.
bool empty() const
Tell if the map is of 0 size.
Encapsulates the map of the game.
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
Generic locator abstracting the location of an image.
tile & operator[](const map_location &loc)
Returns a reference to the tile which is at the position pointed by loc.
bool on_map(const map_location &loc) const
Tests if a location is on the map.
void reset()
Resets the whole tile map.
tilemap(int x, int y)
Constructs a tilemap of dimensions x * y.
void reload(int x, int y)
Rebuilds the map to a new set of dimensions.
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...
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...
std::multiset< building_rule > building_ruleset
A set of building rules.
void parse_config(const config &cfg, bool local=true)
Parses a configuration object containing [terrain_graphics] rules, and fills the building_rules_ memb...
tile * get_tile(const map_location &loc)
void add_rule(building_ruleset &rules, building_rule &rule)
Adds a rule to a ruleset.
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...
void rotate_rule(building_rule &rule, int angle, const std::vector< std::string > &angle_name)
Rotates a template rule to a given angle.
bool draw_border_
Whether the map border should be drawn.
void add_off_map_rule(const std::string &image)
Adds a builder rule for the _off^_usr tile, this tile only has 1 image.
void build_terrains()
Calculates the list of terrains, and fills the tile_map_ member, from the gamemap and the building_ru...
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...
void rebuild_terrain(const map_location &loc)
Performs a "quick-rebuild" of the terrain in a given location.
bool update_animation(const map_location &loc)
Updates the animation at a given tile.
static building_ruleset building_rules_
Parsed terrain rules.
const gamemap & map() const
static const unsigned int DUMMY_HASH
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.
void change_map(const gamemap *m)
static void set_terrain_rules_cfg(const game_config_view &cfg)
Set the config where we will parse the global terrain rules.
std::vector< terrain_constraint > constraint_set
The list of constraints attached to a terrain_graphics WML rule.
const int tilewidth_
The tile width used when using basex and basey.
const gamemap * map_
A pointer to the gamemap class used in the current level.
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.
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 ...
bool load_images(building_rule &rule)
Load images and tests for validity of a rule.
tilemap tile_map_
The tile_map_ for the current level, which is filled by the build_terrains_ method to contain "tiles"...
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...
void rotate(terrain_constraint &constraint, int angle)
"Rotates" a constraint from a rule.
void rebuild_all()
Performs a complete rebuild of the list of terrain graphics attached to a map.
std::multimap< int, map_location > anchormap
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...
TERRAIN_TYPE
Used as a parameter for the get_terrain_at function.
@ BACKGROUND
Represents terrains which are to be drawn behind unit sprites.
std::vector< rule_image > rule_imagelist
A shorthand notation for a vector of rule_images.
terrain_by_type_map terrain_by_type_
A map representing all locations whose terrain is of a given type.
static const game_config_view * rules_cfg_
Config used to parse global terrain rules.
void parse_global_config(const game_config_view &cfg)
void reload_map()
Updates internals that cache map size.
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.
terrain_builder(const config &level, const gamemap *map, const std::string &offmap_image, bool draw_border)
Constructor for the terrain_builder class.
const std::string & minimap_image() const
const std::string & minimap_image_overlay() const
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
Standard logging facilities (interface).
#define log_scope(description)
Game configuration data as global variables.
Functions to load and save images from/to disk.
bool is_empty_hex(const locator &i_locator)
Checks if an image is empty after hex masking.
bool precached_file_exists(const std::string &file)
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
void precache_file_existence(const std::string &subdir)
Precache the existence of files in a binary path subdirectory (e.g.
static const std::string br
std::string img(const std::string &src, const std::string &align, const bool floating)
std::vector< terrain_code > ter_list
ter_map read_builder_map(const std::string &str)
Reads a builder map.
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
const terrain_code OFF_MAP_USER
std::string write_list(const ter_list &list)
Writes a list of terrains to a string, only writes the new format.
const terrain_code NONE_TERRAIN
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.
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::vector< std::string > split(const config_attribute_value &val)
std::string::const_iterator iterator
std::string filename
Filename.
Encapsulates the map of the game.
This structure can be used for matching terrain strings.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
The in-memory representation of a [terrain_graphics] WML rule.
int precedence
Ordering relation between the rules.
map_location modulo_constraints
Used to constrain locations to ones with coordinates that are multiples of the "mod_x" and "mod_y" pa...
map_location location_constraints
The location on which this map may match.
int probability
The probability of this rule to match, when all conditions are met.
unsigned int get_hash() const
constraint_set constraints
The set of [tile] constraints of this rule.
rule_image_variant(const std::string &image_string, const std::string &variations, int random_start=-1)
Constructor for the normal default case.
std::vector< std::string > has_flag
int random_start
Specify the allowed amount of random shift (in milliseconds) applied to the animation start time,...
std::vector< animated< image::locator > > images
An animated image locator built according to the image string.
std::set< std::string > tods
The Time of Day associated to this variant (if any)
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.
Each terrain_graphics rule is associated a set of images, which are applied on the terrain if the rul...
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::vector< rule_image_variant > variants
A list of variants for this image.
int center_x
The position where the center of the image base should be.
The in-memory representation of a [tile] WML rule inside of a [terrain_graphics] WML rule.
t_translation::ter_match terrain_types_match
std::vector< std::string > set_flag
std::vector< std::string > has_flag
bool no_draw
Whether to actually draw the images onto this hex or not.
std::vector< std::string > no_flag
Represent a rule_image applied with a random seed.
Represents a tile of the game map, with all associated builder-specific parameters: flags,...
std::string last_tod
The time-of-day to which the image caches correspond.
std::vector< rule_image_rand > images
The list of rule_images and random seeds associated to this tile.
std::vector< log_details > logs
void clear()
Clears all data in this tile, and resets the cache.
void rebuild_cache(const std::string &tod, logs *log=nullptr)
Rebuilds the whole image cache, for a given time-of-day.
imagelist images_background
The list of images which are behind the unit sprites, attached to this tile.
imagelist images_foreground
The list of images which are in front of the unit sprites, attached to this tile.
bool sorted_images
Indicates if 'images' is sorted.
std::set< std::string > flags
The list of flags present in this tile.
static map_location::direction n
static map_location::direction s