Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #define GETTEXT_DOMAIN "wesnoth-lib"
00017
00018 #include "global.hpp"
00019
00020 #include "config.hpp"
00021 #include "foreach.hpp"
00022 #include "log.hpp"
00023 #include "resources.hpp"
00024 #include "side_filter.hpp"
00025 #include "variable.hpp"
00026 #include "team.hpp"
00027 #include "serialization/string_utils.hpp"
00028
00029 static lg::log_domain log_engine_sf("engine/side_filter");
00030 #define ERR_NG LOG_STREAM(err, log_engine_sf)
00031
00032 #ifdef _MSC_VER
00033
00034
00035 #pragma warning(push)
00036 #pragma warning(disable:4413)
00037 side_filter::side_filter():
00038 cfg_(vconfig::unconstructed_vconfig()),
00039 flat_(),
00040 side_string_()
00041 {
00042 assert(false);
00043 }
00044 #pragma warning(pop)
00045 #endif
00046
00047
00048 side_filter::side_filter(const vconfig& cfg, bool flat_tod) :
00049 cfg_(cfg),
00050 flat_(flat_tod),
00051 side_string_()
00052 {
00053 }
00054
00055 side_filter::side_filter(const std::string &side_string, bool flat_tod)
00056 : cfg_(vconfig::empty_vconfig()), flat_(flat_tod), side_string_(side_string)
00057 {
00058 }
00059
00060 std::vector<int> side_filter::get_teams() const
00061 {
00062
00063 std::vector<int> result;
00064 foreach (const team &t, *resources::teams) {
00065 if (match(t)) {
00066 result.push_back(t.side());
00067 }
00068 }
00069 return result;
00070 }
00071
00072 static bool check_side_number(const team &t, const std::string &str)
00073 {
00074 std::vector<std::pair<int,int> > ranges = utils::parse_ranges(str);
00075 int side_number = t.side();
00076
00077 std::vector<std::pair<int,int> >::const_iterator range, range_end = ranges.end();
00078 for (range = ranges.begin(); range != range_end; ++range) {
00079 if(side_number >= range->first && side_number <= range->second) {
00080 return true;
00081 }
00082 }
00083 return false;
00084 }
00085
00086 bool side_filter::match_internal(const team &t) const
00087 {
00088 if (cfg_.has_attribute("side_in")) {
00089 if (!check_side_number(t,cfg_["side_in"])) {
00090 return false;
00091 }
00092 }
00093 if (cfg_.has_attribute("side")) {
00094 if (!check_side_number(t,cfg_["side"])) {
00095 return false;
00096 }
00097 }
00098 if (!side_string_.empty()) {
00099 if (!check_side_number(t,side_string_)) {
00100 return false;
00101 }
00102 }
00103
00104 config::attribute_value cfg_team_name = cfg_["team_name"];
00105 if (!cfg_team_name.blank()) {
00106 const std::string& that_team_name = cfg_team_name;
00107 const std::string& this_team_name = t.team_name();
00108
00109 if(std::find(this_team_name.begin(), this_team_name.end(), ',') == this_team_name.end()) {
00110 if(this_team_name != that_team_name) return false;
00111 }
00112 else {
00113 const std::vector<std::string>& these_team_names = utils::split(this_team_name);
00114 bool search_futile = true;
00115 foreach(const std::string& this_single_team_name, these_team_names) {
00116 if(this_single_team_name == that_team_name) {
00117 search_futile = false;
00118 break;
00119 }
00120 }
00121 if(search_futile) return false;
00122 }
00123 }
00124
00125
00126 if(cfg_.has_child("has_unit")) {
00127 const vconfig& unit_filter = cfg_.child("has_unit");
00128 bool found = false;
00129 foreach (unit &u, *resources::units) {
00130 if (u.side() != t.side()) {
00131 continue;
00132 }
00133 if (u.matches_filter(unit_filter, u.get_location(), flat_)) {
00134 found = true;
00135 break;
00136 }
00137 }
00138 if(!found && unit_filter["search_recall_list"].to_bool(false)) {
00139 const std::vector<unit>& recall_list = t.recall_list();
00140 foreach(const unit& u, recall_list) {
00141 scoped_recall_unit this_unit("this_unit", t.save_id(), &u - &recall_list[0]);
00142 if(u.matches_filter(unit_filter, u.get_location(), flat_)) {
00143 found = true;
00144 break;
00145 }
00146 }
00147 }
00148 if (!found) {
00149 return false;
00150 }
00151 }
00152
00153 const vconfig& enemy_of = cfg_.child("enemy_of");
00154 if(!enemy_of.null()) {
00155 side_filter s_filter(enemy_of);
00156 const std::vector<int>& teams = s_filter.get_teams();
00157 if(teams.empty()) return false;
00158 foreach(const int side, teams) {
00159 if(!(*resources::teams)[side - 1].is_enemy(t.side()))
00160 return false;
00161 }
00162 }
00163
00164 const vconfig& allied_with = cfg_.child("allied_with");
00165 if(!allied_with.null()) {
00166 side_filter s_filter(allied_with);
00167 const std::vector<int>& teams = s_filter.get_teams();
00168 if(teams.empty()) return false;
00169 foreach(const int side, teams) {
00170 if((*resources::teams)[side - 1].is_enemy(t.side()))
00171 return false;
00172 }
00173 }
00174
00175 return true;
00176 }
00177
00178 bool side_filter::match(int side) const
00179 {
00180 return this->match((*resources::teams)[side-1]);
00181 }
00182
00183 bool side_filter::match(const team& t) const
00184 {
00185 bool matches = match_internal(t);
00186
00187
00188 vconfig::all_children_iterator cond = cfg_.ordered_begin();
00189 vconfig::all_children_iterator cond_end = cfg_.ordered_end();
00190 while (cond != cond_end) {
00191 const std::string& cond_name = cond.get_key();
00192 const vconfig& cond_cfg = cond.get_child();
00193
00194
00195 if(cond_name == "and")
00196 {
00197 matches = matches && side_filter(cond_cfg, flat_).match(t);
00198 }
00199
00200 else if(cond_name == "or")
00201 {
00202 matches = matches || side_filter(cond_cfg, flat_).match(t);
00203 }
00204
00205 else if(cond_name == "not")
00206 {
00207 matches = matches && !side_filter(cond_cfg, flat_).match(t);
00208 }
00209 ++cond;
00210 }
00211 return matches;
00212 }