31 #define ERR_CF LOG_STREAM(err, log_config)
32 #define WRN_CF LOG_STREAM(warn, log_config)
41 int config_to_max(
int value)
43 return value < 0 ? -value : value;
47 int config_to_min(
int value)
49 return value < 0 ? -value : 0;
72 parameters(
int min,
int max,
int (*eval_fun)(
int)=
nullptr,
bool move=
true,
bool high=
false) :
123 void merge(
const config & new_values,
bool overwrite);
129 {
return value(terrain, fallback, 0); }
131 void write(
config & out_cfg,
const std::string & child_name)
const;
133 void write(
config & out_cfg,
const std::string & child_name,
139 const terrain_info * fallback,
unsigned recurse_count)
const;
142 const terrain_info * fallback,
unsigned recurse_count)
const;
145 typedef std::map<t_translation::terrain_code, int>
cache_t;
172 bool overwrite)
const
176 if (
a.second != cfg_[
a.first] )
181 if (
a.second.to_int() != 0 )
206 cfg_.merge_attributes(new_values);
210 int old = dest.
to_int(params_.max_value);
216 int value = std::abs(old) +
a.second.to_int(0);
217 value = std::max(params_.min_value, std::min(
value, params_.max_value));
237 config & out_cfg,
const std::string & child_name)
const
242 if ( child_name.empty() )
257 config & out_cfg,
const std::string & child_name,
const terrain_info * fallback)
const
263 fallback->
write(merged,
"",
true);
279 unsigned recurse_count)
const
282 if ( recurse_count > 100 ) {
283 ERR_CF <<
"infinite terrain_info recursion on "
284 << (params_.use_move ?
"movement" :
"defense") <<
": "
286 <<
" depth " << recurse_count;
287 return params_.default_value;
290 std::shared_ptr<terrain_type_data> tdata;
298 tdata->underlying_mvt_terrain(terrain) :
299 tdata->underlying_def_terrain(terrain);
304 int result = params_.default_value;
306 const std::string &
id = tdata->get_terrain_info(terrain).id();
309 result = val->to_int(params_.default_value);
310 if ( params_.eval !=
nullptr )
311 result = params_.eval(result);
313 else if ( fallback !=
nullptr ) {
315 result = fallback->
value(terrain);
319 if ( result < params_.min_value ) {
320 WRN_CF <<
"Terrain '" << terrain <<
"' has evaluated to " << result
321 <<
" (" << (params_.use_move ?
"cost" :
"defense")
322 <<
"), which is less than " << params_.min_value
323 <<
"; resetting to " << params_.min_value <<
".";
324 result = params_.min_value;
326 if ( result > params_.max_value ) {
327 WRN_CF <<
"Terrain '" << terrain <<
"' has evaluated to " << result
328 <<
" (" << (params_.use_move ?
"cost" :
"defense")
329 <<
"), which is more than " << params_.max_value
330 <<
"; resetting to " << params_.max_value <<
".";
331 result = params_.max_value;
339 bool prefer_high = params_.high_is_good;
340 int result = params_.default_value;
343 result = result == params_.max_value ? params_.min_value :
347 t_translation::ter_list::const_iterator
i;
348 for (
i = underlying.begin();
i != underlying.end(); ++
i )
352 prefer_high = params_.high_is_good;
356 prefer_high = !params_.high_is_good;
360 const int num =
value(*
i, fallback, recurse_count + 1);
362 if ( ( prefer_high && num > result) ||
363 (!prefer_high && num < result) )
382 unsigned recurse_count)
const
385 std::pair<cache_t::iterator, bool> cache_it =
386 cache_.emplace(terrain, -127);
387 if ( cache_it.second )
389 cache_it.first->second = calc_value(terrain, fallback, recurse_count);
391 return cache_it.first->second;
421 unique_data_(new
data(cfg, params)),
477 this->unique_data_.reset();
503 a.min_.swap_data(
b.min_);
504 a.max_.swap_data(
b.max_);
516 a.movement_.swap_data(
b.movement_);
517 a.vision_.swap_data(
b.vision_);
518 a.jamming_.swap_data(
b.jamming_);
519 swap(
a.defense_,
b.defense_);
543 return get_data().empty();
555 const std::vector<movetype::terrain_info * > & dependants)
557 if ( !get_data().config_has_changes(new_values, overwrite) )
567 make_data_writable();
568 for (
auto & dependant : dependants) {
570 dependant->make_data_writable();
573 unique_data_->merge(new_values, overwrite);
582 return get_data().value(terrain,
fallback_);
596 get_data().write(cfg, child_name);
598 get_data().write(cfg, child_name,
fallback_);
613 std::unique_ptr<terrain_costs>
t;
616 t = std::make_unique<terrain_info>(*
this,
nullptr);
618 else if(get_data().empty()) {
625 write(merged,
"",
true);
626 t = std::make_unique<terrain_info>(merged, get_data().params(),
nullptr);
633 assert(unique_data_ || shared_data_);
634 assert(! (unique_data_ && shared_data_));
636 return *unique_data_;
637 return *shared_data_;
658 t->unique_data_.reset(
new data(*shared_data_));
659 t->shared_data_.reset();
663 unique_data_->clear_cache();
683 t->shared_data_ = std::move(
t->unique_data_);
689 min_(that.min_, nullptr),
690 max_(that.max_, nullptr)
695 min_(std::move(that.min_), nullptr),
696 max_(std::move(that.max_), nullptr)
702 min_.copy_data(that.
min_);
703 max_.copy_data(that.
max_);
709 min_.swap_data(that.min_);
710 max_.swap_data(that.max_);
719 min_.merge(new_data, overwrite, {});
720 max_.merge(new_data, overwrite, {});
734 result[attrb.first] = attrb.second;
746 std::pair<std::string, std::string> types = attack.
damage_type();
748 if(!(types.second).empty()){
760 return cfg_[damage_type].to_int(100);
774 cfg_.merge_attributes(new_data);
778 dest = std::max(0, dest.
to_int(100) +
a.second.to_int(0));
792 if ( child_name.empty() )
821 movement_(cfg.child_or_empty(
"movement_costs"), mvj_params_, nullptr),
822 vision_(cfg.child_or_empty(
"vision_costs"), mvj_params_, &movement_),
823 jamming_(cfg.child_or_empty(
"jamming_costs"), mvj_params_, &vision_),
824 defense_(cfg.child_or_empty(
"defense")),
825 resist_(cfg.child_or_empty(
"resistance")),
826 flying_(cfg[
"flies"].to_bool(false))
841 movement_(that.movement_, nullptr),
842 vision_(that.vision_, &movement_),
843 jamming_(that.jamming_, &vision_),
844 defense_(that.defense_),
845 resist_(that.resist_),
846 flying_(that.flying_),
847 special_notes_(that.special_notes_)
855 movement_(std::move(that.movement_), nullptr),
856 vision_(std::move(that.vision_), &movement_),
857 jamming_(std::move(that.jamming_), &vision_),
858 defense_(std::move(that.defense_)),
859 resist_(std::move(that.resist_)),
860 flying_(std::move(that.flying_)),
861 special_notes_(std::move(that.special_notes_))
880 merge(child, applies_to, overwrite);
894 if(applies_to ==
"movement_costs") {
897 else if(applies_to ==
"vision_costs") {
900 else if(applies_to ==
"jamming_costs") {
903 else if(applies_to ==
"defense") {
906 else if(applies_to ==
"resistance") {
910 ERR_CF <<
"movetype::merge with unknown applies_to: " << applies_to;
918 "vision_costs",
"jamming_costs",
"defense",
"resistance"};
929 cfg[
"flying"] =
true;
std::pair< std::string, std::string > damage_type() const
return a modified damage type and/or add a secondary_type for hybrid use if special is active.
Variant for storing WML attributes.
int to_int(int def=0) const
A config object defines a single node in a WML file, with access to child nodes.
const_attr_itors attribute_range() const
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
child_itors child_range(config_key_type key)
attribute_map::value_type attribute
config & add_child(config_key_type key)
static game_config_manager * get()
const std::shared_ptr< terrain_type_data > & terrain_types() const
int resistance_against(const attack_type &attack) const
Returns the resistance against the indicated attack.
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
utils::string_map_res damage_table() const
Returns a map from attack types to resistances.
void write(config &out_cfg, const std::string &child_name="") const
Writes our data to a config, as a child if child_name is specified.
Stores a set of defense levels.
terrain_defense & operator=(const terrain_defense &that)
void write(config &cfg, const std::string &child_name="") const
Writes our data to a config, as a child if child_name is specified.
bool capped(const t_translation::terrain_code &terrain) const
Returns whether there is a defense cap associated to this terrain.
static const terrain_info::parameters params_max_
static const terrain_info::parameters params_min_
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
bool config_has_changes(const config &new_values, bool overwrite) const
Tests if merging new_values would result in changes.
const parameters & params() const
Read-only access to our parameters.
void write(config &out_cfg, const std::string &child_name) const
If there is data, writes it to the config.
data(const config &cfg, const parameters ¶ms)
Constructor.
config cfg_
Config describing the terrain values.
std::map< t_translation::terrain_code, int > cache_t
bool empty() const
Tests for no data in this object.
void merge(const config &new_values, bool overwrite)
Merges the given config over the existing costs.
cache_t cache_
Cache of values based on the config.
void clear_cache() const
Clears the cached data (presumably our fallback has changed).
int calc_value(const t_translation::terrain_code &terrain, const terrain_info *fallback, unsigned recurse_count) const
Calculates the value associated with the given terrain.
int value(const t_translation::terrain_code &terrain, const terrain_info *fallback) const
Returns the value associated with the given terrain.
data(const parameters ¶ms)
Constructor.
const parameters & params_
Various parameters used when calculating values.
Stores a set of data based on terrain, in some cases with raw pointers to other instances of terrain_...
void make_data_writable() const
Copy the immutable data back to unique_data_, no-op if the data is already in unique_data_.
const data & get_data() const
Returns either *unique_data_ or *shared_data_, choosing the one that currently holds the data.
std::unique_ptr< terrain_costs > make_standalone() const override
Does a sufficiently deep copy so that the returned object's lifespan is independent of other objects'...
std::shared_ptr< const data > shared_data_
void swap_data(movetype::terrain_info &that)
Swap function for the terrain_info class.
void copy_data(const movetype::terrain_info &that)
This is only expected to be called either when 1) both this and that have no siblings,...
bool empty() const
Returns whether or not our data is empty.
terrain_info(const parameters ¶ms, const terrain_info *fallback)
Constructor.
void write(config &cfg, const std::string &child_name="", bool merged=true) const override
Writes our data to a config.
int value(const t_translation::terrain_code &terrain) const override
Returns the value associated with the given terrain.
~terrain_info() override
Destructor.
void make_data_shareable() const
Move data to an immutable copy in shared_data_, no-op if the data is already in shared_data_.
const terrain_info *const fallback_
void merge(const config &new_values, bool overwrite, const std::vector< movetype::terrain_info * > &dependants)
Merges the given config over the existing values.
std::unique_ptr< data > unique_data_
The basic "size" of the unit - flying, small land, large land, etc.
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
void write(config &cfg, bool include_notes) const
Writes the movement type data to the provided config.
movetype()
Default constructor.
static const std::set< std::string > effects
The set of applicable effects for movement types.
void merge(const config &new_cfg, bool overwrite=true)
Merges the given config over the existing data, the config should have zero or more children named "m...
bool has_terrain_defense_caps(const std::set< t_translation::terrain_code > &ts) const
Returns whether or not there are any terrain caps with respect to a set of terrains.
movetype & operator=(const movetype &that)
static const terrain_info::parameters mvj_params_
Limits for movement, vision and jamming.
static std::unique_ptr< terrain_costs > read_terrain_costs(const config &cfg)
Reverse of terrain_costs::write.
friend void swap(movetype &a, movetype &b)
Swap function for the movetype class, including its terrain_info members.
std::vector< t_string > special_notes_
int resistance_against(const attack_type &attack) const
Returns the resistance against the indicated attack.
bool is_indivisible() const
Returns true if this terrain has no underlying types other than itself.
const formula_callable * fallback_
Standard logging facilities (interface).
void swap(movetype::terrain_defense &a, movetype::terrain_defense &b)
Swap function for the terrain_defense class.
static lg::log_domain log_config("config")
std::vector< terrain_code > ter_list
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
std::map< std::string, t_string, res_compare > string_map_res
The parameters used when calculating a terrain-based value.
int default_value
The default value (if no data is available).
bool use_move
Whether to look at underlying movement or defense terrains.
parameters(int min, int max, int(*eval_fun)(int)=nullptr, bool move=true, bool high=false)
int max_value
The largest allowable value.
bool high_is_good
Whether we are looking for highest or lowest (unless inverted by the underlying terrain).
int(* eval)(int)
Converter for values taken from a config.
int min_value
The smallest allowable value.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...