#pragma once // Rhiannon facade and ANI attach points. #include "agents/two_way_engine.hpp" #include namespace agents { struct ANI { virtual void tick(const std::vector& z, double e) = 0; virtual ~ANI() = default; }; class Rhiannon { public: explicit Rhiannon(TwoWayEngine::Cfg cfg = {}) : engine_(cfg), last_z_(cfg.dim, 0.0f) {} void set_input(std::span x) { engine_.set_target(x); } void attach_ani(std::unique_ptr ani) { anis_.push_back(std::move(ani)); } void tick() { engine_.step(); last_z_ = engine_.behavior(); const double e = engine_.error(); for (auto& ani : anis_) ani->tick(last_z_, e); // Simple damping example if needed for consumers (does not mutate engine) if (e > 0.1) { for (auto& v : last_z_) v *= 0.99f; } } const std::vector& state_z() const { return last_z_; } double state_e() const { return engine_.error(); } private: TwoWayEngine engine_; std::vector last_z_{}; std::vector> anis_{}; }; } // namespace agents