Threads and tasks

This commit is contained in:
2026-01-29 15:28:50 +03:00
parent 4cf0ea5321
commit da4c1fee0e
21 changed files with 1464 additions and 558 deletions

View File

@@ -1,77 +1,35 @@
#ifndef H_GOAP_H_
#define H_GOAP_H_
#undef NDEBUG
#include <string>
#include <memory>
#include <set>
#include <flecs.h>
namespace ECS
#include <Ogre.h>
namespace goap
{
struct Blackboard;
}
struct BaseAction;
struct BaseActionExec;
namespace ECS
{
struct Blackboard {
enum {
HIGH_LUST = (1 << 0),
LOW_LUST = (1 << 1),
FULL_LUST = (1 << 2),
LOW_HEALTH = (1 << 3),
FULL_HEALTH = (1 << 4),
HAS_TARGET = (1 << 5),
LOW_STAMINA = (1 << 6),
FULL_STAMINA = (1 << 7),
REACHED_TARGET = (1 << 8),
};
flecs::entity me;
int health;
int stamina;
int lust;
uint32_t flags;
std::set<BaseActionExec *> _active;
bool operator==(const Blackboard &other)
{
return flags == other.flags;
}
void set_flag(int flag)
{
flags |= flag;
}
void clear_flag(int flag)
{
flags &= ~flag;
}
bool get_flag(int flag) const
{
return flags & flag;
}
bool check_flag(int flag) const
{
return (flags & flag) == flag;
}
};
}
struct BaseAction {
template <typename State> struct BaseAction {
std::string m_name;
State prereq;
State effects;
int m_cost;
public:
enum { OK = 0, BUSY, ABORT };
private:
std::unique_ptr<BaseActionExec> m_exec;
public:
BaseAction(const std::string &name, BaseActionExec *exec)
: m_name(name)
, m_exec(exec)
BaseAction(const std::string &name, const State &prereq, const State &effects, int cost)
: m_name(name)
, prereq(prereq)
, effects(effects)
, m_cost(cost)
{
}
const std::string &get_name() const
virtual const std::string &get_name() const
{
return m_name;
}
void plan_effects(ECS::Blackboard &state)
void plan_effects(State &state)
{
// std::cout << m_name << " pre: " << &state << " " << state.flags
// << std::endl;
@@ -79,42 +37,20 @@ public:
// std::cout << m_name << " post: " << &state << " " << state.flags
// << std::endl;
}
virtual bool can_run(const ECS::Blackboard &state, bool debug = false);
virtual void _plan_effects(ECS::Blackboard &state);
bool is_active(const ECS::Blackboard &state);
bool stop(ECS::Blackboard &state);
int execute(ECS::Blackboard &state);
virtual int get_cost(const ECS::Blackboard &state) const;
virtual bool can_run(const State &state, bool debug = false)
{
return state.distance_to(prereq) == 0;
}
virtual void _plan_effects(State &state)
{
state.apply(effects);
}
// constant cost
virtual int get_cost(const State &state) const
{
return m_cost;
}
};
struct BaseActionExec {
enum {
OK = BaseAction::OK,
BUSY = BaseAction::BUSY,
ABORT = BaseAction::ABORT
};
BaseActionExec(int set_bits, int clear_bits)
: m_set_bits(set_bits)
, m_clear_bits(clear_bits)
{
}
bool is_active(const ECS::Blackboard &state)
{
return state._active.find(this) != state._active.end();
}
virtual int _execute(ECS::Blackboard &state) = 0;
virtual void _enter(ECS::Blackboard &state) = 0;
virtual void _exit(ECS::Blackboard &state) = 0;
virtual int _get_cost(const ECS::Blackboard &state) const
{
return 1;
}
virtual bool _can_run(const ECS::Blackboard &state, bool debug = false)
{
return true;
}
int m_set_bits, m_clear_bits;
};
template <typename State, typename Act, int N = 100> class BasePlanner {
struct VisitedState {
int priority;
@@ -190,20 +126,24 @@ template <typename State, typename Act, int N = 100> class BasePlanner {
public:
struct BaseGoal {
std::string m_name;
State goal;
public:
BaseGoal(const std::string &name)
: m_name(name)
BaseGoal(const std::string &name, const State &goal)
: m_name(name), goal(goal)
{
}
/** Checks if the goal is reached for the given state. */
virtual bool is_reached(const State &state) const
{
return distance_to(state) == 0;
return distance_to(state) == 0;
}
/** Computes the distance from state to goal. */
virtual int distance_to(const State &state) const = 0;
virtual int distance_to(const State &state) const
{
return state.distance_to(goal);
}
virtual ~BaseGoal() = default;
const std::string &get_name() const
@@ -216,7 +156,7 @@ public:
*
* If path is given, then the found path is stored there.
*/
int plan(const State &state, BaseGoal &goal, Act *actions[],
int plan(const State &state, const BaseGoal &goal, Act *actions[],
unsigned action_count, Act **path = nullptr, int path_len = 10)
{
visited_states_array_to_list(nodes, N);
@@ -244,7 +184,8 @@ public:
}
if (len > path_len) {
return -1;
OgreAssert(len <= path_len, "Out of plan length");
return -3;
}
if (path) {
@@ -255,6 +196,7 @@ public:
}
}
OgreAssert(len >= 0, "Bad plan length");
return len;
}
@@ -274,6 +216,7 @@ public:
}
if (!gc) {
OgreAssert(gc, "Out of memory");
return -2 /* OOM */;
}
@@ -337,14 +280,16 @@ public:
return -1 /* No path */;
}
};
template <class RunnerType> struct DeclareAction : public BaseAction {
template <class RunnerType, class State>
struct DeclareAction : public BaseAction<State> {
RunnerType runner;
template <class... Args>
DeclareAction(const std::string &name, Args... args)
: runner(args...)
, BaseAction(name, &runner)
, BaseAction<State>(name, &runner)
{
}
};
}
#endif