diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a3de0d1..53d1411 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,4 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) +add_executable(main1 main1.cpp) + diff --git a/src/main1.cpp b/src/main1.cpp index 82c7cab..9025d16 100644 --- a/src/main1.cpp +++ b/src/main1.cpp @@ -1,5 +1,166 @@ +// this is a naive-ish implementation +// this is not pure naive, since it implements the less-branch Criterion compare variant discussed in the valve talk + +#include +#include +#include +#include +#include + +#include + +// context aka, kv-dict + +// criterion, predicate that returns true or false based on state and context(query) +// equal: value == min == max +// smaller: value == max -e; min == -inf +// greater: value == min +e; max == +inf +struct Criterion { + std::string key; + float min, max; + + bool compare(const float x) const { + return x >= min && x <= max; + } + + bool operator<(const Criterion& other) const { + return key < other.key && min < other.min && max < other.max; + } +}; + +// rule, list of criterions (obv &&) +struct Rules { + std::set crits; +}; + +// query, ...? +struct Query { + // sorted? + std::map dict; + + Query& add(const std::string& key, float value) { + dict[key] = value; + return *this; + } + + Query& add(const std::string& key, const std::string& value) { + // lol + dict[key] = std::hash{}(value); + return *this; + } + + bool match_criterion(const Criterion& crit) const { + return dict.count(crit.key) && crit.compare(dict.at(crit.key)); + } + + bool match_rules(const Rules& rules) const { + for (const auto& crit : rules.crits) { + if (!match_criterion(crit)) { + return false; + } + } + + return true; + } +}; + +// response -> action (list?) +struct Response { + Rules rules; + + std::function f; +}; + +// special keys (usually bucketalbe): +// - concept: onHit, onIdle, onResponse, onObject? +// - "who": which char talked. gonna name this differently + +struct ResponseDB { +}; int main(void) { + std::map reverse_string_map; + reverse_string_map[std::hash{}("who")] = "who"; + + // crit test + + Criterion hp_not_critical { + "hp", + // have at least 15% of max hp + 0.15f, + std::numeric_limits::infinity() + }; + + assert(hp_not_critical.compare(0.0f) == false); + assert(hp_not_critical.compare(0.15f) == true); + assert(hp_not_critical.compare(0.15f - std::numeric_limits::epsilon()) == false); + assert(hp_not_critical.compare(1.0f) == true); + + Criterion is_hero { + "who", + // tmp + 0.f, 0.f + }; + // key "who" is value "hero" + is_hero.min = std::hash{}("hero"); + is_hero.max = std::hash{}("hero"); + + assert(is_hero.compare(std::hash{}("hero")) == true); + assert(is_hero.compare(std::hash{}("enemy")) == false); + assert(is_hero.compare(std::hash{}("ally")) == false); + + Criterion on_idle { + "concept", + // tmp + 0.f, 0.f + }; + // key "concept" is value "idle" + on_idle.min = std::hash{}("idle"); + on_idle.max = std::hash{}("idle"); + + assert(on_idle.compare(std::hash{}("idle")) == true); + assert(on_idle.compare(std::hash{}("hero")) == false); + assert(on_idle.compare(std::hash{}("hit")) == false); + + Rules rules_hero_idle_chatter {{ + on_idle, is_hero, hp_not_critical + }}; + + // query test + + Query q1{}; + q1 + .add("concept", "idle") + .add("who", "hero") + .add("hp", 0.843122f) + .add("ally_near", 1.f) + .add("enemy_near", 0.f) + .add("in_danger", 0.f) + ; + + Query q2{}; + q2 + .add("concept", "hit") + .add("who", "enemy") + .add("hp", 0.12333f) + .add("ally_near", 0.f) + .add("enemy_near", 1.f) + .add("in_danger", 1.f) + ; + + // add junk to q2 + for (int i = 0; i < 10000; i++) { + q2.add(std::to_string(i) + "asdf", (i - 155) * 12399.3249f); + } + + assert(q1.match_criterion(hp_not_critical) == true); + assert(q1.match_criterion(is_hero) == true); + + assert(q2.match_criterion(hp_not_critical) == false); + assert(q2.match_criterion(is_hero) == false); + + assert(q1.match_rules(rules_hero_idle_chatter) == true); + assert(q2.match_rules(rules_hero_idle_chatter) == false); return 0; }