65 #define DBG_AI LOG_STREAM(debug, log_formula_ai)
66 #define LOG_AI LOG_STREAM(info, log_formula_ai)
67 #define WRN_AI LOG_STREAM(warn, log_formula_ai)
68 #define ERR_AI LOG_STREAM(err, log_formula_ai)
79 const t_string &name = rc_action[
"name"];
83 if(
type ==
"movement") {
85 }
else if(
type ==
"attack") {
86 new_ca = std::make_shared<attack_candidate_action>(name,
type, rc_action, &
function_table_);
88 ERR_AI <<
"Unknown candidate action type: " <<
type;
106 recursion_counter_(context.get_recursion_count()),
111 function_table_(*this)
114 LOG_AI <<
"creating new formula ai";
124 LOG_AI << failed_operation <<
": " <<
e.formula;
128 LOG_AI <<
e.type <<
" in " <<
e.filename <<
":" <<
e.line;
145 return formula::create_optional_formula(formula_string, &
function_table_);
167 const variant v =
f.evaluate(callable,
nullptr);
189 throw formula_error(
"null formula passed to make_action",
"",
"formula",0);
192 const variant var = formula_->evaluate(variables);
198 ERR_AI <<
"skipped execution of action because ai context is not set correctly";
217 if( dst_un != units_.
end() ) {
221 int best_rating = 100;
224 for(std::size_t
n = 0;
n < adj.size(); ++
n) {
229 if(units_.
find(adj[
n]) != units_.
end()) {
234 unsigned int difference = std::abs(
static_cast<int>(preferred -
n));
235 if(difference > NDIRECTIONS/2) {
236 difference = NDIRECTIONS - difference;
239 const int rating = difference * 2;
240 if(rating < best_rating || res.
valid() ==
false) {
241 best_rating = rating;
270 template<
typename Container>
271 variant villages_from_set(
const Container& villages,
const std::set<map_location>* exclude =
nullptr)
273 std::vector<variant> vars;
275 if(exclude && exclude->count(loc)) {
278 vars.emplace_back(std::make_shared<location_callable>(loc));
285 variant visit_helper(
const utils::variant<
bool, std::vector<std::string>>& input)
292 const std::vector<variant> vars(v.begin(), v.end());
304 if(key ==
"aggression")
308 }
else if(key ==
"allow_ally_villages")
312 }
else if(key ==
"avoid")
314 std::set<map_location> av_locs;
316 return villages_from_set(av_locs);
318 }
else if(key ==
"caution")
322 }
else if(key ==
"grouping")
326 }
else if(key ==
"leader_aggression")
330 }
else if(key ==
"leader_ignores_keep")
334 }
else if(key ==
"leader_value")
338 }
else if(key ==
"passive_leader")
342 }
else if(key ==
"passive_leader_shares_keep")
346 }
else if(key ==
"recruitment_pattern")
349 std::vector<variant> vars;
350 for(
const std::string &
i : rp) {
351 vars.emplace_back(
i);
355 }
else if(key ==
"retreat_enemy_weight")
359 }
else if(key ==
"retreat_factor")
363 }
else if(key ==
"scout_village_targeting")
367 }
else if(key ==
"support_villages")
371 }
else if(key ==
"village_value")
375 }
else if(key ==
"villages_per_scout")
379 }
else if(key ==
"attacks")
383 }
else if(key ==
"turn")
387 }
else if(key ==
"time_of_day")
391 }
else if(key ==
"my_side")
395 }
else if(key ==
"my_side_number")
399 }
else if(key ==
"teams")
401 std::vector<variant> vars;
403 vars.emplace_back(std::make_shared<team_callable>(*
i));
407 }
else if(key ==
"allies")
409 std::vector<variant> vars;
412 vars.emplace_back(
i);
416 }
else if(key ==
"enemies")
418 std::vector<variant> vars;
421 vars.emplace_back(
i);
425 }
else if(key ==
"my_recruits")
427 std::vector<variant> vars;
432 if(recruits.empty()) {
435 for(std::set<std::string>::const_iterator
i = recruits.begin();
i != recruits.end(); ++
i)
440 vars.emplace_back(std::make_shared<unit_type_callable>(*ut));
445 }
else if(key ==
"recruits_of_side")
447 std::vector<variant> vars;
448 std::vector< std::vector< variant>> tmp;
454 std::vector<variant> v;
458 if(recruits.empty()) {
461 for(std::set<std::string>::const_iterator str_it = recruits.begin(); str_it != recruits.end(); ++str_it)
466 tmp[
i].emplace_back(std::make_shared<unit_type_callable>(*ut));
471 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
472 vars.emplace_back(tmp[
i]);
475 }
else if(key ==
"units")
477 std::vector<variant> vars;
479 vars.emplace_back(std::make_shared<unit_callable>(*
i));
483 }
else if(key ==
"units_of_side")
485 std::vector<variant> vars;
486 std::vector< std::vector< variant>> tmp;
489 std::vector<variant> v;
492 for(
const unit &u : units) {
493 tmp[u.side() - 1].emplace_back(std::make_shared<unit_callable>(u));
495 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
496 vars.emplace_back(tmp[
i]);
499 }
else if(key ==
"my_units")
501 std::vector<variant> vars;
504 vars.emplace_back(std::make_shared<unit_callable>(*
i));
509 }
else if(key ==
"enemy_units")
511 std::vector<variant> vars;
514 if (!
i->incapacitated()) {
515 vars.emplace_back(std::make_shared<unit_callable>(*
i));
521 }
else if(key ==
"my_moves")
525 }
else if(key ==
"my_attacks")
528 }
else if(key ==
"enemy_moves")
532 }
else if(key ==
"my_leader")
535 if(
i == units.
end()) {
538 return variant(std::make_shared<unit_callable>(*
i));
540 }
else if(key ==
"recall_list")
542 std::vector<variant> tmp;
545 tmp.emplace_back(std::make_shared<unit_callable>(**
i));
550 }
else if(key ==
"vars")
553 }
else if(key ==
"keeps")
556 }
else if(key ==
"map")
559 }
else if(key ==
"villages")
562 }
else if(key ==
"villages_of_side")
564 std::vector<variant> vars;
569 for(std::size_t
i = 0;
i<vars.size(); ++
i)
575 }
else if(key ==
"my_villages")
579 }
else if(key ==
"enemy_and_unowned_villages")
583 else if(key ==
"world") {
584 return variant(std::make_shared<gamestate_callable>());
629 std::vector<variant> vars;
636 vars.emplace_back(std::make_shared<location_callable>(loc));
653 move_map::const_iterator
i;
654 std::pair<move_map::const_iterator,
671 const t_string &name = func[
"name"];
673 const t_string &formula_str = func[
"formula"];
708 fai_ca->update_callable_map( callable );
714 formula_ai::gamestate_change_observer::gamestate_change_observer() :
715 set_var_counter_(), set_unit_var_counter_(), continue_counter_()
720 formula_ai::gamestate_change_observer::~gamestate_change_observer() {
724 void formula_ai::gamestate_change_observer::handle_generic_event(
const std::string& ) {
725 set_var_counter_ = 0;
726 set_unit_var_counter_ = 0;
727 continue_counter_ = 0;
731 bool formula_ai::gamestate_change_observer::set_var_check() {
732 if(set_var_counter_ >= MAX_CALLS)
739 bool formula_ai::gamestate_change_observer::set_unit_var_check() {
740 if(set_unit_var_counter_ >= MAX_CALLS)
743 set_unit_var_counter_++;
747 bool formula_ai::gamestate_change_observer::continue_check() {
748 if(continue_counter_ >= MAX_CALLS)
770 str =
i->second.serialize_to_string();
772 WRN_AI <<
"variable ["<<
i->first <<
"] is not serializable - it will not be persisted across savegames";
777 ai_vars[
i->first] = str;
Managing the AI-Game interaction - AI actions and their results.
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands.
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)
attribute_map::value_type attribute
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Euivalent 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()
iterator end()
end iterator
recall_list_manager & recall_list()
const std::set< std::string > & recruits() const
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.
static config unit_moves(const reports::context &rc, const unit *u, bool is_visible_unit)
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....