The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
contexts.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2017 by Yurii Chernyi <terraninfo@terraninfo.net>
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  * Helper functions for the object which operates in the context of AI for specific side
17  * This is part of AI interface
18  * @file
19  */
20 
21 #include "ai/default/contexts.hpp"
22 
23 #include "game_board.hpp"
24 #include "log.hpp"
25 #include "map/map.hpp"
26 #include "resources.hpp"
27 #include "team.hpp"
28 #include "units/unit.hpp"
29 #include "ai/composite/goal.hpp"
30 #include "pathfind/pathfind.hpp"
31 
32 static lg::log_domain log_ai("ai/general");
33 #define DBG_AI LOG_STREAM(debug, log_ai)
34 #define LOG_AI LOG_STREAM(info, log_ai)
35 #define WRN_AI LOG_STREAM(warn, log_ai)
36 #define ERR_AI LOG_STREAM(err, log_ai)
37 
38 // =======================================================================
39 namespace ai {
40 
41 
42 // default ai context
44 {
45 }
46 
47 
49 {
50 }
51 
52 // default ai context proxy
53 
55 {
56 }
57 
59 {
62 }
63 
65 {
66 }
67 
68 
69 int default_ai_context_impl::count_free_hexes_in_castle(const map_location &loc, std::set<map_location> &checked_hexes)
70 {
71  int ret = 0;
72  unit_map &units_ = resources::gameboard->units();
73  map_location adj[6];
74  get_adjacent_tiles(loc,adj);
75  for(size_t n = 0; n != 6; ++n) {
76  if (checked_hexes.find(adj[n]) != checked_hexes.end())
77  continue;
78  checked_hexes.insert(adj[n]);
79  if (resources::gameboard->map().is_castle(adj[n])) {
80  const unit_map::const_iterator u = units_.find(adj[n]);
81  ret += count_free_hexes_in_castle(adj[n], checked_hexes);
82  if (u == units_.end()
83  || (current_team().is_enemy(u->side())
84  && u->invisible(adj[n], *resources::gameboard))
85  || ((&resources::gameboard->get_team(u->side()) == &current_team())
86  && u->movement_left() > 0)) {
87  ret += 1;
88  }
89  }
90  }
91  return ret;
92 }
93 
94 
96  return *this;
97 }
98 
99 
101 {
102  const gamemap &map_ = resources::gameboard->map();
104  const int defense = u.defense_modifier(terrain);
105  int rating = 100 - defense;
106 
107  const int healing_value = 10;
108  const int friendly_village_value = 5;
109  const int neutral_village_value = 10;
110  const int enemy_village_value = 15;
111 
112  if(map_.gives_healing(terrain) && u.get_ability_bool("regenerate", loc, *resources::gameboard) == false) {
113  rating += healing_value;
114  }
115 
116  if(map_.is_village(terrain)) {
117  int owner = resources::gameboard->village_owner(loc) + 1;
118 
119  if(owner == get_side()) {
120  rating += friendly_village_value;
121  } else if(owner == 0) {
122  rating += neutral_village_value;
123  } else {
124  rating += enemy_village_value;
125  }
126  }
127 
128  return rating;
129 }
130 
131 std::vector<target> default_ai_context_impl::find_targets(const move_map& enemy_dstsrc)
132 {
133 
134  log_scope2(log_ai, "finding targets...");
135  unit_map &units_ = resources::gameboard->units();
136  unit_map::iterator leader = units_.find_leader(get_side());
137  const gamemap &map_ = resources::gameboard->map();
138  std::vector<team> teams_ = resources::gameboard->teams();
139  const bool has_leader = leader != units_.end();
140 
141  std::vector<target> targets;
142 
143  //=== start getting targets
144 
145  //if enemy units are in range of the leader, then we target the enemies who are in range.
146  if(has_leader) {
147  double threat = power_projection(leader->get_location(), enemy_dstsrc);
148  if(threat > 0.0) {
149  //find the location of enemy threats
150  std::set<map_location> threats;
151 
152  map_location adj[6];
153  get_adjacent_tiles(leader->get_location(), adj);
154  for(size_t n = 0; n != 6; ++n) {
155  std::pair<move_map::const_iterator,move_map::const_iterator> itors = enemy_dstsrc.equal_range(adj[n]);
156  while(itors.first != itors.second) {
157  if(units_.count(itors.first->second)) {
158  threats.insert(itors.first->second);
159  }
160 
161  ++itors.first;
162  }
163  }
164 
165  assert(threats.empty() == false);
166 
167  const double value = threat/double(threats.size());
168  for(std::set<map_location>::const_iterator i = threats.begin(); i != threats.end(); ++i) {
169  LOG_AI << "found threat target... " << *i << " with value: " << value << "\n";
170  targets.emplace_back(*i,value,target::TYPE::THREAT);
171  }
172  }
173  }
174 
175  double corner_distance = distance_between(map_location::ZERO(), map_location(map_.w(),map_.h()));
176  double village_value = get_village_value();
177  if(has_leader && village_value > 0.0) {
178  std::map<map_location,pathfind::paths> friends_possible_moves;
179  move_map friends_srcdst, friends_dstsrc;
180  calculate_possible_moves(friends_possible_moves, friends_srcdst, friends_dstsrc, false, true);
181 
182  const std::vector<map_location>& villages = map_.villages();
183  for(std::vector<map_location>::const_iterator t =
184  villages.begin(); t != villages.end(); ++t) {
185 
186  assert(map_.on_board(*t));
187  bool ally_village = false;
188  for (size_t i = 0; i != teams_.size(); ++i)
189  {
190  if (!current_team().is_enemy(i + 1) && teams_[i].owns_village(*t)) {
191  ally_village = true;
192  break;
193  }
194  }
195 
196  if (ally_village)
197  {
198  //Support seems to cause the AI to just 'sit around' a lot, so
199  //only turn it on if it's explicitly enabled.
200  if(get_support_villages()) {
201  double enemy = power_projection(*t, enemy_dstsrc);
202  if (enemy > 0)
203  {
204  enemy *= 1.7;
205  double our = power_projection(*t, friends_dstsrc);
206  double value = village_value * our / enemy;
207  add_target(target(*t, value, target::TYPE::SUPPORT));
208  }
209  }
210  }
211  else
212  {
213  double leader_distance = distance_between(*t, leader->get_location());
214  double value = village_value * (1.0 - leader_distance / corner_distance);
215  LOG_AI << "found village target... " << *t
216  << " with value: " << value
217  << " distance: " << leader_distance << '\n';
218  targets.emplace_back(*t,value,target::TYPE::VILLAGE);
219  }
220  }
221  }
222 
223  std::vector<goal_ptr>& goals = get_goals();
224 
225  //find the enemy leaders and explicit targets
227  if (get_leader_value()>0.0) {
228  for(u = units_.begin(); u != units_.end(); ++u) {
229  //is a visible enemy leader
230  if (u->can_recruit() && current_team().is_enemy(u->side())
231  && !u->invisible(u->get_location(), *resources::gameboard)) {
232  assert(map_.on_board(u->get_location()));
233  LOG_AI << "found enemy leader (side: " << u->side() << ") target... " << u->get_location() << " with value: " << get_leader_value() << "\n";
234  targets.emplace_back(u->get_location(), get_leader_value(), target::TYPE::LEADER);
235  }
236  }
237 
238  }
239 
240  //explicit targets for this team
241  for(std::vector<goal_ptr>::iterator j = goals.begin();
242  j != goals.end(); ++j) {
243 
244  if (!(*j)->active()) {
245  continue;
246  }
247  (*j)->add_targets(std::back_inserter(targets));
248 
249  }
250 
251  //=== end getting targets
252 
253  std::vector<double> new_values;
254 
255  for(std::vector<target>::iterator i = targets.begin();
256  i != targets.end(); ++i) {
257 
258  new_values.push_back(i->value);
259 
260  for(std::vector<target>::const_iterator j = targets.begin(); j != targets.end(); ++j) {
261  if(i->loc == j->loc) {
262  continue;
263  }
264 
265  const double distance = std::abs(j->loc.x - i->loc.x) +
266  std::abs(j->loc.y - i->loc.y);
267  new_values.back() += j->value/(distance*distance);
268  }
269  }
270 
271  assert(new_values.size() == targets.size());
272  for(size_t n = 0; n != new_values.size(); ++n) {
273  LOG_AI << "target value: " << targets[n].value << " -> " << new_values[n] << "\n";
274  targets[n].value = new_values[n];
275  }
276 
277  return targets;
278 }
279 
280 
281 const std::vector<target>& default_ai_context_impl::additional_targets() const
282 {
283  return additional_targets_;
284 }
285 
286 
288 {
289  additional_targets_.push_back(t);
290 }
291 
292 
294 {
295  additional_targets_.clear();
296 }
297 
299 {
300  return config();
301 }
302 
303 } //of namespace ai
virtual default_ai_context & get_default_ai_context()=0
virtual void add_target(const target &t) const
Definition: contexts.cpp:287
virtual int rate_terrain(const unit &u, const map_location &loc) const
Definition: contexts.cpp:100
virtual const unit_map & units() const
Definition: game_board.hpp:97
unit_iterator end()
Definition: map.hpp:415
This class represents a single unit of a specific type.
Definition: unit.hpp:101
size_t count(const map_location &loc) const
Definition: map.hpp:400
unit_iterator find_leader(int side)
Definition: map.cpp:329
virtual double get_leader_value() const override
Definition: contexts.hpp:779
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.hpp:299
bool is_village(const map_location &loc) const
Definition: map.cpp:66
bool is_enemy(int n) const
Definition: team.hpp:241
virtual double get_village_value() const override
Definition: contexts.hpp:875
static const map_location & ZERO()
Old implementation:
Definition: location.hpp:215
unit_iterator begin()
Definition: map.hpp:405
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:55
int village_owner(const map_location &loc) const
Given the location of a village, will return the 0-based index of the team that currently owns it...
virtual const std::vector< team > & teams() const
Definition: game_board.hpp:92
int count_free_hexes_in_castle(const map_location &loc, std::set< map_location > &checked_hexes)
Definition: contexts.cpp:69
virtual std::vector< target > find_targets(const move_map &enemy_dstsrc)
Definition: contexts.cpp:131
-file sdl_utils.hpp
t_translation::terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:301
#define LOG_AI
Definition: contexts.cpp:34
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
Definition: game_info.hpp:45
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
default_ai_context()
Constructor.
Definition: contexts.cpp:43
size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition: location.hpp:382
virtual default_ai_context & get_default_ai_context()
Definition: contexts.cpp:95
virtual const std::vector< goal_ptr > & get_goals() const override
Definition: contexts.hpp:748
static lg::log_domain log_ai("ai/general")
int w() const
Effective map width.
Definition: map.hpp:90
game_board * gameboard
Definition: resources.cpp:20
Encapsulates the map of the game.
Definition: map.hpp:34
int defense_modifier(const t_translation::terrain_code &terrain) const
The unit's defense on a given terrain.
Definition: unit.cpp:1535
#define log_scope2(domain, description)
Definition: log.hpp:187
static const ::config * terrain
The terrain used to create the cache.
Definition: minimap.cpp:133
void init_default_ai_context_proxy(default_ai_context &target)
Definition: contexts.cpp:58
Encapsulates the map of the game.
Definition: location.hpp:40
int h() const
Effective map height.
Definition: map.hpp:93
virtual const team & current_team() const override
Definition: contexts.hpp:536
virtual ~default_ai_context()
Destructor.
Definition: contexts.cpp:48
const std::set< std::string > movetype::effects defense
Definition: movetype.cpp:782
Default AI contexts.
virtual double power_projection(const map_location &loc, const move_map &dstsrc) const override
Function which finds how much 'power' a side can attack a certain location with.
Definition: contexts.hpp:803
#define i
virtual side_number get_side() const override
Get the side number.
Definition: contexts.hpp:477
virtual config to_default_ai_context_config() const
Definition: contexts.cpp:298
virtual const gamemap & map() const
Definition: game_board.hpp:96
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:369
virtual ~default_ai_context_proxy()
Definition: contexts.cpp:54
double t
Definition: astarsearch.cpp:64
virtual void calculate_possible_moves(std::map< map_location, pathfind::paths > &possible_moves, move_map &srcdst, move_map &dstsrc, bool enemy, bool assume_full_movement=false, const terrain_filter *remove_destinations=nullptr) const override
Definition: contexts.hpp:585
default_ai_context * target_
Definition: contexts.hpp:247
virtual void clear_additional_targets() const
Definition: contexts.cpp:293
Standard logging facilities (interface).
Container associating units to locations.
Definition: map.hpp:99
void init_readwrite_context_proxy(readwrite_context &target)
Definition: contexts.hpp:1011
virtual bool get_support_villages() const override
Definition: contexts.hpp:869
std::vector< target > additional_targets_
Definition: contexts.hpp:295
unit_iterator find(size_t id)
Definition: map.cpp:311
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
const std::vector< map_location > & villages() const
Return a list of the locations of villages on the map.
Definition: map.hpp:157
static map_location::DIRECTION n
virtual ~default_ai_context_impl()
Definition: contexts.cpp:64
This module contains various pathfinding functions and utilities.
bool get_ability_bool(const std::string &tag_name, const map_location &loc, const display_context &dc) const
Checks whether this unit currently possesses or is affected by a given ability.
Definition: abilities.cpp:138
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
virtual const std::vector< target > & additional_targets() const
Definition: contexts.cpp:281
int gives_healing(const map_location &loc) const
Definition: map.cpp:68