#include "rituals.hpp" #include "ai_debug.hpp" #include "ai.hpp" namespace combat { RitualEngine::RitualEngine(std::string config_path) : $config(config_path) { $profile = $config["profile"]; auto& actions = $config["actions"]; for(auto& ac : actions) { auto action = ai::config_action($profile, ac); $actions.insert_or_assign(action.name, action); } for(auto& [name, sc] : $config["states"].items()) { auto state = ai::config_state($profile, sc); $states.insert_or_assign(name, state); } auto& scripts = $config["scripts"]; for(auto& [script_name, action_names] : scripts.items()) { std::vector the_script; for(auto name : action_names) { the_script.push_back($actions.at(name)); } $scripts.insert_or_assign(script_name, the_script); } } ai::State RitualEngine::load_state(std::string name) { return $states.at(name); } ai::Action RitualEngine::load_action(std::string name) { return $actions.at(name); } RitualAI RitualEngine::start() { auto start = load_state("initial"); auto goal = load_state("final"); return {"actions", start, goal}; } void RitualEngine::set_state(RitualAI& ritual, std::string name, bool setting) { dbc::check($profile.contains(name), fmt::format("ritual action named {} is not in profile, look in {} config", name, $config.$src_path)); ritual.start.set($profile.at(name), setting); } void RitualEngine::reset(RitualAI& ritual) { ritual.start = ritual.original; } void RitualEngine::plan(RitualAI& ritual) { ritual.plan = ai::plan_actions($scripts.at(ritual.script), ritual.start, ritual.goal); } bool RitualAI::will_do(std::string name) { if(plan.script.size() == 0) return false; return plan.script[0].name == name; } ai::Action RitualAI::pop() { auto result = plan.script.front(); plan.script.pop_front(); return result; } // BUG: maybe this should be called RitualBlanket instead? void RitualAI::dump() { ai::dump_script(script, start, plan.script); } bool RitualAI::is_combined() { dbc::check(!plan.script.empty(), "you are attempting to check an empty plan"); auto& last = plan.script.back(); return plan.script.size() > 1 && last.name == "combined"; } RitualAction RitualEngine::finalize(RitualAI& ritual) { (void)ritual; RitualAction result; auto effects = $config["effects"]; for(auto action : ritual.plan.script) { if(effects.contains(action.name)) { auto& effect = effects[action.name]; result.damage += int(effect["damage"]); result.probability *= float(effect["probability"]); if(effect.contains("kind")) result.kind = RitualKind(int(effect["kind"])); if(effect.contains("element")) result.element = RitualElement(int(effect["element"])); } } return result; } void RitualAction::dump() { fmt::print("ritual has damage {}, prob: {}, kind: {}, element: {}; named: ", damage, probability, int(kind), int(element)); for(auto& name : names) { fmt::print("{} ", name); } fmt::println("\n"); } RitualAction& RitualBelt::get(int index) { return equipped.at(index); } void RitualBelt::equip(int index, RitualAction& action) { equipped.insert_or_assign(index, action); } bool RitualBelt::has(int index) { return equipped.contains(index); } void RitualBelt::unequip(int index) { equipped.erase(index); } }