Add enemy_of WFL function to test alliances

Accepts unit and team callables as well as side numbers
This commit is contained in:
Celtic Minstrel 2017-06-20 00:26:28 -04:00
parent b1b4acf576
commit a4b1c14d5e
2 changed files with 43 additions and 0 deletions

View file

@ -42,6 +42,8 @@ Version 1.13.8+dev:
chance_to_hit, movement_cost
* New builtin functions for manipulating locations (available to all formulas):
adjacent_locs, are_adjacent, relative_dir, direction_from, rotate_loc_around
* New enemy_of function checks if its second argument is an enemy of the first
Arguments can be side or unit objects, or integer side indices (1..n)
* WML Engine
* If ai_algorithm is used in [modify_side][ai], it now replaces the whole AI
with the contents of [modify_side][ai], instead of appending these parameters.

View file

@ -258,6 +258,46 @@ private:
}
};
class enemy_of_function : public function_expression
{
public:
enemy_of_function(const args_list& args)
: function_expression("enemy_of", args, 2, 2)
{}
private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const
{
variant self_v = args()[0]->evaluate(variables, add_debug_info(fdb, 0, "enemy_of:self"));
variant other_v = args()[1]->evaluate(variables, add_debug_info(fdb, 1, "enemy_of:other"));
int self, other;
if(auto uc = self_v.try_convert<unit_callable>()) {
// For some obscure, bizarre reason, the unit callable returns a 0-indexed side. :|
self = uc->get_value("side").as_int() + 1;
} else if(auto tc = self_v.try_convert<team_callable>()) {
self = tc->get_value("side").as_int();
} else {
self = self_v.as_int();
}
if(auto uc = other_v.try_convert<unit_callable>()) {
// For some obscure, bizarre reason, the unit callable returns a 0-indexed side. :|
other = uc->get_value("side").as_int() + 1;
} else if(auto tc = other_v.try_convert<team_callable>()) {
other = tc->get_value("side").as_int();
} else {
other = other_v.as_int();
}
int num_teams = resources::gameboard->teams().size();
if(self < 1 || self > num_teams || other < 1 || other > num_teams) {
return variant(0);
}
return variant(resources::gameboard->get_team(self).is_enemy(other) ? 1 : 0);
}
};
} // namespace gamestate
gamestate_function_symbol_table::gamestate_function_symbol_table(std::shared_ptr<function_symbol_table> parent) : function_symbol_table(parent) {
@ -270,6 +310,7 @@ gamestate_function_symbol_table::gamestate_function_symbol_table(std::shared_ptr
DECLARE_WFL_FUNCTION(movement_cost);
DECLARE_WFL_FUNCTION(adjacent_locs); // This is deliberately duplicated here; this form excludes off-map locations, while the core form does not
DECLARE_WFL_FUNCTION(locations_in_radius);
DECLARE_WFL_FUNCTION(enemy_of);
}
}