ai.hpp

Go to the documentation of this file.
00001 /* $Id: ai.hpp 26083 2008-04-25 01:55:51Z soliton $ */
00002 /*
00003    Copyright (C) 2003 - 2008 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 version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 //! @file ai.hpp
00016 //!
00017 
00018 #ifndef AI_HPP_INCLUDED
00019 #define AI_HPP_INCLUDED
00020 
00021 #include "global.hpp"
00022 
00023 #include "actions.hpp"
00024 #include "ai_interface.hpp"
00025 #include "formula_callable.hpp"
00026 
00027 class ai : public ai_interface {
00028 public:
00029 
00030     ai(ai_interface::info& info);
00031     virtual ~ai() {}
00032 
00033     virtual void play_turn();
00034 
00035     struct target {
00036         enum TYPE { VILLAGE, LEADER, EXPLICIT, THREAT, BATTLE_AID, MASS, SUPPORT };
00037 
00038         target(const location& pos, double val, TYPE target_type=VILLAGE) : loc(pos), value(val), type(target_type)
00039         {}
00040         location loc;
00041         double value;
00042 
00043         TYPE type;
00044     };
00045 
00046     struct defensive_position {
00047         defensive_position() :
00048             loc(),
00049             chance_to_hit(0),
00050             vulnerability(0.0),
00051             support(0.0)
00052             {}
00053 
00054         location loc;
00055         int chance_to_hit;
00056         double vulnerability, support;
00057     };
00058 
00059     defensive_position const& best_defensive_position(const location& unit,
00060             const move_map& dstsrc, const move_map& srcdst, const move_map& enemy_dstsrc);
00061 
00062     void invalidate_defensive_position_cache() { defensive_position_cache_.clear(); }
00063 
00064     bool leader_can_reach_keep();
00065 
00066     //! Return true iff there has been another attack this turn 'close' to this one.
00067     bool attack_close(const location& loc) const;
00068 
00069 protected:
00070 
00071     std::map<location,defensive_position> defensive_position_cache_;
00072 
00073     virtual void do_move();
00074 
00075     virtual bool do_combat(std::map<gamemap::location,paths>& possible_moves,
00076             const move_map& srcdst, const move_map& dstsrc,
00077             const move_map& enemy_srcdst, const move_map& enemy_dstsrc);
00078     virtual bool get_villages(std::map<gamemap::location,paths>& possible_moves,
00079             const move_map& dstsrc, const move_map& enemy_dstsrc,
00080             unit_map::iterator &leader);
00081     virtual bool get_healing(std::map<gamemap::location,paths>& possible_moves,
00082             const move_map& srcdst, const move_map& enemy_dstsrc);
00083     virtual bool retreat_units(std::map<gamemap::location,paths>& possible_moves,
00084             const move_map& srcdst, const move_map& dstsrc,
00085             const move_map& enemy_dstsrc, unit_map::const_iterator leader);
00086     virtual bool move_to_targets(std::map<gamemap::location,paths>& possible_moves,
00087             move_map& srcdst, move_map& dstsrc, const move_map& enemy_dstsrc,
00088             unit_map::const_iterator leader);
00089 
00090     virtual bool should_retreat(const gamemap::location& loc,
00091             const unit_map::const_iterator un, const move_map& srcdst,
00092             const move_map& dstsrc, const move_map& enemy_dstsrc, double caution);
00093 
00094     virtual void do_recruitment();
00095 
00096     virtual void move_leader_to_keep(const move_map& enemy_dstsrc);
00097     virtual void move_leader_after_recruit(const move_map& srcdst,
00098             const move_map& dstsrc, const move_map& enemy_dstsrc);
00099 
00100     virtual void move_leader_to_goals(const move_map& enemy_dstsrc);
00101 
00102 
00103     virtual bool recruit_usage(const std::string& usage);
00104 
00105     virtual bool desperate_attack(const gamemap::location &loc);
00106 
00107     void remove_unit_from_moves(const gamemap::location& u, move_map& srcdst, move_map& dstsrc);
00108 
00109     //! Find enemy units that threaten our valuable assets.
00110     void find_threats();
00111 
00112     bool threats_found_;
00113 
00114     //! Our own version of 'move_unit'. It is like the version in ai_interface,
00115     //! however if it is the leader moving, it will first attempt recruitment.
00116     location move_unit(location from, location to, std::map<location,paths>& possible_moves);
00117 
00118     //! Our own version of 'attack_enemy'. We record all attacks to support group attacking.
00119     void attack_enemy(const location& attacking_unit, const location& target,
00120             int att_weapon, int def_weapon);
00121 
00122     std::set<location> attacks_;
00123 
00124     //! Sees if it's possible for a unit to move 'from' -> 'via' -> 'to' all in one turn.
00125     bool multistep_move_possible(const location& from,
00126         const location& to, const location& via,
00127         const std::map<location,paths>& possible_moves) const;
00128 
00129 public:
00130     struct attack_analysis : public game_logic::formula_callable
00131     {
00132         void analyze(const gamemap& map, unit_map& units,
00133                      const std::vector<team>& teams,
00134                      const gamestatus& status,
00135                      class ai& ai_obj,
00136                      const move_map& dstsrc, const move_map& srcdst,
00137                      const move_map& enemy_dstsrc, double aggression);
00138 
00139         double rating(double aggression, class ai& ai_obj) const;
00140         variant get_value(const std::string& key) const;
00141         void get_inputs(std::vector<game_logic::formula_input>* inputs) const;
00142 
00143         gamemap::location target;
00144         std::vector<std::pair<gamemap::location,gamemap::location> > movements;
00145 
00146         //! The value of the unit being targeted.
00147         double target_value;
00148 
00149         //! The value on average, of units lost in the combat
00150         double avg_losses;
00151 
00152         //! Estimated % chance to kill the unit
00153         double chance_to_kill;
00154 
00155         //! The average hitpoints damage inflicted
00156         double avg_damage_inflicted;
00157 
00158         int target_starting_damage;
00159 
00160         //! The average hitpoints damage taken
00161         double avg_damage_taken;
00162 
00163         //! The sum of the values of units used in the attack
00164         double resources_used;
00165 
00166         //! The weighted average of the % chance to hit each attacking unit
00167         double terrain_quality;
00168 
00169         //! The weighted average of the % defense of the best possible terrain
00170         //! that the attacking units could reach this turn, without attacking
00171         //! (good for comparison to see just how good/bad 'terrain_quality' is).
00172         double alternative_terrain_quality;
00173 
00174         //! The vulnerability is the power projection of enemy units onto the hex
00175         //! we're standing on. support is the power projection of friendly units.
00176         double vulnerability, support;
00177 
00178         //! Is true if the unit is a threat to our leader.
00179         bool leader_threat;
00180 
00181         //! Is true if this attack sequence makes use of the leader.
00182         bool uses_leader;
00183 
00184         //! Is true if the units involved in this attack sequence are surrounded.
00185         bool is_surrounded;
00186     };
00187 
00188 protected:
00189 
00190     virtual void do_attack_analysis(
00191                      const location& loc,
00192                      const move_map& srcdst, const move_map& dstsrc,
00193                      const move_map& fullmove_srcdst, const move_map& fullmove_dstsrc,
00194                      const move_map& enemy_srcdst, const move_map& enemy_dstsrc,
00195                      const location* tiles, bool* used_locations,
00196                      std::vector<location>& units,
00197                      std::vector<attack_analysis>& result,
00198                      attack_analysis& cur_analysis
00199                     );
00200 
00201 
00202     //! Function which finds how much 'power' a side can attack a certain location with.
00203     //! This is basically the maximum hp of damage that can be inflicted upon a unit on loc
00204     //! by full-health units, multiplied by the defense these units will have.
00205     //! (if 'use_terrain' is false, then it will be multiplied by 0.5)
00206     //
00207     // Example: 'loc' can be reached by two units, one of whom has a 10-3 attack
00208     // and has 48/48 hp, and can defend at 40% on the adjacent grassland.
00209     // The other has a 8-2 attack, and has 30/40 hp, and can defend at 60% on the adjacent mountain.
00210     // The rating will be 10*3*1.0*0.4 + 8*2*0.75*0.6 = 19.2
00211     virtual double power_projection(const gamemap::location& loc, const move_map& dstsrc,
00212             bool use_terrain=true) const;
00213 
00214     virtual std::vector<attack_analysis> analyze_targets(
00215                  const move_map& srcdst, const move_map& dstsrc,
00216                  const move_map& enemy_srcdst, const move_map& enemy_dstsrc
00217             );
00218 
00219     bool is_accessible(const location& loc, const move_map& dstsrc) const;
00220 
00221     virtual std::vector<target> find_targets(unit_map::const_iterator leader,
00222             const move_map& enemy_dstsrc);
00223 
00224     //! Function to form a group of units suitable for moving along the route, 'route'.
00225     //! Returns the location which the group may reach this turn.
00226     //! Stores the locations of the units in the group in 'units'
00227     virtual location form_group(const std::vector<location>& route,
00228             const move_map& dstsrc, std::set<location>& units);
00229 
00230     //! Return the group of enemies that threaten a certain path.
00231     virtual void enemies_along_path(const std::vector<location>& route,
00232             const move_map& dstsrc, std::set<location>& units);
00233 
00234     virtual bool move_group(const location& dst, const std::vector<location>& route,
00235             const std::set<location>& units);
00236 
00237     virtual double rate_group(const std::set<location>& group,
00238             const std::vector<location>& battlefield) const;
00239 
00240     virtual double compare_groups(const std::set<location>& our_group,
00241             const std::set<location>& enemy_groups,
00242             const std::vector<location>& battlefield) const;
00243 
00244     virtual std::pair<location,location> choose_move(std::vector<target>& targets,
00245             const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_dstsrc);
00246 
00247     //! Rates the value of moving onto certain terrain for a unit.
00248     virtual int rate_terrain(const unit& u, const location& loc);
00249 
00250     game_display& disp_;
00251     const gamemap& map_;
00252     unit_map& units_;
00253     std::vector<team>& teams_;
00254     unsigned int team_num_;
00255     const gamestatus& state_;
00256     bool consider_combat_;
00257     std::vector<target> additional_targets_;
00258 
00259     void add_target(const target& tgt) { additional_targets_.push_back(tgt); }
00260 
00261     //! Analyze all the units that this side can recruit
00262     //! and rate their movement types.
00263     //! Ratings will be placed in 'unit_movement_scores_',
00264     //! with lower scores being better,
00265     //! and the lowest possible rating being '10'.
00266     virtual void analyze_potential_recruit_movements();
00267 
00268     std::map<std::string,int> unit_movement_scores_;
00269     std::set<std::string> not_recommended_units_;
00270 
00271     //! Analyze all the units that this side can recruit
00272     //! and rate their fighting suitability against enemy units.
00273     //! Ratings will be placed in 'unit_combat_scores_',
00274     //! with a '0' rating indicating that the unit is 'average' against enemy units,
00275     //! negative ratings meaning they are poorly suited,
00276     //! and positive ratings meaning they are well suited.
00277     virtual void analyze_potential_recruit_combat();
00278 
00279     std::map<std::string,int> unit_combat_scores_;
00280 
00281     //! Rates two unit types for their suitability against each other.
00282     // Returns 0 if the units are equally matched,
00283     // a positive number if a is suited against b,
00284     // and a negative number if b is suited against a.
00285     virtual int compare_unit_types(const unit_type& a, const unit_type& b) const;
00286 
00287     //! calculates the average resistance unit type a has
00288     //! against the attacks of unit type b.
00289     virtual int average_resistance_against(const unit_type& a, const unit_type& b) const;
00290 
00291     //! Functions to deal with keeps.
00292     const std::set<location>& keeps();
00293     const location& nearest_keep(const location& loc);
00294 
00295     std::set<location> keeps_;
00296 
00297     //! Function which, given a unit position,
00298     //! and a position the unit wants to get to in two turns,
00299     //! will return all possible positions the unit can move to,
00300     //! that will make the destination position accessible next turn.
00301     void access_points(const move_map& srcdst, const location& u,
00302             const location& dst, std::vector<location>& out);
00303 
00304     //! Function which gets the areas of the map
00305     //! that this AI has been instructed to avoid.
00306     const std::set<location>& avoided_locations();
00307 
00308     std::set<location> avoid_;
00309 
00310     //! Weapon choice cache, to speed simulations.
00311     std::map<std::pair<location,const unit_type *>,
00312         std::pair<battle_context::unit_stats,battle_context::unit_stats> > unit_stats_cache_;
00313 
00314     int attack_depth();
00315     int attack_depth_;
00316     friend struct attack_analysis;
00317 
00318 private:
00319     void find_villages(/*std::vector<unit_map::const_iterator>& our_units,
00320         std::vector<std::vector<gamemap::location> >& reachable_villages, */
00321         std::map<gamemap::location /*unit location*/, std::vector<gamemap::location /* villages we can reach*/> >& reachmap,
00322         std::vector<std::pair<gamemap::location,gamemap::location> >& moves,
00323         const std::multimap<gamemap::location,gamemap::location>& dstsrc,
00324         const std::map<gamemap::location,paths>& possible_moves,
00325         const std::multimap<gamemap::location,gamemap::location>& enemy_dstsrc) const;
00326 };
00327 
00328 #endif

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs