41 #define LOG_AI LOG_STREAM(info, log_formula_ai)
42 #define WRN_AI LOG_STREAM(warn, log_formula_ai)
43 #define ERR_AI LOG_STREAM(err, log_formula_ai)
75 std::vector<attack_type> attacks()
const {
98 class distance_to_nearest_unowned_village_function :
public function_expression {
100 distance_to_nearest_unowned_village_function(
const args_list& args,
const formula_ai&
ai)
101 : function_expression(
"distance_to_nearest_unowned_village", args, 1, 1),
ai_(ai) {
105 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
106 const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"distance_to_nearest_unowned_village:location")))->loc();
109 const std::set<map_location>& my_villages =
ai_.current_team().villages();
110 for(std::vector<map_location>::const_iterator
i = villages.begin();
i != villages.end(); ++
i) {
112 if(distance < best) {
113 if(my_villages.count(*
i) == 0) {
125 static unsigned search_counter;
128 class calculate_map_ownership_function :
public function_expression {
130 calculate_map_ownership_function(
const args_list& args,
const formula_ai& ai)
131 : function_expression(
"calculate_map_ownership", args, 2, 5),
ai_(ai) {
138 indexer(
int a,
int b) : w(a), h(b) { }
140 return loc.
y * w + loc.
x;
156 : movement_cost_(moves)
170 return movement_cost_ < o.movement_cost_;
176 comp(
const std::vector<node>&
n) : nodes(n) { }
177 bool operator()(
int l,
int r)
const {
178 return nodes[
r] < nodes[
l];
182 void find_movemap(
const unit_adapter& u,
const map_location& loc,
183 std::vector<int>& scores,
bool allow_teleport)
const
185 const std::set<map_location>& teleports = allow_teleport ?
ai_.current_team().villages() : std::set<map_location>();
189 std::vector<map_location> locs(6 + teleports.size());
190 std::copy(teleports.begin(), teleports.end(), locs.begin() + 6);
193 if (search_counter == 0) search_counter = 2;
195 static std::vector<node>
nodes;
196 nodes.resize(map.w() * map.h());
198 indexer
index(map.w(), map.h());
199 comp node_comp(nodes);
201 nodes[
index(loc)] = node(0, loc);
203 pq.push_back(
index(loc));
204 while (!pq.empty()) {
205 node&
n = nodes[pq.front()];
206 std::pop_heap(pq.begin(), pq.end(), node_comp);
208 n.in = search_counter;
211 for (
int i = teleports.count(n.loc_) ? locs.size() : 6;
i-- > 0; ) {
212 if (!locs[
i].
valid(map.w(), map.h()))
continue;
215 bool next_visited = next.in - search_counter <= 1u;
219 if (next_visited && !(n < next) )
continue;
220 const int move_cost = u.movement_cost(map[locs[
i]]);
222 node
t = node(n.movement_cost_ + move_cost, locs[i]);
224 if (next_visited && !(t < next) )
continue;
226 bool in_list = next.in == search_counter + 1;
227 t.in = search_counter + 1;
232 std::push_heap(pq.begin(),
std::find(pq.begin(), pq.end(),
index(locs[i])) + 1, node_comp);
234 pq.push_back(
index(locs[i]));
235 std::push_heap(pq.begin(), pq.end(), node_comp);
240 for (
int x = 0;
x < map.w(); ++
x) {
241 for (
int y = 0;
y < map.h(); ++
y)
243 int i =
y * map.w() +
x;
244 const node &n = nodes[
i];
245 scores[
i] = scores[
i] + n.movement_cost_;
251 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
255 const variant units_input = args()[0]->evaluate(variables,fdb);
256 const variant leaders_input = args()[1]->evaluate(variables,fdb);
258 int enemy_tollerancy = 3;
259 if( args().
size() > 2 )
260 enemy_tollerancy = args()[2]->evaluate(variables,fdb).
as_int();
262 int enemy_border_tollerancy = 5;
263 if( args().
size() > 3 )
264 enemy_border_tollerancy = args()[3]->evaluate(variables,fdb).as_int();
266 int ally_tollerancy = 3;
267 if( args().
size() > 4 )
268 ally_tollerancy = args()[4]->evaluate(variables,fdb).as_int();
275 std::vector< std::vector<int> > scores( number_of_teams );
277 for(
size_t i = 0; i< number_of_teams; ++
i)
278 scores[i].resize(w*h);
286 for(
size_t side = 0 ; side < units_input.
num_elements() ; ++side) {
287 if( leaders_input[side].is_empty() )
290 const map_location loc = convert_variant<location_callable>(leaders_input[side][0])->loc();
291 const variant units_of_side = units_input[side];
293 for(
size_t unit_it = 0 ; unit_it < units_of_side.
num_elements() ; ++unit_it) {
294 unit_adapter
unit(units_of_side[unit_it]);
295 find_movemap(
unit, loc, scores[side],
true );
300 for( std::vector< std::vector<int> >::
iterator i = scores.begin() ; i != scores.end() ; ++
i) {
302 if(units_input[index].num_elements() != 0) {
312 std::map<variant, variant>
res;
314 size_t current_side =
ai_.get_side() - 1 ;
316 std::vector<int> enemies;
317 std::vector<int> allies;
319 for(
size_t side = 0 ; side < units_input.
num_elements() ; ++side) {
320 if( side == current_side)
323 if(
ai_.current_team().is_enemy(side+1) ) {
324 if( !leaders_input[side].is_empty() )
325 enemies.push_back(side);
327 if( !leaders_input[side].is_empty() )
328 allies.push_back(side);
334 for (
int x = 0;
x <
w; ++
x) {
335 for (
int y = 0;
y <
h; ++
y)
339 bool enemy_border =
false;
341 if( scores[current_side][i] > 98 )
344 for (
int side : enemies) {
345 int diff = scores[current_side][
i] - scores[side][
i];
346 if ( diff > enemy_tollerancy) {
349 }
else if( abs(diff) < enemy_border_tollerancy )
354 for (
int side : allies) {
355 if ( scores[current_side][i] - scores[side][i] > ally_tollerancy ) {
373 const formula_ai&
ai_;
377 class nearest_loc_function :
public function_expression {
379 nearest_loc_function(
const args_list& args)
380 : function_expression(
"nearest_loc", args, 2, 2)
385 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
386 const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"nearest_loc:location")))->loc();
393 const map_location move_loc = convert_variant<location_callable>(items[
i])->loc();
396 if(distance < best) {
410 class adjacent_locs_function :
public function_expression {
412 adjacent_locs_function(
const args_list& args)
413 : function_expression(
"adjacent_locs", args, 1, 1)
418 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
419 const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"adjacent_locs:location")))->loc();
423 std::vector<variant>
v;
424 for(
int n = 0; n != 6; ++
n) {
434 class locations_in_radius_function :
public function_expression {
436 locations_in_radius_function(
const args_list& args)
437 : function_expression(
"locations_in_radius", args, 2, 2)
442 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
443 const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,fdb))->loc();
445 int range = args()[1]->evaluate(variables,fdb).as_int();
453 std::vector<map_location>
res;
457 std::vector<variant>
v;
458 v.reserve(res.size()+1);
461 for(
size_t n = 0; n != res.size(); ++
n) {
474 class run_file_function :
public function_expression {
476 explicit run_file_function(
const args_list& args, formula_ai& ai)
477 : function_expression(
"run_file", args, 1, 1),
ai_(ai)
480 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
481 const args_list& arguments = args();
488 ERR_AI <<
"run_file : not found [" << filename <<
"]"<< std::endl;
494 formula_ptr parsed_formula =
ai_.create_optional_formula(formula_string);
496 ERR_AI <<
"run_file : unable to create formula"<< std::endl;
499 return parsed_formula->evaluate(variables,
add_debug_info(fdb,-1,
"run_file:formula_from_file"));
506 class castle_locs_function :
public function_expression {
508 castle_locs_function(
const args_list& args)
509 : function_expression(
"castle_locs", args, 1, 1)
514 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
515 const map_location starting_loc = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"castle_locs:location")))->loc();
518 std::set< map_location > visited_locs;
519 std::queue< map_location > queued_locs;
521 queued_locs.push(starting_loc);
523 while( !queued_locs.empty() ) {
527 if ( visited_locs.find( loc ) != visited_locs.end() )
530 visited_locs.insert(loc);
535 for(
int n = 0; n != 6; ++
n) {
536 if (
resources::gameboard->map().on_board(adj[n]) && visited_locs.find( adj[n] ) == visited_locs.end() ) {
539 queued_locs.push(adj[n]);
547 visited_locs.erase(starting_loc);
549 std::vector<variant>
res;
566 class timeofday_modifier_function :
public function_expression {
568 timeofday_modifier_function(
const args_list& args)
569 : function_expression(
"timeofday_modifier", args, 1, 2)
573 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
580 const unit_callable* u_call = try_convert_variant<unit_callable>(u);
582 if (u_call ==
nullptr) {
590 if(args().
size()==2) {
591 loc = &convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"timeofday_modifier:location")))->loc();
594 if (loc ==
nullptr) {
603 class nearest_keep_function :
public function_expression {
605 nearest_keep_function(
const args_list& args,
const formula_ai& ai)
606 : function_expression(
"nearest_keep", args, 1, 1),
ai_(ai) {
610 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
611 const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"nearest_keep:location")))->loc();
616 int size =
ai_.get_keeps_cache().num_elements();
618 for(
int i = 0 ; i <
size; ++
i) {
619 int distance =
distance_between(loc, convert_variant<location_callable>(
ai_.get_keeps_cache()[
i])->loc() );
633 const formula_ai&
ai_;
641 class suitable_keep_function :
public function_expression {
643 suitable_keep_function(
const args_list& args, formula_ai& ai)
644 : function_expression(
"suitable_keep", args, 1, 1),
ai_(ai) {
648 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
649 const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"suitable_keep:location")))->loc();
652 if (u == units.
end()){
663 class find_shroud_function :
public function_expression {
665 find_shroud_function(
const args_list& args,
const formula_ai& ai)
666 : function_expression(
"find_shroud", args, 0, 1),
ai_(ai) {
670 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
671 std::vector<variant> vars;
674 if(args().
size()==1) {
675 const gamemap&
m = convert_variant<gamemap_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"find_shroud:gamemap")))->get_gamemap();
683 for(
int i = 0; i <
w; ++
i)
684 for(
int j = 0; j <
h; ++j) {
692 const formula_ai&
ai_;
696 class close_enemies_function :
public function_expression {
698 close_enemies_function(
const args_list& args,
const formula_ai& ai)
699 : function_expression(
"close_enemies", args, 2, 2),
ai_(ai) {
703 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
704 std::vector<variant> vars;
705 const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"close_enemies:location")))->loc();
706 int range_s = args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"close_enemies:distance")).as_int();
708 WRN_AI <<
"close_enemies_function: range is negative (" << range_s <<
")" << std::endl;
711 size_t range =
static_cast<size_t>(range_s);
716 if (un->side() !=
ai_.get_side()) {
725 const formula_ai&
ai_;
728 class calculate_outcome_function :
public function_expression {
730 calculate_outcome_function(
const args_list& args)
731 : function_expression(
"calculate_outcome", args, 3, 4)
736 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
737 std::vector<variant> vars;
739 if (args().
size() > 3) weapon = args()[3]->evaluate(variables,
add_debug_info(fdb,3,
"calculate_outcome:weapon")).as_int();
744 convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"calculate_outcome:attacker_current_location")))->loc();
745 if(units.
count(attacker_location) == 0) {
746 ERR_AI <<
"Performing calculate_outcome() with non-existent attacker at (" <<
747 attacker_location.
x+1 <<
"," << attacker_location.
y+1 <<
")\n";
752 convert_variant<location_callable>(args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"calculate_outcome:defender_location")))->loc();
753 if(units.
count(defender_location) == 0) {
754 ERR_AI <<
"Performing calculate_outcome() with non-existent defender at (" <<
755 defender_location.
x+1 <<
"," << defender_location.
y+1 <<
")\n";
759 battle_context bc(units, convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"calculate_outcome:attacker_attack_location")))->loc(),
760 defender_location, weapon, -1, 1.0,
nullptr, &*units.
find(attacker_location));
764 std::vector<variant> hitLeft;
765 std::vector<variant> prob;
766 while (it != hp_dist.end()) {
769 prob.push_back(
variant(
int(*it*10000)));
774 std::vector<variant> status;
775 if (bc.get_attacker_combatant().poisoned != 0)
776 status.push_back(
variant(
"Poisoned"));
777 if (bc.get_attacker_combatant().slowed != 0)
778 status.push_back(
variant(
"Slowed"));
779 if (bc.get_defender_stats().petrifies &&
static_cast<unsigned int>(hitLeft[0].as_int()) != bc.get_attacker_stats().hp)
780 status.push_back(
variant(
"Stoned"));
781 if (bc.get_defender_stats().plagues && hitLeft[0].as_int() == 0)
782 status.push_back(
variant(
"Zombiefied"));
783 vars.push_back(
variant(
new outcome_callable(hitLeft, prob, status)));
787 hp_dist = bc.get_defender_combatant().hp_dist;
788 it = hp_dist.begin();
790 while (it != hp_dist.end()) {
793 prob.push_back(
variant(
int(*it*10000)));
798 if (bc.get_defender_combatant().poisoned != 0)
799 status.push_back(
variant(
"Poisoned"));
800 if (bc.get_defender_combatant().slowed != 0)
801 status.push_back(
variant(
"Slowed"));
802 if (bc.get_attacker_stats().petrifies &&
static_cast<unsigned int>(hitLeft[0].as_int()) != bc.get_defender_stats().hp)
803 status.push_back(
variant(
"Stoned"));
804 if (bc.get_attacker_stats().plagues && hitLeft[0].as_int() == 0)
805 status.push_back(
variant(
"Zombiefied"));
806 vars.push_back(
variant(
new outcome_callable(hitLeft, prob, status)));
812 class outcomes_function :
public function_expression {
814 outcomes_function(
const args_list& args)
815 : function_expression(
"outcomes", args, 1, 1)
820 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
829 std::vector<variant> vars;
839 vars.push_back(
variant(
new position_callable( static_cast<int>(100 - analysis->
chance_to_kill*100))));
864 class get_unit_type_function :
public function_expression {
866 explicit get_unit_type_function(
const args_list& args)
867 : function_expression(
"get_unit_type", args, 1, 1)
870 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
884 class rate_action_function :
public function_expression {
886 explicit rate_action_function(
const args_list& args,
const formula_ai &ai)
887 : function_expression(
"rate_action", args, 1, 1),
ai_(ai)
890 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
896 const formula_ai &
ai_;
901 class recall_function :
public function_expression {
903 explicit recall_function(
const args_list& args)
904 : function_expression(
"recall", args, 1, 2)
907 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
910 if(args().
size() >= 2) {
911 loc = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"recall:location")))->loc();
914 return variant(
new recall_callable(loc,
id));
919 class recruit_function :
public function_expression {
921 explicit recruit_function(
const args_list& args)
922 : function_expression(
"recruit", args, 1, 2)
925 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
928 if(args().
size() >= 2) {
929 loc = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"recruit:location")))->loc();
932 return variant(
new recruit_callable(loc, type));
937 class shortest_path_function :
public function_expression {
939 explicit shortest_path_function(
const args_list& args,
const formula_ai& ai)
940 : function_expression(
"shortest_path", args, 2, 3),
ai_(ai)
944 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
948 const map_location src = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"shortest_path:src")))->loc();
949 const map_location dst = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"shortest_path:dst")))->loc();
955 if(args().
size() > 2)
956 unit_loc = convert_variant<location_callable>(args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"shortest_path:unit_location")))->loc();
963 std::ostringstream str;
964 str <<
"shortest_path function: expected unit at location (" << (unit_loc.
x+1) <<
"," << (unit_loc.
y+1) <<
")";
965 throw formula_error( str.str(),
"",
"", 0);
972 if( route.
steps.size() < 2 ) {
976 for (std::vector<map_location>::const_iterator loc_iter = route.
steps.begin() + 1 ; loc_iter !=route.
steps.end(); ++loc_iter) {
983 const formula_ai&
ai_;
987 class simplest_path_function :
public function_expression {
989 explicit simplest_path_function(
const args_list& args,
const formula_ai& ai)
990 : function_expression(
"simplest_path", args, 2, 3),
ai_(ai)
994 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
998 const map_location src = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"simplest_path:src")))->loc();
999 const map_location dst = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"simplest_path:dst")))->loc();
1005 if(args().
size() > 2)
1006 unit_loc = convert_variant<location_callable>(args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"simplest_path:unit_location")))->loc();
1013 std::ostringstream str;
1014 str <<
"simplest_path function: expected unit at location (" << (unit_loc.
x+1) <<
"," << (unit_loc.
y+1) <<
")";
1015 throw formula_error( str.str(),
"",
"", 0);
1024 if( route.
steps.size() < 2 ) {
1028 for (std::vector<map_location>::const_iterator loc_iter = route.
steps.begin() + 1 ; loc_iter !=route.
steps.end(); ++loc_iter) {
1038 const formula_ai&
ai_;
1043 class next_hop_function :
public function_expression {
1045 explicit next_hop_function(
const args_list& args,
const formula_ai& ai)
1046 : function_expression(
"next_hop", args, 2, 3),
ai_(ai)
1050 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1052 const map_location src = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"next_hop:src")))->loc();
1053 const map_location dst = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"next_hop:dst")))->loc();
1059 if(args().
size() > 2)
1060 unit_loc = convert_variant<location_callable>(args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"next_hop:unit_location")))->loc();
1067 std::ostringstream str;
1068 str <<
"next_hop function: expected unit at location (" << (unit_loc.
x+1) <<
"," << (unit_loc.
y+1) <<
")";
1069 throw formula_error( str.str(),
"",
"", 0);
1076 if( route.
steps.size() < 2 ) {
1082 const ai::moves_map::const_iterator& p_it = possible_moves.find(unit_loc);
1083 if (p_it==possible_moves.end() ) {
1087 for (std::vector<map_location>::const_iterator loc_iter = route.
steps.begin() + 1 ; loc_iter !=route.
steps.end(); ++loc_iter) {
1089 if (p_it->second.destinations.find(*loc_iter) != p_it->second.destinations.end() ) {
1101 const formula_ai&
ai_;
1106 class move_function :
public function_expression {
1108 explicit move_function(
const args_list& args)
1109 : function_expression(
"move", args, 2, 2)
1112 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1113 const map_location src = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"move:src")))->loc();
1114 const map_location dst = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"move:dst")))->loc();
1115 LOG_AI <<
"move(): " << src <<
", " << dst <<
")\n";
1116 return variant(
new move_callable(src, dst));
1121 class move_partial_function :
public function_expression {
1123 explicit move_partial_function(
const args_list& args)
1124 : function_expression(
"move_partial", args, 2, 2)
1127 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1128 const map_location src = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"move_partial:src")))->loc();
1129 const map_location dst = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"move_partial:dst")))->loc();
1130 LOG_AI <<
"move_partial(): " << src <<
", " << dst <<
")\n";
1131 return variant(
new move_partial_callable(src, dst));
1136 class set_var_function :
public function_expression {
1138 explicit set_var_function(
const args_list& args)
1139 : function_expression(
"set_var", args, 2, 2)
1142 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1143 return variant(
new set_var_callable(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"set_var:key")).as_string(), args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"set_var:value"))));
1148 class set_unit_var_function :
public function_expression {
1150 explicit set_unit_var_function(
const args_list& args)
1151 : function_expression(
"set_unit_var", args, 3, 3)
1154 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1155 return variant(
new set_unit_var_callable(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"set_unit_var:key")).as_string(), args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"set_unit_var:value")), convert_variant<location_callable>(args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"set_unit_var:unit_location")))->loc()));
1160 class fallback_function :
public function_expression {
1162 explicit fallback_function(
const args_list& args)
1163 : function_expression(
"fallback", args, 0, 1)
1166 variant execute(
const formula_callable& variables, formula_debugger*)
const {
1168 if(args().
size() == 1 && args()[0]->evaluate(variables).as_string() !=
"human")
1170 return variant(
new fallback_callable);
1175 class attack_function :
public function_expression {
1177 explicit attack_function(
const args_list& args)
1178 : function_expression(
"attack", args, 3, 4)
1181 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1182 const map_location move_from = convert_variant<location_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"attack:move_from")))->loc();
1183 const map_location src = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"attack:src")))->loc();
1184 const map_location dst = convert_variant<location_callable>(args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"attack:dst")))->loc();
1185 const int weapon = args().size() == 4 ? args()[3]->evaluate(variables,
add_debug_info(fdb,3,
"attack:weapon")).as_int() : -1;
1187 ERR_AI <<
"AI ERROR: Formula produced illegal attack: " << move_from <<
" -> " << src <<
" -> " << dst << std::endl;
1190 return variant(
new attack_callable(move_from, src, dst, weapon));
1195 class safe_call_function :
public function_expression {
1197 explicit safe_call_function(
const args_list& args)
1198 : function_expression(
"safe_call", args, 2, 2)
1201 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1202 const variant main = args()[0]->evaluate(variables,fdb);
1205 return variant(
new safe_call_callable(main, backup_formula));
1209 class debug_label_function :
public function_expression {
1211 explicit debug_label_function(
const args_list& args,
const formula_ai& ai)
1212 : function_expression(
"debug_label", args, 2, 2),
1216 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1217 const args_list& arguments = args();
1218 const variant var0 = arguments[0]->evaluate(variables,fdb);
1219 const variant var1 = arguments[1]->evaluate(variables,fdb);
1227 display_label(location,text);
1229 std::vector<variant>
res;
1230 res.push_back(var0);
1231 res.push_back(var1);
1247 const formula_ai&
ai_;
1251 class is_village_function :
public function_expression {
1253 explicit is_village_function(
const args_list& args)
1254 : function_expression(
"is_village", args, 2, 3)
1257 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1258 const gamemap& m = convert_variant<gamemap_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"is_village:map")))->get_gamemap();
1261 if(args().
size() == 2) {
1262 loc = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"is_village:location")))->loc();
1265 args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"is_village:y")).as_int() - 1 );
1272 class is_unowned_village_function :
public function_expression {
1274 explicit is_unowned_village_function(
const args_list& args,
const formula_ai& ai)
1275 : function_expression(
"is_unowned_village", args, 2, 3),
1279 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1281 const gamemap& m = convert_variant<gamemap_callable>(args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"is_unowned_village:map")))->get_gamemap();
1282 const std::set<map_location>& my_villages =
ai_.current_team().villages();
1285 if(args().
size() == 2) {
1286 loc = convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"is_unowned_village:location")))->loc();
1289 args()[2]->evaluate(variables,
add_debug_info(fdb,2,
"is_unowned_village:y")).as_int() - 1 );
1292 if(m.
is_village(loc) && (my_villages.count(loc)==0) ) {
1299 const formula_ai&
ai_;
1303 class unit_at_function :
public function_expression {
1305 unit_at_function(
const args_list& args)
1306 : function_expression(
"unit_at", args, 1, 1)
1309 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1325 class unit_moves_function :
public function_expression {
1327 unit_moves_function(
const args_list& args,
const formula_ai& ai_object)
1328 : function_expression(
"unit_moves", args, 1, 1),
ai_(ai_object)
1331 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1333 std::vector<variant> vars;
1338 const map_location& loc = convert_variant<location_callable>(
res)->loc();
1340 typedef ai::move_map::const_iterator Itor;
1341 std::pair<Itor,Itor> range = srcdst.equal_range(loc);
1343 for(Itor i = range.first; i != range.second; ++i) {
1350 const formula_ai&
ai_;
1354 class units_can_reach_function :
public function_expression {
1356 units_can_reach_function(
const args_list& args)
1357 : function_expression(
"units_can_reach", args, 2, 2)
1360 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1361 std::vector<variant> vars;
1362 variant dstsrc_var = args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"units_can_reach:possible_move_list"));
1363 const ai::move_map& dstsrc = convert_variant<move_map_callable>(dstsrc_var)->dstsrc();
1364 std::pair<ai::move_map::const_iterator,ai::move_map::const_iterator> range =
1365 dstsrc.equal_range(convert_variant<location_callable>(args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"units_can_reach:possible_move_list")))->loc());
1366 while(range.first != range.second) {
1378 class defense_on_function :
public function_expression {
1380 defense_on_function(
const args_list& args)
1381 : function_expression(
"defense_on", args, 2, 2)
1384 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1391 const unit_callable* u_call = try_convert_variant<unit_callable>(u);
1393 const map_location& loc = convert_variant<location_callable>(loc_var)->loc();
1411 const unit_type& un = u_type->get_unit_type();
1428 class chance_to_hit_function :
public function_expression {
1430 chance_to_hit_function(
const args_list& args)
1431 : function_expression(
"chance_to_hit", args, 2, 2)
1434 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1441 const unit_callable* u_call = try_convert_variant<unit_callable>(u);
1443 const map_location& loc = convert_variant<location_callable>(loc_var)->loc();
1458 const unit_type& un = u_type->get_unit_type();
1472 class movement_cost_function :
public function_expression {
1474 movement_cost_function(
const args_list& args)
1475 : function_expression(
"movement_cost", args, 2, 2)
1478 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1485 const unit_callable* u_call = try_convert_variant<unit_callable>(u);
1487 const map_location& loc = convert_variant<location_callable>(loc_var)->loc();
1502 const unit_type& un = u_type->get_unit_type();
1515 class is_avoided_location_function :
public function_expression {
1517 is_avoided_location_function(
const args_list& args,
const formula_ai& ai_object)
1518 : function_expression(
"is_avoided_location",args, 1, 1),
ai_(ai_object)
1521 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1526 const map_location& loc = convert_variant<location_callable>(
res)->loc();
1530 const formula_ai &
ai_;
1533 class max_possible_damage_function :
public function_expression {
1535 max_possible_damage_function(
const args_list& args)
1536 : function_expression(
"max_possible_damage", args, 2, 2)
1539 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1545 std::vector<attack_type> attacks_tmp;
1546 std::vector<attack_type>& attacks = attacks_tmp;
1549 const unit_callable* u_attacker = try_convert_variant<unit_callable>(
u1);
1559 const unit_callable* u_defender = try_convert_variant<unit_callable>(
u2);
1564 for(std::vector<attack_type>::const_iterator i = attacks.begin(); i != attacks.end(); ++
i) {
1574 for(std::vector<attack_type>::const_iterator i = attacks.begin(); i != attacks.end(); ++
i) {
1585 class max_possible_damage_with_retaliation_function :
public function_expression {
1587 max_possible_damage_with_retaliation_function(
const args_list& args)
1588 : function_expression(
"max_possible_damage_with_retaliation", args, 2, 2)
1592 std::pair<int, int> best_melee_and_ranged_attacks(unit_adapter attacker, unit_adapter defender)
const {
1593 int highest_melee_damage = 0;
1594 int highest_ranged_damage = 0;
1596 std::vector<attack_type> attacks = attacker.attacks();
1599 const int dmg =
round_damage(attack.damage(), defender.damage_from(attack), 100) * attack.num_attacks();
1600 if (attack.range() ==
"melee") {
1601 highest_melee_damage = std::max(highest_melee_damage, dmg);
1603 highest_ranged_damage = std::max(highest_ranged_damage, dmg);
1607 return std::make_pair(highest_melee_damage, highest_ranged_damage);
1610 variant execute(
const formula_callable& variables, formula_debugger *fdb)
const {
1611 variant u1 = args()[0]->evaluate(variables,
add_debug_info(fdb,0,
"max_possible_damage_with_retaliation:unit1"));
1612 variant u2 = args()[1]->evaluate(variables,
add_debug_info(fdb,1,
"max_possible_damage_with_retaliation:unit2"));
1618 unit_adapter attacker(u1);
1619 unit_adapter defender(u2);
1622 std::pair<int, int> best_attacker_attacks = best_melee_and_ranged_attacks(attacker, defender);
1623 std::pair<int, int> best_defender_attacks = best_melee_and_ranged_attacks(defender, attacker);
1625 std::vector<variant> vars;
1626 vars.push_back(
variant(best_attacker_attacks.first));
1627 vars.push_back(
variant(best_attacker_attacks.second));
1628 vars.push_back(
variant(best_defender_attacks.first));
1629 vars.push_back(
variant(best_defender_attacks.second));
1635 template<
typename T>
1636 class ai_formula_function :
public formula_function {
1650 #define AI_FUNCTION(name) add_function(#name, formula_function_ptr( \
1651 new ai_formula_function<name##_function>(#name, ai)))
1652 #define FUNCTION(name) add_function(#name, formula_function_ptr( \
1653 new builtin_formula_function<name##_function>(#name)))
1680 FUNCTION(max_possible_damage_with_retaliation);
size_t num_elements() const
int total_movement() const
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator *calc, const size_t width, const size_t height, const teleport_map *teleports, bool border)
std::vector< double > hp_dist
Resulting probability distribution (might be not as large as max_hp)
static display * get_singleton()
Returns the display object if a display object exists.
const std::vector< node > & nodes
boost::shared_ptr< formula > formula_ptr
int movement_cost(const t_translation::t_terrain &terrain) const
size_t count(const map_location &loc) const
GLuint GLuint GLsizei GLenum type
const combatant & get_attacker_combatant(const combatant *prev_def=nullptr)
Get the simulation results.
SDL_Color int_to_color(const Uint32 rgb)
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
bool is_village(const map_location &loc) const
std::map< map_location, pathfind::paths > moves_map
The standard way in which a map of possible movement routes to location is recorded.
void get_tiles_in_radius(const map_location ¢er, const int radius, std::vector< map_location > &result)
Function that will add to result all locations within radius tiles of center (excluding center itself...
const movetype & movement_type() const
const map_location & loc() const
unit_type_data unit_types
GLint GLint GLint GLint GLint GLint y
const std::vector< std::string > items
double chance_to_kill
Estimated % chance to kill the unit.
int movement_cost(const t_translation::t_terrain &terrain, bool slowed=false) const
Returns the cost to move through the indicated terrain.
int defense_modifier(const t_translation::t_terrain &terrain) const
const unit & get_unit() const
const terrain_label * set_label(const map_location &loc, const t_string &text, const int creator=-1, const std::string &team="", const SDL_Color color=font::NORMAL_COLOR, const bool visible_in_fog=true, const bool visible_in_shroud=false, const bool immutable=false, const std::string &category="", const t_string &tooltip="")
GLdouble GLdouble GLdouble b
unsigned in
If equal to search_counter, the node is off the list.
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
A small explanation about what's going on here: Each action has access to two game_info objects First...
ai_function_symbol_table(ai::formula_ai &ai)
GLsizei const char ** path
std::vector< map_location > steps
unit_type::ALIGNMENT alignment() const
Structure which holds a single route between one location and another.
size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
GLubyte GLubyte GLubyte GLubyte w
#define AI_FUNCTION(name)
int w() const
Effective map width.
const unit_type & get_unit_type() const
formula_debugger * add_debug_info(formula_debugger *fdb, int arg_number, const std::string &f_name)
GLboolean GLboolean GLboolean GLboolean a
Encapsulates the map of the game.
Computes the statistics of a battle between an attacker and a defender unit.
std::string string_cast() const
map_display and display: classes which take care of displaying the map and game-data on the screen...
Function which only uses terrain, ignoring shroud, enemies, etc.
int damage_from(const attack_type &attack, bool attacker, const map_location &loc) const
static const map_location & null_location()
static const ::config * terrain
The terrain used to create the cache.
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
GLsizei const GLint * locations
GLuint GLuint GLsizei count
const std::vector< attack_type > & attacks() const
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
boost::shared_ptr< function_expression > function_expression_ptr
Encapsulates the map of the game.
const terrain_type & get_terrain_info(const t_translation::t_terrain &terrain) const
int round_damage(int base_damage, int bonus, int divisor)
round (base_damage * bonus / divisor) to the closest integer, but up or down towards base_damage ...
boost::shared_ptr< formula_expression > expression_ptr
static config unit_moves(reports::context &rc, const unit *u)
int resistance_against(const attack_type &attack) const
Returns the resistance against the indicated attack.
int h() const
Effective map height.
std::string get_wml_location(const std::string &filename, const std::string ¤t_dir=std::string())
Returns a complete path to the actual WML file or directory or an empty string if the file isn't pres...
const location & get_location() const
const std::string & as_string() const
static bool operator<(const placing_info &a, const placing_info &b)
GLfloat GLfloat GLfloat GLfloat h
GLint GLint GLint GLint GLint x
Declarations for File-IO.
GLdouble GLdouble GLdouble r
int main(int argc, char **argv)
static lg::log_domain log_formula_ai("ai/engine/fai")
GLuint const GLchar * name
virtual const gamemap & map() const
std::string to_debug_string(std::vector< const game_logic::formula_callable * > *seen=nullptr, bool verbose=false) const
static const unit_type & get_unit_type(const std::string &type_id)
Converts a string ID to a unit_type.
To store label data Class implements logic for rendering.
bool find(E event, F functor)
Tests whether an event handler is available.
std::vector< attack_type > attacks() const
const unit_type * unit_type_
Standard logging facilities (interface).
Object which contains all the possible locations a unit can move to, with associated best routes to t...
Container associating units to locations.
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.
unit_iterator find(size_t id)
static Uint32 get_side_rgb(int side)
GLuint GLdouble GLdouble u2
const std::vector< map_location > & villages() const
Return a list of the locations of villages on the map.
This module contains various pathfinding functions and utilities.
GLsizei const GLcharARB ** string
int defense_modifier(const t_translation::t_terrain &terrain) const
Returns the defensive value of the indicated terrain.
double rating(double aggression, const readonly_context &ai_obj) const
void add_label(const terrain_label *)
const std::string valid
Little parts of regex templates used to parse Wml annoations.
int combat_modifier(const unit_map &units, const gamemap &map, const map_location &loc, unit_type::ALIGNMENT alignment, bool is_fearless)
Returns the amount that a unit's damage should be multiplied by due to the current time of day...