actions.hpp

Go to the documentation of this file.
00001 /* $Id: actions.hpp 53537 2012-03-14 21:35:03Z boucman $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * @file
00018  * Various functions which implement in-game events and commands.
00019  */
00020 
00021 #ifndef ACTIONS_H_INCLUDED
00022 #define ACTIONS_H_INCLUDED
00023 
00024 class attack_type;
00025 class game_display;
00026 class replay;
00027 struct combatant;
00028 class team;
00029 struct time_of_day;
00030 
00031 #include "unit.hpp"
00032 
00033 class unit_creator {
00034 public:
00035     unit_creator(team &tm, const map_location &start_pos);
00036     unit_creator& allow_show(bool b);
00037     unit_creator& allow_get_village(bool b);
00038     unit_creator& allow_rename_side(bool b);
00039     unit_creator& allow_invalidate(bool b);
00040     unit_creator& allow_discover(bool b);
00041     unit_creator& allow_add_to_recall(bool b);
00042 
00043     /**
00044      * finds a suitable location for unit
00045      * @retval map_location::null_location if unit is to be put into recall list
00046      * @retval valid on-board map location otherwise
00047      */
00048     map_location find_location(const config &cfg, const unit* pass_check=NULL);
00049 
00050 
00051     /**
00052      * adds a unit on map without firing any events (so, usable during team construction in gamestatus)
00053      */
00054     void add_unit(const config &cfg, const vconfig* vcfg = NULL);
00055 
00056 private:
00057     void post_create(const map_location &loc, const unit &new_unit, bool anim);
00058 
00059     bool add_to_recall_;
00060     bool discover_;
00061     bool get_village_;
00062     bool invalidate_;
00063     bool rename_side_;
00064     bool show_;
00065     const map_location start_pos_;
00066     team &team_;
00067 
00068 };
00069 
00070 
00071 bool can_recruit_on(const gamemap& map, const map_location& leader, const map_location& loc);
00072 
00073 /**
00074  * Finds a location to place a unit.
00075  * A leader of the @a side must be on a keep
00076  * connected by castle to a legal recruiting location. Otherwise, an error
00077  * message explaining this is returned.
00078  *
00079  * If no errors are encountered, the location where a unit can be recruited
00080  * is stored in @a recruit_location. Its value is considered first, if it is a
00081  * legal option.
00082  *
00083  * @return an empty string on success. Otherwise a human-readable message
00084  *         describing the failure is returned.
00085  */
00086 std::string find_recruit_location(const int side, map_location &recruit_location, map_location& recruited_from, const std::string& unit_type);
00087 
00088 /**
00089  * Finds a location to recall @a unit_recall.
00090  * A leader of the @a side must be on a keep
00091  * connected by castle to a legal recalling location. Otherwise, an error
00092  * message explaining this is returned.
00093  *
00094  * If no errors are encountered, the location where a unit can be recalled
00095  * is stored in @a recall_location. Its value is considered first, if it is a
00096  * legal option.
00097  *
00098  * @return an empty string on success. Otherwise a human-readable message
00099  *         describing the failure is returned.
00100  */
00101 std::string find_recall_location(const int side, map_location& recall_location, map_location& recall_from, const unit &unit_recall);
00102 
00103 /**
00104  * Get's the recruitable units from a side's leaders' personal recruit lists who can recruit on a specific hex field.
00105  * @param side of the leaders to search for their personal recruit lists.
00106  * @param recruit_location the hex field being part of the castle the player wants to recruit on.
00107  * @return a set of units that can be recruited by leaders on a keep connected by castle tiles with @a recruit_location.
00108  */
00109 const std::set<std::string> get_recruits_for_location(int side, const map_location &recruit_location);
00110 
00111 /**
00112  * Get's the recruitable units from a side's leaders' personal recruit lists who can recruit on a specific hex field.
00113  * If no leader is able to recruit on the given location the full recall list of the side is returned.
00114  * @param side of the leaders to search for their personal recruit lists.
00115  * @param recruit_location the hex field being part of the castle the player wants to recruit on.
00116  * @return a set of units that can be recruited by @a side on @a recall_loc or the full recall list of @a side.
00117  */
00118 const std::vector<const unit*> get_recalls_for_location(int side, const map_location &recruit_location);
00119 
00120 /**
00121  * Place a unit into the game.
00122  * The unit will be placed on @a recruit_location, which should be retrieved
00123  * through a call to recruit_location().
00124  */
00125 void place_recruit(const unit &u, const map_location &recruit_location, const map_location& recruited_from,
00126     bool is_recall, bool show = false, bool fire_event = true, bool full_movement = false,
00127     bool wml_triggered = false);
00128 
00129 /** Structure describing the statistics of a unit involved in the battle. */
00130 struct battle_context_unit_stats
00131 {
00132     const attack_type *weapon;  /**< The weapon used by the unit to attack the opponent, or NULL if there is none. */
00133     int attack_num;         /**< Index into unit->attacks() or -1 for none. */
00134     bool is_attacker;       /**< True if the unit is the attacker. */
00135     bool is_poisoned;       /**< True if the unit is poisoned at the beginning of the battle. */
00136     bool is_slowed;         /**< True if the unit is slowed at the beginning of the battle. */
00137     bool slows;             /**< Attack slows opponent when it hits. */
00138     bool drains;            /**< Attack drains opponent when it hits. */
00139     bool petrifies;         /**< Attack petrifies opponent when it hits. */
00140     bool plagues;           /**< Attack turns opponent into a zombie when fatal. */
00141     bool poisons;           /**< Attack poisons opponent when it hits. */
00142     bool backstab_pos;      /**<
00143                                  * True if the attacker is in *position* to backstab the defender (this is used to
00144                      * determine whether to apply the backstab bonus in case the attacker has backstab).
00145                      */
00146     bool swarm;             /**< Attack has swarm special. */
00147     bool firststrike;       /**< Attack has firststrike special. */
00148     unsigned int experience, max_experience;
00149     unsigned int level;
00150 
00151     unsigned int rounds;    /**< Berserk special can force us to fight more than one round. */
00152     unsigned int hp;        /**< Hitpoints of the unit at the beginning of the battle. */
00153     unsigned int max_hp;    /**< Maximum hitpoints of the unit. */
00154     unsigned int chance_to_hit; /**< Effective chance to hit as a percentage (all factors accounted for). */
00155     int damage;             /**< Effective damage of the weapon (all factors accounted for). */
00156     int slow_damage;        /**< Effective damage if unit becomes slowed (== damage, if already slowed) */
00157     int drain_percent;      /**< Percentage of damage recovered as health */
00158     int drain_constant;     /**< Base HP drained regardless of damage dealt */
00159     unsigned int num_blows; /**< Effective number of blows, takes swarm into account. */
00160     unsigned int swarm_min; /**< Minimum number of blows with swarm (equal to num_blows if swarm isn't used). */
00161     unsigned int swarm_max; /**< Maximum number of blows with swarm (equal to num_blows if swarm isn't used). */
00162 
00163     std::string plague_type; /**< The plague type used by the attack, if any. */
00164 
00165     battle_context_unit_stats(const unit &u, const map_location& u_loc,
00166            int u_attack_num, bool attacking,
00167            const unit &opp, const map_location& opp_loc,
00168            const attack_type *opp_weapon,
00169            const unit_map& units);
00170     ~battle_context_unit_stats();
00171 
00172     /** Dumps the statistics of a unit on stdout. Remove it eventually. */
00173     void dump() const;
00174 };
00175 
00176 /** Computes the statistics of a battle between an attacker and a defender unit. */
00177 class battle_context
00178 {
00179 public:
00180 
00181     /**
00182      * If no attacker_weapon is given, we select the best one,
00183      * based on harm_weight (1.0 means 1 hp lost counters 1 hp damage,
00184      * 0.0 means we ignore harm weight).
00185      * prev_def is for predicting multiple attacks against a defender.
00186      */
00187     battle_context(const unit_map &units,
00188                    const map_location& attacker_loc, const map_location& defender_loc,
00189                    int attacker_weapon = -1, int defender_weapon = -1, double aggression = 0.0, const combatant *prev_def = NULL, const unit* attacker_ptr=NULL);
00190 
00191     /** Used by the AI which caches battle_context_unit_stats */
00192     battle_context(const battle_context_unit_stats &att, const battle_context_unit_stats &def);
00193 
00194     battle_context(const battle_context &other);
00195     ~battle_context();
00196 
00197     battle_context& operator=(const battle_context &other);
00198 
00199     /** This method returns the statistics of the attacker. */
00200     const battle_context_unit_stats& get_attacker_stats() const { return *attacker_stats_; }
00201 
00202     /** This method returns the statistics of the defender. */
00203     const battle_context_unit_stats& get_defender_stats() const { return *defender_stats_; }
00204 
00205     /** Get the simulation results. */
00206     const combatant &get_attacker_combatant(const combatant *prev_def = NULL);
00207     const combatant &get_defender_combatant(const combatant *prev_def = NULL);
00208 
00209     /** Given this harm_weight, is this attack better than that? */
00210     bool better_attack(class battle_context &that, double harm_weight);
00211 
00212 private:
00213     bool better_combat(const combatant &us_a, const combatant &them_a,
00214                        const combatant &us_b, const combatant &them_b,
00215                        double harm_weight);
00216 
00217     int choose_attacker_weapon(const unit &attacker, const unit &defender,
00218         const unit_map& units,
00219                                 const map_location& attacker_loc, const map_location& defender_loc,
00220                                 double harm_weight, int *defender_weapon, const combatant *prev_def);
00221 
00222     int choose_defender_weapon(const unit &attacker, const unit &defender, unsigned attacker_weapon,
00223         const unit_map& units,
00224                                const map_location& attacker_loc, const map_location& defender_loc, const combatant *prev_def);
00225 
00226     /** Statistics of the units. */
00227     battle_context_unit_stats *attacker_stats_, *defender_stats_;
00228 
00229     /** Outcome of simulated fight. */
00230     combatant *attacker_combatant_, *defender_combatant_;
00231 };
00232 
00233 /** Performs an attack. */
00234 void attack_unit(const map_location &attacker, const map_location &defender,
00235     int attack_with, int defend_with, bool update_display = true);
00236 
00237 class move_unit_spectator {
00238 public:
00239     /** add a location of a seen friend */
00240     void add_seen_friend(const unit_map::const_iterator &u);
00241 
00242 
00243     /** add the location of new seen enemy */
00244     void add_seen_enemy(const unit_map::const_iterator &u);
00245 
00246 
00247     /** get the location of an ambusher */
00248     const unit_map::const_iterator& get_ambusher() const;
00249 
00250 
00251     /** get the location of a failed teleport */
00252     const unit_map::const_iterator& get_failed_teleport() const;
00253 
00254 
00255     /** get the locations of seen enemies */
00256     const std::vector<unit_map::const_iterator>& get_seen_enemies() const;
00257 
00258 
00259     /** get the locations of seen friends */
00260     const std::vector<unit_map::const_iterator>& get_seen_friends() const;
00261 
00262 
00263     /** get new location of moved unit */
00264     const unit_map::const_iterator& get_unit() const;
00265 
00266 
00267     /** constructor */
00268     move_unit_spectator(const unit_map &units);
00269 
00270 
00271     /** destructor */
00272     virtual ~move_unit_spectator();
00273 
00274     /** reset all locations to empty values*/
00275     void reset(const unit_map &units);
00276 
00277 
00278     /** set the location of an ambusher */
00279     void set_ambusher(const unit_map::const_iterator &u);
00280 
00281 
00282     /** set the location of a failed teleport */
00283     void set_failed_teleport(const unit_map::const_iterator &u);
00284 
00285 
00286     /** set the iterator to moved unit*/
00287     void set_unit(const unit_map::const_iterator &u);
00288 private:
00289     unit_map::const_iterator ambusher_;
00290     unit_map::const_iterator failed_teleport_;
00291     std::vector<unit_map::const_iterator> seen_enemies_;
00292     std::vector<unit_map::const_iterator> seen_friends_;
00293     unit_map::const_iterator unit_;
00294 };
00295 
00296 /**
00297  * Given the location of a village, will return the 0-based index
00298  * of the team that currently owns it, and -1 if it is unowned.
00299  */
00300 int village_owner(const map_location& loc, const std::vector<team>& teams);
00301 
00302 /**
00303  * Makes it so the village at the given location is owned by the given side.
00304  * Returns true if getting the village triggered a mutating event.
00305  */
00306 bool get_village(const map_location& loc, int side, int *time_bonus = NULL);
00307 
00308 /**
00309  * Resets resting for all units on this side: should be called after calculate_healing().
00310  * @todo FIXME: Try moving this to unit::new_turn, then move it above calculate_healing().
00311  */
00312 void reset_resting(unit_map& units, int side);
00313 
00314 /**
00315  * Calculates healing for all units for the given side.
00316  * Should be called at the beginning of a side's turn.
00317  */
00318 void calculate_healing(int side, bool update_display);
00319 
00320 /**
00321  * Returns the advanced version of unit (with traits and items retained).
00322  */
00323 unit get_advanced_unit(const unit &u, const std::string &advance_to);
00324 
00325 /**
00326  * Function which will advance the unit at @a loc to 'advance_to'.
00327  * Note that 'loc' is not a reference, because if it were a reference,
00328  * we couldn't safely pass in a reference to the item in the map
00329  * that we're going to delete, since deletion would invalidate the reference.
00330  */
00331 void advance_unit(map_location loc, const std::string &advance_to, const bool &fire_event = true);
00332 
00333 /**
00334  * function which tests if the unit at loc is currently affected by leadership.
00335  * (i.e. has a higher-level 'leadership' unit next to it).
00336  * If it does, then the location of the leader unit will be returned,
00337  * Otherwise map_location::null_location will be returned.
00338  * If 'bonus' is not NULL, the % bonus will be stored in it.
00339  */
00340 map_location under_leadership(const unit_map& units,
00341                                    const map_location& loc, int* bonus=NULL);
00342 
00343 /**
00344  * Returns the amount that a unit's damage should be multiplied by
00345  * due to the current time of day.
00346  */
00347 int combat_modifier(const map_location &loc,
00348     unit_type::ALIGNMENT alignment, bool is_fearless);
00349 
00350 /** Records information to be able to undo a movement. */
00351 struct undo_action {
00352     enum ACTION_TYPE { NONE, RECRUIT, RECALL, DISMISS };
00353 
00354     undo_action(const unit& u, const std::vector<map_location>& rt, int sm,
00355         int timebonus=0, int orig=-1,
00356         const map_location::DIRECTION dir=map_location::NDIRECTIONS) :
00357             route(rt),
00358             starting_moves(sm),
00359             original_village_owner(orig),
00360             recall_loc(),
00361             recall_from(),
00362             type(NONE),
00363             affected_unit(u),
00364             countdown_time_bonus(timebonus),
00365             starting_dir(dir == map_location::NDIRECTIONS ? u.facing() : dir)
00366         {
00367         }
00368 
00369     undo_action(const unit& u, const map_location& loc, const map_location& from,
00370         const ACTION_TYPE action_type=NONE) :
00371             route(),
00372             starting_moves(),
00373             original_village_owner(),
00374             recall_loc(loc),
00375             recall_from(from),
00376             type(action_type),
00377             affected_unit(u),
00378             countdown_time_bonus(1),
00379             starting_dir(u.facing())
00380         {}
00381 
00382     std::vector<map_location> route;
00383     int starting_moves;
00384     int original_village_owner;
00385     map_location recall_loc;
00386     map_location recall_from;
00387     ACTION_TYPE type;
00388     unit affected_unit;
00389     int countdown_time_bonus;
00390     map_location::DIRECTION starting_dir;
00391 
00392     bool is_dismiss() const { return type == DISMISS; }
00393     bool is_recall() const { return type == RECALL; }
00394     bool is_recruit() const { return type == RECRUIT; }
00395 };
00396 
00397 typedef std::vector<undo_action> undo_list;
00398 
00399 /**
00400  * function which moves a unit along the sequence of locations given by steps.
00401  * If the unit cannot make it completely along the path this turn,
00402  * a goto order will be set.
00403  * If move_recorder is not NULL, the move will be recorded in it.
00404  * If undos is not NULL, undo information will be added.
00405  * If units_sighted_result is not NULL, it will indicate whether a sighting occurred.
00406  */
00407 size_t move_unit(move_unit_spectator* move_spectator,
00408     const std::vector<map_location> &steps,
00409                 replay* move_recorder, undo_list* undos,
00410                 bool show_move,
00411                 map_location *next_unit = NULL,
00412                 bool continue_move = false, bool should_clear_shroud=true, bool is_replay=false,
00413                 bool* units_sighted_result = NULL);
00414 
00415 /// Function that recalculates the fog of war.
00416 void recalculate_fog(int side);
00417 
00418 /// Function that will clear shroud (and fog) based on current unit positions.
00419 bool clear_shroud(int side, bool reset_fog=false);
00420 
00421 /**
00422  * Function to apply pending shroud changes in the undo stack.
00423  */
00424 void apply_shroud_changes(undo_list &undos, int side);
00425 
00426 /**
00427  * Will return true iff the unit @a u has any possible moves
00428  * it can do (including attacking etc).
00429  */
00430 bool unit_can_move(const unit &u);
00431 
00432 /**
00433  * Function to check if an attack will satisfy the requirements for backstab.
00434  * Input:
00435  * - the location from which the attack will occur,
00436  * - the defending unit location,
00437  * - the list of units on the map and
00438  * - the list of teams.
00439  * The defender and opposite units should be in place already.
00440  * The attacking unit doesn't need to be, but if it isn't,
00441  * an external check should be made to make sure the opposite unit
00442  * isn't also the attacker.
00443  */
00444 bool backstab_check(const map_location& attacker_loc,
00445     const map_location& defender_loc,
00446     const unit_map& units, const std::vector<team>& teams);
00447 
00448 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Tue May 22 2012 01:03:34 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs