The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
movetype.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Handle movement types.
18  */
19 
20 #include "movetype.hpp"
21 
22 #include "game_board.hpp"
23 #include "game_config_manager.hpp"
24 #include "log.hpp"
25 #include "map/map.hpp"
26 #include "terrain/translation.hpp"
27 #include "terrain/type_data.hpp"
28 #include "units/types.hpp" // for attack_type
29 
30 static lg::log_domain log_config("config");
31 #define ERR_CF LOG_STREAM(err, log_config)
32 #define WRN_CF LOG_STREAM(warn, log_config)
33 
34 
35 /* *** parameters *** */
36 
37 
38 namespace { // Some functions for use with parameters::eval.
39 
40  /// Converts config defense values to a "max" value.
41  int config_to_max(int value)
42  {
43  return value < 0 ? -value : value;
44  }
45 
46  /// Converts config defense values to a "min" value.
47  int config_to_min(int value)
48  {
49  return value < 0 ? -value : 0;
50  }
51 }
52 
53 
54 /// The parameters used when calculating a terrain-based value.
56 {
57  int min_value; /// The smallest allowable value.
58  int max_value; /// The largest allowable value.
59  int default_value; /// The default value (if no data is available).
60 
61  int (*eval)(int); /// Converter for values taken from a config. May be nullptr.
62 
63  bool use_move; /// Whether to look at underlying movement or defense terrains.
64  bool high_is_good; /// Whether we are looking for highest or lowest (unless inverted by the underlying terrain).
65 
66  parameters(int min, int max, int (*eval_fun)(int)=nullptr, bool move=true, bool high=false) :
67  min_value(min), max_value(max), default_value(high ? min : max),
68  eval(eval_fun), use_move(move), high_is_good(high)
69  {}
70 };
71 
72 
75 
77  movetype::terrain_defense::params_min_(0, 100, config_to_min, false, true);
79  movetype::terrain_defense::params_max_(0, 100, config_to_max, false, false);
80 
81 
82 /* *** data *** */
83 
84 
86 {
87 public:
88  /// Constructor.
89  /// @a params must be long-lived (typically a static variable).
90  explicit data(const parameters & params) :
91  cfg_(), cache_(), params_(params)
92  {}
93  /// Constructor.
94  /// @a params must be long-lived (typically a static variable).
95  data(const config & cfg, const parameters & params) :
96  cfg_(cfg), cache_(), params_(params)
97  {}
98 
99  // The copy constructor does not bother copying the cache since
100  // typically the cache will be cleared shortly after the copy.
101  data(const data & that) :
102  cfg_(that.cfg_), cache_(), params_(that.params_)
103  {}
104 
105  /// Clears the cached data (presumably our fallback has changed).
106  void clear_cache(const terrain_info * cascade) const;
107  /// Tests if merging @a new_values would result in changes.
108  bool config_has_changes(const config & new_values, bool overwrite) const;
109  /// Tests for no data in this object.
110  bool empty() const { return cfg_.empty(); }
111  /// Merges the given config over the existing costs.
112  void merge(const config & new_values, bool overwrite,
113  const terrain_info * cascade);
114  /// Read-only access to our parameters.
115  const parameters & params() const { return params_; }
116  /// Returns the value associated with the given terrain.
118  const terrain_info * fallback) const
119  { return value(terrain, fallback, 0); }
120  /// If there is data, writes it to the config.
121  void write(config & out_cfg, const std::string & child_name) const;
122  /// If there is (merged) data, writes it to the config.
123  void write(config & out_cfg, const std::string & child_name,
124  const terrain_info * fallback) const;
125 
126 private:
127  /// Calculates the value associated with the given terrain.
129  const terrain_info * fallback, unsigned recurse_count) const;
130  /// Returns the value associated with the given terrain (possibly cached).
132  const terrain_info * fallback, unsigned recurse_count) const;
133 
134 private:
135  typedef std::map<t_translation::terrain_code, int> cache_t;
136 
137  /// Config describing the terrain values.
139  /// Cache of values based on the config.
140  mutable cache_t cache_;
141  /// Various parameters used when calculating values.
143 };
144 
145 
146 /**
147  * Clears the cached data (presumably our fallback has changed).
148  * @param[in] cascade Cache clearing will be cascaded into this terrain_info.
149  */
151 {
152  cache_.clear();
153  // Cascade the clear to whichever terrain_info falls back on us.
154  if ( cascade )
155  cascade->clear_cache();
156 }
157 
158 
159 /**
160  * Tests if merging @a new_values would result in changes.
161  * This allows the shared data to actually work, as otherwise each unit created
162  * via WML (including unstored units) would "overwrite" its movement data with
163  * a usually identical copy and thus break the sharing.
164  */
166  bool overwrite) const
167 {
168  if ( overwrite ) {
169  for (const config::attribute & a : new_values.attribute_range())
170  if ( a.second != cfg_[a.first] )
171  return true;
172  }
173  else {
174  for (const config::attribute & a : new_values.attribute_range())
175  if ( a.second.to_int() != 0 )
176  return true;
177  }
178 
179  // If we make it here, new_values has no changes for us.
180  return false;
181 }
182 
183 
184 /**
185  * Merges the given config over the existing costs.
186  * @param[in] new_values The new values.
187  * @param[in] overwrite If true, the new values overwrite the old.
188  * If false, the new values are added to the old.
189  * @param[in] cascade Cache clearing will be cascaded into this terrain_info.
190  */
191 void movetype::terrain_info::data::merge(const config & new_values, bool overwrite,
192  const terrain_info * cascade)
193 {
194  if ( overwrite )
195  // We do not support child tags here, so do not copy any that might
196  // be in the input. (If in the future we need to support child tags,
197  // change "merge_attributes" to "merge_with".)
198  cfg_.merge_attributes(new_values);
199  else {
200  for (const config::attribute & a : new_values.attribute_range()) {
201  config::attribute_value & dest = cfg_[a.first];
202  int old = dest.to_int(params_.max_value);
203 
204  // The new value is the absolute value of the old plus the
205  // provided value, capped between minimum and maximum, then
206  // given the sign of the old value.
207  // (Think defenses for why we might have negative values.)
208  int value = std::abs(old) + a.second.to_int(0);
209  value = std::max(params_.min_value, std::min(value, params_.max_value));
210  if ( old < 0 )
211  value = -value;
212 
213  dest = value;
214  }
215  }
216 
217  // The new data has invalidated the cache.
218  clear_cache(cascade);
219 }
220 
221 
222 /**
223  * If there is data, writes it to a config.
224  * @param[out] out_cfg The config that will receive the data.
225  * @param[in] child_name If not empty, create and write to a child config with this tag.
226  * This child will *not* be created if there is no data to write.
227  */
229  config & out_cfg, const std::string & child_name) const
230 {
231  if ( cfg_.empty() )
232  return;
233 
234  if ( child_name.empty() )
235  out_cfg.merge_with(cfg_);
236  else
237  out_cfg.add_child(child_name, cfg_);
238 }
239 
240 
241 /**
242  * Writes merged data to a config.
243  * @param[out] out_cfg The config that will receive the data.
244  * @param[in] child_name If not empty, create and write to a child config with this tag.
245  * This *will* be created even if there is no data to write.
246  * @param[in] fallback If not nullptr, its data will be merged with ours for the write.
247  */
249  config & out_cfg, const std::string & child_name, const terrain_info * fallback) const
250 {
251  // Get a place to write to.
252  config & merged = child_name.empty() ? out_cfg : out_cfg.add_child(child_name);
253 
254  if ( fallback )
255  fallback->write(merged, "", true);
256  merged.merge_with(cfg_);
257 }
258 
259 
260 /**
261  * Calculates the value associated with the given terrain.
262  * This is separate from value() to separate the calculating of the
263  * value from the caching of it.
264  * @param[in] terrain The terrain whose value is requested.
265  * @param[in] fallback Consulted if we are missing data.
266  * @param[in] recurse_count Detects (probable) infinite recursion.
267  */
270  const terrain_info * fallback,
271  unsigned recurse_count) const
272 {
273  // Infinite recursion detection:
274  if ( recurse_count > 100 ) {
275  ERR_CF << "infinite terrain_info recursion on "
276  << (params_.use_move ? "movement" : "defense") << ": "
278  << " depth " << recurse_count << '\n';
279  return params_.default_value;
280  }
281 
282  ter_data_cache tdata;
284  tdata = game_config_manager::get()->terrain_types(); //This permits to get terrain info in unit help pages from the help in title screen, even if there is no residual gamemap object
285  }
286  assert(tdata);
287 
288  // Get a list of underlying terrains.
289  const t_translation::ter_list & underlying = params_.use_move ?
290  tdata->underlying_mvt_terrain(terrain) :
291  tdata->underlying_def_terrain(terrain);
292  assert(!underlying.empty());
293 
294 
295  if ( underlying.size() == 1 && underlying.front() == terrain )
296  {
297  // This is not an alias; get the value directly.
298  int result = params_.default_value;
299 
300  const std::string & id = tdata->get_terrain_info(terrain).id();
301  if (const config::attribute_value *val = cfg_.get(id)) {
302  // Read the value from our config.
303  result = val->to_int(params_.default_value);
304  if ( params_.eval != nullptr )
305  result = params_.eval(result);
306  }
307  else if ( fallback != nullptr ) {
308  // Get the value from our fallback.
309  result = fallback->value(terrain);
310  }
311 
312  // Validate the value.
313  if ( result < params_.min_value ) {
314  WRN_CF << "Terrain '" << terrain << "' has evaluated to " << result
315  << " (" << (params_.use_move ? "cost" : "defense")
316  << "), which is less than " << params_.min_value
317  << "; resetting to " << params_.min_value << ".\n";
318  result = params_.min_value;
319  }
320  if ( result > params_.max_value ) {
321  WRN_CF << "Terrain '" << terrain << "' has evaluated to " << result
322  << " (" << (params_.use_move ? "cost" : "defense")
323  << "), which is more than " << params_.max_value
324  << "; resetting to " << params_.max_value << ".\n";
325  result = params_.max_value;
326  }
327 
328  return result;
329  }
330  else
331  {
332  // This is an alias; select the best of all underlying terrains.
333  bool prefer_high = params_.high_is_good;
334  int result = params_.default_value;
335  if ( underlying.front() == t_translation::MINUS )
336  // Use the other value as the initial value.
337  result = result == params_.max_value ? params_.min_value :
338  params_.max_value;
339 
340  // Loop through all underlying terrains.
341  t_translation::ter_list::const_iterator i;
342  for ( i = underlying.begin(); i != underlying.end(); ++i )
343  {
344  if ( *i == t_translation::PLUS ) {
345  // Prefer what is good.
346  prefer_high = params_.high_is_good;
347  }
348  else if ( *i == t_translation::MINUS ) {
349  // Prefer what is bad.
350  prefer_high = !params_.high_is_good;
351  }
352  else {
353  // Test the underlying terrain's value against the best so far.
354  const int num = value(*i, fallback, recurse_count + 1);
355 
356  if ( ( prefer_high && num > result) ||
357  (!prefer_high && num < result) )
358  result = num;
359  }
360  }
361 
362  return result;
363  }
364 }
365 
366 
367 /**
368  * Returns the value associated with the given terrain (possibly cached).
369  * @param[in] terrain The terrain whose value is requested.
370  * @param[in] fallback Consulted if we are missing data.
371  * @param[in] recurse_count Detects (probable) infinite recursion.
372  */
375  const terrain_info * fallback,
376  unsigned recurse_count) const
377 {
378  // Check the cache.
379  std::pair<cache_t::iterator, bool> cache_it =
380  cache_.emplace(terrain, -127); // Bogus value that should never be seen.
381  if ( cache_it.second )
382  // The cache did not have an entry for this terrain, so calculate the value.
383  cache_it.first->second = calc_value(terrain, fallback, recurse_count);
384 
385  return cache_it.first->second;
386 }
387 
388 
389 /* *** terrain_info *** */
390 
391 
392 /**
393  * Constructor.
394  * @param[in] params The parameters to use when calculating values.
395  * This is stored as a reference, so it must be long-lived (typically a static variable).
396  * @param[in] fallback Used as a backup in case we are asked for data we do not have (think vision costs falling back to movement costs).
397  * @param[in] cascade A terrain_info that uses us as a fallback. (Needed to sync cache clearing.)
398  * @note The fallback/cascade mechanism is a bit fragile and really should only
399  * be used by movetype.
400  */
402  const terrain_info * fallback,
403  const terrain_info * cascade) :
404  data_(new data(params)),
405  merged_data_(),
406  fallback_(fallback),
407  cascade_(cascade)
408 {
409 }
410 
411 
412 /**
413  * Constructor.
414  * @param[in] cfg An initial data set.
415  * @param[in] params The parameters to use when calculating values.
416  * This is stored as a reference, so it must be long-lived (typically a static variable).
417  * @param[in] fallback Used as a backup in case we are asked for data we do not have (think vision costs falling back to movement costs).
418  * @param[in] cascade A terrain_info that uses us as a fallback. (Needed to sync cache clearing.)
419  * @note The fallback/cascade mechanism is a bit fragile and really should only
420  * be used by movetype.
421  */
423  const terrain_info * fallback,
424  const terrain_info * cascade) :
425  data_(new data(cfg, params)),
426  merged_data_(),
427  fallback_(fallback),
428  cascade_(cascade)
429 {
430 }
431 
432 
433 /**
434  * Copy constructor.
435  * @param[in] that The terran_info to copy.
436  * @param[in] fallback Used as a backup in case we are asked for data we do not have (think vision costs falling back to movement costs).
437  * @param[in] cascade A terrain_info that uses us as a fallback. (Needed to sync cache clearing.)
438  * @note The fallback/cascade mechanism is a bit fragile and really should only
439  * be used by movetype.
440  */
442  const terrain_info * fallback,
443  const terrain_info * cascade) :
444  // If we do not have a fallback, we need to incorporate that's fallback.
445  // (See also the assignment operator.)
446  data_(fallback ? that.data_ : that.get_merged()),
447  merged_data_(that.merged_data_),
448  fallback_(fallback),
449  cascade_(cascade)
450 {
451 }
452 
453 
454 /**
455  * Destructor
456  */
458 {
459  // While this appears to be simply the default destructor, it needs
460  // to be defined in this file so that it knows about ~data(), which
461  // is called from the smart pointers' destructor.
462 }
463 
464 
465 /**
466  * Assignment operator.
467  */
469 {
470  if ( this != &that ) {
471  // If we do not have a fallback, we need to incorporate that's fallback.
472  // (See also the copy constructor.)
473  data_ = fallback_ ? that.data_ : that.get_merged();
474  merged_data_ = that.merged_data_;
475  // We do not change our fallback nor our cascade.
476  }
477 
478  return *this;
479 }
480 
481 
482 /**
483  * Clears the cache of values.
484  */
486 {
487  merged_data_.reset();
488  data_->clear_cache(cascade_);
489 }
490 
491 
492 /**
493  * Returns whether or not our data is empty.
494  */
496 {
497  return data_->empty();
498 }
499 
500 
501 /**
502  * Merges the given config over the existing values.
503  * @param[in] new_values The new values.
504  * @param[in] overwrite If true, the new values overwrite the old.
505  * If false, the new values are added to the old.
506  */
507 void movetype::terrain_info::merge(const config & new_values, bool overwrite)
508 {
509  if ( !data_->config_has_changes(new_values, overwrite) )
510  // Nothing will change, so skip the copy-on-write.
511  return;
512 
513  // Reset merged_data_ before seeing if data_ is unique, since the two might
514  // point to the same thing.
515  merged_data_.reset();
516 
517  // Copy-on-write.
518  if ( !data_.unique() ) {
519  data_.reset(new data(*data_));
520  // We also need to make copies of our fallback and cascade.
521  // This is to keep the caching manageable, as this means each
522  // individual movetype will either share *all* of its cost data
523  // or not share *all* of its cost data. In particular, we avoid:
524  // 1) many sets of (unshared) vision costs whose cache would need
525  // to be cleared when a shared set of movement costs changes;
526  // 2) a caching nightmare when shared vision costs fallback to
527  // unshared movement costs.
528  if ( fallback_ )
529  fallback_->make_unique_fallback();
530  if ( cascade_ )
531  cascade_->make_unique_cascade();
532  }
533 
534  data_->merge(new_values, overwrite, cascade_);
535 }
536 
537 
538 /**
539  * Returns the value associated with the given terrain.
540  */
542 {
543  return data_->value(terrain, fallback_);
544 }
545 
546 
547 /**
548  * Writes our data to a config.
549  * @param[out] cfg The config that will receive the data.
550  * @param[in] child_name If not empty, create and write to a child config with this tag.
551  * @param[in] merged If true, our data will be merged with our fallback's, and it is possible an empty child will be created.
552  * If false, data will not be merged, and an empty child will not be created.
553  */
554 void movetype::terrain_info::write(config & cfg, const std::string & child_name,
555  bool merged) const
556 {
557  if ( !merged )
558  data_->write(cfg, child_name);
559  else
560  data_->write(cfg, child_name, fallback_);
561 }
562 
563 
564 /**
565  * Returns a pointer to data the incorporates our fallback.
566  */
567 const std::shared_ptr<movetype::terrain_info::data> &
569 {
570  // Create-on-demand.
571  if ( !merged_data_ )
572  {
573  if ( !fallback_ )
574  // Nothing to incorporate.
575  merged_data_ = data_;
576 
577  else if ( data_->empty() )
578  // Pure fallback.
579  merged_data_ = fallback_->get_merged();
580 
581  else {
582  // Need to merge data.
583  config merged;
584  write(merged, "", true);
585  merged_data_ = std::make_shared<data>(merged, data_->params());
586  }
587  }
588  return merged_data_;
589 }
590 
591 
592 /**
593  * Ensures our data is not shared, and propagates to our cascade.
594  */
596 {
597  if ( !data_.unique() )
598  // Const hack because this is not really changing the data.
599  const_cast<terrain_info *>(this)->data_.reset(new data(*data_));
600 
601  if ( cascade_ )
602  cascade_->make_unique_cascade();
603 }
604 
605 
606 /**
607  * Ensures our data is not shared, and propagates to our fallback.
608  */
610 {
611  if ( !data_.unique() )
612  // Const hack because this is not really changing the data.
613  const_cast<terrain_info *>(this)->data_.reset(new data(*data_));
614 
615  if ( fallback_ )
616  fallback_->make_unique_fallback();
617 }
618 
619 
620 /* *** resistances *** */
621 
622 
623 /**
624  * Returns a map from attack types to resistances.
625  */
627 {
628  utils::string_map result;
629 
630  for (const config::attribute & attrb : cfg_.attribute_range()) {
631  result[attrb.first] = attrb.second;
632  }
633 
634  return result;
635 }
636 
637 
638 /**
639  * Returns the resistance against the indicated attack.
640  */
642 {
643  return cfg_[attack.type()].to_int(100);
644 }
645 
646 
647 /**
648  * Returns the resistance against the indicated damage type.
649  */
651 {
652  return cfg_[damage_type].to_int(100);
653 }
654 
655 
656 /**
657  * Merges the given config over the existing costs.
658  * If @a overwrite is false, the new values will be added to the old.
659  */
660 void movetype::resistances::merge(const config & new_data, bool overwrite)
661 {
662  if ( overwrite )
663  // We do not support child tags here, so do not copy any that might
664  // be in the input. (If in the future we need to support child tags,
665  // change "merge_attributes" to "merge_with".)
666  cfg_.merge_attributes(new_data);
667  else
668  for (const config::attribute & a : new_data.attribute_range()) {
669  config::attribute_value & dest = cfg_[a.first];
670  dest = std::max(0, dest.to_int(100) + a.second.to_int(0));
671  }
672 }
673 
674 
675 /**
676  * Writes our data to a config, as a child if @a child_name is specified.
677  * (No child is created if there is no data.)
678  */
679 void movetype::resistances::write(config & out_cfg, const std::string & child_name) const
680 {
681  if ( cfg_.empty() )
682  return;
683 
684  if ( child_name.empty() )
685  out_cfg.merge_with(cfg_);
686  else
687  out_cfg.add_child(child_name, cfg_);
688 }
689 
690 
691 /* *** movetype *** */
692 
693 
694 /**
695  * Default constructor
696  */
698  movement_(nullptr, &vision_), // This is not access before initialization; the address is merely stored at this point.
699  vision_(&movement_, &jamming_), // This is not access before initialization; the address is merely stored at this point.
700  jamming_(&vision_, nullptr),
701  defense_(),
702  resist_(),
703  flying_(false)
704 {
705 }
706 
707 
708 /**
709  * Constructor from a config
710  */
712  movement_(cfg.child_or_empty("movement_costs"), nullptr, &vision_), // This is not access before initialization; the address is merely stored at this point.
713  vision_(cfg.child_or_empty("vision_costs"), &movement_, &jamming_), // This is not access before initialization; the address is merely stored at this point.
714  jamming_(cfg.child_or_empty("jamming_costs"), &vision_, nullptr),
715  defense_(cfg.child_or_empty("defense")),
716  resist_(cfg.child_or_empty("resistance")),
717  flying_(cfg["flies"].to_bool(false))
718 {
719 }
720 
721 
722 /**
723  * Copy constructor
724  */
726  movement_(that.movement_, nullptr, &vision_), // This is not access before initialization; the address is merely stored at this point.
727  vision_(that.vision_, &movement_, &jamming_), // This is not access before initialization; the address is merely stored at this point.
728  jamming_(that.jamming_, &vision_, nullptr),
729  defense_(that.defense_),
730  resist_(that.resist_),
731  flying_(that.flying_)
732 {
733 }
734 
735 /**
736  * Checks if we have a defense cap (nontrivial min value) for any of the given terrain types.
737  */
738 bool movetype::has_terrain_defense_caps(const std::set<t_translation::terrain_code> & ts) const {
739  for (const t_translation::terrain_code & t : ts) {
740  if (defense_.capped(t))
741  return true;
742  }
743  return false;
744 }
745 
746 /**
747  * Merges the given config over the existing data.
748  * If @a overwrite is false, the new values will be added to the old.
749  */
750 void movetype::merge(const config & new_cfg, bool overwrite)
751 {
752  for (const config & child : new_cfg.child_range("movement_costs")) {
753  movement_.merge(child, overwrite);
754  }
755 
756  for (const config & child : new_cfg.child_range("vision_costs")) {
757  vision_.merge(child, overwrite);
758  }
759 
760  for (const config & child : new_cfg.child_range("jamming_costs")) {
761  jamming_.merge(child, overwrite);
762  }
763 
764  for (const config & child : new_cfg.child_range("defense")) {
765  defense_.merge(child, overwrite);
766  }
767 
768  for (const config & child : new_cfg.child_range("resistance")) {
769  resist_.merge(child, overwrite);
770  }
771 
772  // "flies" is used when WML defines a movetype.
773  // "flying" is used when WML defines a unit.
774  // It's easier to support both than to track which case we are in.
775  flying_ = new_cfg["flies"].to_bool(flying_);
776  flying_ = new_cfg["flying"].to_bool(flying_);
777 }
778 
779 /**
780  * The set of strings defining effects which apply to movetypes.
781  */
782 const std::set<std::string> movetype::effects {"movement_costs",
783  "vision_costs", "jamming_costs", "defense", "resistance"};
784 
785 /**
786  * Writes the movement type data to the provided config.
787  */
788 void movetype::write(config & cfg) const
789 {
790  movement_.write(cfg, "movement_costs", false);
791  vision_.write(cfg, "vision_costs", false);
792  jamming_.write(cfg, "jamming_costs", false);
793  defense_.write(cfg, "defense");
794  resist_.write(cfg, "resistance");
795 
796  if ( flying_ )
797  cfg["flying"] = true;
798 }
799 
int value(const t_translation::terrain_code &terrain) const
Returns the value associated with the given terrain.
Definition: movetype.cpp:541
const parameters & params() const
Read-only access to our parameters.
Definition: movetype.cpp:115
static const std::set< std::string > effects
The set of applicable effects for movement types.
Definition: movetype.hpp:231
std::vector< char_t > string
cache_t cache_
Cache of values based on the config.
Definition: movetype.cpp:140
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).
Definition: movetype.cpp:66
config cfg_
Config describing the terrain values.
Definition: movetype.cpp:138
void clear_cache() const
Clears the cache of values.
Definition: movetype.cpp:485
std::map< std::string, t_string > string_map
data(const parameters &params)
Constructor.
Definition: movetype.cpp:90
const terrain_info *const fallback_
Created as needed.
Definition: movetype.hpp:75
bool capped(const t_translation::terrain_code &terrain) const
Returns whether there is a defense cap associated to this terrain.
Definition: movetype.hpp:132
std::map< t_translation::terrain_code, int > cache_t
Definition: movetype.cpp:135
int max_value
The smallest allowable value.
Definition: movetype.cpp:58
void clear_cache(const terrain_info *cascade) const
Clears the cached data (presumably our fallback has changed).
Definition: movetype.cpp:150
Variant for storing WML attributes.
void make_unique_fallback() const
Ensures our data is not shared, and propagates to our fallback.
Definition: movetype.cpp:609
#define a
void write(config &cfg, const std::string &child_name="", bool merged=true) const
Writes our data to a config.
Definition: movetype.cpp:554
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
Definition: movetype.hpp:83
movetype()
Default constructor.
Definition: movetype.cpp:697
child_itors child_range(config_key_type key)
Definition: config.cpp:362
data(const data &that)
Definition: movetype.cpp:101
attribute_map::value_type attribute
Definition: config.hpp:257
static const parameters params_
Definition: movetype.hpp:88
int resistance_against(const attack_type &attack) const
Returns the resistance against the indicated attack.
Definition: movetype.cpp:641
~terrain_info()
Destructor.
Definition: movetype.cpp:457
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
Definition: movetype.cpp:660
void write(config &cfg) const
Writes the movement type data to the provided config.
Definition: movetype.cpp:788
void merge(const config &new_cfg, bool overwrite=true)
Merges the given config over the existing data.
Definition: movetype.cpp:750
The basic "size" of the unit - flying, small land, large land, etc.
Definition: movetype.hpp:26
bool empty() const
Definition: config.cpp:830
utils::string_map damage_table() const
Returns a map from attack types to resistances.
Definition: movetype.cpp:626
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.
Definition: movetype.cpp:738
void write(config &out_cfg, const std::string &child_name) const
If there is data, writes it to the config.
Definition: movetype.cpp:228
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
Definition: config.cpp:1113
static game_config_manager * get()
const std::shared_ptr< data > & get_merged() const
Returns a pointer to data the incorporates our fallback.
Definition: movetype.cpp:568
const terrain_info *const cascade_
Definition: movetype.hpp:76
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.
Definition: movetype.cpp:268
bool use_move
Converter for values taken from a config. May be nullptr.
Definition: movetype.cpp:63
const terrain_code MINUS
Stores a set of data based on terrain.
Definition: movetype.hpp:29
const terrain_code PLUS
bool empty() const
Tests for no data in this object.
Definition: movetype.cpp:110
terrain_costs jamming_
Definition: movetype.hpp:239
static const ::config * terrain
The terrain used to create the cache.
Definition: minimap.cpp:130
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
Definition: movetype.hpp:136
const std::string & type() const
Definition: attack_type.hpp:41
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
terrain_costs movement_
Definition: movetype.hpp:237
int default_value
The largest allowable value.
Definition: movetype.cpp:59
bool config_has_changes(const config &new_values, bool overwrite) const
Tests if merging new_values would result in changes.
Definition: movetype.cpp:165
bool high_is_good
Whether to look at underlying movement or defense terrains.
Definition: movetype.cpp:64
void write(config &cfg, const std::string &child_name="") const
Writes our data to a config, as a child if child_name is specified.
Definition: movetype.hpp:140
terrain_info & operator=(const terrain_info &that)
Assignment operator.
Definition: movetype.cpp:468
int to_int(int def=0) const
bool flying_
Definition: movetype.hpp:243
const_attr_itors attribute_range() const
Definition: config.cpp:755
static const terrain_info::parameters params_max_
Definition: movetype.hpp:120
size_t i
Definition: function.cpp:933
terrain_costs vision_
Definition: movetype.hpp:238
const parameters & params_
Various parameters used when calculating values.
Definition: movetype.cpp:142
#define ERR_CF
Definition: movetype.cpp:31
config & add_child(config_key_type key)
Definition: config.cpp:475
#define WRN_CF
Definition: movetype.cpp:32
const formula_callable * fallback_
Definition: function.cpp:721
void merge(const config &new_values, bool overwrite, const terrain_info *cascade)
Merges the given config over the existing costs.
Definition: movetype.cpp:191
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.
Definition: movetype.cpp:679
bool empty() const
Returns whether or not our data is empty.
Definition: movetype.cpp:495
static lg::log_domain log_config("config")
double t
Definition: astarsearch.cpp:64
resistances resist_
Definition: movetype.hpp:241
int value(const t_translation::terrain_code &terrain, const terrain_info *fallback) const
Returns the value associated with the given terrain.
Definition: movetype.cpp:117
terrain_defense defense_
Definition: movetype.hpp:240
std::shared_ptr< data > merged_data_
Never nullptr.
Definition: movetype.hpp:74
Standard logging facilities (interface).
std::vector< terrain_code > ter_list
Definition: translation.hpp:77
The parameters used when calculating a terrain-based value.
Definition: movetype.cpp:55
void make_unique_cascade() const
Ensures our data is not shared, and propagates to our cascade.
Definition: movetype.cpp:595
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
terrain_info(const parameters &params, const terrain_info *fallback=nullptr, const terrain_info *cascade=nullptr)
Constructor.
Definition: movetype.cpp:401
const ter_data_cache & terrain_types() const
static const terrain_info::parameters params_min_
Definition: movetype.hpp:119
void merge(const config &new_values, bool overwrite)
Merges the given config over the existing values.
Definition: movetype.cpp:507
int(* eval)(int)
The default value (if no data is available).
Definition: movetype.cpp:61
data(const config &cfg, const parameters &params)
Constructor.
Definition: movetype.cpp:95
std::shared_ptr< data > data_
Definition: movetype.hpp:73
std::shared_ptr< terrain_type_data > ter_data_cache