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 t_string &name = rc_action[
"name"];
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>(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>(*
i));
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;
422 if(recruits.empty()) {
425 for(std::set<std::string>::const_iterator
i = recruits.begin();
i != recruits.end(); ++
i)
430 vars.emplace_back(std::make_shared<unit_type_callable>(*ut));
435 }
else if(key ==
"recruits_of_side")
437 std::vector<variant> vars;
438 std::vector< std::vector< variant>> tmp;
444 std::vector<variant> v;
448 if(recruits.empty()) {
451 for(std::set<std::string>::const_iterator str_it = recruits.begin(); str_it != recruits.end(); ++str_it)
456 tmp[
i].emplace_back(std::make_shared<unit_type_callable>(*ut));
461 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
462 vars.emplace_back(tmp[
i]);
465 }
else if(key ==
"units")
467 std::vector<variant> vars;
469 vars.emplace_back(std::make_shared<unit_callable>(*
i));
473 }
else if(key ==
"units_of_side")
475 std::vector<variant> vars;
476 std::vector< std::vector< variant>> tmp;
479 std::vector<variant> v;
482 for(
const unit &u : units) {
483 tmp[u.side() - 1].emplace_back(std::make_shared<unit_callable>(u));
485 for( std::size_t
i = 0;
i<tmp.size(); ++
i)
486 vars.emplace_back(tmp[
i]);
489 }
else if(key ==
"my_units")
491 std::vector<variant> vars;
494 vars.emplace_back(std::make_shared<unit_callable>(*
i));
499 }
else if(key ==
"enemy_units")
501 std::vector<variant> vars;
504 if (!
i->incapacitated()) {
505 vars.emplace_back(std::make_shared<unit_callable>(*
i));
511 }
else if(key ==
"my_moves")
515 }
else if(key ==
"my_attacks")
518 }
else if(key ==
"enemy_moves")
522 }
else if(key ==
"my_leader")
525 if(
i == units.
end()) {
528 return variant(std::make_shared<unit_callable>(*
i));
530 }
else if(key ==
"recall_list")
532 std::vector<variant> tmp;
535 tmp.emplace_back(std::make_shared<unit_callable>(**
i));
540 }
else if(key ==
"vars")
543 }
else if(key ==
"keeps")
546 }
else if(key ==
"map")
549 }
else if(key ==
"villages")
552 }
else if(key ==
"villages_of_side")
554 std::vector<variant> vars;
559 for(std::size_t
i = 0;
i<vars.size(); ++
i)
565 }
else if(key ==
"my_villages")
569 }
else if(key ==
"enemy_and_unowned_villages")
573 else if(key ==
"world") {
574 return variant(std::make_shared<gamestate_callable>());
619 std::vector<variant> vars;
626 vars.emplace_back(std::make_shared<location_callable>(loc));
643 move_map::const_iterator
i;
644 std::pair<move_map::const_iterator,
661 const t_string &name = func[
"name"];
663 const t_string &formula_str = func[
"formula"];
698 fai_ca->update_callable_map( callable );
704 formula_ai::gamestate_change_observer::gamestate_change_observer() :
705 set_var_counter_(), set_unit_var_counter_(), continue_counter_()
710 formula_ai::gamestate_change_observer::~gamestate_change_observer() {
714 void formula_ai::gamestate_change_observer::handle_generic_event(
const std::string& ) {
715 set_var_counter_ = 0;
716 set_unit_var_counter_ = 0;
717 continue_counter_ = 0;
721 bool formula_ai::gamestate_change_observer::set_var_check() {
722 if(set_var_counter_ >= MAX_CALLS)
729 bool formula_ai::gamestate_change_observer::set_unit_var_check() {
730 if(set_unit_var_counter_ >= MAX_CALLS)
733 set_unit_var_counter_++;
737 bool formula_ai::gamestate_change_observer::continue_check() {
738 if(continue_counter_ >= MAX_CALLS)
760 str =
i->second.serialize_to_string();
762 WRN_AI <<
"variable ["<<
i->first <<
"] is not serializable - it will not be persisted across savegames";
767 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)
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....