Push [and],[or],[not] tags from event weapon filters to all weapon filters.

This commit is contained in:
J. Tyne 2012-09-23 20:48:55 +00:00
parent 9a8140ca34
commit b45a6fa04f
3 changed files with 44 additions and 42 deletions

View file

@ -33,6 +33,8 @@ Version 1.11.0+svn:
delayed shroud updates (which is still a major caveat).
* Added [effect] apply_to=overlay
* Added [terrain_type] max_light= and min_light=.
* Standardize weapon filters, supporting special=, [and], [or], and [not]
wherever weapons can be filtered.
* Miscellaneous and bug fixes:
* Fix invalid memory access crash resulting from deleting all saved games
in the Load Game dialog

View file

@ -3365,34 +3365,7 @@ namespace game_events {
return false;
}
const attack_type attack(cfg);
bool matches = attack.matches_filter(filter.get_parsed_config());
// Handle [and], [or], and [not] with in-order precedence
vconfig::all_children_iterator cond_i = filter.ordered_begin();
vconfig::all_children_iterator cond_end = filter.ordered_end();
while(cond_i != cond_end)
{
const std::string& cond_name = cond_i.get_key();
const vconfig& cond_filter = cond_i.get_child();
// Handle [and]
if(cond_name == "and")
{
matches = matches && matches_special_filter(cfg, cond_filter);
}
// Handle [or]
else if(cond_name == "or")
{
matches = matches || matches_special_filter(cfg, cond_filter);
}
// Handle [not]
else if(cond_name == "not")
{
matches = matches && !matches_special_filter(cfg, cond_filter);
}
++cond_i;
}
return matches;
return attack.matches_filter(filter.get_parsed_config());
}
bool unit_matches_filter(const unit &u, const vconfig& filter)

View file

@ -91,11 +91,10 @@ std::string attack_type::accuracy_parry_description() const
}
/**
* Returns whether or not *this matches the given @a filter.
* If @a ignore_special is set to true, then the special= attribute of the
* filter is ignored.
* Returns whether or not *this matches the given @a filter, ignoring the
* complexities introduced by [and], [or], and [not].
*/
bool attack_type::matches_filter(const config& filter) const
static bool matches_simple_filter(const attack_type & attack, const config & filter)
{
const std::vector<std::string>& filter_range = utils::split(filter["range"]);
const std::string& filter_damage = filter["damage"];
@ -103,25 +102,53 @@ bool attack_type::matches_filter(const config& filter) const
const std::vector<std::string> filter_type = utils::split(filter["type"]);
const std::string filter_special = filter["special"];
if(filter_range.empty() == false && std::find(filter_range.begin(),filter_range.end(),range()) == filter_range.end())
return false;
if(filter_damage.empty() == false && !in_ranges(damage(), utils::parse_ranges(filter_damage))) {
return false;
}
if(filter_name.empty() == false && std::find(filter_name.begin(),filter_name.end(),id()) == filter_name.end())
if ( !filter_range.empty() && std::find(filter_range.begin(), filter_range.end(), attack.range()) == filter_range.end() )
return false;
if(filter_type.empty() == false && std::find(filter_type.begin(),filter_type.end(),type()) == filter_type.end())
if ( !filter_damage.empty() && !in_ranges(attack.damage(), utils::parse_ranges(filter_damage)) )
return false;
if ( !filter_special.empty() && !get_special_bool(filter_special, true) )
if ( !filter_name.empty() && std::find(filter_name.begin(), filter_name.end(), attack.id()) == filter_name.end() )
return false;
if ( !filter_type.empty() && std::find(filter_type.begin(), filter_type.end(), attack.type()) == filter_type.end() )
return false;
if ( !filter_special.empty() && !attack.get_special_bool(filter_special, true) )
return false;
// Passed all tests.
return true;
}
/**
* Returns whether or not *this matches the given @a filter.
*/
bool attack_type::matches_filter(const config& filter) const
{
// Handle the basic filter.
bool matches = matches_simple_filter(*this, filter);
// Handle [and], [or], and [not] with in-order precedence
BOOST_FOREACH( const config::any_child &condition, filter.all_children_range() )
{
// Handle [and]
if ( condition.key == "and" )
matches = matches && matches_filter(condition.cfg);
// Handle [or]
else if ( condition.key == "or" )
matches = matches || matches_filter(condition.cfg);
// Handle [not]
else if ( condition.key == "not" )
matches = matches && !matches_filter(condition.cfg);
}
return matches;
}
/**
* Modifies *this using the specifications in @a cfg, but only if *this matches
* @a cfg viewed as a filter.