1 /*
2    Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3    Part of the Battle for Wesnoth Project https://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 #pragma once
16 
17 #include "units/id.hpp"
18 #include "units/ptr.hpp"
19 #include "units/types.hpp"
20 
21 #include "utils/type_trait_aliases.hpp"
22 
23 #include <bitset>
24 #include <boost/dynamic_bitset_fwd.hpp>
25 #include <boost/ptr_container/ptr_vector.hpp>
26 #include <boost/variant.hpp>
27 
28 class display;
29 class display_context;
30 class team;
31 class unit_animation_component;
32 class unit_formula_manager;
33 class vconfig;
34 struct color_t;
35 
36 namespace unit_detail
37 {
38 	template<typename T>
get_or_default(const std::unique_ptr<T> & v)39 	const T& get_or_default(const std::unique_ptr<T>& v)
40 	{
41 		if(v) {
42 			return *v;
43 		} else {
44 			static const T def;
45 			return def;
46 		}
47 	}
48 }
49 
50 // Data typedef for unit_ability_list.
51 using unit_ability = std::pair<const config*, map_location>;
52 
53 class unit_ability_list
54 {
55 public:
unit_ability_list(const map_location & loc=map_location ())56 	unit_ability_list(const map_location& loc = map_location()) : cfgs_() , loc_(loc) {}
57 
58 	// Implemented in unit_abilities.cpp
highest(const std::string & key,int def=0) const59 	std::pair<int, map_location> highest(const std::string& key, int def=0) const
60 	{
61 		return get_extremum(key, def, std::less<int>());
62 	}
lowest(const std::string & key,int def=0) const63 	std::pair<int, map_location> lowest(const std::string& key, int def=0) const
64 	{
65 		return get_extremum(key, def, std::greater<int>());
66 	}
67 
68 	template<typename TComp>
69 	std::pair<int, map_location> get_extremum(const std::string& key, int def, const TComp& comp) const;
70 
71 	// The following make this class usable with standard library algorithms and such
72 	typedef std::vector<unit_ability>::iterator       iterator;
73 	typedef std::vector<unit_ability>::const_iterator const_iterator;
74 
begin()75 	iterator       begin()        { return cfgs_.begin(); }
begin() const76 	const_iterator begin() const  { return cfgs_.begin(); }
end()77 	iterator       end()          { return cfgs_.end();   }
end() const78 	const_iterator end()   const  { return cfgs_.end();   }
79 
80 	// Vector access
empty() const81 	bool                empty() const  { return cfgs_.empty(); }
front()82 	unit_ability&       front()        { return cfgs_.front(); }
front() const83 	const unit_ability& front() const  { return cfgs_.front(); }
back()84 	unit_ability&       back()         { return cfgs_.back();  }
back() const85 	const unit_ability& back()  const  { return cfgs_.back();  }
86 
erase(const iterator & erase_it)87 	iterator erase(const iterator& erase_it)  { return cfgs_.erase(erase_it); }
push_back(const unit_ability & ability)88 	void push_back(const unit_ability& ability)  { cfgs_.push_back(ability); }
89 
loc() const90 	const map_location& loc() const { return loc_; }
91 private:
92 	// Data
93 	std::vector<unit_ability> cfgs_;
94 	map_location loc_;
95 };
96 
97 /**
98  * This class represents a *single* unit of a specific type.
99  */
100 class unit
101 {
102 public:
103 	/**
104 	 * Clear this unit status cache for all units. Currently only the hidden
105 	 * status of units is cached this way.
106 	 */
107 	static void clear_status_caches();
108 
109 	/** The path to the leader crown overlay. */
110 	static const std::string& leader_crown();
111 private:
112 	void init(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr);
113 
114 	void init(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS);
115 
116 	// Copy constructor
117 	unit(const unit& u);
118 
119 	unit();
120 
121 public:
122 	/** Initializes a unit from a config */
create(const config & cfg,bool use_traits=false,const vconfig * vcfg=nullptr)123 	static unit_ptr create(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr)
124 	{
125 		unit_ptr res(new unit());
126 		res->init(cfg, use_traits, vcfg);
127 		return res;
128 	}
129 
130 	/**
131 	 * Initializes a unit from a unit type.
132 	 *
133 	 * Only real_unit-s should have random traits, name and gender (to prevent OOS caused by RNG calls)
134 	 */
create(const unit_type & t,int side,bool real_unit,unit_race::GENDER gender=unit_race::NUM_GENDERS)135 	static unit_ptr create(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS)
136 	{
137 		unit_ptr res(new unit());
138 		res->init(t, side, real_unit, gender);
139 		return res;
140 	}
141 
clone() const142 	unit_ptr clone() const
143 	{
144 		return unit_ptr(new unit(*this));
145 	}
146 
147 	virtual ~unit();
148 
149 	void swap(unit&);
150 
151 	unit& operator=(const unit&) = delete;
152 
153 	/**
154 	 * @defgroup unit_advance Advancement functions
155 	 * @{
156 	 */
157 
158 	/** Advances this unit to another type */
159 	void advance_to(const unit_type& t, bool use_traits = false);
160 
161 	/**
162 	 * Gets the possible types this unit can advance to on level-up.
163 	 *
164 	 * @returns                   A list of type IDs this unit may advance to.
165 	 */
advances_to() const166 	const std::vector<std::string>& advances_to() const
167 	{
168 		return advances_to_;
169 	}
170 
171 	/**
172 	 * Gets the names of the possible types this unit can advance to on level-up.
173 	 *
174 	 * @returns                   A list of the names of the types this unit may advance to.
175 	 */
176 	const std::vector<std::string> advances_to_translated() const;
177 
178 	/**
179 	 * Sets this unit's advancement options.
180 	 *
181 	 * @param advances_to         A list of new type IDs this unit may advance to.
182 	 */
183 	void set_advances_to(const std::vector<std::string>& advances_to);
184 
185 	/**
186 	 * Checks whether this unit has any options to advance to.
187 	 *
188 	 * This considers both whether it has types to advance to OR whether any modifications
189 	 * specify non-type advancement options.
190 	 *
191 	 * Note this does not consider unit experience at all, it only checks option availability.
192 	 * See @ref advances if an experience check is necessary.
193 	 */
can_advance() const194 	bool can_advance() const
195 	{
196 		return !advances_to_.empty() || !get_modification_advances().empty();
197 	}
198 
199 	/**
200 	 * Checks whether this unit is eligible for level-up.
201 	 *
202 	 * @retval true              This unit has sufficient experience to level up and has advancement
203 	 *                           options available.
204 	 */
advances() const205 	bool advances() const
206 	{
207 		return experience_ >= max_experience() && can_advance();
208 	}
209 
210 	/**
211 	 * Gets and image path and and associated description for each advancement option.
212 	 *
213 	 * Covers both type and modification-based advancements.
214 	 *
215 	 * @returns                  A data map, in image/description format. If the option is a unit type,
216 	 *                           advancement, the key is the type's image and the value the type ID.
217 	 *
218 	 *                           If the option is a modification, the key and value are set from config data
219 	 *                           (see @ref get_modification_advances).
220 	 */
221 	std::map<std::string, std::string> advancement_icons() const;
222 
223 	/**
224 	 * Gets any non-typed advanced options set by modifications.
225 	 *
226 	 * These are usually used to give a unit special advancement options that don't invole transforming to a
227 	 * new type.
228 	 *
229 	 * Note this is not the raw option data. Parsing is performed to ensure each option appears only once.
230 	 * Use @ref modification_advancements is the raw data is needed.
231 	 *
232 	 * @returns                  A config list of options data. Each option is unique.
233 	 */
234 	std::vector<config> get_modification_advances() const;
235 
236 	/**
237 	 * Gets the image and description data for modification advancements.
238 	 *
239 	 * @returns                  A list of pairs of the image paths(first) and descriptions (second) for
240 	 *                           each advancement option.
241 	 */
242 	std::vector<std::pair<std::string, std::string>> amla_icons() const;
243 
244 	using advancements_list= boost::ptr_vector<config>;
245 	/** The raw, unparsed data for modification advancements. */
modification_advancements() const246 	const advancements_list& modification_advancements() const
247 	{
248 		return advancements_;
249 	}
250 
251 	/** Sets the raw modification advancement option data */
252 	void set_advancements(std::vector<config> advancements);
253 
254 	/**
255 	 * @}
256 	 * @defgroup unit_access Basic data setters and getters
257 	 * @{
258 	 **/
259 
260 public:
261 	/**
262 	 * The side this unit belongs to.
263 	 *
264 	 * Note that side numbers starts from 1, not 0, so be sure to subtract 1 if using as a container index.
265 	 */
side() const266 	int side() const
267 	{
268 		return side_;
269 	}
270 
271 	/** Sets the side this unit belongs to. */
set_side(unsigned int new_side)272 	void set_side(unsigned int new_side)
273 	{
274 		side_ = new_side;
275 	}
276 
277 	/** This unit's type, accounting for gender and variation. */
type() const278 	const unit_type& type() const
279 	{
280 		return *type_;
281 	}
282 
283 	/**
284 	 * The id of this unit's type.
285 	 *
286 	 * If you are dealing with creating units (e.g. recruitment), this is not what you want, as a
287 	 * variation can change this; use type().base_id() instead.
288 	 */
type_id() const289 	const std::string& type_id() const
290 	{
291 		return type_->id();
292 	}
293 
294 	/** Gets the translatable name of this unit's type. */
type_name() const295 	const t_string& type_name() const
296 	{
297 		return type_name_;
298 	}
299 
300 	/**
301 	 * Gets this unit's id.
302 	 *
303 	 * This is a unique string usually set by WML. It should *not* be used for internal tracking in
304 	 * the unit_map. Use @ref underlying_id for that.
305 	 */
id() const306 	const std::string& id() const
307 	{
308 		return id_;
309 	}
310 
311 	/** Sets this unit's string ID. */
set_id(const std::string & id)312 	void set_id(const std::string& id)
313 	{
314 		id_ = id;
315 	}
316 
317 	/** This unit's unique internal ID. This should *not* be used for user-facing operations. */
underlying_id() const318 	size_t underlying_id() const
319 	{
320 		return underlying_id_.value;
321 	}
322 
323 private:
324 	/** Sets the internal ID. */
325 	void set_underlying_id(n_unit::id_manager& id_manager);
326 
327 public:
328 	/** Gets this unit's translatable display name. */
name() const329 	const t_string& name() const
330 	{
331 		return name_;
332 	}
333 
334 	/**
335 	 * Sets this unit's translatable display name.
336 	 *
337 	 * This should only be used internally since it ignores the 'unrenamable' flag.
338 	 */
set_name(const t_string & name)339 	void set_name(const t_string& name)
340 	{
341 		name_ = name;
342 	}
343 
344 	/**
345 	 * Attempts to rename this unit's translatable display name, taking the 'unrenamable' flag into account.
346 	 *
347 	 * If a direct rename is desired, use @ref set_name.
348 	 * @todo should this also take a t_string?
349 	 */
rename(const std::string & name)350 	void rename(const std::string& name)
351 	{
352 		if(!unrenamable_) {
353 			name_ = name;
354 		}
355 	}
356 
357 	/**
358 	 * Whether this unit can be renamed.
359 	 *
360 	 * This flag is considered by @ref rename, but not @ref set_name.
361 	 */
unrenamable() const362 	bool unrenamable() const
363 	{
364 		return unrenamable_;
365 	}
366 
367 	/**
368 	 * Sets the 'unrenamable' flag. Usually used for scenario-specific units which should not be renamed.
369 	 */
set_unrenamable(bool unrenamable)370 	void set_unrenamable(bool unrenamable)
371 	{
372 		unrenamable_ = unrenamable;
373 	}
374 
375 	/** A detailed description of this unit. */
unit_description() const376 	t_string unit_description() const
377 	{
378 		return description_;
379 	}
380 
381 	/** The gender of this unit. */
gender() const382 	unit_race::GENDER gender() const
383 	{
384 		return gender_;
385 	}
386 
387 	/**
388 	 * The alignment of this unit.
389 	 *
390 	 * This affects the time of day during which this unit's attacks do the most damage.
391 	 */
alignment() const392 	unit_type::ALIGNMENT alignment() const
393 	{
394 		return alignment_;
395 	}
396 
397 	/** Sets the alignment of this unit. */
set_alignment(unit_type::ALIGNMENT alignment)398 	void set_alignment(unit_type::ALIGNMENT alignment)
399 	{
400 		alignment_ = alignment;
401 	}
402 
403 	/**
404 	 * Gets this unit's race.
405 	 *
406 	 * @returns                  A pointer to a unit_race object - never nullptr, but it may point
407 	 *                           to the null race.
408 	 */
race() const409 	const unit_race* race() const
410 	{
411 		return race_;
412 	}
413 
414 	/** The current number of hitpoints this unit has. */
hitpoints() const415 	int hitpoints() const
416 	{
417 		return hit_points_;
418 	}
419 
420 	/** The max number of hitpoints this unit can have. */
max_hitpoints() const421 	int max_hitpoints() const
422 	{
423 		return max_hit_points_;
424 	}
425 
426 	/** Sets the current hitpoint amount. */
set_hitpoints(int hp)427 	void set_hitpoints(int hp)
428 	{
429 		hit_points_ = hp;
430 	}
431 
432 	/** The current number of experience points this unit has. */
experience() const433 	int experience() const
434 	{
435 		return experience_;
436 	}
437 
438 	/** The max number of experience points this unit can have. */
max_experience() const439 	int max_experience() const
440 	{
441 		return max_experience_;
442 	}
443 
444 	/** The number of experience points this unit needs to level up, or 0 if current XP > max XP. */
experience_to_advance() const445 	unsigned int experience_to_advance() const
446 	{
447 		return std::max(0, max_experience_ - experience_);
448 	}
449 
450 	/** The number of experience points over max this unit has, or 0 if current XP < max XP. */
experience_overflow() const451 	unsigned int experience_overflow() const
452 	{
453 		return std::max(0, experience_ - max_experience_);
454 	}
455 
456 	/** Sets the current experience point amount. */
set_experience(int xp)457 	void set_experience(int xp)
458 	{
459 		experience_ = xp;
460 	}
461 
462 	/** The current level of this unit. */
level() const463 	int level() const
464 	{
465 		return level_;
466 	}
467 
468 	/** Sets the current level of this unit. */
set_level(int level)469 	void set_level(int level)
470 	{
471 		level_ = level;
472 	}
473 
474 	/** The ID of the variation of this unit's type. */
variation() const475 	const std::string& variation() const
476 	{
477 		return variation_;
478 	}
479 
480 	/** The ID of the undead variation (ie, dwarf, swimmer) of this unit. */
undead_variation() const481 	const std::string& undead_variation() const
482 	{
483 		return undead_variation_;
484 	}
485 
486 	/**
487 	 * An optional profile image to display in Help.
488 	 *
489 	 * @returns                   The specified image, this unit's type's sprite image if empty
490 	 *                            or 'unit_image' was set.
491 	 */
492 	std::string small_profile() const;
493 
494 	/**
495 	 * An optional profile image displays when this unit is 'speaking' via [message].
496 	 *
497 	 * @returns                   The specified image, this unit's type's sprite image if empty
498 	 *                            or 'unit_image' was set.
499 	 */
500 	std::string big_profile() const;
501 
502 	/** Whether this unit can recruit other units - ie, are they a leader unit. */
can_recruit() const503 	bool can_recruit() const
504 	{
505 		return canrecruit_;
506 	}
507 
508 	/** Sets whether this unit can recruit other units. */
set_can_recruit(bool canrecruit)509 	void set_can_recruit(bool canrecruit)
510 	{
511 		canrecruit_ = canrecruit;
512 	}
513 
514 	/** The type IDs of the other units this unit may recruit, if possible. */
recruits() const515 	const std::vector<std::string>& recruits() const
516 	{
517 		return recruit_list_;
518 	}
519 
520 	/** Sets the recruit list. */
521 	void set_recruits(const std::vector<std::string>& recruits);
522 
523 	/** How much gold is required to recruit this unit. */
cost() const524 	int cost() const
525 	{
526 		return unit_value_;
527 	}
528 
529 	/** How much gold it costs to recall this unit, or -1 if the side's default
530 	 * recall cost is used. */
recall_cost() const531 	int recall_cost() const
532 	{
533 		return recall_cost_;
534 	}
535 
536 	/** Sets the cost of recalling this unit. */
set_recall_cost(int recall_cost)537 	void set_recall_cost(int recall_cost)
538 	{
539 		recall_cost_ = recall_cost;
540 	}
541 
542 	/** Gets the filter constraints upon which units this unit may recall, if able. */
recall_filter() const543 	const config& recall_filter() const
544 	{
545 		return filter_recall_;
546 	}
547 
548 	/**
549 	 * Gets this unit's role.
550 	 *
551 	 * A role is a special string flag usually used to represent a unit's purpose in a scenario.
552 	 * It can be filtered on.
553 	 */
get_role() const554 	const std::string& get_role() const
555 	{
556 		return role_;
557 	}
558 
559 	/** Sets a unit's role */
set_role(const std::string & role)560 	void set_role(const std::string& role)
561 	{
562 		role_ = role;
563 	}
564 
565 	/**
566 	 * Gets this unit's usage. This is relevant to the AI.
567 	 *
568 	 * Usage refers to how the AI may consider utilizing this unit in combat.
569 	 * @todo document further
570 	 */
usage() const571 	std::string usage() const
572 	{
573 		return unit_detail::get_or_default(usage_);
574 	}
575 
576 	/** Sets this unit's usage. */
set_usage(const std::string & usage)577 	void set_usage(const std::string& usage)
578 	{
579 		usage_.reset(new std::string(usage));
580 	}
581 
582 	/**
583 	 * Gets any user-defined variables this unit 'owns'.
584 	 *
585 	 * These are accessible via WML if the unit's data is serialized to a variable. They're strictly
586 	 * user-facing; internal engine calculations shouldn't use this.
587 	 */
variables()588 	config& variables()
589 	{
590 		return variables_;
591 	}
592 
593 	/** Const overload of @ref variables. */
variables() const594 	const config& variables() const
595 	{
596 		return variables_;
597 	}
598 
599 	/**
600 	 * Gets whether this unit is currently hidden on the map.
601 	 * @todo document hiddenness
602 	 */
get_hidden() const603 	bool get_hidden() const
604 	{
605 		return hidden_;
606 	}
607 
608 	/** Sets whether the unit is hidden on the map. */
609 	void set_hidden(bool state) const;
610 
611 	/**
612 	 * The factor by which the HP bar should be scaled.
613 	 * @todo: document further
614 	 */
hp_bar_scaling() const615 	double hp_bar_scaling() const
616 	{
617 		return hp_bar_scaling_;
618 	}
619 
620 	/**
621 	 * The factor by which the XP bar should be scaled.
622 	 * @todo: document further
623 	 */
xp_bar_scaling() const624 	double xp_bar_scaling() const
625 	{
626 		return xp_bar_scaling_;
627 	}
628 
629 	/**
630 	 * Whether the unit has been instructed to hold its position.
631 	 * This excludes it from the unit cycling function.
632 	 * @return true if it is holding position
633 	 */
hold_position() const634 	bool hold_position() const
635 	{
636 		return hold_position_;
637 	}
638 
639 	/**
640 	 * Toggle the unit's hold position status.
641 	 */
toggle_hold_position()642 	void toggle_hold_position()
643 	{
644 		hold_position_ = !hold_position_;
645 		if(hold_position_) {
646 			end_turn_ = true;
647 		}
648 	}
649 
650 	/**
651 	 * Set whether the user ended their turn
652 	 * @todo Verify meaning and explain better
653 	 */
set_user_end_turn(bool value=true)654 	void set_user_end_turn(bool value = true)
655 	{
656 		end_turn_ = value;
657 	}
658 
659 	/**
660 	 * Toggle whether the user ended their turn
661 	 * @todo Verify meaning and explain better
662 	 */
toggle_user_end_turn()663 	void toggle_user_end_turn()
664 	{
665 		end_turn_ = !end_turn_;
666 		if(!end_turn_) {
667 			hold_position_ = false;
668 		}
669 	}
670 
671 	/**
672 	 * Check whether the user ended their turn
673 	 * @todo Verify meaning and explain better
674 	 */
user_end_turn() const675 	bool user_end_turn() const
676 	{
677 		return end_turn_;
678 	}
679 
680 	/**
681 	 * Refresh unit for the beginning of a turn
682 	 */
683 	void new_turn();
684 
685 	/**
686 	 * Refresh unit for the end of a turn
687 	 */
688 	void end_turn();
689 
690 	/**
691 	 * Refresh unit for the beginning of a new scenario
692 	 */
693 	void new_scenario();
694 
695 	/**
696 	 * Damage the unit.
697 	 * @returns true if the unit dies as a result
698 	 */
take_hit(int damage)699 	bool take_hit(int damage)
700 	{
701 		hit_points_ -= damage;
702 		return hit_points_ <= 0;
703 	}
704 
705 	/**
706 	 * Heal the unit
707 	 * @amount The number of hitpoints to gain
708 	 */
709 	void heal(int amount);
710 
711 	/**
712 	 * Fully heal the unit, restoring it to max hitpoints
713 	 */
heal_fully()714 	void heal_fully()
715 	{
716 		hit_points_ = max_hitpoints();
717 	}
718 
719 	/**
720 	 * Get the status effects currently affecting the unit.
721 	 * @return A set of status keys
722 	 */
723 	const std::set<std::string> get_states() const;
724 
725 	/**
726 	 * Check if the unit is affected by a status effect
727 	 * @param state The status effect to check
728 	 * @returns true if the unit is affected by the status effect
729 	 */
730 	bool get_state(const std::string& state) const;
731 
732 	/**
733 	 * Set whether the unit is affected by a status effect
734 	 * @param state The status effect to change
735 	 * @param value Whether the unit should be affected by the status
736 	 */
737 	void set_state(const std::string& state, bool value);
738 
739 	/**
740 	 * Built-in status effects known to the engine
741 	 */
742 	enum state_t {
743 		STATE_SLOWED = 0, ///< The unit is slowed - it moves slower and does less damage
744 		STATE_POISONED,   ///< The unit is poisoned - it loses health each turn
745 		STATE_PETRIFIED,  ///< The unit is petrified - it cannot move or be attacked
746 		STATE_UNCOVERED,  ///< The unit is uncovered - it was hiding but has been spotted
747 		STATE_NOT_MOVED,  ///< The unit has not moved @todo Explain better
748 		STATE_UNHEALABLE, ///< The unit cannot be healed
749 		STATE_GUARDIAN,   ///< The unit is a guardian - it won't move unless a target is sighted
750 		STATE_UNKNOWN = -1///< A status effect not known to the engine
751 	};
752 
753 	/**
754 	 * Set whether the unit is affected by a status effect
755 	 * @param state The status effect to change
756 	 * @param value Whether the unit should be affected by the status
757 	 */
758 	void set_state(state_t state, bool value);
759 
760 	/**
761 	 * Check if the unit is affected by a status effect
762 	 * @param state The status effect to check
763 	 * @returns true if the unit is affected by the status effect
764 	 */
765 	bool get_state(state_t state) const;
766 
767 	/**
768 	 * Convert a string status effect ID to a built-in status effect ID
769 	 * @returns the state_t representing the status, or STATE_UNKNOWN if it's not built-in
770 	 */
771 	static state_t get_known_boolean_state_id(const std::string& state);
772 
773 	/**
774 	 * Check if the unit has been poisoned
775 	 * @returns true if it's poisoned
776 	 */
poisoned() const777 	bool poisoned() const
778 	{
779 		return get_state(STATE_POISONED);
780 	}
781 
782 	/**
783 	 * Check if the unit has been petrified
784 	 * @returns true if it's petrified
785 	 */
incapacitated() const786 	bool incapacitated() const
787 	{
788 		return get_state(STATE_PETRIFIED);
789 	}
790 
791 	/**
792 	 * Check if the unit has been slowed
793 	 * @returns true if it's slowed
794 	 */
slowed() const795 	bool slowed() const
796 	{
797 		return get_state(STATE_SLOWED);
798 	}
799 
800 	/**
801 	 * @}
802 	 * @defgroup unit_atk Attack and resistance functions
803 	 * @{
804 	 */
805 
806 public:
807 	/** Gets an iterator over this unit's attacks. */
attacks()808 	attack_itors attacks()
809 	{
810 		return make_attack_itors(attacks_);
811 	}
812 
813 	/** Const overload of @ref attacks. */
attacks() const814 	const_attack_itors attacks() const
815 	{
816 		return make_attack_itors(attacks_);
817 	}
818 
819 	/**
820 	 * Adds a new attack to the unit.
821 	 * @param position An iterator pointing to the attack before which to insert the new one.
822 	 * @param args The arguments for constructing the attack
823 	 */
824 	template<typename... Args>
add_attack(attack_itors::iterator position,Args &&...args)825 	attack_ptr add_attack(attack_itors::iterator position, Args&&... args)
826 	{
827 		return *attacks_.emplace(position.base(), new attack_type(std::forward<Args>(args)...));
828 	}
829 
830 	/**
831 	 * Remove an attack from the unit
832 	 * @param atk A pointer to the attack to remove
833 	 * @return true if the attack was removed, false if it didn't exist on the unit
834 	 */
835 	bool remove_attack(attack_ptr atk);
836 
837 	/**
838 	 * Set the unit to have no attacks left for this turn.
839 	 */
840 	void remove_attacks_ai();
841 
842 	/**
843 	 * Calculates the damage this unit would take from a certain attack.
844 	 *
845 	 * @param attack              The attack to consider.
846 	 * @param attacker            Whether this unit should be considered the attacker.
847 	 * @param loc                 TODO: what does this do?
848 	 *
849 	 * @returns                   The expected damage.
850 	 */
damage_from(const attack_type & attack,bool attacker,const map_location & loc) const851 	int damage_from(const attack_type& attack, bool attacker, const map_location& loc) const
852 	{
853 		return resistance_against(attack, attacker, loc);
854 	}
855 
856 	/** The maximum number of attacks this unit may perform per turn, usually 1. */
max_attacks() const857 	int max_attacks() const
858 	{
859 		return max_attacks_;
860 	}
861 
862 	/**
863 	 * Gets the remaining number of attacks this unit can perform this turn.
864 	 *
865 	 * If the 'incapacitated' status is set, this will always be 0.
866 	 */
attacks_left() const867 	int attacks_left() const
868 	{
869 		return (attacks_left_ == 0 || incapacitated()) ? 0 : attacks_left_;
870 	}
871 
872 	/**
873 	 * Gets the remaining number of attacks this unit can perform this turn.
874 	 *
875 	 * @param base_value          If false, consider the `incapacitated` flag.
876 	 *
877 	 * @returns                   If @a base_value is true, the raw value is returned.
878 	 */
attacks_left(bool base_value) const879 	int attacks_left(bool base_value) const
880 	{
881 		return base_value ? attacks_left_ : attacks_left();
882 	}
883 
884 	/**
885 	 * Sets the number of attacks this unit has left this turn.
886 	 * @param left The number of attacks left
887 	 */
set_attacks(int left)888 	void set_attacks(int left)
889 	{
890 		attacks_left_ = std::max<int>(0, left);
891 	}
892 
893 	/**
894 	 * The unit's defense on a given terrain
895 	 * @param terrain The terrain to check
896 	 */
897 	int defense_modifier(const t_translation::terrain_code& terrain) const;
898 
899 	/**
900 	 * The unit's resistance against a given damage type
901 	 * @param damage_name The damage type
902 	 * @param attacker True if this unit is on the offensive (to resolve [resistance] abilities)
903 	 * @param loc The unit's location (to resolve [resistance] abilities)
904 	 */
905 	int resistance_against(const std::string& damage_name, bool attacker, const map_location& loc) const;
906 
907 	/**
908 	 * The unit's resistance against a given attack
909 	 * @param atk The attack
910 	 * @param attacker True if this unit is on the offensive (to resolve [resistance] abilities)
911 	 * @param loc The unit's location (to resolve [resistance] abilities)
912 	 */
resistance_against(const attack_type & atk,bool attacker,const map_location & loc) const913 	int resistance_against(const attack_type& atk, bool attacker, const map_location& loc) const
914 	{
915 		return resistance_against(atk.type(), attacker, loc);
916 	}
917 
918 	/** Gets resistances without any abilities applied. */
get_base_resistances() const919 	utils::string_map get_base_resistances() const
920 	{
921 		return movement_type_.damage_table();
922 	}
923 
924 private:
925 	bool resistance_filter_matches(const config& cfg, bool attacker, const std::string& damage_name, int res) const;
926 
927 	/**
928 	 * @}
929 	 * @defgroup unit_trait Trait and upkeep functions
930 	 * @{
931 	 */
932 public:
933 	/**
934 	 * Applies mandatory traits (e.g. undead, mechanical) to a unit and then fills in the remaining traits
935 	 * traits until no more are available (leaders have a restricted set of available traits) or the unit has
936 	 * its maximum number of traits.
937 	 *
938 	 * This routine does not apply the effects of added traits to a unit; that must be done by the caller.
939 	 *
940 	 * Note that random numbers used in config files don't work in multiplayer, so leaders should be barred
941 	 * from all random traits until that is fixed. Later the restrictions will be based on play balance.
942 	 *
943 	 * @param must_have_only      Whether random or optional traits should be included or not. If false only
944 	 *                            mandatory traits will be used.
945 	 */
946 	void generate_traits(bool must_have_only = false);
947 
948 	/**
949 	 * Gets the names of the currently registered traits.
950 	 *
951 	 * @returns                   A list of translatable trait names.
952 	 */
trait_names() const953 	const std::vector<t_string>& trait_names() const
954 	{
955 		return trait_names_;
956 	}
957 
958 	/**
959 	 * Gets the descriptions of the currently registered traits.
960 	 *
961 	 * @returns                   A list of translatable trait descriptions.
962 	 */
trait_descriptions() const963 	const std::vector<t_string>& trait_descriptions() const
964 	{
965 		return trait_descriptions_;
966 	}
967 
968 	/**
969 	 * Gets a list of the traits this unit currently has.
970 	 *
971 	 * @returns                   A list of trait IDs.
972 	 */
973 	std::vector<std::string> get_traits_list() const;
974 
975 	/**
976 	 * Register a trait's name and its description for the UI's use.
977 	 *
978 	 * The resulting data can be fetched with @ref trait_names and @ref trait_descriptions.
979 	 *
980 	 * @param trait               A config containing the trait's attributes.
981 	 * @param description         The translatable description of the trait.
982 	 */
983 	void add_trait_description(const config& trait, const t_string& description);
984 
985 	/**
986 	 * Gets the amount of gold this unit costs a side per turn.
987 	 *
988 	 * This fetches an actual numeric gold value:
989 	 * - If @rec can_recruit is true, no upkeep is paid (0 is returned).
990 	 * - If a special upkeep flag is set, the associated gold amount is returned (see @ref upkeep_value_visitor).
991 	 * - If a numeric value is already set, it is returned directly.
992 	 *
993 	 * @returns                   A gold value, evaluated based on the state of @ref upkeep_raw.
994 	 */
995 	int upkeep() const;
996 
997 	struct upkeep_full
998 	{
typeunit::upkeep_full999 		static std::string type() { static std::string v = "full"; return v; }
1000 	};
1001 
1002 	struct upkeep_loyal
1003 	{
typeunit::upkeep_loyal1004 		static std::string type() { static std::string v = "loyal"; return v; }
1005 	};
1006 
1007 	/** Visitor helper class to fetch the appropriate upkeep value. */
1008 	class upkeep_value_visitor : public boost::static_visitor<int>
1009 	{
1010 	public:
upkeep_value_visitor(const unit & unit)1011 		explicit upkeep_value_visitor(const unit& unit) : u_(unit) {}
1012 
1013 		/** Full upkeep equals the unit's level. */
operator ()(const upkeep_full &) const1014 		int operator()(const upkeep_full&) const
1015 		{
1016 			return u_.level();
1017 		}
1018 
1019 		/** Loyal units cost no upkeep. */
operator ()(const upkeep_loyal &) const1020 		int operator()(const upkeep_loyal&) const
1021 		{
1022 			return 0;
1023 		}
1024 
operator ()(int v) const1025 		int operator()(int v) const
1026 		{
1027 			return v;
1028 		}
1029 
1030 	private:
1031 		const unit& u_;
1032 	};
1033 
1034 	/** Visitor helper struct to fetch the upkeep type flag if applicable, or the the value otherwise. */
1035 	struct upkeep_type_visitor : public boost::static_visitor<std::string>
1036 	{
1037 		template<typename T>
1038 		utils::enable_if_t<!std::is_same<int, T>::value, std::string>
operator ()unit::upkeep_type_visitor1039 		operator()(T&) const
1040 		{
1041 			// Any special upkeep type should have an associated @ref type getter in its helper struct.
1042 			return T::type();
1043 		}
1044 
operator ()unit::upkeep_type_visitor1045 		std::string operator()(int v) const
1046 		{
1047 			return std::to_string(v);
1048 		}
1049 	};
1050 
1051 	using upkeep_t = boost::variant<upkeep_full, upkeep_loyal, int>;
1052 
1053 	/**
1054 	 * Gets the raw variant controlling the upkeep value.
1055 	 *
1056 	 * This should not usually be called directly. To get an actual numeric value of upkeep use @ref upkeep.
1057 	 */
upkeep_raw() const1058 	upkeep_t upkeep_raw() const
1059 	{
1060 		return upkeep_;
1061 	}
1062 
1063 	/** Sets the upkeep value to a specific value value. Does not necessarily need to be numeric */
set_upkeep(upkeep_t v)1064 	void set_upkeep(upkeep_t v)
1065 	{
1066 		upkeep_ = v;
1067 	}
1068 
1069 	/** Gets whether this unit is loyal - ie, it costs no upkeep. */
1070 	bool loyal() const;
1071 
1072 	/** Gets whether this unit is fearless - ie, unaffected by time of day. */
is_fearless() const1073 	bool is_fearless() const
1074 	{
1075 		return is_fearless_;
1076 	}
1077 
1078 	/** Gets whether this unit is healthy - ie, always rest heals. */
is_healthy() const1079 	bool is_healthy() const
1080 	{
1081 		return is_healthy_;
1082 	}
1083 
1084 	/**
1085 	 * @}
1086 	 * @defgroup unit_mvmt Movement and location functions
1087 	 * @{
1088 	 */
1089 
1090 public:
1091 	/** The maximum moves this unit has. */
total_movement() const1092 	int total_movement() const
1093 	{
1094 		return max_movement_;
1095 	}
1096 
1097 	/**
1098 	 * Gets how far a unit can move, considering the `incapacitated` flag.
1099 	 *
1100 	 * @returns                   The remaining movement, or zero if incapacitated.
1101 	 */
movement_left() const1102 	int movement_left() const
1103 	{
1104 		return (movement_ == 0 || incapacitated()) ? 0 : movement_;
1105 	}
1106 
1107 	/**
1108 	 * Gets how far a unit can move.
1109 	 *
1110 	 * @param base_value          If false, consider the `incapacitated` flag.
1111 	 *
1112 	 * @returns                   If @a base_value is true, the raw value is returned.
1113 	 */
movement_left(bool base_value) const1114 	int movement_left(bool base_value) const
1115 	{
1116 		return base_value ? movement_ : movement_left();
1117 	}
1118 
1119 	/**
1120 	 * Set this unit's remaining movement to @a moves.
1121 	 *
1122 	 * This does not affect maximum movement.
1123 	 *
1124 	 * @param moves               The new number of moves
1125 	 * @param unit_action         If to true, the "end turn" and "hold position" flags will be cleared
1126 	 *                            (as they should be if a unit acts, as opposed to the movement being set
1127 	 *                            by the engine for other reasons).
1128 	 */
1129 	void set_movement(int moves, bool unit_action = false);
1130 
1131 	/** Checks if this unit has moved. */
has_moved() const1132 	bool has_moved() const
1133 	{
1134 		return movement_left() != total_movement();
1135 	}
1136 
1137 	/** Sets the unit to have no moves left for this turn. */
1138 	void remove_movement_ai();
1139 
1140 	/**
1141 	 * Checks whether this unit is 'resting'.
1142 	 *
1143 	 * Resting refers to whether this unit has not moved yet this turn. Note that this can be true even
1144 	 * if @ref movement_left is not equal to @ref total_movement.
1145 	 */
resting() const1146 	bool resting() const
1147 	{
1148 		return resting_;
1149 	}
1150 
1151 	/** Sets this unit's resting status. */
set_resting(bool rest)1152 	void set_resting(bool rest)
1153 	{
1154 		resting_ = rest;
1155 	}
1156 
1157 	/** Tests whether the unit has a zone-of-control, considering @ref incapacitated. */
emits_zoc() const1158 	bool emits_zoc() const
1159 	{
1160 		return emit_zoc_  && !incapacitated();
1161 	}
1162 
1163 	/** Gets the raw zone-of-control flag, disregarding @ref incapacitated. */
get_emit_zoc() const1164 	bool get_emit_zoc() const
1165 	{
1166 		return emit_zoc_;
1167 	}
1168 
1169 	/** Sets the raw zone-of-control flag. */
set_emit_zoc(bool val)1170 	void set_emit_zoc(bool val)
1171 	{
1172 		emit_zoc_ = val;
1173 	}
1174 
1175 	/** The current map location this unit is at. */
get_location() const1176 	const map_location& get_location() const
1177 	{
1178 		return loc_;
1179 	}
1180 
1181 	/**
1182 	 * Sets this unit's map location.
1183 	 *
1184 	 * Note this should only be called by unit_map or for temporary units.
1185 	 */
set_location(const map_location & loc)1186 	void set_location(const map_location& loc)
1187 	{
1188 		loc_ = loc;
1189 	}
1190 
1191 	/** The current directin this unit is facing within its hex. */
facing() const1192 	map_location::DIRECTION facing() const
1193 	{
1194 		return facing_;
1195 	}
1196 
1197 	/** The this unit's facing. */
1198 	void set_facing(map_location::DIRECTION dir) const;
1199 
1200 	/** Gets whether this unit has a multi-turn destination set. */
has_goto() const1201 	bool has_goto() const
1202 	{
1203 		return get_goto().valid();
1204 	}
1205 
1206 	/** The map location to which this unit is moving over multiple turns, if any. */
get_goto() const1207 	const map_location& get_goto() const
1208 	{
1209 		return goto_;
1210 	}
1211 
1212 	/** Sets this unit's long term destination. */
set_goto(const map_location & new_goto)1213 	void set_goto(const map_location& new_goto)
1214 	{
1215 		goto_ = new_goto;
1216 	}
1217 
1218 	/** Gets the unit's vision points. */
vision() const1219 	int vision() const
1220 	{
1221 		return vision_ < 0 ? max_movement_ : vision_;
1222 	}
1223 
1224 	/** Gets the unit's jamming points. */
jamming() const1225 	int jamming() const
1226 	{
1227 		return jamming_;
1228 	}
1229 
1230 	/** Check whether the unit's move has been interrupted. */
move_interrupted() const1231 	bool move_interrupted() const
1232 	{
1233 		return movement_left() > 0 && interrupted_move_.x >= 0 && interrupted_move_.y >= 0;
1234 	}
1235 
1236 	/** Get the target location of the unit's interrupted move. */
get_interrupted_move() const1237 	const map_location& get_interrupted_move() const
1238 	{
1239 		return interrupted_move_;
1240 	}
1241 
1242 	/** Set the target location of the unit's interrupted move. */
set_interrupted_move(const map_location & interrupted_move)1243 	void set_interrupted_move(const map_location& interrupted_move)
1244 	{
1245 		interrupted_move_ = interrupted_move;
1246 	}
1247 
1248 	/** Get the unit's movement type. */
movement_type() const1249 	const movetype& movement_type() const
1250 	{
1251 		return movement_type_;
1252 	}
1253 
1254 	/**
1255 	 * Get the unit's movement cost on a particular terrain
1256 	 * @param terrain The terrain to check
1257 	 * @returns the number of movement points to enter that terrain
1258 	 */
movement_cost(const t_translation::terrain_code & terrain) const1259 	int movement_cost(const t_translation::terrain_code& terrain) const
1260 	{
1261 		return movement_type_.movement_cost(terrain, get_state(STATE_SLOWED));
1262 	}
1263 
1264 	/**
1265 	 * Get the unit's vision cost on a particular terrain
1266 	 * @param terrain The terrain to check
1267 	 * @returns the number of vision points to see into that terrain
1268 	 */
vision_cost(const t_translation::terrain_code & terrain) const1269 	int vision_cost(const t_translation::terrain_code& terrain) const
1270 	{
1271 		return movement_type_.vision_cost(terrain, get_state(STATE_SLOWED));
1272 	}
1273 
1274 	/**
1275 	 * Get the unit's jamming cost on a particular terrain
1276 	 * @param terrain The terrain to check
1277 	 * @returns the number of jamming points to jam that terrain
1278 	 */
jamming_cost(const t_translation::terrain_code & terrain) const1279 	int jamming_cost(const t_translation::terrain_code& terrain) const
1280 	{
1281 		return movement_type_.jamming_cost(terrain, get_state(STATE_SLOWED));
1282 	}
1283 
1284 	/** Check if the unit is a flying unit. */
is_flying() const1285 	bool is_flying() const
1286 	{
1287 		return movement_type_.is_flying();
1288 	}
1289 
1290 	/**
1291 	 * @}
1292 	 * @defgroup unit_mod Modification functions
1293 	 * @{
1294 	 */
1295 
1296 public:
1297 	/** Get the raw modifications. */
get_modifications()1298 	config& get_modifications()
1299 	{
1300 		return modifications_;
1301 	}
1302 
1303 	/** Set the raw modifications. */
get_modifications() const1304 	const config& get_modifications() const
1305 	{
1306 		return modifications_;
1307 	}
1308 
1309 	/**
1310 	 * Count modifications of a particular type.
1311 	 * @param type The type of modification to count.
1312 	 *             Valid values are "advancement", "trait", "object"
1313 	 * @param id The ID of the modification to count
1314 	 * @return The total number of modifications of that type and ID.
1315 	 */
1316 	size_t modification_count(const std::string& type, const std::string& id) const;
1317 
1318 	/**
1319 	 * Add a new modification to the unit.
1320 	 * @param type The type of modification to add.
1321 	 *             Valid values are "advancement", "trait", "object"
1322 	 * @param modification The details of the modification
1323 	 * @param no_add If true, apply the modification but don't save it for unit rebuild time.
1324 	 *               Defaults to false.
1325 	 */
1326 	void add_modification(const std::string& type, const config& modification, bool no_add = false);
1327 
1328 	/**
1329 	 * Clears those modifications whose duration has expired.
1330 	 *
1331 	 * @param duration            If empty, all temporary modifications (those not lasting forever) expire.
1332 	 *                            Otherwise, modifications whose duration equals @a duration expire.
1333 	 */
1334 	void expire_modifications(const std::string& duration);
1335 
1336 	static const std::set<std::string> builtin_effects;
1337 
1338 	/**
1339 	 * Apply a builtin effect to the unit.
1340 	 * @param type The effect to apply. Must be one of the effects in @ref builtin_effects.
1341 	 * @param effect The details of the effect
1342 	 */
1343 	void apply_builtin_effect(std::string type, const config& effect);
1344 
1345 	/**
1346 	 * Construct a string describing a built-in effect.
1347 	 * @param type The effect to describe. Must be one of the effects in @ref builtin_effects.
1348 	 * @param effect The details of the effect
1349 	 */
1350 	std::string describe_builtin_effect(std::string type, const config& effect);
1351 
1352 	/** Re-apply all saved modifications. */
1353 	void apply_modifications();
1354 
1355 	/**
1356 	 * @}
1357 	 * @defgroup unit_img Image and animations functions
1358 	 * @{
1359 	 */
1360 
1361 public:
1362 	/** @todo Document this */
anim_comp() const1363 	unit_animation_component& anim_comp() const
1364 	{
1365 		return *anim_comp_;
1366 	}
1367 
1368 	/** The name of the file to game_display (used in menus). */
1369 	std::string absolute_image() const;
1370 
1371 	/** The default image to use for animation frames with no defined image. */
1372 	std::string default_anim_image() const;
1373 
1374 	/** Get the unit's halo image. */
image_halo() const1375 	std::string image_halo() const
1376 	{
1377 		return unit_detail::get_or_default(halo_);
1378 	}
1379 
1380 	/** Set the unit's halo image. */
1381 	void set_image_halo(const std::string& halo);
1382 
1383 	/** Get the unit's ellipse image. */
image_ellipse() const1384 	std::string image_ellipse() const
1385 	{
1386 		return unit_detail::get_or_default(ellipse_);
1387 	}
1388 
1389 	/** Set the unit's ellipse image. */
set_image_ellipse(const std::string & ellipse)1390 	void set_image_ellipse(const std::string& ellipse)
1391 	{
1392 		appearance_changed_ = true;
1393 		ellipse_.reset(new std::string(ellipse));
1394 	}
1395 
1396 	/**
1397 	 * Get the source color palette to use when recoloring the unit's image.
1398 	 */
1399 	const std::string& flag_rgb() const;
1400 
1401 	/** Constructs a recolor (RC) IPF string for this unit's team color. */
1402 	std::string TC_image_mods() const;
1403 
1404 	/** Gets any IPF image mods applied by effects. */
effect_image_mods() const1405 	const std::string& effect_image_mods() const
1406 	{
1407 		return image_mods_;
1408 	}
1409 
1410 	/**
1411 	 * Gets an IPF string containing all IPF image mods.
1412 	 *
1413 	 * @returns                 An amalgamation of @ref effect_image_mods followed by @ref TC_image_mods.
1414 	 */
1415 	std::string image_mods() const;
1416 
1417 	/** Get the unit's overlay images. */
overlays() const1418 	const std::vector<std::string>& overlays() const
1419 	{
1420 		return overlays_;
1421 	}
1422 
1423 	/**
1424 	 * Color for this unit's *current* hitpoints.
1425 	 *
1426 	 * @returns                   A color between green and red representing how wounded this unit is.
1427 	 *                            The maximum_hitpoints are considered as base.
1428 	 */
1429 	color_t hp_color() const;
1430 
1431 	/**
1432 	 * Color for this unit's hitpoints.
1433 	 *
1434 	 * @param hitpoints           The number of hitpoints the color represents.
1435 	 * @returns                   The color considering the current hitpoints as base.
1436 	 */
1437 	color_t hp_color(int hitpoints) const;
1438 
1439 	/**
1440 	 * Color for this unit's XP. See also @ref hp_color
1441 	 */
1442 	color_t xp_color() const;
1443 
1444 	/**
1445 	 * @}
1446 	 * @defgroup unit_abil Ability functions
1447 	 * @{
1448 	 */
1449 
1450 public:
1451 	/**
1452 	 * Checks whether this unit currently possesses or is affected by a given ability.
1453 	 *
1454 	 * This means that the ability could be owned by this unit itself or by an adjacent unit, should
1455 	 * the ability affect an AoE in which this unit happens to be.
1456 	 *
1457 	 * @param tag_name            The name of the ability to check for.
1458 	 * @param loc                 The location around which to check for affected units. This may or
1459 	 *                            may not be the location of this unit.
1460 	 * @param dc                  A display_context object, used in calculations.
1461 	 */
1462 	bool get_ability_bool(const std::string& tag_name, const map_location& loc, const display_context& dc) const;
1463 
1464 	/**
1465 	 * Checks whether this unit currently possesses or is affected by a given ability.
1466 	 *
1467 	 * This means that the ability could be owned by this unit itself or by an adjacent unit, should
1468 	 * the ability affect an AoE in which this unit happens to be.
1469 	 *
1470 	 * This overload uses the location of this unit for calculations.
1471 	 *
1472 	 * @param tag_name            The name of the ability to check for.
1473 	 * @param dc                  A display_context object, used in calculations.
1474 	 */
get_ability_bool(const std::string & tag_name,const display_context & dc) const1475 	bool get_ability_bool(const std::string& tag_name, const display_context& dc) const
1476 	{
1477 		return get_ability_bool(tag_name, loc_, dc);
1478 	}
1479 
1480 	/**
1481 	 * Gets the unit's active abilities of a particular type if it were on a specified location.
1482 	 * @param tag_name The type of ability to check for
1483 	 * @param loc The location to use for resolving abilities
1484 	 * @return A list of active abilities, paired with the location they are active on
1485 	 */
1486 	unit_ability_list get_abilities(const std::string& tag_name, const map_location& loc) const;
1487 
1488 	/**
1489 	 * Gets the unit's active abilities of a particular type.
1490 	 * @param tag_name The type of ability to check for
1491 	 * @return A list of active abilities, paired with the location they are active on
1492 	 */
get_abilities(const std::string & tag_name) const1493 	unit_ability_list get_abilities(const std::string& tag_name) const
1494 	{
1495 		return get_abilities(tag_name, loc_);
1496 	}
1497 
1498 	/**
1499 	 * Gets the names and descriptions of this unit's abilities. Location-independent variant
1500 	 * with all abilities shown as active.
1501 	 *
1502 	 * @returns                   A list of quadruples consisting of (in order) id, base name,
1503 	 *                            male or female name as appropriate for the unit, and description.
1504 	 */
1505 	std::vector<std::tuple<std::string, t_string, t_string, t_string>>
1506 	ability_tooltips() const;
1507 
1508 	/**
1509 	 * Gets the names and descriptions of this unit's abilities.
1510 	 *
1511 	 * @param active_list         This vector will be the same length as the returned one and will
1512 	 *                            indicate whether or not the corresponding ability is active.
1513 	 *
1514 	 * @param loc                 The location on which to resolve the ability.
1515 	 *
1516 	 * @returns                   A list of quadruples consisting of (in order) id, base name,
1517 	 *                            male or female name as appropriate for the unit, and description.
1518 	 */
1519 	std::vector<std::tuple<std::string, t_string, t_string, t_string>>
1520 	ability_tooltips(boost::dynamic_bitset<>& active_list, const map_location& loc) const;
1521 
1522 	/** Get a list of all abilities by ID. */
1523 	std::vector<std::string> get_ability_list() const;
1524 
1525 	/**
1526 	 * Check if the unit has an ability of a specific type.
1527 	 * @param ability The type of ability (tag name) to check for.
1528 	 * @returns true if the ability is present
1529 	 */
1530 	bool has_ability_type(const std::string& ability) const;
1531 
1532 	/**
1533 	 * Check if the unit has an ability of a specific ID.
1534 	 * @param ability The ID of ability to check for.
1535 	 * @returns true if the ability is present
1536 	 */
1537 	bool has_ability_by_id(const std::string& ability) const;
1538 
1539 	/**
1540 	 * Removes a unit's abilities with a specific ID.
1541 	 * @param ability The type of ability (tag name) to remove.
1542 	 */
1543 	void remove_ability_by_id(const std::string& ability);
1544 
1545 private:
1546 	/**
1547 	 * Check if an ability is active.
1548 	 * @param ability The type (tag name) of the ability
1549 	 * @param cfg an ability WML structure
1550 	 * @param loc The location on which to resolve the ability
1551 	 * @returns true if it is active
1552 	 */
1553 	bool ability_active(const std::string& ability, const config& cfg, const map_location& loc) const;
1554 
1555 	/**
1556 	 * Check if an ability affects adjacent units.
1557 	 * @param ability The type (tag name) of the ability
1558 	 * @param cfg an ability WML structure
1559 	 * @param loc The location on which to resolve the ability
1560 	 * @param from The "other unit" for filter matching
1561 	 */
1562 	bool ability_affects_adjacent(const std::string& ability, const config& cfg, int dir, const map_location& loc, const unit& from) const;
1563 
1564 	/**
1565 	 * Check if an ability affects the owning unit.
1566 	 * @param ability The type (tag name) of the ability
1567 	 * @param cfg an ability WML structure
1568 	 * @param loc The location on which to resolve the ability
1569 	 */
1570 	bool ability_affects_self(const std::string& ability, const config& cfg, const map_location& loc) const;
1571 
1572 public:
1573 	/** Get the unit formula manager. */
formula_manager() const1574 	unit_formula_manager& formula_manager() const
1575 	{
1576 		return *formula_man_;
1577 	}
1578 
1579 	/** Generates a random race-appropriate name if one has not already been provided. */
1580 	void generate_name();
1581 
1582 	// Only see_all = true use caching
1583 	bool invisible(const map_location& loc, const display_context& dc, bool see_all = true) const;
1584 
1585 	bool is_visible_to_team(const team& team, const display_context& dc, bool const see_all = true) const;
1586 	/// Return true if the unit would be visible to team if its location were loc.
1587 	bool is_visible_to_team(const map_location& loc, const team& team, const display_context& dc, bool const see_all = true) const;
1588 
1589 	/**
1590 	 * Serializes the current unit metadata values.
1591 	 *
1592 	 * @param cfg                 The config to write to.
1593 	 */
1594 	void write(config& cfg) const;
1595 
1596 	/**
1597 	 * Mark this unit as clone so it can be inserted to unit_map.
1598 	 *
1599 	 * @returns                   self (for convenience)
1600 	 */
1601 	unit& mark_clone(bool is_temporary);
1602 
1603 	/** @} */
1604 
ref_count() const1605 	long ref_count() const
1606 	{
1607 		return ref_count_;
1608 	}
1609 
1610 	friend void intrusive_ptr_add_ref(const unit*);
1611 	friend void intrusive_ptr_release(const unit*);
1612 
set_appearance_changed(bool value)1613 	void set_appearance_changed(bool value) { appearance_changed_ = value; }
appearance_changed() const1614 	bool appearance_changed() const { return appearance_changed_; }
1615 
1616 protected:
1617 	mutable long ref_count_; // used by intrusive_ptr
1618 
1619 private:
1620 	map_location loc_;
1621 
1622 	std::vector<std::string> advances_to_;
1623 
1624 	/** Never nullptr. Adjusted for gender and variation. */
1625 	const unit_type* type_;
1626 
1627 	/** The displayed name of this unit type. */
1628 	t_string type_name_;
1629 
1630 	/** Never nullptr, but may point to the null race. */
1631 	const unit_race* race_;
1632 
1633 	std::string id_;
1634 	t_string name_;
1635 	n_unit::unit_id underlying_id_;
1636 
1637 	std::string undead_variation_;
1638 	std::string variation_;
1639 
1640 	int hit_points_;
1641 	int max_hit_points_;
1642 	int experience_;
1643 	int max_experience_;
1644 
1645 	int level_;
1646 
1647 	int recall_cost_;
1648 	bool canrecruit_;
1649 	std::vector<std::string> recruit_list_;
1650 	unit_type::ALIGNMENT alignment_;
1651 
1652 	std::string flag_rgb_;
1653 	std::string image_mods_;
1654 
1655 	bool unrenamable_;
1656 
1657 	int side_;
1658 
1659 	unit_race::GENDER gender_;
1660 
1661 	std::unique_ptr<unit_formula_manager> formula_man_;
1662 
1663 	int movement_;
1664 	int max_movement_;
1665 	int vision_;
1666 	int jamming_;
1667 
1668 	movetype movement_type_;
1669 
1670 	bool hold_position_;
1671 	bool end_turn_;
1672 	bool resting_;
1673 
1674 	int attacks_left_;
1675 	int max_attacks_;
1676 
1677 	std::set<std::string> states_;
1678 
1679 	static const size_t num_bool_states = 7;
1680 
1681 	std::bitset<num_bool_states> known_boolean_states_;
1682 	static std::map<std::string, state_t> known_boolean_state_names_;
1683 
1684 	config variables_;
1685 	config events_;
1686 	config filter_recall_;
1687 
1688 	bool emit_zoc_;
1689 
1690 	std::vector<std::string> overlays_;
1691 
1692 	std::string role_;
1693 	attack_list attacks_;
1694 
1695 protected:
1696 	// TODO: I think we actually consider this to be part of the gamestate, so it might be better if it's not mutable,
1697 	// but it's not easy to separate this guy from the animation code right now.
1698 	mutable map_location::DIRECTION facing_;
1699 
1700 private:
1701 	std::vector<t_string> trait_names_;
1702 	std::vector<t_string> trait_descriptions_;
1703 
1704 	int unit_value_;
1705 	map_location goto_, interrupted_move_;
1706 
1707 	bool is_fearless_, is_healthy_;
1708 
1709 	utils::string_map modification_descriptions_;
1710 
1711 	// Animations:
1712 	friend class unit_animation_component;
1713 
1714 	std::unique_ptr<unit_animation_component> anim_comp_;
1715 
1716 	mutable bool hidden_;
1717 	double hp_bar_scaling_, xp_bar_scaling_;
1718 
1719 	config modifications_;
1720 	config abilities_;
1721 
1722 	advancements_list advancements_;
1723 
1724 	t_string description_;
1725 
1726 	std::unique_ptr<std::string> usage_;
1727 	std::unique_ptr<std::string> halo_;
1728 	std::unique_ptr<std::string> ellipse_;
1729 
1730 	bool random_traits_;
1731 	bool generate_name_;
1732 
1733 	upkeep_t upkeep_;
1734 
1735 	std::string profile_;
1736 	std::string small_profile_;
1737 
1738 	//Used to check whether the moving units during a move needs to be updated
1739 	mutable bool appearance_changed_ = true;
1740 
1741 	void parse_upkeep(const config::attribute_value& upkeep);
1742 	void write_upkeep(config::attribute_value& upkeep) const;
1743 
1744 	/**
1745 	 * Hold the visibility status cache for a unit, when not uncovered.
1746 	 * This is mutable since it is a cache.
1747 	 */
1748 	mutable std::map<map_location, bool> invisibility_cache_;
1749 
1750 	/**
1751 	 * Clears the cache.
1752 	 *
1753 	 * Since we don't change the state of the object we're marked const (also
1754 	 * required since the objects in the cache need to be marked const).
1755 	 */
clear_visibility_cache() const1756 	void clear_visibility_cache() const
1757 	{
1758 		invisibility_cache_.clear();
1759 	}
1760 };
1761 
1762 /** Implement non-member swap function for std::swap (calls @ref unit::swap). */
1763 void swap(unit& lhs, unit& rhs);
1764 
1765 /**
1766  * Object which temporarily resets a unit's movement.
1767  *
1768  * @warning A unit whose movement is reset may not be deleted while held in a
1769  * @ref unit_movement_resetter object, so it's best to use thus only in a small scope.
1770  */
1771 struct unit_movement_resetter
1772 {
1773 	unit_movement_resetter(const unit_movement_resetter&) = delete;
1774 	unit_movement_resetter& operator=(const unit_movement_resetter&) = delete;
1775 
1776 	unit_movement_resetter(const unit& u, bool operate = true);
1777 	~unit_movement_resetter();
1778 
1779 private:
1780 	unit& u_;
1781 	int moves_;
1782 };
1783 
1784 /**
1785  * Gets a checksum for a unit.
1786  *
1787  * In MP games the descriptions are locally generated and might differ, so it
1788  * should be possible to discard them.  Not sure whether replays suffer the
1789  * same problem.
1790  *
1791  *  @param u                    this unit
1792  *
1793  *  @returns                    the checksum for a unit
1794  */
1795 std::string get_checksum(const unit& u);
1796