Files
PixelDefense/engine/breeze/ai/behaviour_tree.h

268 lines
7.1 KiB
C

#ifndef BREEZE_BEHAVIOUR_TREE_H
#define BREEZE_BEHAVIOUR_TREE_H
#include "../defines.h"
typedef struct BzBTNode BzBTNode;
typedef enum BzBTStatus {
BZ_BT_RUNNING,
BZ_BT_SUCCESS,
BZ_BT_FAIL,
BZ_BT_ERROR,
} BzBTStatus;
typedef BzBTStatus(*BzBTActionFn)(void *data, f32 dt);
typedef enum BzBTNodeType {
// Composite
BZ_BT_COMP_SELECTOR,
BZ_BT_COMP_SEQUENCE,
BZ_BT_COMP_PSELECTOR,
BZ_BT_COMP_PSEQUENCE,
// Decorator
BZ_BT_DECOR_DUMMY,
BZ_BT_DECOR_SUCCESS,
BZ_BT_DECOR_FAIL,
BZ_BT_DECOR_INVERT,
BZ_BT_DECOR_UNTIL_SUCCESS,
BZ_BT_DECOR_UNTIL_FAIL,
BZ_BT_DECOR_REPEAT,
BZ_BT_DECOR_DELAY,
// Action/Task
BZ_BT_ACTION,
} BzBTNodeType;
typedef struct BzObjectPool BzObjectPool;
typedef struct BzBTNodeState BzBTNodeState;
typedef struct BzBTState {
const BzBTNode *root;
BzBTNodeState *_first;
BzBTNodeState *_last;
BzBTActionFn onSuccess;
BzBTActionFn onFailure;
BzBTActionFn onError;
BzObjectPool *nodeStatePool;
void *userData;
} BzBTState;
typedef struct BzBTStateDesc {
const BzBTNode *root;
BzObjectPool *pool;
void *userData;
} BzBTStateDesc;
/**
* @brief Useful for allocating BzBTNode pools.
* @return size of BzBTNode
*/
size_t bzBTGetNodeSize();
/**
* @brief Useful for allocating BzBTNodeState pools.
* @return size of BzBTNodeState
*/
size_t bzBTGetNodeStateSize();
/**
* @brief Utility function for converting enum type to human readable string.
* @return human-readable node type
*/
const char *bzBTNodeTypeToStr(BzBTNodeType type);
/**
* @brief Starting point of BT.
* @param nodePool pool
* @return allocated node
*/
BzBTNode *bzBTMakeRoot(BzObjectPool *nodePool);
/**
* @brief Recursively cleans up BT.
* @param nodePool pool
* @param node BT root
*/
void bzBTDestroyRoot(BzObjectPool *nodePool, BzBTNode *node);
void bzBTSubTree(BzBTNode *tree, BzBTNode *parent);
/**
* @brief Execute all children in turn until one fails.
*
* Execution is BZ_BT_SUCCESS, if all children are ran successfully.
* Child execution, does not progress unless child finishes (no BZ_BT_RUNNING status).
*
* @param nodePool pool
* @param parent parent of the composite
* @return allocated composite
*/
BzBTNode *bzBTCompSelector(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Execute all children in turn until first one succeeds.
*
* Execution is BZ_BT_FAIL, if no children are ran successfully.
* Child execution is blocking -> it does not progress unless child
* finishes (is not BZ_BT_RUNNING).
*
* @param nodePool pool
* @param parent parent of the composite
* @return allocated composite
*/
BzBTNode *bzBTCompSequence(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Execute all children in turn until one fails.
*
* Execution is BZ_BT_SUCCESS, if all children are ran successfully.
* Children are executed in non-blocking way in the order of BT.
*
* @param nodePool pool
* @param parent parent of the composite
* @return allocated composite
*/
BzBTNode *bzBTCompPSelector(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Execute all children in turn until first one succeeds.
*
* Execution is BZ_BT_FAIL, if no children are ran successfully.
* Children are executed in non-blocking way in the order of BT.
*
* @param nodePool pool
* @param parent parent of the composite
* @return allocated composite
*/
BzBTNode *bzBTCompPSequence(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Returns child status.
*
* Note: Useful when nesting BTs.
*
* @param nodePool pool
* @param parent parent of the decorator
* @return allocated decorator
*/
BzBTNode *bzBTDecorDummy(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Returns BZ_BT_SUCCESS, if no BZ_BT_ERROR occurred.
* @param nodePool pool
* @param parent parent of the decorator
* @return allocated decorator
*/
BzBTNode *bzBTDecorSuccess(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Returns BZ_BT_FAIL, if no BZ_BT_ERROR occurred.
* @param nodePool pool
* @param parent parent of the decorator
* @return allocated decorator
*/
BzBTNode *bzBTDecorFail(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Inverts child result.
*
* Note: Only for BZ_BT_SUCCESS and BZ_BT_FAIL. Other statuses
* are propagated up.
*
* @param nodePool pool
* @param parent parent of the decorator
* @return allocated decorator
*/
BzBTNode *bzBTDecorInvert(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Repeats child execution until it returns BZ_BT_SUCCESS.
*
* Note: BZ_BT_ERROR also causes it to return.
*
* @param nodePool pool
* @param parent parent of the decorator
* @return allocated decorator
*/
BzBTNode *bzBTDecorUntilSuccess(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Repeats child execution until it returns BZ_BT_FAIL.
*
* Note: BZ_BT_ERROR also causes it to return.
*
* @param nodePool pool
* @param parent parent of the decorator
* @return allocated decorator
*/
BzBTNode *bzBTDecorUntilFail(BzObjectPool *nodePool, BzBTNode *parent);
/**
* @brief Repeats child execution n-times.
* @param nodePool pool
* @param parent parent of the decorator
* @param n number of repeats
* @return allocated decorator
*/
BzBTNode *bzBTDecorRepeat(BzObjectPool *nodePool, BzBTNode *parent, i32 n);
/**
* @brief Delays child/sibling execution for specified ms.
*
* Note: for this to properly work, correct dt must be passed
* in when executing BT.
*
* @param nodePool pool
* @param parent parent of the decorator
* @param ms milliseconds to wait
* @return allocated decorator
*/
BzBTNode *bzBTDecorDelay(BzObjectPool *nodePool, BzBTNode *parent, f32 ms);
/**
* @brief Creates BT task.
* @param nodePool pool
* @param parent parent of the task
* @param fn function pointer for the task
* @return allocated action
*/
BzBTNode *bzBTAction(BzObjectPool *nodePool, BzBTNode *parent, BzBTActionFn fn);
// Reflection data
void bzBTNodeSetName(BzBTNode *node, const char *name);
const char *bzBTNodeGetName(const BzBTNode *node);
i32 bzBTDecorGetRepeat(const BzBTNode *node);
f32 bzBTDecorGetDelay(const BzBTNode *node);
BzBTActionFn bzBTActionGetFn(const BzBTNode *node);
BzBTNodeType bzBTGetNodeType(const BzBTNode *node);
BzBTNode *bzBTNodeChild(const BzBTNode *node);
BzBTNode *bzBTNodeNext(const BzBTNode *node);
const BzBTNode *bzBTNodeStateGetNode(const BzBTNodeState *state);
const BzBTNodeState *bzBTNodeStateNext(const BzBTNodeState *state);
bool bzBTNodeMatchesState(const BzBTNode *node, const BzBTNodeState *state);
BzBTNode *bzBTCompStateGetRunningChild(const BzBTNodeState *state);
i32 bzBTRepeatStateGetIter(const BzBTNodeState *state);
f32 bzBTDelayStateGetElapsed(const BzBTNodeState *state);
/**
* @brief Creates state for a given BT.
* @param desc input parameters
* @return BT state
*/
BzBTState bzBTCreateState(const BzBTStateDesc *desc);
/**
* @brief Cleans up state (does not modify BT).
* @param state state to clean up
*/
void bzBTDestroyState(BzBTState *state);
/**
* @brief Tick behaviour tree.
* @param state state of the behaviour tree
* @param dt delta time
* @return status of BT tick
*/
BzBTStatus bzBTExecute(BzBTState *state, f32 dt);
#endif //BREEZE_BEHAVIOUR_TREE_H