55 #define DBG_AI LOG_STREAM(debug, log_formula_ai)
56 #define LOG_AI LOG_STREAM(info, log_formula_ai)
57 #define WRN_AI LOG_STREAM(warn, log_formula_ai)
58 #define ERR_AI LOG_STREAM(err, log_formula_ai)
69 const std::string name = rc_action[
"name"];
71 const std::string&
type = rc_action[
"type"];
73 if(
type ==
"movement") {
75 }
else if(
type ==
"attack") {
76 new_ca = std::make_shared<attack_candidate_action>(name,
type, rc_action, &
function_table_);
78 ERR_AI <<
"Unknown candidate action type: " <<
type;
96 recursion_counter_(context.get_recursion_count()),
101 function_table_(*this)
104 LOG_AI <<
"creating new formula ai";
114 LOG_AI << failed_operation <<
": " <<
e.formula;
118 LOG_AI <<
e.type <<
" in " <<
e.filename <<
":" <<
e.line;
135 return formula::create_optional_formula(formula_string, &
function_table_);
157 const variant v =
f.evaluate(callable,
nullptr);
179 throw formula_error(
"null formula passed to make_action",
"",
"formula",0);
182 const variant var = formula_->evaluate(variables);
188 ERR_AI <<
"skipped execution of action because ai context is not set correctly";
207 if( dst_un != units_.
end() ) {
211 int best_rating = 100;
214 for(std::size_t
n = 0;
n < adj.size(); ++
n) {
219 if(units_.
find(adj[
n]) != units_.
end()) {
224 unsigned int difference = std::abs(
static_cast<int>(
static_cast<int>(preferred) -
n));
225 if(difference > ndirections/2) {
226 difference = ndirections - difference;
229 const int rating = difference * 2;
230 if(rating < best_rating || res.
valid() ==
false) {
231 best_rating = rating;
260 template<
typename Container>
261 variant villages_from_set(
const Container& villages,
const std::set<map_location>* exclude =
nullptr)
263 std::vector<variant> vars;
265 if(exclude && exclude->count(loc)) {
268 vars.emplace_back(std::make_shared<location_callable>(loc));
275 variant visit_helper(
const utils::variant<
bool, std::vector<std::string>>& input)
282 const std::vector<variant> vars(v.begin(), v.end());
294 if(key ==
"aggression")
298 }
else if(key ==
"allow_ally_villages")
302 }
else if(key ==
"avoid")
304 std::set<map_location> av_locs;
306 return villages_from_set(av_locs);
308 }
else if(key ==
"caution")
312 }
else if(key ==
"grouping")
316 }
else if(key ==
"leader_aggression")
320 }
else if(key ==
"leader_ignores_keep")
324 }
else if(key ==
"leader_value")
328 }
else if(key ==
"passive_leader")
332 }
else if(key ==
"passive_leader_shares_keep")
336 }
else if(key ==
"recruitment_pattern")
339 std::vector<variant> vars;
340 for(
const std::string &
i : rp) {
341 vars.emplace_back(
i);
345 }
else if(key ==
"retreat_enemy_weight")
349 }
else if(key ==
"retreat_factor")
353 }
else if(key ==
"scout_village_targeting")
357 }
else if(key ==
"support_villages")
361 }
else if(key ==
"village_value")
365 }
else if(key ==
"villages_per_scout")
369 }
else if(key ==
"attacks")
373 }
else if(key ==
"turn")
377 }
else if(key ==
"time_of_day")
381 }
else if(key ==
"my_side")
385 }
else if(key ==
"my_side_number")
389 }
else if(key ==
"teams")
391 std::vector<variant> vars;
393 vars.emplace_back(std::make_shared<team_callable>(
t));
397 }
else if(key ==
"allies")
399 std::vector<variant> vars;
402 vars.emplace_back(
i);
406 }
else if(key ==
"enemies")
408 std::vector<variant> vars;
411 vars.emplace_back(
i);
415 }
else if(key ==
"my_recruits")
417 std::vector<variant> vars;
421 for(
const std::string& recruit :
current_team().recruits()) {
423 vars.emplace_back(std::make_shared<unit_type_callable>(*ut));
428 }
else if(key ==
"recruits_of_side")
430 std::vector<variant> vars;
435 for(std::size_t
i = 0;
i < tmp.size(); ++
i) {
438 tmp[
i].emplace_back(std::make_shared<unit_type_callable>(*ut));
443 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
444 vars.emplace_back(tmp[
i]);
447 }
else if(key ==
"units")
449 std::vector<variant> vars;
450 for(
const unit& u : units) {
451 vars.emplace_back(std::make_shared<unit_callable>(u));
455 }
else if(key ==
"units_of_side")
457 std::vector<variant> vars;
459 for(
const unit &u : units) {
460 tmp[u.side() - 1].emplace_back(std::make_shared<unit_callable>(u));
462 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
463 vars.emplace_back(tmp[
i]);
466 }
else if(key ==
"my_units")
468 std::vector<variant> vars;
469 for(
const unit& u : units) {
471 vars.emplace_back(std::make_shared<unit_callable>(u));
476 }
else if(key ==
"enemy_units")
478 std::vector<variant> vars;
479 for(
const unit& u : units) {
480 if(
current_team().is_enemy(u.side()) && !u.incapacitated()) {
481 vars.emplace_back(std::make_shared<unit_callable>(u));
486 }
else if(key ==
"my_moves")
490 }
else if(key ==
"my_attacks")
493 }
else if(key ==
"enemy_moves")
497 }
else if(key ==
"my_leader")
500 if(
i == units.
end()) {
503 return variant(std::make_shared<unit_callable>(*
i));
505 }
else if(key ==
"recall_list")
507 std::vector<variant> tmp;
509 tmp.emplace_back(std::make_shared<unit_callable>(*ptr));
514 }
else if(key ==
"vars")
517 }
else if(key ==
"keeps")
520 }
else if(key ==
"map")
523 }
else if(key ==
"villages")
526 }
else if(key ==
"villages_of_side")
528 std::vector<variant> vars;
530 vars.push_back(villages_from_set(
t.villages()));
534 }
else if(key ==
"my_villages")
538 }
else if(key ==
"enemy_and_unowned_villages")
542 else if(key ==
"world") {
543 return variant(std::make_shared<gamestate_callable>());
588 std::vector<variant> vars;
595 vars.emplace_back(std::make_shared<location_callable>(loc));
612 move_map::const_iterator
i;
613 std::pair<move_map::const_iterator,
630 const std::string name = func[
"name"];
631 const std::string
inputs = func[
"inputs"];
632 const std::string formula_str = func[
"formula"];
650 for(
const auto& [key, value] : ai_vars->attribute_range()) {
667 fai_ca->update_callable_map( callable );
673 formula_ai::gamestate_change_observer::gamestate_change_observer() :
674 set_var_counter_(), set_unit_var_counter_(), continue_counter_()
679 formula_ai::gamestate_change_observer::~gamestate_change_observer() {
683 void formula_ai::gamestate_change_observer::handle_generic_event(
const std::string& ) {
684 set_var_counter_ = 0;
685 set_unit_var_counter_ = 0;
686 continue_counter_ = 0;
690 bool formula_ai::gamestate_change_observer::set_var_check() {
691 if(set_var_counter_ >= MAX_CALLS)
698 bool formula_ai::gamestate_change_observer::set_unit_var_check() {
699 if(set_unit_var_counter_ >= MAX_CALLS)
702 set_unit_var_counter_++;
706 bool formula_ai::gamestate_change_observer::continue_check() {
707 if(continue_counter_ >= MAX_CALLS)
729 str =
i->second.serialize_to_string();
731 WRN_AI <<
"variable ["<<
i->first <<
"] is not serializable - it will not be persisted across savegames";
736 ai_vars[
i->first] = str;
Defines formula ai candidate actions - headers.
void remove_gamestate_observer(events::observer *event_observer)
Removes an observer of game events except ai_user_interact event and ai_sync_network event.
void add_gamestate_observer(events::observer *event_observer)
Adds observer of game events except ai_user_interact event and ai_sync_network event.
static manager & get_singleton()
virtual double get_caution() const override
virtual utils::variant< bool, std::vector< std::string > > get_passive_leader() const override
virtual const team & current_team() const override
virtual const move_map & get_enemy_srcdst() const override
virtual const wfl::variant & get_attacks_as_variant() const override
virtual const move_map & get_dstsrc() const override
virtual const terrain_filter & get_avoid() const override
virtual double get_retreat_enemy_weight() const override
virtual std::string get_grouping() const override
virtual double get_retreat_factor() const override
virtual const move_map & get_srcdst() const override
virtual utils::variant< bool, std::vector< std::string > > get_leader_ignores_keep() const override
virtual double get_scout_village_targeting() const override
virtual const std::vector< std::string > get_recruitment_pattern() const override
virtual double get_village_value() const override
virtual double get_leader_value() const override
virtual utils::variant< bool, std::vector< std::string > > get_passive_leader_shares_keep() const override
virtual double get_aggression() const override
virtual int get_villages_per_scout() const override
virtual double get_leader_aggression() const override
void init_readonly_context_proxy(readonly_context &target)
virtual bool get_support_villages() const override
virtual bool get_allow_ally_villages() const override
virtual const move_map & get_enemy_dstsrc() const override
int get_count() const
Get the current value of the recursion counter.
virtual side_number get_side() const override
Get the side number.
A config object defines a single node in a WML file, with access to child nodes.
void clear_children(T... keys)
child_itors child_range(config_key_type key)
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
void add_chat_message(const std::time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
virtual const std::vector< team > & teams() const override
virtual const unit_map & units() const override
static game_display * get_singleton()
display_chat_manager & get_chat_manager()
This class stores all the data for a single 'side' (in game nomenclature).
void get_locations(std::set< map_location > &locs, bool with_border=false) const
gets all locations on the map that match this filter
Container associating units to locations.
unit_iterator find(std::size_t id)
unit_iterator find_leader(int side)
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
void build_all(unit_type::BUILD_STATUS status)
Makes sure the all unit_types are built to the specified level.
A single unit type that the player may recruit.
This class represents a single unit of a specific type.
void add_function(const std::string &name, formula_function_ptr &&fcn)
variant execute_variant(const variant &to_exec)
void serialize_from_string(const std::string &str)
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
bool is_null() const
Functions to test the type of the internal value.
Game information for the AI.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Standard logging facilities (interface).
A small explanation about what's going on here: Each action has access to two game_info objects First...
wfl::candidate_action_ptr ca_ptr
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator &calc, const std::size_t width, const std::size_t height, const teleport_map *teleports, bool border)
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units, bool check_vision)
::tod_manager * tod_manager
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except both types are passed through std::decay first.
std::vector< std::string > split(const config_attribute_value &val)
std::vector< formula_input > formula_input_vector
std::shared_ptr< const formula > const_formula_ptr
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
std::shared_ptr< formula > formula_ptr
std::shared_ptr< base_candidate_action > candidate_action_ptr
This module contains various pathfinding functions and utilities.
std::shared_ptr< unit > unit_ptr
static config unit_moves(const reports::context &rc, const unit *u, bool is_visible_unit)
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
Encapsulates the map of the game.
direction
Valid directions which can be moved in our hexagonal world.
direction get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
Structure which holds a single route between one location and another.
static map_location::direction n
unit_type_data unit_types
MacOS doesn't support std::visit when targing MacOS < 10.14 (currently we target 10....