implement standard way of filtering for side in WML tags,

using patch #2637 as inspiration
This commit is contained in:
Iurii Chernyi 2011-04-14 18:53:39 +00:00
parent 62a549d28a
commit 64c8d70828
3 changed files with 110 additions and 61 deletions

View file

@ -42,6 +42,7 @@
#include "reports.hpp"
#include "resources.hpp"
#include "scripting/lua.hpp"
#include "side_filter.hpp"
#include "sound.hpp"
#include "soundsource.hpp"
#include "terrain_filter.hpp"
@ -542,43 +543,52 @@ namespace {
} // end anonymous namespace (4)
static void toggle_shroud(const bool remove, const vconfig& cfg)
/** Gets a set of sides from side= attribute in a given config node.
Promotes consistent behaviour and returns always non-empty set with valid teams.
Default side, when in doubt is currently side 1. */
std::set<int> get_sides_set(const vconfig& cfg)
{
std::string side_for_raw = cfg["side"];
std::set<int> result;
const config::attribute_value sides = cfg["side"];
const vconfig &ssf = cfg.child("filter_side");
// If they didn't define any sides fall back to the old behaviour of
// selecting side 1.
if (side_for_raw.empty()) {
side_for_raw = "1";
if (!ssf.null()) {
side_filter filter(ssf,sides.str());
return filter.get_teams();
}
//iterate through the list
std::vector<std::string> side_for =
utils::split(side_for_raw, ',', utils::STRIP_SPACES | utils::REMOVE_EMPTY);
std::vector<std::string>::iterator itSide;
size_t side;
for (itSide = side_for.begin(); itSide != side_for.end(); ++itSide)
{
side = lexical_cast_default<size_t>(*itSide);
size_t index = side-1;
if (index < resources::teams->size())
{
team &t = (*resources::teams)[index];
std::set<map_location> locs;
terrain_filter filter(cfg, *resources::units);
filter.restrict_size(game_config::max_loop);
filter.get_locations(locs, true);
if (sides.blank()) {
put_wml_message("error","empty side= and no [filter_side] is deprecated");
result.insert(1); // we make sure the set is not empty and the current default is maintained
return result;
}
side_filter filter(sides.str());
return filter.get_teams();
}
foreach (map_location const &loc, locs)
{
if (remove) {
t.clear_shroud(loc);
} else {
t.place_shroud(loc);
}
static void toggle_shroud(const bool remove, const vconfig& cfg)
{
std::set<int> sides = get_sides_set(cfg);
size_t index;
foreach (const int &side_num, sides)
{
index = side_num - 1;
team &t = (*resources::teams)[index];
std::set<map_location> locs;
terrain_filter filter(cfg, *resources::units);
filter.restrict_size(game_config::max_loop);
filter.get_locations(locs, true);
foreach (map_location const &loc, locs)
{
if (remove) {
t.clear_shroud(loc);
} else {
t.place_shroud(loc);
}
}
}
}
resources::screen->labels().recalculate_shroud();
resources::screen->recalculate_minimap();
@ -674,29 +684,18 @@ WML_HANDLER_FUNCTION(teleport, event_info, cfg)
WML_HANDLER_FUNCTION(allow_recruit, /*event_info*/, cfg)
{
const config::attribute_value sides = cfg["side"];
const std::string& sides_string = sides;
std::set<int> sides = get_sides_set(cfg);
if (sides.blank() || (std::find(sides_string.begin(), sides_string.end(), ',') == sides_string.end())) {
//no side= given or not a comma-separated list
const unsigned index = sides.to_int(1) - 1;
if (index >= resources::teams->size()) return;
foreach (const std::string &type, utils::split(cfg["type"])) {
foreach(const int &side_num, sides)
{
const std::vector<std::string> types = utils::split(cfg["type"]);
foreach(const std::string &type, types)
{
const unsigned index = side_num - 1;
(*resources::teams)[index].add_recruit(type);
preferences::encountered_units().insert(type);
}
}
else {
const std::vector<std::string> types = utils::split(cfg["type"]);
foreach (const std::string& side, utils::split(sides_string)) {
const unsigned index = lexical_cast_default<int, const std::string&>(side, 1) - 1;
if (index >= resources::teams->size()) continue;
foreach (const std::string& type, types) {
(*resources::teams)[index].add_recruit(type);
preferences::encountered_units().insert(type);
}
}
}
}
WML_HANDLER_FUNCTION(volume, /*event_info*/, cfg)
@ -785,11 +784,11 @@ WML_HANDLER_FUNCTION(inspect, /*event_info*/, cfg)
WML_HANDLER_FUNCTION(modify_ai, /*event_info*/, cfg)
{
int side_num = cfg["side"].to_int(1);
if (side_num==0) {
return;
std::set<int> sides = get_sides_set(cfg);
foreach (const int &side_num, sides)
{
ai::manager::modify_active_ai_for_side(side_num,cfg.get_parsed_config());
}
ai::manager::modify_active_ai_for_side(side_num,cfg.get_parsed_config());
}
WML_HANDLER_FUNCTION(modify_side, /*event_info*/, cfg)
@ -810,11 +809,12 @@ WML_HANDLER_FUNCTION(modify_side, /*event_info*/, cfg)
*/
std::string switch_ai = cfg["switch_ai"];
int side_num = cfg["side"].to_int(1);
const size_t team_index = side_num-1;
std::set<int> sides = get_sides_set(cfg);
size_t team_index;
if (team_index < teams.size())
foreach (const int &side_num, sides)
{
team_index = side_num - 1;
LOG_NG << "modifying side: " << side_num << "\n";
if(!team_name.empty()) {
LOG_NG << "change side's team to team_name '" << team_name << "'\n";

View file

@ -36,7 +36,8 @@ static lg::log_domain log_engine_sf("engine/side_filter");
#pragma warning(disable:4413)
side_filter::side_filter():
cfg_(vconfig::unconstructed_vconfig()),
flat_()
flat_(),
side_string_()
{
assert(false);
}
@ -46,17 +47,60 @@ side_filter::side_filter():
side_filter::side_filter(const vconfig& cfg, bool flat_tod) :
cfg_(cfg),
flat_(flat_tod)
flat_(flat_tod),
side_string_()
{
}
side_filter::side_filter(const vconfig &cfg, const std::string &side_string, bool flat_tod)
: cfg_(cfg), flat_(flat_tod), side_string_(side_string)
{
}
side_filter::side_filter(const std::string &side_string, bool flat_tod)
: cfg_(vconfig::empty_vconfig()), flat_(flat_tod), side_string_(side_string)
{
}
std::set<int> side_filter::get_teams() const
{
//@todo: replace with better implementation
std::set<int> result;
foreach (const team &t, *resources::teams) {
if (match(t)) {
result.insert(t.side());
}
}
return result;
}
static bool check_side_number(const team &t, const std::string &str)
{
std::vector<std::string> list = utils::split(str);
std::string side_number = str_cast(t.side());
if ((std::find(list.begin(),list.end(),side_number)==list.end())
&& (std::find(list.begin(),list.end(),"all")==list.end()))
{
return false;
}
return true;
}
bool side_filter::match_internal(const team &t) const
{
if (cfg_.has_attribute("side_in")) {
std::vector<std::string> list = utils::split(cfg_["side_in"]);
std::string side_number = str_cast(t.side());
if (std::find(list.begin(),list.end(),side_number)==list.end())
{
if (!check_side_number(t,cfg_["side_in"])) {
return false;
}
}
if (cfg_.has_attribute("side")) {
if (!check_side_number(t,cfg_["side"])) {
return false;
}
}
if (!side_string_.empty()) {
if (!check_side_number(t,side_string_)) {
return false;
}
}

View file

@ -36,11 +36,14 @@ public:
side_filter();
#endif
side_filter(const vconfig &cfg, const std::string &side_string, bool flat_tod = false);
side_filter(const std::string &side_string, bool flat_tod = false);
side_filter(const vconfig &cfg, bool flat_tod = false);
//match: returns true if and only if the given team matches this filter
bool match(const team& t) const;
bool match(const int side) const;
std::set<int> get_teams() const;
private:
side_filter(const side_filter &other);
@ -51,6 +54,8 @@ private:
const vconfig cfg_; //config contains WML for a Standard Side Filter
bool flat_;
std::string side_string_;
};
#endif