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