The Battle for Wesnoth  1.13.4+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 - 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  * @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 "log.hpp"
27 #include "resources.hpp"
28 #include "units/unit.hpp"
30 #include <boost/lexical_cast.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  game_logic::unit_formula_set units_with_formulas;
57 
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  game_logic::const_formula_ptr priority_formula(fai_.create_optional_formula(i->formula_manager().get_priority_formula()));
68  if (priority_formula) {
70  callable.add_ref();
71  callable.add("me", variant(new unit_callable(*i)));
72  priority = (game_logic::formula::evaluate(priority_formula, callable)).as_int();
73  } else {
74  WRN_AI << "priority formula skipped, maybe it's empty or incorrect"<< std::endl;
75  }
76  } catch(game_logic::formula_error& e) {
77  if(e.filename == "formula")
78  e.line = 0;
79  fai_.handle_exception( e, "Unit priority formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().x + 1) + "," + std::to_string(i->get_location().y + 1) + ")");
80 
81  priority = 0;
82  } catch(type_error& e) {
83  priority = 0;
84  ERR_AI << "formula type error while evaluating unit priority formula " << e.message << std::endl;
85  }
86  }
87 
88  units_with_formulas.insert( game_logic::unit_formula_pair( i, priority ) );
89  }
90  }
91  }
92 
93  for(game_logic::unit_formula_set::iterator pair_it = units_with_formulas.begin() ; pair_it != units_with_formulas.end() ; ++pair_it)
94  {
95  unit_map::iterator i = pair_it->first;
96 
97  if( i.valid() ) {
98 
99  if (i->formula_manager().has_formula()) {
100  try {
101  game_logic::const_formula_ptr formula(fai_.create_optional_formula(i->formula_manager().get_formula()));
102  if (formula) {
104  callable.add_ref();
105  callable.add("me", variant(new unit_callable(*i)));
106  fai_.make_action(formula, callable);
107  } else {
108  WRN_AI << "unit formula skipped, maybe it's empty or incorrect" << std::endl;
109  }
110  }
111  catch(game_logic::formula_error& e) {
112  if(e.filename == "formula") {
113  e.line = 0;
114  }
115  fai_.handle_exception( e, "Unit formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().x + 1) + "," + std::to_string(i->get_location().y + 1) + ")");
116  }
117  }
118  }
119 
120  if( i.valid() ) {
121  if (i->formula_manager().has_loop_formula())
122  {
123  try {
124  game_logic::const_formula_ptr loop_formula(fai_.create_optional_formula(i->formula_manager().get_loop_formula()));
125  if (loop_formula) {
127  callable.add_ref();
128  callable.add("me", variant(new unit_callable(*i)));
129  while ( !fai_.make_action(loop_formula, callable).is_empty() && i.valid() )
130  {
131  }
132  } else {
133  WRN_AI << "Loop formula skipped, maybe it's empty or incorrect" << std::endl;
134  }
135  } catch(game_logic::formula_error& e) {
136  if (e.filename == "formula") {
137  e.line = 0;
138  }
139  fai_.handle_exception( e, "Unit loop formula error for unit: '" + i->type_id() + "' standing at (" + std::to_string(i->get_location().x + 1) + "," + std::to_string(i->get_location().y + 1) + ")");
140  }
141  }
142  }
143  }
144  return false;
145 }
146 
147 
149 {
150  //we have no state on our own
151 }
152 
153 
155 {
156  config cfg = stage::to_config();
157  //we have no state on our own
158  return cfg;
159 }
160 
161 } // end of namespace ai
Defines formula ai.
virtual side_number get_side() const
Get the side number.
Definition: contexts.hpp:480
unit_iterator end()
Definition: map.hpp:311
game_logic::formula_ptr create_optional_formula(const std::string &formula_string)
Create a new formula from the string, using the symbol table which is stored in the AI...
Definition: ai.cpp:148
static const struct @12 priority[]
unit_iterator begin()
Definition: map.hpp:308
Stage which executes unit formulas.
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:57
variant make_action(game_logic::const_formula_ptr formula_, const game_logic::formula_callable &variables)
Definition: ai.cpp:194
virtual config to_config() const
serialize
Definition: stage.cpp:66
#define ERR_AI
#define WRN_AI
std::pair< unit_map::unit_iterator, int > unit_formula_pair
Definition: ai.hpp:55
bool is_empty() const
Definition: variant.cpp:511
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:31
size_t i
Definition: function.cpp:1057
map_formula_callable & add(const std::string &key, const variant &value)
Definition: formula.cpp:41
boost::shared_ptr< std::vector< unit_const_ptr > > units_
Definition: dialogs.cpp:100
stage_unit_formulas(ai_context &context, const config &cfg, formula_ai &fai)
static lg::log_domain log_formula_ai("ai/stage/unit_formulas")
bool do_play_stage()
Play the turn - implementation.
void on_create()
Initialization.
std::multiset< unit_formula_pair, game_logic::unit_formula_compare > unit_formula_set
Definition: ai.hpp:65
Standard logging facilities (interface).
std::string message
Definition: exceptions.hpp:29
Container associating units to locations.
Definition: map.hpp:90
#define e
bool valid() const
Definition: map.hpp:229
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
unit_map * units
Definition: resources.cpp:35
void handle_exception(game_logic::formula_error &e) const
Definition: ai.cpp:122