30 #include <boost/assign.hpp>
31 #include <boost/make_shared.hpp>
35 #define ERR_CF LOG_STREAM(err, log_config)
36 #define WRN_CF LOG_STREAM(warn, log_config)
45 int config_to_max(
int value)
47 return value < 0 ? -value :
value;
51 int config_to_min(
int value)
53 return value < 0 ? -value : 0;
70 parameters(
int min,
int max,
int (*eval_fun)(
int)=
nullptr,
bool move=
true,
bool high=
false) :
71 min_value(min), max_value(max), default_value(high ? min : max),
72 eval(eval_fun), use_move(move), high_is_good(high)
116 void merge(
const config & new_values,
bool overwrite,
123 {
return value(terrain, fallback, 0); }
133 const terrain_info * fallback,
unsigned recurse_count)
const;
136 const terrain_info * fallback,
unsigned recurse_count)
const;
139 typedef std::map<t_translation::t_terrain, int>
cache_t;
170 bool overwrite)
const
174 if (
a.second != cfg_[
a.first] )
179 if (
a.second.to_int() != 0 )
202 cfg_.merge_attributes(new_values);
206 int old = dest.
to_int(params_.max_value);
212 int value = abs(old) +
a.second.to_int(0);
213 value = std::max(params_.min_value, std::min(value, params_.max_value));
238 if ( child_name.empty() )
259 fallback->
write(merged,
"",
true);
275 unsigned recurse_count)
const
278 if ( recurse_count > 100 ) {
279 ERR_CF <<
"infinite terrain_info recursion on "
280 << (params_.use_move ?
"movement" :
"defense") <<
": "
282 <<
" depth " << recurse_count <<
'\n';
283 return params_.default_value;
294 tdata->underlying_mvt_terrain(terrain) :
295 tdata->underlying_def_terrain(terrain);
296 assert(!underlying.empty());
299 if ( underlying.size() == 1 && underlying.front() ==
terrain )
302 int result = params_.default_value;
304 const std::string &
id = tdata->get_terrain_info(terrain).id();
307 result =
val->to_int(params_.default_value);
308 if ( params_.eval !=
nullptr )
309 result = params_.eval(result);
311 else if ( fallback !=
nullptr ) {
313 result = fallback->
value(terrain);
317 if ( result < params_.min_value ) {
318 WRN_CF <<
"Terrain '" << terrain <<
"' has evaluated to " << result
319 <<
" (" << (params_.use_move ?
"cost" :
"defense")
320 <<
"), which is less than " << params_.min_value
321 <<
"; resetting to " << params_.min_value <<
".\n";
322 result = params_.min_value;
324 if ( result > params_.max_value ) {
325 WRN_CF <<
"Terrain '" << terrain <<
"' has evaluated to " << result
326 <<
" (" << (params_.use_move ?
"cost" :
"defense")
327 <<
"), which is more than " << params_.max_value
328 <<
"; resetting to " << params_.max_value <<
".\n";
329 result = params_.max_value;
337 bool prefer_high = params_.high_is_good;
338 int result = params_.default_value;
341 result = result == params_.max_value ? params_.min_value :
345 t_translation::t_list::const_iterator
i;
346 for (
i = underlying.begin();
i != underlying.end(); ++
i )
350 prefer_high = params_.high_is_good;
354 prefer_high = !params_.high_is_good;
358 const int num =
value(*
i, fallback, recurse_count + 1);
360 if ( ( prefer_high && num > result) ||
361 (!prefer_high && num < result) )
380 unsigned recurse_count)
const
383 std::pair<cache_t::iterator, bool> cache_it =
384 cache_.insert(std::make_pair(terrain, -127));
385 if ( cache_it.second )
387 cache_it.first->second = calc_value(terrain, fallback, recurse_count);
389 return cache_it.first->second;
429 data_(new
data(cfg, params)),
450 data_(fallback ? that.data_ : that.get_merged()),
451 merged_data_(that.merged_data_),
474 if (
this != &that ) {
491 merged_data_.reset();
492 data_->clear_cache(cascade_);
501 return data_->empty();
513 if ( !data_->config_has_changes(new_values, overwrite) )
519 merged_data_.reset();
522 if ( !data_.unique() ) {
523 data_.reset(
new data(*data_));
535 cascade_->make_unique_cascade();
538 data_->merge(new_values, overwrite, cascade_);
562 data_->write(cfg, child_name);
564 data_->write(cfg, child_name,
fallback_);
579 merged_data_ = data_;
581 else if ( data_->empty() )
588 write(merged,
"",
true);
589 merged_data_ = boost::make_shared<data>(merged, data_->params());
601 if ( !data_.unique() )
603 const_cast<terrain_info *>(
this)->data_.reset(
new data(*data_));
606 cascade_->make_unique_cascade();
615 if ( !data_.unique() )
617 const_cast<terrain_info *>(
this)->data_.reset(
new data(*data_));
635 result[attrb.first] = attrb.second;
647 return cfg_[attack.
type()].to_int(100);
656 return cfg_[damage_type].to_int(100);
670 cfg_.merge_attributes(new_data);
674 dest = std::max(0, dest.
to_int(100) +
a.second.to_int(0));
688 if ( child_name.empty() )
716 movement_(cfg.child_or_empty(
"movement_costs"), nullptr, &vision_),
717 vision_(cfg.child_or_empty(
"vision_costs"), &movement_, &jamming_),
718 jamming_(cfg.child_or_empty(
"jamming_costs"), &vision_, nullptr),
719 defense_(cfg.child_or_empty(
"defense")),
720 resist_(cfg.child_or_empty(
"resistance")),
721 flying_(cfg[
"flies"].to_bool(false))
730 movement_(that.movement_, nullptr, &vision_),
731 vision_(that.vision_, &movement_, &jamming_),
732 jamming_(that.jamming_, &vision_, nullptr),
733 defense_(that.defense_),
734 resist_(that.resist_),
735 flying_(that.flying_)
787 "vision_costs",
"jamming_costs",
"defense",
"resistance"};
801 cfg[
"flying"] =
true;
child_itors child_range(const std::string &key)
const parameters & params() const
Read-only access to our parameters.
cache_t cache_
Cache of values based on the config.
parameters(int min, int max, int(*eval_fun)(int)=nullptr, bool move=true, bool high=false)
Whether we are looking for highest or lowest (unless inverted by the underlying terrain).
int calc_value(const t_translation::t_terrain &terrain, const terrain_info *fallback, unsigned recurse_count) const
Calculates the value associated with the given terrain.
config cfg_
Config describing the terrain values.
void clear_cache() const
Clears the cache of values.
data(const parameters ¶ms)
Constructor.
const terrain_info *const fallback_
Created as needed.
const boost::shared_ptr< data > & get_merged() const
Returns a pointer to data the incorporates our fallback.
int max_value
The smallest allowable value.
void clear_cache(const terrain_info *cascade) const
Clears the cached data (presumably our fallback has changed).
void make_unique_fallback() const
Ensures our data is not shared, and propagates to our fallback.
void write(config &cfg, const std::string &child_name="", bool merged=true) const
Writes our data to a config.
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
boost::shared_ptr< data > merged_data_
Never nullptr.
movetype()
Default constructor.
attribute_map::value_type attribute
static const parameters params_
int resistance_against(const attack_type &attack) const
Returns the resistance against the indicated attack.
~terrain_info()
Destructor.
boost::shared_ptr< data > data_
GLuint const GLfloat * val
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
void write(config &cfg) const
Writes the movement type data to the provided config.
void merge(const config &new_cfg, bool overwrite=true)
Merges the given config over the existing data.
The basic "size" of the unit - flying, small land, large land, etc.
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
bool capped(const t_translation::t_terrain &terrain) const
Returns whether there is a defense cap associated to this terrain.
utils::string_map damage_table() const
Returns a map from attack types to resistances.
Variant for storing WML attributes.
void write(config &out_cfg, const std::string &child_name) const
If there is data, writes it to the config.
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
static game_config_manager * get()
std::map< std::string, t_string > string_map
const terrain_info *const cascade_
bool use_move
Converter for values taken from a config. May be nullptr.
GLsizei const GLfloat * value
static const std::set< std::string > effects
The set of applicable effects for movement types.
GLboolean GLboolean GLboolean GLboolean a
Stores a set of data based on terrain.
config & add_child(const std::string &key)
bool empty() const
Tests for no data in this object.
static const ::config * terrain
The terrain used to create the cache.
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
const std::string & type() const
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
int default_value
The largest allowable value.
bool config_has_changes(const config &new_values, bool overwrite) const
Tests if merging new_values would result in changes.
bool high_is_good
Whether to look at underlying movement or defense terrains.
void write(config &cfg, const std::string &child_name="") const
Writes our data to a config, as a child if child_name is specified.
terrain_info & operator=(const terrain_info &that)
Assignment operator.
int value(const t_translation::t_terrain &terrain) const
Returns the value associated with the given terrain.
const_attr_itors attribute_range() const
static const terrain_info::parameters params_max_
const parameters & params_
Various parameters used when calculating values.
const tdata_cache & terrain_types() const
std::string write_terrain_code(const t_terrain &tcode)
Writes a single terrain code to a string.
const formula_callable * fallback_
void merge(const config &new_values, bool overwrite, const terrain_info *cascade)
Merges the given config over the existing costs.
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.
bool empty() const
Returns whether or not our data is empty.
static lg::log_domain log_config("config")
bool has_terrain_defense_caps(const std::set< t_translation::t_terrain > &ts) const
Returns whether or not there are any terrain caps with respect to a set of terrains.
Standard logging facilities (interface).
int to_int(int def=0) const
std::map< t_translation::t_terrain, int > cache_t
int value(const t_translation::t_terrain &terrain, const terrain_info *fallback) const
Returns the value associated with the given terrain.
The parameters used when calculating a terrain-based value.
void make_unique_cascade() const
Ensures our data is not shared, and propagates to our cascade.
A config object defines a single node in a WML file, with access to child nodes.
terrain_info(const parameters ¶ms, const terrain_info *fallback=nullptr, const terrain_info *cascade=nullptr)
Constructor.
GLsizei const GLcharARB ** string
static const terrain_info::parameters params_min_
void merge(const config &new_values, bool overwrite)
Merges the given config over the existing values.
int(* eval)(int)
The default value (if no data is available).
data(const config &cfg, const parameters ¶ms)
Constructor.
std::vector< t_terrain > t_list