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;
134 return formula::create_optional_formula(formula_string, &
function_table_);
156 const variant v =
f.evaluate(callable,
nullptr);
178 throw formula_error(
"null formula passed to make_action",
"",
"formula",0);
181 const variant var = formula_->evaluate(variables);
187 ERR_AI <<
"skipped execution of action because ai context is not set correctly";
206 if( dst_un != units_.
end() ) {
210 int best_rating = 100;
213 for(std::size_t
n = 0;
n < adj.size(); ++
n) {
218 if(units_.
find(adj[
n]) != units_.
end()) {
223 unsigned int difference = std::abs(
static_cast<int>(
static_cast<int>(preferred) -
n));
224 if(difference > ndirections/2) {
225 difference = ndirections - difference;
228 const int rating = difference * 2;
229 if(rating < best_rating || res.
valid() ==
false) {
230 best_rating = rating;
259 template<
typename Container>
260 variant villages_from_set(
const Container& villages,
const std::set<map_location>* exclude =
nullptr)
262 std::vector<variant> vars;
264 if(exclude && exclude->count(
loc)) {
267 vars.emplace_back(std::make_shared<location_callable>(
loc));
274 variant visit_helper(
const utils::variant<
bool, std::vector<std::string>>& input)
281 const std::vector<variant> vars(v.begin(), v.end());
293 if(key ==
"aggression")
297 }
else if(key ==
"allow_ally_villages")
301 }
else if(key ==
"avoid")
303 std::set<map_location> av_locs;
305 return villages_from_set(av_locs);
307 }
else if(key ==
"caution")
311 }
else if(key ==
"grouping")
315 }
else if(key ==
"leader_aggression")
319 }
else if(key ==
"leader_ignores_keep")
323 }
else if(key ==
"leader_value")
327 }
else if(key ==
"passive_leader")
331 }
else if(key ==
"passive_leader_shares_keep")
335 }
else if(key ==
"recruitment_pattern")
338 std::vector<variant> vars;
339 for(
const std::string &
i : rp) {
340 vars.emplace_back(
i);
344 }
else if(key ==
"retreat_enemy_weight")
348 }
else if(key ==
"retreat_factor")
352 }
else if(key ==
"scout_village_targeting")
356 }
else if(key ==
"support_villages")
360 }
else if(key ==
"village_value")
364 }
else if(key ==
"villages_per_scout")
368 }
else if(key ==
"attacks")
372 }
else if(key ==
"turn")
376 }
else if(key ==
"time_of_day")
380 }
else if(key ==
"my_side")
384 }
else if(key ==
"my_side_number")
388 }
else if(key ==
"teams")
390 std::vector<variant> vars;
392 vars.emplace_back(std::make_shared<team_callable>(
t));
396 }
else if(key ==
"allies")
398 std::vector<variant> vars;
401 vars.emplace_back(
i);
405 }
else if(key ==
"enemies")
407 std::vector<variant> vars;
410 vars.emplace_back(
i);
414 }
else if(key ==
"my_recruits")
416 std::vector<variant> vars;
420 for(
const std::string& recruit :
current_team().recruits()) {
422 vars.emplace_back(std::make_shared<unit_type_callable>(*ut));
427 }
else if(key ==
"recruits_of_side")
429 std::vector<variant> vars;
434 for(std::size_t
i = 0;
i < tmp.size(); ++
i) {
437 tmp[
i].emplace_back(std::make_shared<unit_type_callable>(*ut));
442 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
443 vars.emplace_back(tmp[
i]);
446 }
else if(key ==
"units")
448 std::vector<variant> vars;
449 for(
const unit& u : units) {
450 vars.emplace_back(std::make_shared<unit_callable>(u));
454 }
else if(key ==
"units_of_side")
456 std::vector<variant> vars;
458 for(
const unit &u : units) {
459 tmp[u.side() - 1].emplace_back(std::make_shared<unit_callable>(u));
461 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
462 vars.emplace_back(tmp[
i]);
465 }
else if(key ==
"my_units")
467 std::vector<variant> vars;
468 for(
const unit& u : units) {
470 vars.emplace_back(std::make_shared<unit_callable>(u));
475 }
else if(key ==
"enemy_units")
477 std::vector<variant> vars;
478 for(
const unit& u : units) {
479 if(
current_team().is_enemy(u.side()) && !u.incapacitated()) {
480 vars.emplace_back(std::make_shared<unit_callable>(u));
485 }
else if(key ==
"my_moves")
489 }
else if(key ==
"my_attacks")
492 }
else if(key ==
"enemy_moves")
496 }
else if(key ==
"my_leader")
499 if(
i == units.
end()) {
502 return variant(std::make_shared<unit_callable>(*
i));
504 }
else if(key ==
"recall_list")
506 std::vector<variant> tmp;
508 tmp.emplace_back(std::make_shared<unit_callable>(*ptr));
513 }
else if(key ==
"vars")
516 }
else if(key ==
"keeps")
519 }
else if(key ==
"map")
522 }
else if(key ==
"villages")
525 }
else if(key ==
"villages_of_side")
527 std::vector<variant> vars;
529 vars.push_back(villages_from_set(
t.villages()));
533 }
else if(key ==
"my_villages")
537 }
else if(key ==
"enemy_and_unowned_villages")
541 else if(key ==
"world") {
542 return variant(std::make_shared<gamestate_callable>());
587 std::vector<variant> vars;
594 vars.emplace_back(std::make_shared<location_callable>(
loc));
611 move_map::const_iterator
i;
626 const std::string name = func[
"name"];
627 const std::string
inputs = func[
"inputs"];
628 const std::string formula_str = func[
"formula"];
646 for(
const auto& [key, value] : ai_vars->attribute_range()) {
663 fai_ca->update_callable_map( callable );
669 formula_ai::gamestate_change_observer::gamestate_change_observer() :
670 set_var_counter_(), set_unit_var_counter_(), continue_counter_()
675 formula_ai::gamestate_change_observer::~gamestate_change_observer() {
679 void formula_ai::gamestate_change_observer::handle_generic_event(
const std::string& ) {
680 set_var_counter_ = 0;
681 set_unit_var_counter_ = 0;
682 continue_counter_ = 0;
686 bool formula_ai::gamestate_change_observer::set_var_check() {
687 if(set_var_counter_ >= MAX_CALLS)
694 bool formula_ai::gamestate_change_observer::set_unit_var_check() {
695 if(set_unit_var_counter_ >= MAX_CALLS)
698 set_unit_var_counter_++;
702 bool formula_ai::gamestate_change_observer::continue_check() {
703 if(continue_counter_ >= MAX_CALLS)
725 str =
i->second.serialize_to_string();
727 WRN_AI <<
"variable ["<<
i->first <<
"] is not serializable - it will not be persisted across savegames";
732 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::chrono::system_clock::time_point &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(std::string_view 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....