From 61d16477b01bcfbe8c3a481a232658ac60309f57 Mon Sep 17 00:00:00 2001 From: Aki Date: Thu, 27 Apr 2023 00:36:46 +0200 Subject: Extracted KeepAtRange action It seems an abstraction level is of some kind is needed here. One thing to handle "AI", another to handle primitive commands and their execution. --- kurator/src/inspect.cpp | 2 +- sim/include/kurator/sim/ai.h | 9 +++++- sim/src/BaseSimulation.cpp | 2 +- sim/src/Builder.cpp | 2 +- sim/src/ai.cpp | 69 +++++++++++++++++++++++++++++++++++++++----- sim/src/ai.h | 2 +- sim/src/sim.cpp | 6 +--- 7 files changed, 74 insertions(+), 18 deletions(-) diff --git a/kurator/src/inspect.cpp b/kurator/src/inspect.cpp index 38f5394..ab52bb8 100644 --- a/kurator/src/inspect.cpp +++ b/kurator/src/inspect.cpp @@ -178,7 +178,7 @@ template <> void inspect(entt::handle&, sim::AIShip& ai) { - ImGui::InputDouble("Keep At Range", &ai.keep_at_range, 0, 0, "%.1f"); + ImGui::Text("Nothing to inspect in AIShip for now"); } diff --git a/sim/include/kurator/sim/ai.h b/sim/include/kurator/sim/ai.h index f9899d6..0ffa1cc 100644 --- a/sim/include/kurator/sim/ai.h +++ b/sim/include/kurator/sim/ai.h @@ -1,9 +1,13 @@ #pragma once +#include + #include #include +#include "State.h" + namespace kurator { @@ -11,9 +15,12 @@ namespace sim { +using Action = std::function; + + struct AIShip { - double keep_at_range; + Action action; engine::Point destination; entt::entity target = entt::null; }; diff --git a/sim/src/BaseSimulation.cpp b/sim/src/BaseSimulation.cpp index b1add54..2731c67 100644 --- a/sim/src/BaseSimulation.cpp +++ b/sim/src/BaseSimulation.cpp @@ -24,7 +24,7 @@ void BaseSimulation::operator()(State& ctx) { pick_random_targets(ctx, manager); - keep_at_range(ctx); + take_actions(ctx); FloatingMovement::update(ctx); update_turrets(ctx); shoot_at_targets(ctx); diff --git a/sim/src/Builder.cpp b/sim/src/Builder.cpp index 4cf0bc6..2b2bd24 100644 --- a/sim/src/Builder.cpp +++ b/sim/src/Builder.cpp @@ -42,7 +42,7 @@ Builder::operator()(const universe::ShipType& ship_type, const int team) const ship_type.max_speed, ship_type.max_speed * 2.0, ship_type.max_speed * 3.0); - registry.emplace(entity, 15000.0, Point{0.0, 0.0}); + registry.emplace(entity); registry.emplace(entity, ship_type); return entity; } diff --git a/sim/src/ai.cpp b/sim/src/ai.cpp index 1f2a4ec..7a0f637 100644 --- a/sim/src/ai.cpp +++ b/sim/src/ai.cpp @@ -1,5 +1,10 @@ #include "ai.h" +#include +#include + +#include + #include #include #include @@ -13,6 +18,42 @@ namespace sim { +static double find_worst_range(State& ctx, entt::entity ship); + + +class KeepAtRange +{ +public: + KeepAtRange(State& ctx_, AIShip& ai_, entt::entity self_, entt::entity target_, double distance_) : + ctx {ctx_}, + ai {ai_}, + self {std::move(self_)}, + target {std::move(target_)}, + distance {distance_} + { + } + + void operator()() + { + if (!ctx.registry.valid(target)) { + if (ctx.registry.valid(ai.target)) + ai.action = KeepAtRange(ctx, ai, self, ai.target, distance); + return; + } + const auto here = ctx.registry.get(self).position; + const auto there = ctx.registry.get(target).position; + const auto offset = there - here; + ai.destination = there - offset.normalized().scale(distance); + } +private: + State& ctx; + AIShip& ai; + entt::entity self; + entt::entity target; + double distance; +}; + + void pick_random_targets(State& ctx, TeamManager& manager) { @@ -20,20 +61,19 @@ pick_random_targets(State& ctx, TeamManager& manager) for (auto&& [entity, team, ai] : view.each()) { if (!ctx.registry.valid(ai.target)) ai.target = manager.random(team.id); + if (!ai.action) + ai.action = KeepAtRange(ctx, ai, entity, ai.target, find_worst_range(ctx, entity)); } } void -keep_at_range(State& ctx) +take_actions(State& ctx) { - auto view = ctx.registry.view(); - for (auto&& [entity, self, ai] : view.each()) { - if (!ctx.registry.valid(ai.target)) - continue; - const auto target = ctx.registry.get(ai.target); - const auto offset = target.position - self.position; - ai.destination = target.position - offset.normalized().scale(ai.keep_at_range); + auto view = ctx.registry.view(); + for (auto&& [_, ai] : view.each()) { + if (ai.action) + ai.action(); } } @@ -56,5 +96,18 @@ shoot_at_targets(State& ctx) } +double +find_worst_range(State& ctx, entt::entity ship) +{ + double range = 20000.0; + auto turrets = ctx.registry.view(); + for (const auto& [_, turret] : turrets.each()) { + if (turret.owner == ship) + range = std::min(range, turret.type.optimal_range); + } + return range; +} + + } // namespace sim } // namespace kurator diff --git a/sim/src/ai.h b/sim/src/ai.h index 9173891..d1e9c29 100644 --- a/sim/src/ai.h +++ b/sim/src/ai.h @@ -13,7 +13,7 @@ namespace sim void pick_random_targets(State& ctx, TeamManager& manager); -void keep_at_range(State& ctx); +void take_actions(State& ctx); void shoot_at_targets(State& ctx); diff --git a/sim/src/sim.cpp b/sim/src/sim.cpp index 740e6af..879f7fb 100644 --- a/sim/src/sim.cpp +++ b/sim/src/sim.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include #include @@ -26,11 +25,8 @@ load_scenario(const campaign::Scenario& scenario) for (const auto& ship : scenario.ships) { const auto entity = build(ship.loadout.type, ship.team); ctx.registry.emplace(entity, ship.identifier); - auto& state = ctx.registry.get(entity); - for (const auto& turret_type : ship.loadout.turrets) { + for (const auto& turret_type : ship.loadout.turrets) build(turret_type, entity); - state.keep_at_range = std::min(state.keep_at_range, turret_type.optimal_range); - } } return ctx; } -- cgit v1.1