载入中...
搜索中...
未找到
RuleEngine.cpp
浏览该文件的文档.
24bool exactFields(const eve::Value::Object& object, std::initializer_list<std::string_view> allowed) {
36 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "value must be an integer", path ? path : "", {}, "emergence.rule_engine"));
47 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "integer out of int range", path ? path : "", {}, "emergence.rule_engine"));
56 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "value must be non-negative", path ? path : "", {}, "emergence.rule_engine"));
65 eve::DiagnosticCode::InvalidArgument, "rule id must be non-empty", "id", {}, "emergence.rule_engine"));
67 return eve::Result<RuleDefinition>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument,
82 rule.watchKeys.erase(std::unique(rule.watchKeys.begin(), rule.watchKeys.end()), rule.watchKeys.end());
89 return eve::Result<RuleDefinition>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument,
97 return eve::Result<int>::failure(eve::Diagnostic::error(eve::DiagnosticCode::PreconditionViolation,
122 return eve::Result<int>::success(static_cast<int>(rules_.size()), eve::Status::success(eve::StatusCode::Applied));
131 eve::DiagnosticCode::InvalidArgument, "rules document must be an object", {}, {}, "emergence.rule_engine"));
136 eve::DiagnosticCode::InvalidArgument, "unexpected rules schema", "schema", {}, "emergence.rule_engine"));
139 eve::DiagnosticCode::UnknownVersion, "unsupported rules version", "version", {}, "emergence.rule_engine"));
141 const auto* rulesArray = rulesValue == nullptr ? nullptr : rulesValue->getIf<eve::Value::Array>();
144 eve::DiagnosticCode::InvalidArgument, "rules must be an array", "rules", {}, "emergence.rule_engine"));
209 eve::DiagnosticCode::InvalidArgument, "watch key must be a non-empty string", "rules.watchKeys",
255bool RuleEngine::contains(std::string_view ruleId) const { return idToIndex_.contains(std::string(ruleId)); }
272 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "value key must be non-empty", "key", {}, "emergence.rule_engine"));
281 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "tag must be non-empty", "tag", {}, "emergence.rule_engine"));
290 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "attribute key must be non-empty", "key", {}, "emergence.rule_engine"));
299 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "resource key must be non-empty", "key", {}, "emergence.rule_engine"));
308 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "state key must be non-empty", "key", {}, "emergence.rule_engine"));
318 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "authority scope must be non-empty", "scope", {}, "emergence.rule_engine"));
327 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "policy name must be non-empty", "name", {}, "emergence.rule_engine"));
329 const bool changed = facts_.setPolicy(std::move(name), std::move(result)) == FactChange::Changed;
335eve::Result<void> RuleEngine::executeOne(const EmergenceAction& action, std::uint64_t /*tick*/) {
340 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "fact.set args must be an object", "args", {}, "emergence.rule_engine"));
344 if (domain == nullptr || !domain->isString() || key == nullptr || !key->isString() || value == nullptr)
346 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "fact.set requires domain, key, value", "args", {}, "emergence.rule_engine"));
353 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "tag value must be bool", "value", {}, "emergence.rule_engine"));
354 return setTag(keyText, value->asBool()).andThen([](bool) { return eve::Result<void>::success(); });
357 return setAttribute(keyText, *value).andThen([](bool) { return eve::Result<void>::success(); });
365 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "authority value must be bool", "value", {}, "emergence.rule_engine"));
366 return setAuthority(keyText, value->asBool()).andThen([](bool) { return eve::Result<void>::success(); });
369 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "unknown fact.set domain", "domain", {}, "emergence.rule_engine"));
375 eve::Diagnostic::error(eve::DiagnosticCode::PreconditionViolation, "IEconomy provider is absent", action.kind.c_str() ? action.kind.c_str() : "", {}, "emergence.rule_engine"));
379 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "economy action args must be an object", "args", {}, "emergence.rule_engine"));
385 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "economy action requires player, type, amount", "args", {}, "emergence.rule_engine"));
391 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "amount must be non-negative", "amount", {}, "emergence.rule_engine"));
398 eve::Diagnostic::error(eve::DiagnosticCode::Conflict, "economy debit rejected", "amount", {}, "emergence.rule_engine"));
424eve::Result<void> RuleEngine::executeActions(const std::vector<EmergenceAction>& actions, std::uint64_t tick) {
434 return eve::Result<int>::failure(eve::Diagnostic::error(eve::DiagnosticCode::PreconditionViolation,
461 if (rules_[left].priority != rules_[right].priority) return rules_[left].priority > rules_[right].priority;
514 return eve::Result<int>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvariantViolation,
518 produced, eve::Status::success(produced > 0 ? eve::StatusCode::Applied : eve::StatusCode::NoOp));
531 eve::Diagnostic::error(eve::DiagnosticCode::NotFound, "rule id not found", "ruleId", {}, "emergence.rule_engine"));
567 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "runtime snapshot must be an object", "", {}, "emergence.rule_engine"));
570 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "runtime snapshot contains an unknown field", "", {}, "emergence.rule_engine"));
575 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "unexpected runtime schema", "schema", {}, "emergence.rule_engine"));
578 eve::Diagnostic::error(eve::DiagnosticCode::UnknownVersion, "unsupported runtime version", "version", {}, "emergence.rule_engine"));
583 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "runtime snapshot requires facts", "facts", {}, "emergence.rule_engine"));
586 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "runtime snapshot requires rules", "rules", {}, "emergence.rule_engine"));
599 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "rules must be an array", "rules", {}, "emergence.rule_engine"));
604 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "rule latch must be an object", "", {}, "emergence.rule_engine"));
607 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "rule latch contains an unknown field", "", {}, "emergence.rule_engine"));
611 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "rule latch requires id", "id", {}, "emergence.rule_engine"));
614 eve::Diagnostic::error(eve::DiagnosticCode::AlreadyExists, "duplicate rule latch id", "id", {}, "emergence.rule_engine"));
618 eve::Diagnostic::error(eve::DiagnosticCode::NotFound, "runtime rule id missing from catalogue", "id", {}, "emergence.rule_engine"));
626 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "passed must be bool", "passed", {}, "emergence.rule_engine"));
629 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "fired must be bool", "fired", {}, "emergence.rule_engine"));
632 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "disabled must be bool", "disabled", {}, "emergence.rule_engine"));
635 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "cooldownUntil is required", "cooldownUntil", {}, "emergence.rule_engine"));
645 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "runtime snapshot must include every catalogue rule", "rules", {}, "emergence.rule_engine"));
Value/JSON codec for decision::Condition trees owned by emergence rules.
Derive inverted-index watch keys from a decision::Condition AST.
Stable, structured diagnostics shared by engine modules.
Optional multi-listener sink for emergence rule actions outside built-ins.
High-performance indexed rule engine for emergent gameplay triggers.
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Capability listener that may consume one emergence action kind.
Definition IEmergenceActionHandler.h:27
auto andThen(Function &&function) &&-> std::invoke_result_t< Function, T && >
Compose a successful value with a function returning another Result.
Definition Result.h:365
bool ok() const noexcept
Whether this result represents a non-failure outcome.
Definition Result.h:255
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Result< std::string > toJson() const
Serialize this value as deterministic compact JSON.
Definition Value.cpp:67
static Result< Value > fromJson(std::string_view json)
Parse one strict JSON value into an owning Value.
Definition Value.cpp:57
Value * find(const std::string &key) noexcept
Return an object member, or nullptr when absent.
Definition Value.cpp:124
Explain one condition evaluation in a UI- and log-friendly form.
Definition Condition.h:129
Mutable fact bag that doubles as a read-only Condition evaluation context.
Definition FactStore.h:60
eve::Result< void > restoreJson(std::string_view json)
Transactionally restore facts from a snapshot produced by snapshotJson().
Definition FactStore.cpp:282
Dense, sorted multi-map used to wake O(watchers) rules on a fact change.
Definition WatchIndex.h:23
Definition ConditionCodec.cpp:10
eve::Result< std::vector< std::string > > collectWatchKeys(const decision::Condition &condition)
Collect the canonical fact keys a condition depends on.
Definition ConditionWatch.cpp:81
eve::Result< std::pair< FactDomain, std::string > > parseFactKey(std::string_view key)
Parse a canonical watch key into domain and leaf name.
Definition FactStore.cpp:113
std::string makeFactKey(FactDomain domain, std::string_view name)
Build the canonical watch key for one fact domain.
Definition FactStore.cpp:106
eve::Result< decision::Condition > decodeCondition(const eve::Value &value)
Decode one validated condition tree from an owning Value.
Definition ConditionCodec.cpp:257
@ InvalidArgument
@ NotFound
@ UnknownVersion
@ PreconditionViolation
@ AlreadyExists
@ InvariantViolation
@ Conflict
@ NoOp
@ Applied
One deferred side-effect descriptor; domains interpret kind.
Definition RuleTypes.h:27
One immutable rule definition owned by the catalogue.
Definition RuleTypes.h:38
std::vector< std::string > watchKeys
Definition RuleTypes.h:45
std::vector< EmergenceAction > actions
Definition RuleTypes.h:46