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