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). delayed shroud updates (which is still a major caveat).
* Added [effect] apply_to=overlay * Added [effect] apply_to=overlay
* Added [terrain_type] max_light= and min_light=. * 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: * Miscellaneous and bug fixes:
* Fix invalid memory access crash resulting from deleting all saved games * Fix invalid memory access crash resulting from deleting all saved games
in the Load Game dialog in the Load Game dialog

View File

@ -3365,34 +3365,7 @@ namespace game_events {
return false; return false;
} }
const attack_type attack(cfg); const attack_type attack(cfg);
bool matches = attack.matches_filter(filter.get_parsed_config()); return 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;
} }
bool unit_matches_filter(const unit &u, const vconfig& filter) 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. * Returns whether or not *this matches the given @a filter, ignoring the
* If @a ignore_special is set to true, then the special= attribute of the * complexities introduced by [and], [or], and [not].
* filter is ignored.
*/ */
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::vector<std::string>& filter_range = utils::split(filter["range"]);
const std::string& filter_damage = filter["damage"]; 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::vector<std::string> filter_type = utils::split(filter["type"]);
const std::string filter_special = filter["special"]; const std::string filter_special = filter["special"];
if(filter_range.empty() == false && std::find(filter_range.begin(),filter_range.end(),range()) == filter_range.end()) if ( !filter_range.empty() && std::find(filter_range.begin(), filter_range.end(), attack.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())
return false; 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; 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; 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; 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 * Modifies *this using the specifications in @a cfg, but only if *this matches
* @a cfg viewed as a filter. * @a cfg viewed as a filter.