The Battle for Wesnoth  1.13.4+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 - 2016 by Yurii Chernyi <[email protected]>
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;
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]))
85  || ((&(*resources::teams)[u->side() - 1]) == &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();
103  const t_translation::t_terrain terrain = map_.get_terrain(loc);
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) == 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...");
136  unit_map::iterator leader = units_.find_leader(get_side());
137  const gamemap &map_ = resources::gameboard->map();
138  std::vector<team> teams_ = *resources::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 #ifdef SUOKKO
168  //FIXME: suokko's revision 29531 included this change. Correct?
169  const double value = threat*get_protect_leader()/leader->second.hitpoints();
170 #else
171  const double value = threat/double(threats.size());
172 #endif
173  for(std::set<map_location>::const_iterator i = threats.begin(); i != threats.end(); ++i) {
174  LOG_AI << "found threat target... " << *i << " with value: " << value << "\n";
175  targets.push_back(target(*i,value,target::TYPE::THREAT));
176  }
177  }
178  }
179 
180  double corner_distance = distance_between(map_location::ZERO(), map_location(map_.w(),map_.h()));
181  double village_value = get_village_value();
182  if(has_leader && village_value > 0.0) {
183  std::map<map_location,pathfind::paths> friends_possible_moves;
184  move_map friends_srcdst, friends_dstsrc;
185  calculate_possible_moves(friends_possible_moves, friends_srcdst, friends_dstsrc, false, true);
186 
187  const std::vector<map_location>& villages = map_.villages();
188  for(std::vector<map_location>::const_iterator t =
189  villages.begin(); t != villages.end(); ++t) {
190 
191  assert(map_.on_board(*t));
192  bool ally_village = false;
193  for (size_t i = 0; i != teams_.size(); ++i)
194  {
195  if (!current_team().is_enemy(i + 1) && teams_[i].owns_village(*t)) {
196  ally_village = true;
197  break;
198  }
199  }
200 
201  if (ally_village)
202  {
203  //Support seems to cause the AI to just 'sit around' a lot, so
204  //only turn it on if it's explicitly enabled.
205  if(get_support_villages()) {
206  double enemy = power_projection(*t, enemy_dstsrc);
207  if (enemy > 0)
208  {
209  enemy *= 1.7;
210  double our = power_projection(*t, friends_dstsrc);
211  double value = village_value * our / enemy;
212  add_target(target(*t, value, target::TYPE::SUPPORT));
213  }
214  }
215  }
216  else
217  {
218  double leader_distance = distance_between(*t, leader->get_location());
219  double value = village_value * (1.0 - leader_distance / corner_distance);
220  LOG_AI << "found village target... " << *t
221  << " with value: " << value
222  << " distance: " << leader_distance << '\n';
223  targets.push_back(target(*t,value,target::TYPE::VILLAGE));
224  }
225  }
226  }
227 
228  std::vector<goal_ptr>& goals = get_goals();
229 
230  //find the enemy leaders and explicit targets
232  if (get_leader_value()>0.0) {
233  for(u = units_.begin(); u != units_.end(); ++u) {
234  //is a visible enemy leader
235  if (u->can_recruit() && current_team().is_enemy(u->side())
236  && !u->invisible(u->get_location())) {
237  assert(map_.on_board(u->get_location()));
238  LOG_AI << "found enemy leader (side: " << u->side() << ") target... " << u->get_location() << " with value: " << get_leader_value() << "\n";
239  targets.push_back(target(u->get_location(), get_leader_value(), target::TYPE::LEADER));
240  }
241  }
242 
243  }
244 
245  //explicit targets for this team
246  for(std::vector<goal_ptr>::iterator j = goals.begin();
247  j != goals.end(); ++j) {
248 
249  if (!(*j)->active()) {
250  continue;
251  }
252  (*j)->add_targets(std::back_inserter(targets));
253 
254  }
255 
256  //=== end getting targets
257 
258  std::vector<double> new_values;
259 
260  for(std::vector<target>::iterator i = targets.begin();
261  i != targets.end(); ++i) {
262 
263  new_values.push_back(i->value);
264 
265  for(std::vector<target>::const_iterator j = targets.begin(); j != targets.end(); ++j) {
266  if(i->loc == j->loc) {
267  continue;
268  }
269 
270  const double distance = abs(j->loc.x - i->loc.x) +
271  abs(j->loc.y - i->loc.y);
272  new_values.back() += j->value/(distance*distance);
273  }
274  }
275 
276  assert(new_values.size() == targets.size());
277  for(size_t n = 0; n != new_values.size(); ++n) {
278  LOG_AI << "target value: " << targets[n].value << " -> " << new_values[n] << "\n";
279  targets[n].value = new_values[n];
280  }
281 
282  return targets;
283 }
284 
285 
286 const std::vector<target>& default_ai_context_impl::additional_targets() const
287 {
288  return additional_targets_;
289 }
290 
291 
293 {
294  additional_targets_.push_back(t);
295 }
296 
297 
299 {
300  additional_targets_.clear();
301 }
302 
304 {
305  return config();
306 }
307 
308 } //of namespace ai
virtual side_number get_side() const
Get the side number.
Definition: contexts.hpp:480
virtual default_ai_context & get_default_ai_context()=0
virtual void add_target(const target &t) const
Definition: contexts.cpp:292
virtual int rate_terrain(const unit &u, const map_location &loc) const
Definition: contexts.cpp:100
unit_iterator end()
Definition: map.hpp:311
Definition: unit.hpp:95
size_t count(const map_location &loc) const
Definition: map.hpp:306
unit_iterator find_leader(int side)
Definition: map.cpp:297
variant map_
Definition: formula.cpp:306
virtual double get_leader_value() const
Definition: contexts.hpp:782
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:274
bool is_village(const map_location &loc) const
Definition: map.cpp:68
bool is_enemy(int n) const
Definition: team.hpp:247
static const map_location & ZERO()
Old implementation:
Definition: location.hpp:190
unit_iterator begin()
Definition: map.hpp:308
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...
int count_free_hexes_in_castle(const map_location &loc, std::set< map_location > &checked_hexes)
Definition: contexts.cpp:69
virtual const std::vector< goal_ptr > & get_goals() const
Definition: contexts.hpp:751
virtual std::vector< target > find_targets(const move_map &enemy_dstsrc)
Definition: contexts.cpp:131
bool get_ability_bool(const std::string &tag_name, const map_location &loc) const
Returns true if the unit is currently under effect by an ability with this given TAG NAME...
Definition: abilities.cpp:129
-file sdl_utils.hpp
GLdouble GLdouble t
Definition: glew.h:1366
int defense_modifier(const t_translation::t_terrain &terrain) const
Definition: unit.cpp:1520
virtual double power_projection(const map_location &loc, const move_map &dstsrc) const
Function which finds how much 'power' a side can attack a certain location with.
Definition: contexts.hpp:806
#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:47
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:57
std::vector< team > * teams
Definition: resources.cpp:29
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:357
virtual default_ai_context & get_default_ai_context()
Definition: contexts.cpp:95
GLsizei const GLfloat * value
Definition: glew.h:1817
static lg::log_domain log_ai("ai/general")
int w() const
Effective map width.
Definition: map.hpp:105
game_board * gameboard
Definition: resources.cpp:20
Encapsulates the map of the game.
Definition: map.hpp:37
#define log_scope2(domain, description)
Definition: log.hpp:186
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
Definition: contexts.hpp:588
static const ::config * terrain
The terrain used to create the cache.
Definition: minimap.cpp:135
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:47
void init_default_ai_context_proxy(default_ai_context &target)
Definition: contexts.cpp:58
Encapsulates the map of the game.
Definition: location.hpp:38
virtual bool get_support_villages() const
Definition: contexts.hpp:872
int h() const
Effective map height.
Definition: map.hpp:108
virtual ~default_ai_context()
Destructor.
Definition: contexts.cpp:48
Default AI contexts.
size_t i
Definition: function.cpp:1057
virtual config to_default_ai_context_config() const
Definition: contexts.cpp:303
boost::shared_ptr< std::vector< unit_const_ptr > > units_
Definition: dialogs.cpp:100
virtual const team & current_team() const
Definition: contexts.hpp:539
virtual const gamemap & map() const
Definition: game_board.hpp:98
t_translation::t_terrain get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:341
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:467
virtual ~default_ai_context_proxy()
Definition: contexts.cpp:54
GLclampd n
Definition: glew.h:5903
default_ai_context * target_
Definition: contexts.hpp:251
virtual double get_village_value() const
Definition: contexts.hpp:878
virtual void clear_additional_targets() const
Definition: contexts.cpp:298
Standard logging facilities (interface).
Container associating units to locations.
Definition: map.hpp:90
void init_readwrite_context_proxy(readwrite_context &target)
Definition: contexts.hpp:1014
std::vector< target > additional_targets_
Definition: contexts.hpp:299
unit_iterator find(size_t id)
Definition: map.cpp:285
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
const std::vector< map_location > & villages() const
Return a list of the locations of villages on the map.
Definition: map.hpp:163
virtual ~default_ai_context_impl()
Definition: contexts.cpp:64
This module contains various pathfinding functions and utilities.
unit_map * units
Definition: resources.cpp:35
virtual const std::vector< target > & additional_targets() const
Definition: contexts.cpp:286
GLenum target
Definition: glew.h:5190
int gives_healing(const map_location &loc) const
Definition: map.cpp:70