#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