Skip to content

Commit

Permalink
Enable filtering by upkeep in SUF
Browse files Browse the repository at this point in the history
Supports both numeric values and the special values loyal, free, full.

Closes #3333
  • Loading branch information
CelticMinstrel committed Nov 10, 2019
1 parent 61963d7 commit f82fdb2
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 10 deletions.
15 changes: 15 additions & 0 deletions src/units/filter.cpp
Expand Up @@ -433,6 +433,21 @@ void unit_filter_compound::fill(vconfig cfg)
return gender == args.u.gender();
}
);

create_attribute(literal["upkeep"],
[](const config::attribute_value& c) -> unit::upkeep_t
{
try {
return c.apply_visitor(unit::upkeep_parser_visitor());
} catch(std::invalid_argument&) {
return unit::upkeep_full();
}
},
[](unit::upkeep_t upkeep, const unit_filter_args& args)
{
return args.u.upkeep() == boost::apply_visitor(unit::upkeep_value_visitor(args.u), upkeep);
}
);

create_attribute(literal["side"],
[](const config::attribute_value& c)
Expand Down
14 changes: 4 additions & 10 deletions src/units/unit.cpp
Expand Up @@ -2635,16 +2635,10 @@ void unit::parse_upkeep(const config::attribute_value& upkeep)
return;
}

// TODO: create abetter way to check whether it is actually an int.
int upkeep_int = upkeep.to_int(-99);
if(upkeep_int != -99) {
upkeep_ = upkeep_int;
} else if(upkeep == upkeep_loyal::type() || upkeep == "free") {
upkeep_ = upkeep_loyal();
} else if(upkeep == upkeep_full::type()) {
upkeep_ = upkeep_full();
} else {
WRN_UT << "Found invalid upkeep=\"" << upkeep << "\" in a unit" << std::endl;
try {
upkeep_ = upkeep.apply_visitor(upkeep_parser_visitor());
} catch(std::invalid_argument& e) {
WRN_UT << "Found invalid upkeep=\"" << e.what() << "\" in a unit" << std::endl;
upkeep_ = upkeep_full();
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/units/unit.hpp
Expand Up @@ -1132,6 +1132,41 @@ class unit
};

using upkeep_t = boost::variant<upkeep_full, upkeep_loyal, int>;

/** Visitor helper class to parse the upkeep value from a config. */
class upkeep_parser_visitor : public boost::static_visitor<upkeep_t>
{
public:
template<typename N>
std::enable_if_t<std::is_arithmetic<N>::value, upkeep_t>
operator()(N n) const
{
if(n == 0) return upkeep_loyal();
if(n < 0) throw std::invalid_argument(std::to_string(n));
return n;
}

template<typename B>
std::enable_if_t<std::is_convertible<B, bool>::value && !std::is_arithmetic<B>::value, upkeep_t>
operator()(B b) const
{
throw std::invalid_argument(b.str());
}

upkeep_t operator()(boost::blank) const
{
return upkeep_full();
}

upkeep_t operator()(const std::string& s) const
{
if(s == "loyal" || s == "free")
return upkeep_loyal();
if(s == "full")
return upkeep_full();
throw std::invalid_argument(s);
}
};

/**
* Gets the raw variant controlling the upkeep value.
Expand Down

0 comments on commit f82fdb2

Please sign in to comment.