1 /* 2 Copyright (C) 2009 - 2018 by Yurii Chernyi <terraninfo@terraninfo.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 /** 16 * @file 17 * Default AI contexts 18 */ 19 20 #pragma once 21 22 #include "ai/contexts.hpp" 23 #include "formula/callable.hpp" 24 #include "utils/make_enum.hpp" 25 26 //============================================================================ 27 namespace ai { 28 29 30 struct target { 31 MAKE_ENUM(TYPE, 32 (VILLAGE, "village") 33 (LEADER, "leader") 34 (EXPLICIT, "explicit") 35 (THREAT, "threat") 36 (BATTLE_AID, "battle aid") 37 (MASS, "mass") 38 (SUPPORT, "support") 39 ) 40 targetai::target41 target(const map_location& pos, double val, TYPE target_type=TYPE::VILLAGE) : loc(pos), value(val), type(target_type) 42 {} 43 map_location loc; 44 double value; 45 46 TYPE type; 47 ///@todo 1.7: ai goals: this is a 'target' marker class which should be expanded with additional information which is generic enough to apply to all targets. 48 }; 49 50 51 class attack_analysis : public wfl::action_callable 52 { 53 public: attack_analysis()54 attack_analysis() : 55 wfl::action_callable(), 56 target(), 57 movements(), 58 target_value(0.0), 59 avg_losses(0.0), 60 chance_to_kill(0.0), 61 avg_damage_inflicted(0.0), 62 target_starting_damage(0), 63 avg_damage_taken(0.0), 64 resources_used(0.0), 65 terrain_quality(0.0), 66 alternative_terrain_quality(0.0), 67 vulnerability(0.0), 68 support(0.0), 69 leader_threat(false), 70 uses_leader(false), 71 is_surrounded(false) 72 { 73 } 74 75 void analyze(const gamemap& map, unit_map& units, 76 const readonly_context& ai_obj, 77 const move_map& dstsrc, const move_map& srcdst, 78 const move_map& enemy_dstsrc, double aggression); 79 80 double rating(double aggression, const readonly_context& ai_obj) const; 81 wfl::variant get_value(const std::string& key) const override; 82 void get_inputs(wfl::formula_input_vector& inputs) const override; 83 84 bool attack_close(const map_location& loc) const; 85 86 map_location target; 87 std::vector<std::pair<map_location,map_location>> movements; 88 89 /** The value of the unit being targeted. */ 90 double target_value; 91 92 /** The value on average, of units lost in the combat. */ 93 double avg_losses; 94 95 /** Estimated % chance to kill the unit. */ 96 double chance_to_kill; 97 98 /** The average hitpoints damage inflicted. */ 99 double avg_damage_inflicted; 100 101 int target_starting_damage; 102 103 /** The average hitpoints damage taken. */ 104 double avg_damage_taken; 105 106 /** The sum of the values of units used in the attack. */ 107 double resources_used; 108 109 /** The weighted average of the % chance to hit each attacking unit. */ 110 double terrain_quality; 111 112 /** 113 * The weighted average of the % defense of the best possible terrain 114 * that the attacking units could reach this turn, without attacking 115 * (good for comparison to see just how good/bad 'terrain_quality' is). 116 */ 117 double alternative_terrain_quality; 118 119 /** 120 * The vulnerability is the power projection of enemy units onto the hex 121 * we're standing on. support is the power projection of friendly units. 122 */ 123 double vulnerability, support; 124 125 /** Is true if the unit is a threat to our leader. */ 126 bool leader_threat; 127 128 /** Is true if this attack sequence makes use of the leader. */ 129 bool uses_leader; 130 131 /** Is true if the units involved in this attack sequence are surrounded. */ 132 bool is_surrounded; 133 134 wfl::variant execute_self(wfl::variant ctxt) override; 135 }; 136 137 138 class default_ai_context; 139 class default_ai_context : public virtual readwrite_context{ 140 public: 141 142 virtual int count_free_hexes_in_castle(const map_location& loc, std::set<map_location> &checked_hexes) = 0; 143 144 145 /** Constructor */ 146 default_ai_context(); 147 148 149 /** Destructor */ 150 virtual ~default_ai_context(); 151 152 153 virtual const std::vector<target>& additional_targets() const = 0; 154 155 156 virtual void add_target(const target& t) const = 0; 157 158 159 virtual void clear_additional_targets() const = 0; 160 161 162 virtual default_ai_context& get_default_ai_context() = 0; 163 164 165 virtual std::vector<target> find_targets(const move_map& enemy_dstsrc) = 0; 166 167 168 virtual int rate_terrain(const unit& u, const map_location& loc) const = 0; 169 170 171 virtual config to_default_ai_context_config() const = 0; 172 173 174 }; 175 176 177 // proxies 178 class default_ai_context_proxy : public virtual default_ai_context, public virtual readwrite_context_proxy { 179 public: 180 count_free_hexes_in_castle(const map_location & loc,std::set<map_location> & checked_hexes)181 int count_free_hexes_in_castle(const map_location& loc, std::set<map_location> &checked_hexes) 182 { 183 return target_->count_free_hexes_in_castle(loc, checked_hexes); 184 } 185 186 default_ai_context_proxy()187 default_ai_context_proxy() 188 : target_(nullptr) 189 { 190 } 191 192 193 virtual ~default_ai_context_proxy(); 194 195 additional_targets() const196 virtual const std::vector<target>& additional_targets() const 197 { 198 return target_->additional_targets(); 199 } 200 201 add_target(const target & t) const202 virtual void add_target(const target& t) const 203 { 204 target_->add_target(t); 205 } 206 207 clear_additional_targets() const208 virtual void clear_additional_targets() const 209 { 210 target_->clear_additional_targets(); 211 } 212 213 get_default_ai_context()214 virtual default_ai_context& get_default_ai_context() 215 { 216 return target_->get_default_ai_context(); 217 } 218 219 find_targets(const move_map & enemy_dstsrc)220 virtual std::vector<target> find_targets(const move_map& enemy_dstsrc) 221 { 222 return target_->find_targets(enemy_dstsrc); 223 } 224 225 226 void init_default_ai_context_proxy(default_ai_context &target); 227 228 rate_terrain(const unit & u,const map_location & loc) const229 virtual int rate_terrain(const unit& u, const map_location& loc) const 230 { 231 return target_->rate_terrain(u,loc); 232 } 233 234 to_default_ai_context_config() const235 virtual config to_default_ai_context_config() const 236 { 237 return target_->to_default_ai_context_config(); 238 } 239 240 private: 241 default_ai_context *target_; 242 }; 243 244 245 class default_ai_context_impl : public virtual readwrite_context_proxy, public default_ai_context { 246 public: 247 248 int count_free_hexes_in_castle(const map_location& loc, std::set<map_location> &checked_hexes); 249 250 default_ai_context_impl(readwrite_context & context,const config &)251 default_ai_context_impl(readwrite_context &context, const config &/*cfg*/) 252 : recursion_counter_(context.get_recursion_count()),additional_targets_() 253 { 254 init_readwrite_context_proxy(context); 255 } 256 257 258 virtual ~default_ai_context_impl(); 259 260 261 virtual default_ai_context& get_default_ai_context(); 262 263 264 virtual const std::vector<target>& additional_targets() const; 265 266 267 virtual void add_target(const target& t) const; 268 269 270 virtual void clear_additional_targets() const; 271 272 get_recursion_count() const273 int get_recursion_count() const 274 { 275 return recursion_counter_.get_count(); 276 } 277 278 279 virtual std::vector<target> find_targets(const move_map& enemy_dstsrc); 280 281 282 virtual int rate_terrain(const unit& u, const map_location& loc) const; 283 284 285 virtual config to_default_ai_context_config() const; 286 287 private: 288 recursion_counter recursion_counter_; 289 mutable std::vector<target> additional_targets_;///@todo 1.9 refactor this 290 291 292 }; 293 294 } //end of namespace ai 295