The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
stage_unit_formulas.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  * @file
17  * Defines formula ai unit formulas stage
18  * */
19 
20 
22 #include "ai/formula/ai.hpp"
23 
24 #include "formula/formula.hpp"
25 #include "formula/function.hpp"
26 #include "game_board.hpp"
27 #include "log.hpp"
28 #include "resources.hpp"
29 #include "units/unit.hpp"
31 
32 static lg::log_domain log_formula_ai("ai/stage/unit_formulas");
33 #define LOG_AI LOG_STREAM(info, log_formula_ai)
34 #define WRN_AI LOG_STREAM(warn, log_formula_ai)
35 #define ERR_AI LOG_STREAM(err, log_formula_ai)
36 
37 namespace ai {
38 
40  ai_context &context
41  , const config &cfg
42  , formula_ai &fai)
43  : stage(context,cfg), fai_(fai)
44 {
45 
46 }
47 
48 
50 {
51 }
52 
54 {
55  //execute units formulas first
56  wfl::unit_formula_set units_with_formulas;
57 
58  unit_map &units_ = resources::gameboard->units();
59 
60  for(unit_map::unit_iterator i = units_.begin() ; i != units_.end() ; ++i)
61  {
62  if (i->side() == get_side()) {
63  if (i->formula_manager().has_formula() || i->formula_manager().has_loop_formula()) {
64  int priority = 0;
65  if (i->formula_manager().has_priority_formula()) {
66  try {
67  wfl::const_formula_ptr priority_formula(fai_.create_optional_formula(i->formula_manager().get_priority_formula()));
68  if (priority_formula) {
70  callable.add("me", wfl::variant(std::make_shared<wfl::unit_callable>(*i)));
71  priority = (wfl::formula::evaluate(priority_formula, callable)).as_int();
72  } else {
73  WRN_AI << "priority formula skipped, maybe it's empty or incorrect"<< std::endl;
74  }
75  } catch(wfl::formula_error& e) {
76  if(e.filename == "formula")
77  e.line = 0;
78  fai_.handle_exception( e, "Unit priority formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().wml_x()) + "," + std::to_string(i->get_location().wml_y()) + ")");
79 
80  priority = 0;
81  } catch(wfl::type_error& e) {
82  priority = 0;
83  ERR_AI << "formula type error while evaluating unit priority formula " << e.message << std::endl;
84  }
85  }
86 
87  units_with_formulas.insert( wfl::unit_formula_pair( i, priority ) );
88  }
89  }
90  }
91 
92  for(wfl::unit_formula_set::iterator pair_it = units_with_formulas.begin() ; pair_it != units_with_formulas.end() ; ++pair_it)
93  {
94  unit_map::iterator i = pair_it->first;
95 
96  if( i.valid() ) {
97 
98  if (i->formula_manager().has_formula()) {
99  try {
100  wfl::const_formula_ptr formula(fai_.create_optional_formula(i->formula_manager().get_formula()));
101  if (formula) {
103  callable.add("me", wfl::variant(std::make_shared<wfl::unit_callable>(*i)));
104  fai_.make_action(formula, callable);
105  } else {
106  WRN_AI << "unit formula skipped, maybe it's empty or incorrect" << std::endl;
107  }
108  }
109  catch(wfl::formula_error& e) {
110  if(e.filename == "formula") {
111  e.line = 0;
112  }
113  fai_.handle_exception( e, "Unit formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().wml_x()) + "," + std::to_string(i->get_location().wml_y()) + ")");
114  }
115  }
116  }
117 
118  if( i.valid() ) {
119  if (i->formula_manager().has_loop_formula())
120  {
121  try {
122  wfl::const_formula_ptr loop_formula(fai_.create_optional_formula(i->formula_manager().get_loop_formula()));
123  if (loop_formula) {
125  callable.add("me", wfl::variant(std::make_shared<wfl::unit_callable>(*i)));
126  while ( !fai_.make_action(loop_formula, callable).is_empty() && i.valid() )
127  {
128  }
129  } else {
130  WRN_AI << "Loop formula skipped, maybe it's empty or incorrect" << std::endl;
131  }
132  } catch(wfl::formula_error& e) {
133  if (e.filename == "formula") {
134  e.line = 0;
135  }
136  fai_.handle_exception( e, "Unit loop formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().wml_x()) + "," + std::to_string(i->get_location().wml_y()) + ")");
137  }
138  }
139  }
140  }
141  return false;
142 }
143 
144 
146 {
147  //we have no state on our own
148 }
149 
150 
152 {
153  config cfg = stage::to_config();
154  //we have no state on our own
155  return cfg;
156 }
157 
158 } // end of namespace ai
Defines formula ai.
virtual const unit_map & units() const
Definition: game_board.hpp:97
unit_iterator end()
Definition: map.hpp:415
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:39
std::string filename
Definition: formula.hpp:107
void handle_exception(wfl::formula_error &e) const
Definition: ai.cpp:117
unit_iterator begin()
Definition: map.hpp:405
Stage which executes unit formulas.
wfl::formula_ptr create_optional_formula(const std::string &formula_string) const
Create a new formula from the string, using the symbol table which is stored in the AI...
Definition: ai.cpp:143
std::multiset< unit_formula_pair, unit_formula_compare > unit_formula_set
Definition: ai.hpp:64
config to_config() const
serialize
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
virtual config to_config() const
serialize
Definition: stage.cpp:66
#define ERR_AI
#define WRN_AI
map_formula_callable & add(const std::string &key, const variant &value)
Definition: callable.hpp:252
game_board * gameboard
Definition: resources.cpp:20
bool is_empty() const
Definition: variant.cpp:271
formula_callable_ptr fake_ptr()
Definition: callable.hpp:41
size_t i
Definition: function.cpp:933
virtual side_number get_side() const override
Get the side number.
Definition: contexts.hpp:477
std::shared_ptr< const formula > const_formula_ptr
Definition: formula_fwd.hpp:23
stage_unit_formulas(ai_context &context, const config &cfg, formula_ai &fai)
static lg::log_domain log_formula_ai("ai/stage/unit_formulas")
std::pair< unit_map::unit_iterator, int > unit_formula_pair
Definition: ai.hpp:54
static const struct @6 priority[]
bool do_play_stage()
Play the turn - implementation.
void on_create()
Initialization.
Standard logging facilities (interface).
std::string message
Definition: exceptions.hpp:31
Container associating units to locations.
Definition: map.hpp:99
#define e
bool valid() const
Definition: map.hpp:276
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
wfl::variant make_action(wfl::const_formula_ptr formula_, const wfl::formula_callable &variables)
Definition: ai.cpp:188
std::string::const_iterator iterator
Definition: tokenizer.hpp:24