Skip to content

Commit

Permalink
Support multiple super tags and even conditional super tags
Browse files Browse the repository at this point in the history
Use this to conditionally import [unit] keys in [side] based on no_leader
  • Loading branch information
CelticMinstrel committed Mar 18, 2018
1 parent 37e766f commit 51902b6
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 40 deletions.
10 changes: 8 additions & 2 deletions data/schema/core/addons.cfg
Expand Up @@ -17,8 +17,14 @@
[tag]
name="$side"
max=0
# TODO: This superclass should only be used if no_leader=no
super="units/$unit"
[if]
[not]
no_leader=yes
[/not]
[then]
super="units/$unit"
[/then]
[/if]
{DEFAULT_KEY no_leader bool no}
{SIMPLE_KEY recruit string}
{DEFAULT_KEY gold int 100}
Expand Down
2 changes: 1 addition & 1 deletion data/schema/units/modifications.cfg
Expand Up @@ -12,7 +12,7 @@
key=apply_to
[case]
value=new_attack
super="units/unit_type/attack"
super="units/unit_type~core/attack"
[/case]
{FILTER_TAG "case" weapon value=remove_attacks}
{FILTER_TAG "case" weapon (
Expand Down
71 changes: 40 additions & 31 deletions src/serialization/tag.cpp
Expand Up @@ -215,13 +215,13 @@ void class_tag::add_link(const std::string& link)
links_.emplace(name_link, link);
}

const class_key* class_tag::find_key(const std::string& name, const config& match) const
const class_key* class_tag::find_key(const std::string& name, const config& match, bool ignore_super) const
{
// Check the conditions first, so that conditional definitions
// override base definitions in the event of duplicates.
for(auto& cond : conditions_) {
if(cond.matches(match)) {
if(auto key = cond.find_key(name, match)) {
if(auto key = cond.find_key(name, match, true)) {
return key;
}
}
Expand All @@ -241,6 +241,23 @@ const class_key* class_tag::find_key(const std::string& name, const config& matc
if(it_fuzzy != keys_.end()) {
return &(it_fuzzy->second);
}

if(!ignore_super) {
for(auto& cond : conditions_) {
if(cond.matches(match)) {
// This results in a little redundancy (checking things twice) but at least it still works.
if(auto key = cond.find_key(name, match, false)) {
return key;
}
}
}
for(auto& super_tag : super_refs_) {
if(const class_key* found_key = super_tag->find_key(name, match)) {
return found_key;
}
}
}

return nullptr;
}

Expand All @@ -254,7 +271,7 @@ const std::string* class_tag::find_link(const std::string& name) const
return nullptr;
}

const class_tag* class_tag::find_tag(const std::string& fullpath, const class_tag& root, const config& match) const
const class_tag* class_tag::find_tag(const std::string& fullpath, const class_tag& root, const config& match, bool ignore_super) const
{
if(fullpath.empty()) {
return nullptr;
Expand All @@ -275,7 +292,7 @@ const class_tag* class_tag::find_tag(const std::string& fullpath, const class_ta
// override base definitions in the event of duplicates.
for(auto& cond : conditions_) {
if(cond.matches(match)) {
if(auto tag = cond.find_tag(fullpath, root, match)) {
if(auto tag = cond.find_tag(fullpath, root, match, true)) {
return tag;
}
}
Expand Down Expand Up @@ -309,6 +326,22 @@ const class_tag* class_tag::find_tag(const std::string& fullpath, const class_ta
}
}

if(!ignore_super) {
for(auto& cond : conditions_) {
if(cond.matches(match)) {
// This results in a little redundancy (checking things twice) but at least it still works.
if(auto tag = cond.find_tag(fullpath, root, match, false)) {
return tag;
}
}
}
for(auto& super_tag : super_refs_) {
if(const class_tag* found_tag = super_tag->find_tag(fullpath, root, match)) {
return found_tag;
}
}
}

if(any_tag_) {
return &any_tag;
}
Expand Down Expand Up @@ -448,37 +481,13 @@ void class_tag::add_tag(const std::string& path, const class_tag& tag, class_tag
it_tags->second.add_tag(next_path, tag, root);
}

void class_tag::append_super(const class_tag& tag, const std::string& path)
{
// TODO: Ensure derived tag definitions override base tag definitions in the event of duplicates
add_keys(tag.keys_);
add_links(tag.links_);
add_conditions(tag.conditions_);

for(const auto& t : tag.tags_) {
links_.erase(t.first);
if(t.second.is_fuzzy()) {
// Fuzzy tags won't work as links, so make a copy
// (Links just don't hold enough info for this to work.)
add_tag(t.second);
} else {
add_link(path + "/" + t.first);
}
}
if(tag.any_tag_) {
any_tag_ = true;
}
}

void class_tag::expand(class_tag& root)
{
if(!super_.empty()) {
class_tag* super_tag = root.find_tag(super_, root, config());
for(auto& super : utils::split(super_)) {
class_tag* super_tag = root.find_tag(super, root, config());
if(super_tag) {
if(super_tag != this) {
super_tag->expand(root);
append_super(*super_tag, super_);
super_.clear();
super_refs_.push_back(super_tag);
} else {
// TODO: Detect super cycles too!
std::cerr << "the same" << super_tag->name_ << "\n";
Expand Down
13 changes: 7 additions & 6 deletions src/serialization/tag.hpp
Expand Up @@ -256,6 +256,7 @@ class class_tag
using key_map = std::map<std::string, class_key>;
using link_map = std::map<std::string, std::string>;
using condition_list = std::vector<class_condition>;
using super_list = std::vector<class_tag*>;
private:
void push_new_tag_conditions(std::queue<const class_tag*> q, const class_tag& tag);
template<typename T, typename Map = std::map<std::string, T>>
Expand Down Expand Up @@ -478,7 +479,7 @@ class class_tag
}

/** Returns pointer to child key. */
const class_key* find_key(const std::string& name, const config& match) const;
const class_key* find_key(const std::string& name, const config& match, bool ignore_super = false) const;

/** Returns pointer to child link. */
const std::string* find_link(const std::string& name) const;
Expand All @@ -487,7 +488,7 @@ class class_tag
* Returns pointer to tag using full path to it.
* Also work with links
*/
const class_tag* find_tag(const std::string& fullpath, const class_tag& root, const config& match) const;
const class_tag* find_tag(const std::string& fullpath, const class_tag& root, const config& match, bool ignore_super = false) const;

/** Calls the expansion on each child. */
void expand_all(class_tag& root);
Expand Down Expand Up @@ -551,6 +552,9 @@ class class_tag
/** conditional partial matches */
condition_list conditions_;

/** super-tag references */
super_list super_refs_;

/** whether this is a "fuzzy" tag. */
bool fuzzy_;

Expand Down Expand Up @@ -591,10 +595,7 @@ class class_tag
conditions_.insert(conditions_.end(), list.begin(), list.end());
}

/** Copies tags, keys and links of tag to this. */
void append_super(const class_tag& tag, const std::string& super);

/** Expands all "super" copying their data to this. */
/** Expands all "super", storing direct references for easier access. */
void expand(class_tag& root);
};

Expand Down

0 comments on commit 51902b6

Please sign in to comment.