The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
attack.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
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  * Various functions that implement attacks and attack calculations.
18  * Unit advancements are also included, as they usually occur as a
19  * result of combat.
20  */
21 
22 #ifndef ACTIONS_ATTACK_H_INCLUDED
23 #define ACTIONS_ATTACK_H_INCLUDED
24 
25 struct combatant;
26 struct map_location;
27 class team;
28 class unit;
29 class unit_map;
30 class gamemap;
31 
32 #include "units/types.hpp"
34 
35 #include <vector>
36 
37 
38 /// Calculates the number of blows resulting from swarm.
39 inline unsigned swarm_blows(unsigned min_blows, unsigned max_blows, unsigned hp,
40  unsigned max_hp)
41 {
42  return hp >= max_hp ? max_blows :
43  max_blows < min_blows ? min_blows - (min_blows-max_blows) * hp / max_hp :
44  min_blows + (max_blows-min_blows) * hp / max_hp;
45 }
46 
47 
48 /** Structure describing the statistics of a unit involved in the battle. */
50 {
51  const attack_type *weapon; /**< The weapon used by the unit to attack the opponent, or nullptr if there is none. */
52  int attack_num; /**< Index into unit->attacks() or -1 for none. */
53  bool is_attacker; /**< True if the unit is the attacker. */
54  bool is_poisoned; /**< True if the unit is poisoned at the beginning of the battle. */
55  bool is_slowed; /**< True if the unit is slowed at the beginning of the battle. */
56  bool slows; /**< Attack slows opponent when it hits. */
57  bool drains; /**< Attack drains opponent when it hits. */
58  bool petrifies; /**< Attack petrifies opponent when it hits. */
59  bool plagues; /**< Attack turns opponent into a zombie when fatal. */
60  bool poisons; /**< Attack poisons opponent when it hits. */
61  bool backstab_pos; /**<
62  * True if the attacker is in *position* to backstab the defender (this is used to
63  * determine whether to apply the backstab bonus in case the attacker has backstab).
64  */
65  bool swarm; /**< Attack has swarm special. */
66  bool firststrike; /**< Attack has firststrike special. */
67  bool disable; /**< Attack has disable special. */
68  unsigned int experience, max_experience;
69  unsigned int level;
70 
71  unsigned int rounds; /**< Berserk special can force us to fight more than one round. */
72  unsigned int hp; /**< Hitpoints of the unit at the beginning of the battle. */
73  unsigned int max_hp; /**< Maximum hitpoints of the unit. */
74  unsigned int chance_to_hit; /**< Effective chance to hit as a percentage (all factors accounted for). */
75  int damage; /**< Effective damage of the weapon (all factors accounted for). */
76  int slow_damage; /**< Effective damage if unit becomes slowed (== damage, if already slowed) */
77  int drain_percent; /**< Percentage of damage recovered as health */
78  int drain_constant; /**< Base HP drained regardless of damage dealt */
79  unsigned int num_blows; /**< Effective number of blows, takes swarm into account. */
80  unsigned int swarm_min; /**< Minimum number of blows with swarm (equal to num_blows if swarm isn't used). */
81  unsigned int swarm_max; /**< Maximum number of blows with swarm (equal to num_blows if swarm isn't used). */
82 
83  std::string plague_type; /**< The plague type used by the attack, if any. */
84 
85  battle_context_unit_stats(const unit &u, const map_location& u_loc,
86  int u_attack_num, bool attacking,
87  const unit &opp, const map_location& opp_loc,
88  const attack_type *opp_weapon,
89  const unit_map& units);
90 
91  /** Used by AI for combat analysis */
93  const attack_type* att_weapon, bool attacking,
94  const unit_type* opp_type, const attack_type* opp_weapon,
95  unsigned int opp_terrain_defense,
96  int lawful_bonus = 0);
97 
99  {}
100 
101  /// Calculates the number of blows we would have if we had @a new_hp
102  // instead of the recorded hp.
103  unsigned int calc_blows(unsigned new_hp) const
104  { return swarm_blows(swarm_min, swarm_max, new_hp, max_hp); }
105 
106 #if defined(BENCHMARK) || defined(CHECK)
107  /// Special constructor for the stand-alone version of attack_prediction.cpp.
108  /// (This hardcodes some standard abilities for testing purposes.)
109  battle_context_unit_stats(int dmg, int blows, int hitpoints, int maximum_hp,
110  int hit_chance, bool drain, bool slows, bool slowed,
111  bool berserk, bool first, bool do_swarm) :
112  weapon(nullptr), attack_num(0), is_attacker(true), // These are not used in attack prediction.
113  is_poisoned(false), is_slowed(slowed),
114  slows(slows), drains(drain), petrifies(false), plagues(false),
115  poisons(false), backstab_pos(false), swarm(do_swarm), firststrike(first), disable(false),
116  experience(0), max_experience(50), level(1), // No units should advance in the attack prediction tests.
117  rounds(berserk ? 30 : 1),
118  hp(std::max<int>(0, hitpoints)), max_hp(std::max<int>(1, maximum_hp)),
119  chance_to_hit(hit_chance),
120  damage(std::max(0, dmg)), slow_damage(round_damage(damage, 1, 2)),
121  drain_percent(drain ? 50 : 0), drain_constant(0),
122  num_blows(do_swarm ? blows * hp / max_hp : blows),
123  swarm_min(do_swarm ? 0 : blows), swarm_max(blows),
124  plague_type()
125  {
126  if ( slowed )
127  damage = slow_damage;
128  if ( hp > max_hp )
129  hp = max_hp; // Keeps the prob_matrix from going out of bounds.
130  }
131 #endif
132 };
133 
134 /** Computes the statistics of a battle between an attacker and a defender unit. */
136 {
137 public:
138 
139  /**
140  * If no attacker_weapon is given, we select the best one,
141  * based on harm_weight (1.0 means 1 hp lost counters 1 hp damage,
142  * 0.0 means we ignore harm weight).
143  * prev_def is for predicting multiple attacks against a defender.
144  */
146  const map_location& attacker_loc, const map_location& defender_loc,
147  int attacker_weapon = -1, int defender_weapon = -1,
148  double aggression = 0.0, const combatant *prev_def = nullptr,
149  const unit* attacker_ptr=nullptr);
150 
151  /** Used by the AI which caches battle_context_unit_stats */
153 
154  battle_context(const battle_context &other);
155  ~battle_context();
156 
157  battle_context& operator=(const battle_context &other);
158 
159  /** This method returns the statistics of the attacker. */
161 
162  /** This method returns the statistics of the defender. */
164 
165  /** Get the simulation results. */
166  const combatant &get_attacker_combatant(const combatant *prev_def = nullptr);
167  const combatant &get_defender_combatant(const combatant *prev_def = nullptr);
168 
169  /** Given this harm_weight, is this attack better than that? */
170  bool better_attack(class battle_context &that, double harm_weight);
171  static bool better_combat(const combatant &us_a, const combatant &them_a,
172  const combatant &us_b, const combatant &them_b,
173  double harm_weight);
174 
175 private:
176 
177  int choose_attacker_weapon(const unit &attacker, const unit &defender,
178  const unit_map& units,
179  const map_location& attacker_loc, const map_location& defender_loc,
180  double harm_weight, int *defender_weapon,
181  const combatant *prev_def);
182 
183  int choose_defender_weapon(const unit &attacker, const unit &defender,
184  unsigned attacker_weapon, const unit_map& units,
185  const map_location& attacker_loc,
186  const map_location& defender_loc,
187  const combatant *prev_def);
188 
189  /** Statistics of the units. */
191 
192  /** Outcome of simulated fight. */
194 };
195 
196 /** Performs an attack. */
197 void attack_unit(const map_location &attacker, const map_location &defender,
198  int attack_with, int defend_with, bool update_display = true);
199 
200 /** Performs an attack, and advanced the units afterwards */
201 void attack_unit_and_advance(const map_location &attacker, const map_location &defender,
202  int attack_with, int defend_with, bool update_display = true,
204 
205 /**
206  advances the unit at loc if it has enough experience, maximum 20 times.
207  if the unit is on the currently active side, and that side is controlled by a human, a dialog pops up.
208  if we are in a non mp game, and the side is controlled by a human then a dialog is shown too.
209  if the side is controlled by an ai, and if ai_advancement is passed, then ai_advancement will be used.
210  otherwise a random decision will be taken.
211 
212  this method is currently not used by unstore_unit, if we want to do that we'd need to allow more arguments (animate, fire_events).
213 */
215 {
216  advance_unit_params(const map_location& loc) : loc_(loc), ai_advancements_(nullptr), force_dialog_(false), fire_events_(true), animate_(true) {}
220  advance_unit_params& animate(bool value) {animate_ = value; return *this;}
221  friend void advance_unit_at(const advance_unit_params&);
222 private:
227  bool animate_;
228 };
230 /**
231  * Returns the advanced version of a unit (with traits and items retained).
232  */
233 unit_ptr get_advanced_unit(const unit &u, const std::string &advance_to);
234 
235 /**
236  * Returns the AMLA-advanced version of a unit (with traits and items retained).
237  */
238 unit_ptr get_amla_unit(const unit &u, const config &mod_option);
239 
240 /**
241  * Function which will advance the unit at @a loc to 'advance_to'.
242  * (Unless mod_option is supplied, in which case an AMLA is performed.)
243  * Note that 'loc' is not a reference, because if it were a reference,
244  * we couldn't safely pass in a reference to the item in the map
245  * that we're going to delete, since deletion would invalidate the reference.
246  */
247 void advance_unit(map_location loc, const std::string &advance_to,
248  const bool &fire_event = true, const config * mod_option = nullptr);
249 
250 /**
251  * function which tests if the unit at loc is currently affected by leadership.
252  * (i.e. has a higher-level 'leadership' unit next to it).
253  * If it does, then the location of the leader unit will be returned,
254  * Otherwise map_location::null_location() will be returned.
255  * If 'bonus' is not nullptr, the % bonus will be stored in it.
256  */
258  int* bonus=nullptr);
259 
260 /**
261  * Returns the amount that a unit's damage should be multiplied by
262  * due to the current time of day.
263  */
264 int combat_modifier(const unit_map & units, const gamemap & map, const map_location &loc, unit_type::ALIGNMENT alignment,
265  bool is_fearless);
266 
267 /**
268  * Returns the amount that a unit's damage should be multiplied by
269  * due to a given lawful_bonus.
270  */
271 int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment,
272  bool is_fearless);
273 /**
274  * Function to check if an attack will satisfy the requirements for backstab.
275  * Input:
276  * - the location from which the attack will occur,
277  * - the defending unit location,
278  * - the list of units on the map and
279  * - the list of teams.
280  * The defender and opposite units should be in place already.
281  * The attacking unit doesn't need to be, but if it isn't,
282  * an external check should be made to make sure the opposite unit
283  * isn't also the attacker.
284  */
285 bool backstab_check(const map_location& attacker_loc,
286  const map_location& defender_loc,
287  const unit_map& units, const std::vector<team>& teams);
288 
289 #endif
unsigned int calc_blows(unsigned new_hp) const
Calculates the number of blows we would have if we had new_hp.
Definition: attack.hpp:103
const ai::unit_advancements_aspect * ai_advancements_
Definition: attack.hpp:224
std::string plague_type
The plague type used by the attack, if any.
Definition: attack.hpp:83
Definition: unit.hpp:95
void advance_unit_at(const advance_unit_params &params)
Definition: attack.cpp:1478
unsigned int hp
Hitpoints of the unit at the beginning of the battle.
Definition: attack.hpp:72
int choose_defender_weapon(const unit &attacker, const unit &defender, unsigned attacker_weapon, const unit_map &units, const map_location &attacker_loc, const map_location &defender_loc, const combatant *prev_def)
Definition: attack.cpp:569
static bool better_combat(const combatant &us_a, const combatant &them_a, const combatant &us_b, const combatant &them_b, double harm_weight)
Definition: attack.cpp:442
const combatant & get_attacker_combatant(const combatant *prev_def=nullptr)
Get the simulation results.
Definition: attack.cpp:410
unit_ptr get_advanced_unit(const unit &u, const std::string &advance_to)
Returns the advanced version of a unit (with traits and items retained).
Definition: attack.cpp:1541
friend void advance_unit_at(const advance_unit_params &)
Definition: attack.cpp:1478
advance_unit_params & force_dialog(bool value)
Definition: attack.hpp:218
bool is_slowed
True if the unit is slowed at the beginning of the battle.
Definition: attack.hpp:55
STL namespace.
battle_context_unit_stats * attacker_stats_
Statistics of the units.
Definition: attack.hpp:190
const attack_type * weapon
The weapon used by the unit to attack the opponent, or nullptr if there is none.
Definition: attack.hpp:51
const GLfloat * params
Definition: glew.h:1499
advance_unit_params & fire_events(bool value)
Definition: attack.hpp:219
battle_context(const unit_map &units, const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon=-1, int defender_weapon=-1, double aggression=0.0, const combatant *prev_def=nullptr, const unit *attacker_ptr=nullptr)
If no attacker_weapon is given, we select the best one, based on harm_weight (1.0 means 1 hp lost cou...
Definition: attack.cpp:320
bool slows
Attack slows opponent when it hits.
Definition: attack.hpp:56
int drain_constant
Base HP drained regardless of damage dealt.
Definition: attack.hpp:78
const map_location & loc_
Definition: attack.hpp:223
unsigned int chance_to_hit
Effective chance to hit as a percentage (all factors accounted for).
Definition: attack.hpp:74
void attack_unit(const map_location &attacker, const map_location &defender, int attack_with, int defend_with, bool update_display=true)
Performs an attack.
Definition: attack.cpp:1384
advance_unit_params & animate(bool value)
Definition: attack.hpp:220
void attack_unit_and_advance(const map_location &attacker, const map_location &defender, int attack_with, int defend_with, bool update_display=true, const ai::unit_advancements_aspect &ai_advancement=ai::unit_advancements_aspect())
Performs an attack, and advanced the units afterwards.
Definition: attack.cpp:1524
bool poisons
Attack poisons opponent when it hits.
Definition: attack.hpp:60
const combatant & get_defender_combatant(const combatant *prev_def=nullptr)
Definition: attack.cpp:422
static std::vector< team > *& teams
Definition: team.cpp:50
bool backstab_pos
True if the attacker is in position to backstab the defender (this is used to determine whether to ap...
Definition: attack.hpp:61
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:50
int damage
Effective damage of the weapon (all factors accounted for).
Definition: attack.hpp:75
unsigned int level
Definition: attack.hpp:69
combatant * defender_combatant_
Definition: attack.hpp:193
unsigned int rounds
Berserk special can force us to fight more than one round.
Definition: attack.hpp:71
unsigned int swarm_min
Minimum number of blows with swarm (equal to num_blows if swarm isn't used).
Definition: attack.hpp:80
GLsizei const GLfloat * value
Definition: glew.h:1817
advance_unit_params & ai_advancements(const ai::unit_advancements_aspect &value)
Definition: attack.hpp:217
const battle_context_unit_stats & get_defender_stats() const
This method returns the statistics of the defender.
Definition: attack.hpp:163
bool plagues
Attack turns opponent into a zombie when fatal.
Definition: attack.hpp:59
bool better_attack(class battle_context &that, double harm_weight)
Given this harm_weight, is this attack better than that?
Definition: attack.cpp:435
Encapsulates the map of the game.
Definition: map.hpp:37
Computes the statistics of a battle between an attacker and a defender unit.
Definition: attack.hpp:135
int attack_num
Index into unit->attacks() or -1 for none.
Definition: attack.hpp:52
Structure describing the statistics of a unit involved in the battle.
Definition: attack.hpp:49
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
int choose_attacker_weapon(const unit &attacker, const unit &defender, const unit_map &units, const map_location &attacker_loc, const map_location &defender_loc, double harm_weight, int *defender_weapon, const combatant *prev_def)
Definition: attack.cpp:472
advances the unit at loc if it has enough experience, maximum 20 times.
Definition: attack.hpp:214
bool backstab_check(const map_location &attacker_loc, const map_location &defender_loc, const unit_map &units, const std::vector< team > &teams)
Function to check if an attack will satisfy the requirements for backstab.
Definition: attack.cpp:1684
Encapsulates the map of the game.
Definition: location.hpp:38
battle_context_unit_stats(const unit &u, const map_location &u_loc, int u_attack_num, bool attacking, const unit &opp, const map_location &opp_loc, const attack_type *opp_weapon, const unit_map &units)
Definition: attack.cpp:68
unsigned swarm_blows(unsigned min_blows, unsigned max_blows, unsigned hp, unsigned max_hp)
Calculates the number of blows resulting from swarm.
Definition: attack.hpp:39
All combat-related info.
battle_context & operator=(const battle_context &other)
Definition: attack.cpp:393
int round_damage(int base_damage, int bonus, int divisor)
round (base_damage * bonus / divisor) to the closest integer, but up or down towards base_damage ...
Definition: util.hpp:60
int combat_modifier(const unit_map &units, const gamemap &map, const map_location &loc, unit_type::ALIGNMENT alignment, bool is_fearless)
Returns the amount that a unit's damage should be multiplied by due to the current time of day...
Definition: attack.cpp:1649
bool swarm
Attack has swarm special.
Definition: attack.hpp:65
int slow_damage
Effective damage if unit becomes slowed (== damage, if already slowed)
Definition: attack.hpp:76
int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bool is_fearless)
Returns the amount that a unit's damage should be multiplied by due to a given lawful_bonus.
Definition: attack.cpp:1657
unsigned int experience
Definition: attack.hpp:68
combatant * attacker_combatant_
Outcome of simulated fight.
Definition: attack.hpp:193
bool disable
Attack has disable special.
Definition: attack.hpp:67
bool firststrike
Attack has firststrike special.
Definition: attack.hpp:66
bool is_poisoned
True if the unit is poisoned at the beginning of the battle.
Definition: attack.hpp:54
advance_unit_params(const map_location &loc)
Definition: attack.hpp:216
bool fire_event(const tevent event, std::vector< std::pair< twidget *, tevent > > &event_chain, twidget *dispatcher, twidget *widget, F functor)
Helper function for fire_event.
void advance_unit(map_location loc, const std::string &advance_to, const bool &fire_event=true, const config *mod_option=nullptr)
Function which will advance the unit at loc to 'advance_to'.
Definition: attack.cpp:1573
int drain_percent
Percentage of damage recovered as health.
Definition: attack.hpp:77
GLint * first
Definition: glew.h:1496
Container associating units to locations.
Definition: map.hpp:90
unsigned int num_blows
Effective number of blows, takes swarm into account.
Definition: attack.hpp:79
unsigned int max_hp
Maximum hitpoints of the unit.
Definition: attack.hpp:73
const battle_context_unit_stats & get_attacker_stats() const
This method returns the statistics of the attacker.
Definition: attack.hpp:160
bool is_attacker
True if the unit is the attacker.
Definition: attack.hpp:53
unsigned int max_experience
Definition: attack.hpp:68
bool petrifies
Attack petrifies opponent when it hits.
Definition: attack.hpp:58
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
map_location under_leadership(const unit_map &units, const map_location &loc, int *bonus=nullptr)
function which tests if the unit at loc is currently affected by leadership.
Definition: attack.cpp:1635
unit_ptr get_amla_unit(const unit &u, const config &mod_option)
Returns the AMLA-advanced version of a unit (with traits and items retained).
Definition: attack.cpp:1564
bool drains
Attack drains opponent when it hits.
Definition: attack.hpp:57
GLsizei const GLcharARB ** string
Definition: glew.h:4503
unit_map * units
Definition: resources.cpp:35
battle_context_unit_stats * defender_stats_
Definition: attack.hpp:190
unsigned int swarm_max
Maximum number of blows with swarm (equal to num_blows if swarm isn't used).
Definition: attack.hpp:81