#include "rituals.hpp" #include "ai_debug.hpp" #include "ai.hpp" namespace combat { void BattleEngine::add_enemy(DinkyECS::Entity enemy_id, ai::EntityAI& enemy) { combatants.insert_or_assign(enemy_id, enemy); } bool BattleEngine::plan() { int active = 0; for(auto& [entity, enemy_ai] : combatants) { enemy_ai.set_state("enemy_found", true); enemy_ai.set_state("in_combat", true); enemy_ai.update(); active += enemy_ai.active(); } return active > 0; } void BattleEngine::fight(std::function cb) { for(auto& [entity, enemy_ai] : combatants) { if(enemy_ai.wants_to("kill_enemy")) { cb(entity, enemy_ai); } else if(!enemy_ai.active()) { enemy_ai.dump(); dbc::sentinel("enemy AI ended early, fix your ai.json"); } else { dbc::log("enemy doesn't want to fight"); enemy_ai.dump(); } } } void BattleEngine::dump() { for(auto& [entity, enemy_ai] : combatants) { fmt::println("\n\n###### ENTITY #{}", entity); enemy_ai.dump(); } } 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) { 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; } void RitualAI::dump() { ai::dump_script(script, start, plan.script); } }