The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
goal.cpp
Go to the documentation of this file.
1 
2 /*
3  Copyright (C) 2009 - 2016 by Yurii Chernyi <[email protected]>
4  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  */
19 
20 #include "ai/composite/goal.hpp"
21 #include "global.hpp"
22 
23 #include "ai/default/contexts.hpp"
24 #include "ai/lua/core.hpp"
25 #include "ai/lua/lua_object.hpp"
26 #include "ai/manager.hpp"
27 #include "filter_context.hpp"
28 #include "game_board.hpp"
29 #include "log.hpp"
30 #include "map/location.hpp"
31 #include "resources.hpp"
33 #include "terrain/filter.hpp"
34 #include "units/unit.hpp"
35 #include "units/map.hpp"
36 #include "units/filter.hpp"
37 #include "wml_exception.hpp"
38 
39 #include <boost/lexical_cast.hpp>
40 #include <set>
41 #include <sstream>
42 
43 namespace ai {
44 
45 static lg::log_domain log_ai_goal("ai/goal");
46 #define DBG_AI_GOAL LOG_STREAM(debug, log_ai_goal)
47 #define LOG_AI_GOAL LOG_STREAM(info, log_ai_goal)
48 #define ERR_AI_GOAL LOG_STREAM(err, log_ai_goal)
49 
50 goal::goal(readonly_context &context, const config &cfg)
51  : readonly_context_proxy(), cfg_(cfg), ok_(true)
52 {
54 }
55 
56 
57 
59 {
60  LOG_AI_GOAL << "side " << get_side() << " : " << " created goal with name=[" << cfg_["name"] << "]" << std::endl;
61 }
62 
64 {
65  unrecognized();
66 }
67 
69 {
70  ERR_AI_GOAL << "side " << get_side() << " : " << " tried to create goal with name=[" << cfg_["name"] << "], but the [" << cfg_["engine"] << "] engine did not recognize that type of goal. " << std::endl;
71  ok_ = false;
72 }
73 
74 
76 {
77 }
78 
79 
80 void goal::add_targets(std::back_insert_iterator< std::vector< target > > /*target_list*/)
81 {
82 }
83 
84 
85 
87 {
88  return cfg_;
89 }
90 
92 {
93  return cfg_["id"];
94 }
95 
97 {
98  return cfg_["id"];
99 }
100 
102 {
103  return cfg_["engine"];
104 }
105 
106 
107 bool goal::redeploy(const config &cfg)
108 {
109  cfg_ = cfg;
110  on_create();
111  return true;
112 }
113 
114 
115 bool goal::ok() const
116 {
117  return ok_;
118 }
119 
120 
121 bool goal::active() const
122 {
123  return is_active(cfg_["time_of_day"],cfg_["turns"]);
124 }
125 
126 
128 {
129  goal::on_create();
130  if (!cfg_["engine"].empty() && cfg_["engine"] != "cpp") {
131  unrecognized();
132  value_ = 0;
133  return;
134  }
135  if (const config::attribute_value *v = cfg_.get("value")) {
136  try {
137  value_ = boost::lexical_cast<double>(*v);
138  } catch (boost::bad_lexical_cast){
139  ERR_AI_GOAL << "bad value of goal"<<std::endl;
140  value_ = 0;
141  }
142  }
143 }
144 
145 void target_unit_goal::add_targets(std::back_insert_iterator< std::vector< target > > target_list)
146 {
147  if (!(this)->active()) {
148  return;
149  }
150 
151  const config &criteria = cfg_.child("criteria");
152  if (!criteria) return;
153 
154  //find the enemy leaders and explicit targets
155  const unit_filter ufilt(vconfig(criteria), resources::filter_con);
156  for (const unit &u : *resources::units) {
157  if (ufilt( u )) {
158  LOG_AI_GOAL << "found explicit target unit at ... " << u.get_location() << " with value: " << value() << "\n";
159  *target_list = target(u.get_location(), value(), target::TYPE::EXPLICIT);
160  }
161  }
162 
163 
164 }
165 
166 
168  : goal(context,cfg)
169  , value_(0.0)
170 {
171 }
172 
173 
175 {
176  goal::on_create();
177  if (!cfg_["engine"].empty() && cfg_["engine"] != "cpp") {
178  unrecognized();
179  value_ = 0;
180  return;
181  }
182  if (cfg_.has_attribute("value")) {
183  try {
184  value_ = boost::lexical_cast<double>(cfg_["value"]);
185  } catch (boost::bad_lexical_cast){
186  ERR_AI_GOAL << "bad value of goal"<<std::endl;
187  value_ = 0;
188  }
189  }
190  const config &criteria = cfg_.child("criteria");
191  if (criteria) {
193  }
194 }
195 
196 void target_location_goal::add_targets(std::back_insert_iterator< std::vector< target > > target_list)
197 {
198  if (!(this)->active()) {
199  return;
200  }
201 
202  if (!filter_ptr_) return;
203 
204  std::set<map_location> items;
205  filter_ptr_->get_locations(items);
206  for (const map_location &loc : items)
207  {
208  LOG_AI_GOAL << "found explicit target location ... " << loc << " with value: " << value() << std::endl;
209  *target_list = target(loc, value(), target::TYPE::EXPLICIT);
210  }
211 
212 }
213 
215  : goal(context,cfg)
216  , filter_ptr_()
217  , value_(0.0)
218 {
219 }
220 
221 
222 
224 {
225  goal::on_create();
226  if (!cfg_["engine"].empty() && cfg_["engine"] != "cpp") {
227  unrecognized();
228  value_ = 0;
229  return;
230  }
231  if (const config::attribute_value *v = cfg_.get("value")) {
232  try {
233  value_ = boost::lexical_cast<double>(*v);
234  } catch (boost::bad_lexical_cast){
235  ERR_AI_GOAL << "bad value of protect_goal"<<std::endl;
236  value_ = 0;
237  }
238  }
239  if (const config::attribute_value *v = cfg_.get("protect_radius")) {
240  try {
241  radius_ = boost::lexical_cast<int>(*v);
242  } catch (boost::bad_lexical_cast){
243  ERR_AI_GOAL << "bad protection radius of protect_goal"<<std::endl;
244  radius_ = 1;
245  }
246  }
247 
248  if (radius_<1) {
249  radius_=20;
250  }
251  const config &criteria = cfg_.child("criteria");
252  if (criteria) {
254  }
255 
256 
257 }
258 
259 
260 void protect_goal::add_targets(std::back_insert_iterator< std::vector< target > > target_list)
261 {
262  std::string goal_type;
263  if (protect_unit_) {
264  goal_type = "protect_unit";
265  } else {
266  goal_type ="protect_location";
267  }
268 
269  if (!(this)->active()) {
270  LOG_AI_GOAL << "skipping " << goal_type << " goal - not active" << std::endl;
271  return;
272  }
273 
274  const config &criteria = cfg_.child("criteria");
275  if (!criteria) {
276  LOG_AI_GOAL << "skipping " << goal_type << " goal - no criteria given" << std::endl;
277  return;
278  } else {
279  DBG_AI_GOAL << "side " << get_side() << ": "<< goal_type << " goal with criteria" << std::endl << cfg_.child("criteria") << std::endl;
280  }
281 
283 
284  std::set<map_location> items;
285  if (protect_unit_) {
286  const unit_filter ufilt(vconfig(criteria), resources::filter_con);
287  for (const unit &u : units)
288  {
289  //TODO: we will protect hidden units, by not testing for invisibility to current side
290  if (ufilt(u)) {
291  DBG_AI_GOAL << "side " << get_side() << ": in " << goal_type << ": " << u.get_location() << " should be protected\n";
292  items.insert(u.get_location());
293  }
294  }
295  } else {
296  filter_ptr_->get_locations(items);
297  }
298  DBG_AI_GOAL << "side " << get_side() << ": seaching for threats in "+goal_type+" goal" << std::endl;
299  // Look for directions to protect a specific location or specific unit.
300  for (const map_location &loc : items)
301  {
302  for (const unit &u : units)
303  {
304  int distance = distance_between(u.get_location(), loc);
305  if (current_team().is_enemy(u.side()) && distance < radius_ &&
306  !u.invisible(u.get_location()))
307  {
308  DBG_AI_GOAL << "side " << get_side() << ": in " << goal_type << ": found threat target. " << u.get_location() << " is a threat to "<< loc << '\n';
309  *target_list = target(u.get_location(),
310  value_ * double(radius_ - distance) /
311  radius_, target::TYPE::THREAT);
312  }
313  }
314  }
315 
316 
317 }
318 
319 
320 protect_goal::protect_goal(readonly_context &context, const config &cfg, bool protect_unit)
321  : goal(context,cfg)
322  , filter_ptr_()
323  , protect_unit_(protect_unit)
324  , radius_(20) //this default radius is taken from old code
325  , value_(1.0) //this default value taken from old code
326 {
327 }
328 
330  : goal(context, cfg)
331  , code_()
332  , handler_()
333 {
334  if (cfg.has_attribute("code")) {
335  code_ = cfg["code"].str();
336  }
337  else
338  {
339  ERR_AI_GOAL << "side " << get_side() << " : Error creating Lua goal (missing code= key)" << std::endl;
340  }
341 }
342 
344 {
346 }
347 
348 void lua_goal::add_targets(std::back_insert_iterator< std::vector< target > > target_list)
349 {
352  config c(cfg_.child_or_empty("args"));
353  handler_->handle(c, true, l_obj);
354  try {
355  std::vector < target > targets = *(l_obj->get());
356 
357  for (target tg : targets)
358  {
359  *target_list = tg;
360  }
361  } catch(bad_enum_cast& e) {
362  ERR_AI_GOAL << "A Lua goal returned a target of an unknown type (\"" << e.value() << "\"; unfortunately, the engine cannot recover from this error. As a result, all targets returned by the goal have been lost.\n";
363  }
364 
365 }
366 
367 
368 // This is defined in the source file so that it can easily access the logger
370 {
371  if (get_list().find(name) != get_list().end()) {
372  ERR_AI_GOAL << "Error: Attempt to double-register goal " << name << std::endl;
373  return true;
374  }
375  return false;
376 }
377 
378 
379 } //end of namespace ai
virtual side_number get_side() const
Get the side number.
Definition: contexts.hpp:480
virtual void add_targets(std::back_insert_iterator< std::vector< target > > target_list)
Definition: goal.cpp:145
virtual void add_targets(std::back_insert_iterator< std::vector< target > > target_list)
Definition: goal.cpp:260
Definition: unit.hpp:95
const GLfloat * c
Definition: glew.h:12741
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
boost::shared_ptr< lua_ai_action_handler > handler_
Definition: goal.hpp:177
static lg::log_domain log_ai_goal("ai/goal")
target_location_goal(readonly_context &context, const config &cfg)
Definition: goal.cpp:214
bool is_enemy(int n) const
Definition: team.hpp:247
static factory_map & get_list()
Definition: goal.hpp:188
goal(readonly_context &context, const config &cfg)
Definition: goal.cpp:50
virtual void on_create()
Definition: goal.cpp:174
config cfg_
Definition: goal.hpp:83
const std::vector< std::string > items
const config & child_or_empty(const std::string &key) const
Returns the first child with the given key, or an empty config if there is none.
Definition: config.cpp:722
To lexical_cast(From value)
Lexical cast converts one type to another.
const char * value() const
Definition: make_enum.hpp:113
Lua object(value) wrapper implementation.
Variant for storing WML attributes.
Definition: config.hpp:223
virtual std::string get_engine() const
Definition: goal.cpp:101
virtual void on_create()
Definition: goal.cpp:223
double value_
Definition: goal.hpp:148
boost::shared_ptr< terrain_filter > filter_ptr_
Definition: goal.hpp:123
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:57
virtual void on_create()
Definition: goal.cpp:58
bool ok_
Definition: goal.hpp:84
GLuint GLuint end
Definition: glew.h:1221
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
filter_context * filter_con
Definition: resources.cpp:23
const GLdouble * v
Definition: glew.h:1359
bool active() const
Definition: goal.cpp:121
void unrecognized()
Definition: goal.cpp:68
virtual void add_targets(std::back_insert_iterator< std::vector< target > > target_list)
Definition: goal.cpp:196
bool protect_unit_
Definition: goal.hpp:146
Managing the AIs lifecycle - headers.
lua_goal(readonly_context &context, const config &cfg)
Definition: goal.cpp:329
virtual config to_config() const
Definition: goal.cpp:86
virtual bool is_active(const std::string &time_of_day, const std::string &turns) const
Definition: contexts.hpp:891
Encapsulates the map of the game.
Definition: location.hpp:38
virtual std::string get_id() const
Definition: goal.cpp:91
bool redeploy(const config &cfg)
Definition: goal.cpp:107
std::string code_
Definition: goal.hpp:176
virtual void add_targets(std::back_insert_iterator< std::vector< target > > target_list)
Definition: goal.cpp:80
Default AI contexts.
virtual void add_targets(std::back_insert_iterator< std::vector< target > > target_list)
Definition: goal.cpp:348
ai::lua_ai_action_handler * create_lua_ai_action_handler(char const *code, ai::lua_ai_context &context)
boost::shared_ptr< terrain_filter > filter_ptr_
Definition: goal.hpp:145
#define ERR_AI_GOAL
Definition: goal.cpp:48
GLuint const GLchar * name
Definition: glew.h:1782
virtual const team & current_team() const
Definition: contexts.hpp:539
const attribute_value * get(const std::string &key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition: config.cpp:935
virtual std::string get_name() const
Definition: goal.cpp:96
tformula< unsigned > radius_
The radius of the circle.
Definition: canvas.cpp:842
bool has_attribute(const std::string &key) const
Definition: config.cpp:514
protect_goal(readonly_context &context, const config &cfg, bool protect_unit)
Definition: goal.cpp:320
double value() const
Definition: goal.hpp:119
bool find(E event, F functor)
Tests whether an event handler is available.
virtual void on_create()
Definition: goal.cpp:127
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
A variable-expanding proxy for the config class.
Definition: variable.hpp:36
Standard logging facilities (interface).
target_unit_goal(readonly_context &context, const config &cfg)
Definition: goal.cpp:167
#define DBG_AI_GOAL
Definition: goal.cpp:46
bool is_duplicate(const std::string &name)
Definition: goal.cpp:369
game_lua_kernel * lua_kernel
Definition: resources.cpp:25
Container associating units to locations.
Definition: map.hpp:90
#define c
Definition: glew.h:12743
#define LOG_AI_GOAL
Definition: goal.cpp:47
#define e
double value() const
Definition: goal.hpp:100
bool ok() const
Definition: goal.cpp:115
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLsizei const GLcharARB ** string
Definition: glew.h:4503
unit_map * units
Definition: resources.cpp:35
virtual ~goal()
Definition: goal.cpp:75
void init_readonly_context_proxy(readonly_context &target)
Definition: contexts.hpp:521
GLenum target
Definition: glew.h:5190