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;
91 handle_exception(e,
"Error while registering candidate action '" + name +
"'");
114 LOG_AI <<
"creating new formula ai";
145 return formula::create_optional_formula(formula_string, &
function_table_);
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>());
618 add_input(inputs,
"enemy_and_unowned_villages");
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,
657 unit_moves =
get_srcdst().equal_range(unit_A);
658 for(i = unit_moves.first; i != unit_moves.second; ++i) {
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)
774 str =
i->second.serialize_to_string();
776 WRN_AI <<
"variable ["<<
i->first <<
"] is not serializable - it will not be persisted across savegames";
781 ai_vars[
i->first] = str;
variant execute_variant(const variant &to_exec)
virtual std::string get_grouping() const override
::tod_manager * tod_manager
virtual const move_map & get_enemy_srcdst() const override
virtual int get_villages_per_scout() const override
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.
virtual const std::vector< team > & teams() const override
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
virtual const unit_map & units() const override
Defines formula ai candidate actions - headers.
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
void clear_children(T... keys)
This class represents a single unit of a specific type.
static manager & get_singleton()
unit_iterator find_leader(int side)
virtual double get_leader_value() const override
Managing the AI-Game interaction - AI actions and their results.
child_itors child_range(config_key_type key)
wfl::candidate_action_ptr ca_ptr
attribute_map::value_type attribute
virtual double get_village_value() const override
virtual const move_map & get_srcdst() const override
std::vector< formula_input > formula_input_vector
void build_all(unit_type::BUILD_STATUS status)
Makes sure the all unit_types are built to the specified level.
unit_type_data unit_types
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
virtual double get_retreat_factor() const override
void get_locations(std::set< map_location > &locs, bool with_border=false) const
gets all locations on the map that match this filter
A single unit type that the player may recruit.
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 utils::variant< bool, std::vector< std::string > > get_passive_leader() const override
A small explanation about what's going on here: Each action has access to two game_info objects First...
void remove_gamestate_observer(events::observer *event_observer)
Removes an observer of game events except ai_user_interact event and ai_sync_network event...
Structure which holds a single route between one location and another.
virtual double get_leader_aggression() const override
virtual utils::variant< bool, std::vector< std::string > > get_leader_ignores_keep() const override
void serialize_from_string(const std::string &str)
bool is_enemy(int n) const
virtual const move_map & get_enemy_dstsrc() const override
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands...
virtual const std::vector< std::string > get_recruitment_pattern() const override
utils::optional_reference< config > optional_child(config_key_type key, int n=0)
Euivalent to child, but returns an empty optional if the nth child was not found. ...
iterator end()
end iterator
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except both types are passed through std::decay first.
virtual double get_retreat_enemy_weight() const override
Encapsulates the map of the game.
unit_iterator find(std::size_t id)
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
virtual const team & current_team() const override
Game information for the AI.
virtual double get_scout_village_targeting() const override
virtual side_number get_side() const override
Get the side number.
DIRECTION
Valid directions which can be moved in our hexagonal world.
std::shared_ptr< const formula > const_formula_ptr
config & add_child(config_key_type key)
std::shared_ptr< base_candidate_action > candidate_action_ptr
virtual bool get_allow_ally_villages() const override
display_chat_manager & get_chat_manager()
virtual const move_map & get_dstsrc() const override
bool is_null() const
Functions to test the type of the internal value.
virtual double get_aggression() const override
virtual const wfl::variant & get_attacks_as_variant() const override
std::vector< std::string > split(const config_attribute_value &val)
void add_gamestate_observer(events::observer *event_observer)
Adds observer of game events except ai_user_interact event and ai_sync_network event.
Standard logging facilities (interface).
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units, bool check_vision)
static config unit_moves(reports::context &rc, const unit *u, bool is_visible_unit)
recall_list_manager & recall_list()
void add_function(const std::string &name, formula_function_ptr &&fcn)
Container associating units to locations.
int get_count() const
Get the current value of the recursion counter.
MacOS doesn't support std::visit when targing MacOS < 10.14 (currently we target 10.11).
virtual bool get_support_villages() const override
virtual const terrain_filter & get_avoid() const override
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)
A config object defines a single node in a WML file, with access to child nodes.
const std::string & str() const
virtual double get_caution() const override
virtual utils::variant< bool, std::vector< std::string > > get_passive_leader_shares_keep() const override
static map_location::DIRECTION n
This module contains various pathfinding functions and utilities.
void init_readonly_context_proxy(readonly_context &target)
const std::set< std::string > & recruits() const
static game_display * get_singleton()
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
std::shared_ptr< formula > formula_ptr