Remove AI prefix from behaviour_tree
This commit is contained in:
@@ -5,16 +5,16 @@
|
||||
|
||||
//#define GET_NODE(idx) ((BzAIBTNode *) bzObjectPoolGetObject(bt->nodePool, idx))
|
||||
|
||||
struct BzAIBTNode {
|
||||
BzAIBTNode *parent;
|
||||
struct BzBTNode {
|
||||
BzBTNode *parent;
|
||||
// Children
|
||||
BzAIBTNode *first;
|
||||
BzAIBTNode *last;
|
||||
BzBTNode *first;
|
||||
BzBTNode *last;
|
||||
// Siblings
|
||||
BzAIBTNode *prev;
|
||||
BzAIBTNode *next;
|
||||
BzBTNode *prev;
|
||||
BzBTNode *next;
|
||||
|
||||
BzAIBTNodeType type;
|
||||
BzBTNodeType type;
|
||||
union {
|
||||
struct {
|
||||
i32 n;
|
||||
@@ -23,21 +23,21 @@ struct BzAIBTNode {
|
||||
f32 ms;
|
||||
} delay;
|
||||
struct {
|
||||
BzAIBTActionFn fn;
|
||||
BzBTActionFn fn;
|
||||
const char *name;
|
||||
} action;
|
||||
} as;
|
||||
|
||||
};
|
||||
|
||||
struct BzAIBTNodeState {
|
||||
const BzAIBTNode *node;
|
||||
BzAIBTNodeState *next;
|
||||
BzAIBTNodeState *prev;
|
||||
struct BzBTNodeState {
|
||||
const BzBTNode *node;
|
||||
BzBTNodeState *next;
|
||||
BzBTNodeState *prev;
|
||||
|
||||
union {
|
||||
struct {
|
||||
BzAIBTNode *running;
|
||||
BzBTNode *running;
|
||||
} composite;
|
||||
struct {
|
||||
i32 iter;
|
||||
@@ -49,48 +49,48 @@ struct BzAIBTNodeState {
|
||||
};
|
||||
|
||||
|
||||
size_t bzAIBTGetNodeSize() {
|
||||
return sizeof(BzAIBTNode);
|
||||
size_t bzBTGetNodeSize() {
|
||||
return sizeof(BzBTNode);
|
||||
}
|
||||
size_t bzAIBTGetNodeStateSize() {
|
||||
return sizeof(BzAIBTNodeState);
|
||||
size_t bzBTGetNodeStateSize() {
|
||||
return sizeof(BzBTNodeState);
|
||||
}
|
||||
|
||||
const char *bzAIBTNodeTypeToStr(BzAIBTNodeType type) {
|
||||
const char *bzBTNodeTypeToStr(BzBTNodeType type) {
|
||||
switch (type) {
|
||||
case BZ_AIBT_COMP_SELECTOR:
|
||||
case BZ_BT_COMP_SELECTOR:
|
||||
return "SELECTOR";
|
||||
case BZ_AIBT_COMP_SEQUENCE:
|
||||
case BZ_BT_COMP_SEQUENCE:
|
||||
return "SEQUENCE";
|
||||
case BZ_AIBT_COMP_PARALLEL_SELECTOR:
|
||||
case BZ_BT_COMP_PARALLEL_SELECTOR:
|
||||
return "PARALLEL_SELECTOR";
|
||||
case BZ_AIBT_COMP_PARALLEL_SEQUENCE:
|
||||
case BZ_BT_COMP_PARALLEL_SEQUENCE:
|
||||
return "PARALLEL_SEQUENCE";
|
||||
case BZ_AIBT_DECOR_DUMMY:
|
||||
case BZ_BT_DECOR_DUMMY:
|
||||
return "DUMMY";
|
||||
case BZ_AIBT_DECOR_SUCCESS:
|
||||
case BZ_BT_DECOR_SUCCESS:
|
||||
return "SUCCESS";
|
||||
case BZ_AIBT_DECOR_FAIL:
|
||||
case BZ_BT_DECOR_FAIL:
|
||||
return "FAIL";
|
||||
case BZ_AIBT_DECOR_INVERT:
|
||||
case BZ_BT_DECOR_INVERT:
|
||||
return "INVERT";
|
||||
case BZ_AIBT_DECOR_UNTIL_SUCCESS:
|
||||
case BZ_BT_DECOR_UNTIL_SUCCESS:
|
||||
return "UNTIL_SUCCESS";
|
||||
case BZ_AIBT_DECOR_UNTIL_FAIL:
|
||||
case BZ_BT_DECOR_UNTIL_FAIL:
|
||||
return "UNTIL_FAIL";
|
||||
case BZ_AIBT_DECOR_REPEAT:
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
return "REPEAT";
|
||||
case BZ_AIBT_DECOR_DELAY:
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
return "DELAY";
|
||||
case BZ_AIBT_ACTION:
|
||||
case BZ_BT_ACTION:
|
||||
return "ACTION";
|
||||
}
|
||||
}
|
||||
|
||||
static BzAIBTNode *bzAIBTNodeMake(BzObjectPool *nodePool, BzAIBTNode *parent, BzAIBTNodeType type) {
|
||||
static BzBTNode *bzBTNodeMake(BzObjectPool *nodePool, BzBTNode *parent, BzBTNodeType type) {
|
||||
BZ_ASSERT(nodePool);
|
||||
BZ_ASSERT(bzObjectPoolGetObjectSize(nodePool) == bzAIBTGetNodeSize());
|
||||
BzAIBTNode *node = bzObjectPool(nodePool);
|
||||
BZ_ASSERT(bzObjectPoolGetObjectSize(nodePool) == bzBTGetNodeSize());
|
||||
BzBTNode *node = bzObjectPool(nodePool);
|
||||
bzMemSet(node, 0, sizeof(*node));
|
||||
|
||||
node->type = type;
|
||||
@@ -108,123 +108,123 @@ static BzAIBTNode *bzAIBTNodeMake(BzObjectPool *nodePool, BzAIBTNode *parent, Bz
|
||||
return node;
|
||||
}
|
||||
|
||||
BzAIBTNode *bzAIBTMakeRoot(BzObjectPool *nodePool) {
|
||||
return bzAIBTNodeMake(nodePool, NULL, BZ_AIBT_DECOR_DUMMY);
|
||||
BzBTNode *bzBTMakeRoot(BzObjectPool *nodePool) {
|
||||
return bzBTNodeMake(nodePool, NULL, BZ_BT_DECOR_DUMMY);
|
||||
}
|
||||
|
||||
void bzAIBTDestroyRoot(BzObjectPool *nodePool, BzAIBTNode *node) {
|
||||
void bzBTDestroyRoot(BzObjectPool *nodePool, BzBTNode *node) {
|
||||
BZ_ASSERT(node);
|
||||
BzAIBTNode *pNode = node;
|
||||
BzBTNode *pNode = node;
|
||||
|
||||
while (pNode) {
|
||||
BzAIBTNode *next = pNode->next;
|
||||
bzAIBTDestroyRoot(nodePool, pNode);
|
||||
BzBTNode *next = pNode->next;
|
||||
bzBTDestroyRoot(nodePool, pNode);
|
||||
pNode = next;
|
||||
}
|
||||
|
||||
bzObjectPoolRelease(nodePool, node);
|
||||
}
|
||||
|
||||
BzAIBTNode *bzAIBTCompSelector(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel) {
|
||||
BzAIBTNodeType type = parallel ?
|
||||
BZ_AIBT_COMP_PARALLEL_SELECTOR :
|
||||
BZ_AIBT_COMP_SELECTOR;
|
||||
return bzAIBTNodeMake(nodePool, parent, type);
|
||||
BzBTNode *bzBTCompSelector(BzObjectPool *nodePool, BzBTNode *parent, bool parallel) {
|
||||
BzBTNodeType type = parallel ?
|
||||
BZ_BT_COMP_PARALLEL_SELECTOR :
|
||||
BZ_BT_COMP_SELECTOR;
|
||||
return bzBTNodeMake(nodePool, parent, type);
|
||||
}
|
||||
BzAIBTNode *bzAIBTCompSequence(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel) {
|
||||
BzAIBTNodeType type = parallel ?
|
||||
BZ_AIBT_COMP_PARALLEL_SEQUENCE :
|
||||
BZ_AIBT_COMP_SEQUENCE;
|
||||
return bzAIBTNodeMake(nodePool, parent, type);
|
||||
BzBTNode *bzBTCompSequence(BzObjectPool *nodePool, BzBTNode *parent, bool parallel) {
|
||||
BzBTNodeType type = parallel ?
|
||||
BZ_BT_COMP_PARALLEL_SEQUENCE :
|
||||
BZ_BT_COMP_SEQUENCE;
|
||||
return bzBTNodeMake(nodePool, parent, type);
|
||||
}
|
||||
|
||||
BzAIBTNode *bzAIBTDecorDummy(BzObjectPool *nodePool, BzAIBTNode *parent) {
|
||||
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_DUMMY);
|
||||
BzBTNode *bzBTDecorDummy(BzObjectPool *nodePool, BzBTNode *parent) {
|
||||
return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_DUMMY);
|
||||
}
|
||||
BzAIBTNode *bzAIBTDecorSuccess(BzObjectPool *nodePool, BzAIBTNode *parent) {
|
||||
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_SUCCESS);
|
||||
BzBTNode *bzBTDecorSuccess(BzObjectPool *nodePool, BzBTNode *parent) {
|
||||
return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_SUCCESS);
|
||||
}
|
||||
BzAIBTNode *bzAIBTDecorFail(BzObjectPool *nodePool, BzAIBTNode *parent) {
|
||||
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_FAIL);
|
||||
BzBTNode *bzBTDecorFail(BzObjectPool *nodePool, BzBTNode *parent) {
|
||||
return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_FAIL);
|
||||
}
|
||||
BzAIBTNode *bzAIBTDecorInvert(BzObjectPool *nodePool, BzAIBTNode *parent) {
|
||||
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_INVERT);
|
||||
BzBTNode *bzBTDecorInvert(BzObjectPool *nodePool, BzBTNode *parent) {
|
||||
return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_INVERT);
|
||||
}
|
||||
BzAIBTNode *bzAIBTDecorUntilSuccess(BzObjectPool *nodePool, BzAIBTNode *parent) {
|
||||
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_UNTIL_SUCCESS);
|
||||
BzBTNode *bzBTDecorUntilSuccess(BzObjectPool *nodePool, BzBTNode *parent) {
|
||||
return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_UNTIL_SUCCESS);
|
||||
}
|
||||
BzAIBTNode *bzAIBTDecorUntilFail(BzObjectPool *nodePool, BzAIBTNode *parent) {
|
||||
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_UNTIL_FAIL);
|
||||
BzBTNode *bzBTDecorUntilFail(BzObjectPool *nodePool, BzBTNode *parent) {
|
||||
return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_UNTIL_FAIL);
|
||||
}
|
||||
BzAIBTNode *bzAIBTDecorRepeat(BzObjectPool *nodePool, BzAIBTNode *parent, i32 n) {
|
||||
BzAIBTNode *node = bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_REPEAT);
|
||||
BzBTNode *bzBTDecorRepeat(BzObjectPool *nodePool, BzBTNode *parent, i32 n) {
|
||||
BzBTNode *node = bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_REPEAT);
|
||||
node->as.repeat.n = n;
|
||||
return node;
|
||||
}
|
||||
BzAIBTNode *bzAIBTDecorDelay(BzObjectPool *nodePool, BzAIBTNode *parent, f32 ms) {
|
||||
BzAIBTNode *node = bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_DELAY);
|
||||
BzBTNode *bzBTDecorDelay(BzObjectPool *nodePool, BzBTNode *parent, f32 ms) {
|
||||
BzBTNode *node = bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_DELAY);
|
||||
node->as.delay.ms = ms;
|
||||
return node;
|
||||
}
|
||||
|
||||
BzAIBTNode *bzAIBTAction(BzObjectPool *nodePool, BzAIBTNode *parent, BzAIBTActionFn fn,
|
||||
const char *name) {
|
||||
BzAIBTNode *node = bzAIBTNodeMake(nodePool, parent, BZ_AIBT_ACTION);
|
||||
BzBTNode *bzBTAction(BzObjectPool *nodePool, BzBTNode *parent, BzBTActionFn fn,
|
||||
const char *name) {
|
||||
BzBTNode *node = bzBTNodeMake(nodePool, parent, BZ_BT_ACTION);
|
||||
node->as.action.fn = fn;
|
||||
node->as.action.name = name;
|
||||
return node;
|
||||
}
|
||||
|
||||
i32 bzAIBTDecorGetRepeat(const BzAIBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_AIBT_DECOR_REPEAT);
|
||||
i32 bzBTDecorGetRepeat(const BzBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_BT_DECOR_REPEAT);
|
||||
return node->as.repeat.n;
|
||||
}
|
||||
f32 bzAIBTDecorGetDelay(const BzAIBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_AIBT_DECOR_DELAY);
|
||||
f32 bzBTDecorGetDelay(const BzBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_BT_DECOR_DELAY);
|
||||
return node->as.delay.ms;
|
||||
}
|
||||
|
||||
BzAIBTActionFn bzAIBTActionGetFn(const BzAIBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_AIBT_ACTION);
|
||||
BzBTActionFn bzBTActionGetFn(const BzBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_BT_ACTION);
|
||||
return node->as.action.fn;
|
||||
}
|
||||
const char *bzAIBTActionGetName(const BzAIBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_AIBT_ACTION);
|
||||
const char *bzBTActionGetName(const BzBTNode *node) {
|
||||
BZ_ASSERT(node->type == BZ_BT_ACTION);
|
||||
return node->as.action.name;
|
||||
}
|
||||
|
||||
BzAIBTNodeType bzAIBTGetNodeType(const BzAIBTNode *node) {
|
||||
BzBTNodeType bzBTGetNodeType(const BzBTNode *node) {
|
||||
return node->type;
|
||||
}
|
||||
BzAIBTNode *bzAIBTNodeChild(const BzAIBTNode *node) {
|
||||
BzBTNode *bzBTNodeChild(const BzBTNode *node) {
|
||||
return node->first;
|
||||
}
|
||||
BzAIBTNode *bzAIBTNodeNext(const BzAIBTNode *node) {
|
||||
BzBTNode *bzBTNodeNext(const BzBTNode *node) {
|
||||
return node->next;
|
||||
}
|
||||
|
||||
const BzAIBTNodeState *bzAIBTNodeStateNext(const BzAIBTNodeState *state) {
|
||||
const BzBTNodeState *bzBTNodeStateNext(const BzBTNodeState *state) {
|
||||
BZ_ASSERT(state);
|
||||
return state->next;
|
||||
}
|
||||
bool bzAIBTNodeMatchesState(const BzAIBTNode *node, const BzAIBTNodeState *state) {
|
||||
bool bzBTNodeMatchesState(const BzBTNode *node, const BzBTNodeState *state) {
|
||||
return state && state->node == node;
|
||||
}
|
||||
|
||||
i32 bzAIBTRepeatStateGetIter(const BzAIBTNodeState *state) {
|
||||
BZ_ASSERT(state->node && state->node->type == BZ_AIBT_DECOR_REPEAT);
|
||||
i32 bzBTRepeatStateGetIter(const BzBTNodeState *state) {
|
||||
BZ_ASSERT(state->node && state->node->type == BZ_BT_DECOR_REPEAT);
|
||||
return state->as.repeat.iter;
|
||||
}
|
||||
f32 bzAIBTDelayStateGetElapsed(const BzAIBTNodeState *state) {
|
||||
BZ_ASSERT(state->node && state->node->type == BZ_AIBT_DECOR_DELAY);
|
||||
f32 bzBTDelayStateGetElapsed(const BzBTNodeState *state) {
|
||||
BZ_ASSERT(state->node && state->node->type == BZ_BT_DECOR_DELAY);
|
||||
return state->as.delay.elapsed;
|
||||
}
|
||||
|
||||
BzAIBTState bzAIBTCreateState(const BzAIBTStateDesc *desc) {
|
||||
BzBTState bzBTCreateState(const BzBTStateDesc *desc) {
|
||||
BZ_ASSERT(desc->pool);
|
||||
BZ_ASSERT(bzObjectPoolGetObjectSize(desc->pool) == bzAIBTGetNodeStateSize());
|
||||
BZ_ASSERT(bzObjectPoolGetObjectSize(desc->pool) == bzBTGetNodeStateSize());
|
||||
BZ_ASSERT(desc->root);
|
||||
return (BzAIBTState) {
|
||||
return (BzBTState) {
|
||||
.root = desc->root,
|
||||
.first = NULL,
|
||||
.last = NULL,
|
||||
@@ -232,17 +232,17 @@ BzAIBTState bzAIBTCreateState(const BzAIBTStateDesc *desc) {
|
||||
.userData = desc->userData
|
||||
};
|
||||
}
|
||||
void bzAIBTDestroyState(BzAIBTState *state) {
|
||||
BzAIBTNodeState *pNodeState = state->first;
|
||||
void bzBTDestroyState(BzBTState *state) {
|
||||
BzBTNodeState *pNodeState = state->first;
|
||||
while (pNodeState) {
|
||||
BzAIBTNodeState *next = pNodeState->next;
|
||||
BzBTNodeState *next = pNodeState->next;
|
||||
bzObjectPoolRelease(state->nodeStatePool, pNodeState);
|
||||
pNodeState = next;
|
||||
}
|
||||
bzMemSet(state, 0, sizeof(*state));
|
||||
}
|
||||
|
||||
void bzAIBTStateAppend(BzAIBTState *state, BzAIBTNodeState *nodeState) {
|
||||
void bzBTStateAppend(BzBTState *state, BzBTNodeState *nodeState) {
|
||||
nodeState->next = NULL;
|
||||
nodeState->prev = state->last;
|
||||
if (state->last)
|
||||
@@ -251,11 +251,11 @@ void bzAIBTStateAppend(BzAIBTState *state, BzAIBTNodeState *nodeState) {
|
||||
state->first = nodeState;
|
||||
state->last = nodeState;
|
||||
}
|
||||
void bzAIBTStatePop(BzAIBTState *state, BzAIBTNodeState *nodeState) {
|
||||
void bzBTStatePop(BzBTState *state, BzBTNodeState *nodeState) {
|
||||
if (state->first == nodeState) state->first = nodeState->next;
|
||||
if (state->last == nodeState) state->last = nodeState->prev;
|
||||
BzAIBTNodeState *next = nodeState->next;
|
||||
BzAIBTNodeState *prev = nodeState->prev;
|
||||
BzBTNodeState *next = nodeState->next;
|
||||
BzBTNodeState *prev = nodeState->prev;
|
||||
if (nodeState->prev)
|
||||
nodeState->prev->next = next;
|
||||
if (nodeState->next)
|
||||
@@ -263,155 +263,155 @@ void bzAIBTStatePop(BzAIBTState *state, BzAIBTNodeState *nodeState) {
|
||||
nodeState->next = NULL;
|
||||
nodeState->prev = NULL;
|
||||
}
|
||||
void bzAIBTStateRenew(BzAIBTState *oldState, BzAIBTState *newState, BzAIBTNodeState *nodeState) {
|
||||
void bzBTStateRenew(BzBTState *oldState, BzBTState *newState, BzBTNodeState *nodeState) {
|
||||
// Pop nodeState and transfer it to the back
|
||||
bzAIBTStatePop(oldState, nodeState);
|
||||
bzAIBTStateAppend(newState, nodeState);
|
||||
bzBTStatePop(oldState, nodeState);
|
||||
bzBTStateAppend(newState, nodeState);
|
||||
}
|
||||
BzAIBTNodeState *bzAIBTStatePool(BzAIBTState *state, const BzAIBTNode *node) {
|
||||
BzAIBTNodeState *nodeState = bzObjectPool(state->nodeStatePool);
|
||||
BzBTNodeState *bzBTStatePool(BzBTState *state, const BzBTNode *node) {
|
||||
BzBTNodeState *nodeState = bzObjectPool(state->nodeStatePool);
|
||||
nodeState->next = NULL;
|
||||
nodeState->prev = NULL;
|
||||
nodeState->node = node;
|
||||
return nodeState;
|
||||
}
|
||||
void bzAIBTStateRelease(BzAIBTState *state, BzAIBTNodeState *nodeState) {
|
||||
void bzBTStateRelease(BzBTState *state, BzBTNodeState *nodeState) {
|
||||
bzObjectPoolRelease(state->nodeStatePool, nodeState);
|
||||
}
|
||||
|
||||
bool nodeMatchesState(const BzAIBTNode *node, const BzAIBTNodeState *state) {
|
||||
return bzAIBTNodeMatchesState(node, state);
|
||||
bool nodeMatchesState(const BzBTNode *node, const BzBTNodeState *state) {
|
||||
return bzBTNodeMatchesState(node, state);
|
||||
}
|
||||
BzAIBTNodeState *getNextNodeState(const BzAIBTNode *node, BzAIBTNodeState *nodeState) {
|
||||
BzBTNodeState *getNextNodeState(const BzBTNode *node, BzBTNodeState *nodeState) {
|
||||
if (nodeState && nodeMatchesState(node, nodeState))
|
||||
return nodeState->next;
|
||||
return nodeState;
|
||||
}
|
||||
|
||||
static inline BzAIBTStatus bzAIBTExecuteNode(const BzAIBTNode *node, f32 dt,
|
||||
BzAIBTNodeState *nodeState,
|
||||
BzAIBTState *oldState, BzAIBTState *newState);
|
||||
static inline BzAIBTStatus bzAIBTExecuteComposite(const BzAIBTNode *node, f32 dt,
|
||||
BzAIBTNodeState *nodeState,
|
||||
BzAIBTState *oldState, BzAIBTState *newState) {
|
||||
BzAIBTNodeState *nextState = getNextNodeState(node, nodeState);
|
||||
BzAIBTNode *start = node->first;
|
||||
bool isParallel = node->type == BZ_AIBT_COMP_PARALLEL_SEQUENCE ||
|
||||
node->type == BZ_AIBT_COMP_PARALLEL_SELECTOR;
|
||||
static inline BzBTStatus bzBTExecuteNode(const BzBTNode *node, f32 dt,
|
||||
BzBTNodeState *nodeState,
|
||||
BzBTState *oldState, BzBTState *newState);
|
||||
static inline BzBTStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt,
|
||||
BzBTNodeState *nodeState,
|
||||
BzBTState *oldState, BzBTState *newState) {
|
||||
BzBTNodeState *nextState = getNextNodeState(node, nodeState);
|
||||
BzBTNode *start = node->first;
|
||||
bool isParallel = node->type == BZ_BT_COMP_PARALLEL_SEQUENCE ||
|
||||
node->type == BZ_BT_COMP_PARALLEL_SELECTOR;
|
||||
|
||||
if (!isParallel && nodeMatchesState(node, nodeState))
|
||||
start = nodeState->as.composite.running;
|
||||
|
||||
// Always push dummy state
|
||||
if (nodeMatchesState(node, nodeState)) {
|
||||
bzAIBTStateRenew(oldState, newState, nodeState);
|
||||
bzBTStateRenew(oldState, newState, nodeState);
|
||||
} else {
|
||||
nodeState = bzAIBTStatePool(oldState, node);
|
||||
bzAIBTStateAppend(newState, nodeState);
|
||||
nodeState = bzBTStatePool(oldState, node);
|
||||
bzBTStateAppend(newState, nodeState);
|
||||
}
|
||||
i32 numRunning = 0;
|
||||
i32 numSuccessful = 0;
|
||||
i32 numFailed = 0;
|
||||
i32 numChildren = 0;
|
||||
BzAIBTStatus status = BZ_AIBT_ERROR;
|
||||
BzAIBTNode *child = start;
|
||||
BzBTStatus status = BZ_BT_ERROR;
|
||||
BzBTNode *child = start;
|
||||
for (;child; child = child->next) {
|
||||
BzAIBTStatus childStatus = bzAIBTExecuteNode(child, dt, nextState, oldState, newState);
|
||||
BzBTStatus childStatus = bzBTExecuteNode(child, dt, nextState, oldState, newState);
|
||||
numChildren++;
|
||||
switch (childStatus) {
|
||||
case BZ_AIBT_RUNNING:
|
||||
case BZ_BT_RUNNING:
|
||||
numRunning++;
|
||||
break;
|
||||
case BZ_AIBT_SUCCESS:
|
||||
case BZ_BT_SUCCESS:
|
||||
numSuccessful++;
|
||||
break;
|
||||
case BZ_AIBT_FAIL:
|
||||
case BZ_BT_FAIL:
|
||||
numFailed++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (node->type) {
|
||||
case BZ_AIBT_COMP_SELECTOR:
|
||||
case BZ_AIBT_COMP_PARALLEL_SELECTOR:
|
||||
if (childStatus == BZ_AIBT_SUCCESS)
|
||||
status = BZ_AIBT_SUCCESS;
|
||||
case BZ_BT_COMP_SELECTOR:
|
||||
case BZ_BT_COMP_PARALLEL_SELECTOR:
|
||||
if (childStatus == BZ_BT_SUCCESS)
|
||||
status = BZ_BT_SUCCESS;
|
||||
break;
|
||||
case BZ_AIBT_COMP_SEQUENCE:
|
||||
case BZ_AIBT_COMP_PARALLEL_SEQUENCE:
|
||||
if (childStatus == BZ_AIBT_FAIL)
|
||||
status = BZ_AIBT_FAIL;
|
||||
case BZ_BT_COMP_SEQUENCE:
|
||||
case BZ_BT_COMP_PARALLEL_SEQUENCE:
|
||||
if (childStatus == BZ_BT_FAIL)
|
||||
status = BZ_BT_FAIL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (status == BZ_AIBT_FAIL || status == BZ_AIBT_SUCCESS)
|
||||
if (status == BZ_BT_FAIL || status == BZ_BT_SUCCESS)
|
||||
break;
|
||||
if (numRunning > 0 && !isParallel) {
|
||||
status = BZ_AIBT_RUNNING;
|
||||
status = BZ_BT_RUNNING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (node->type) {
|
||||
case BZ_AIBT_COMP_SELECTOR:
|
||||
case BZ_AIBT_COMP_PARALLEL_SELECTOR:
|
||||
case BZ_BT_COMP_SELECTOR:
|
||||
case BZ_BT_COMP_PARALLEL_SELECTOR:
|
||||
if (numFailed == numChildren)
|
||||
status = BZ_AIBT_FAIL;
|
||||
status = BZ_BT_FAIL;
|
||||
break;
|
||||
case BZ_AIBT_COMP_SEQUENCE:
|
||||
case BZ_AIBT_COMP_PARALLEL_SEQUENCE:
|
||||
case BZ_BT_COMP_SEQUENCE:
|
||||
case BZ_BT_COMP_PARALLEL_SEQUENCE:
|
||||
if (numSuccessful == numChildren)
|
||||
status = BZ_AIBT_SUCCESS;
|
||||
status = BZ_BT_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == BZ_AIBT_ERROR) {
|
||||
bzAIBTStatePop(newState, nodeState);
|
||||
return BZ_AIBT_ERROR;
|
||||
if (status == BZ_BT_ERROR) {
|
||||
bzBTStatePop(newState, nodeState);
|
||||
return BZ_BT_ERROR;
|
||||
}
|
||||
|
||||
bool finished = status == BZ_AIBT_SUCCESS ||
|
||||
status == BZ_AIBT_FAIL;
|
||||
bool finished = status == BZ_BT_SUCCESS ||
|
||||
status == BZ_BT_FAIL;
|
||||
if (finished) {
|
||||
// Dummy state is no longer needed
|
||||
bzAIBTStatePop(newState, nodeState);
|
||||
bzBTStatePop(newState, nodeState);
|
||||
} else {
|
||||
BZ_ASSERT(status == BZ_AIBT_RUNNING);
|
||||
BZ_ASSERT(status == BZ_BT_RUNNING);
|
||||
nodeState->as.composite.running = child;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
static inline BzAIBTStatus bzAIBTExecuteDecorator(const BzAIBTNode *node, f32 dt,
|
||||
BzAIBTNodeState *nodeState,
|
||||
BzAIBTState *oldState, BzAIBTState *newState) {
|
||||
static inline BzBTStatus bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
|
||||
BzBTNodeState *nodeState,
|
||||
BzBTState *oldState, BzBTState *newState) {
|
||||
// Ensure decorator has only one child, if any
|
||||
BZ_ASSERT(!node->first || node->first == node->last);
|
||||
BzAIBTNodeState *nextState = getNextNodeState(node, nodeState);
|
||||
BzBTNodeState *nextState = getNextNodeState(node, nodeState);
|
||||
|
||||
switch (node->type) {
|
||||
case BZ_AIBT_DECOR_REPEAT:
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
if (!nodeMatchesState(node, nodeState)) {
|
||||
BzAIBTNodeState *newNodeState = bzAIBTStatePool(oldState, node);
|
||||
BzBTNodeState *newNodeState = bzBTStatePool(oldState, node);
|
||||
newNodeState->as.repeat.iter = 0;
|
||||
bzAIBTStateAppend(newState, newNodeState);
|
||||
bzBTStateAppend(newState, newNodeState);
|
||||
nodeState = newNodeState;
|
||||
} else {
|
||||
bzAIBTStateRenew(oldState, newState, nodeState);
|
||||
bzBTStateRenew(oldState, newState, nodeState);
|
||||
}
|
||||
break;
|
||||
case BZ_AIBT_DECOR_DELAY:
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
if (!nodeMatchesState(node, nodeState)) {
|
||||
BzAIBTNodeState *newNodeState = bzAIBTStatePool(oldState, node);
|
||||
BzBTNodeState *newNodeState = bzBTStatePool(oldState, node);
|
||||
newNodeState->as.delay.elapsed = dt;
|
||||
bzAIBTStateAppend(newState, newNodeState);
|
||||
return BZ_AIBT_RUNNING;
|
||||
bzBTStateAppend(newState, newNodeState);
|
||||
return BZ_BT_RUNNING;
|
||||
}
|
||||
nodeState->as.delay.elapsed += dt;
|
||||
if (nodeState->as.delay.elapsed < node->as.delay.ms) {
|
||||
bzAIBTStateRenew(oldState, newState, nodeState);
|
||||
return BZ_AIBT_RUNNING;
|
||||
bzBTStateRenew(oldState, newState, nodeState);
|
||||
return BZ_BT_RUNNING;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -419,109 +419,109 @@ static inline BzAIBTStatus bzAIBTExecuteDecorator(const BzAIBTNode *node, f32 dt
|
||||
}
|
||||
|
||||
// Implicit success, if no children are present
|
||||
BzAIBTStatus inStatus = BZ_AIBT_SUCCESS;
|
||||
BzBTStatus inStatus = BZ_BT_SUCCESS;
|
||||
if (node->first)
|
||||
inStatus = bzAIBTExecuteNode(node->first, dt, nextState, oldState, newState);
|
||||
inStatus = bzBTExecuteNode(node->first, dt, nextState, oldState, newState);
|
||||
|
||||
// Propagate ERROR, RUNNING up
|
||||
if (inStatus == BZ_AIBT_ERROR)
|
||||
return BZ_AIBT_ERROR;
|
||||
if (inStatus == BZ_AIBT_RUNNING)
|
||||
return BZ_AIBT_RUNNING;
|
||||
if (inStatus == BZ_BT_ERROR)
|
||||
return BZ_BT_ERROR;
|
||||
if (inStatus == BZ_BT_RUNNING)
|
||||
return BZ_BT_RUNNING;
|
||||
|
||||
BzAIBTStatus status = BZ_AIBT_ERROR;
|
||||
BzBTStatus status = BZ_BT_ERROR;
|
||||
switch (node->type) {
|
||||
case BZ_AIBT_DECOR_DUMMY:
|
||||
case BZ_AIBT_DECOR_DELAY: // Delay already handled
|
||||
case BZ_BT_DECOR_DUMMY:
|
||||
case BZ_BT_DECOR_DELAY: // Delay already handled
|
||||
status = inStatus;
|
||||
break;
|
||||
case BZ_AIBT_DECOR_SUCCESS:
|
||||
status = BZ_AIBT_SUCCESS;
|
||||
case BZ_BT_DECOR_SUCCESS:
|
||||
status = BZ_BT_SUCCESS;
|
||||
break;
|
||||
case BZ_AIBT_DECOR_FAIL:
|
||||
status = BZ_AIBT_FAIL;
|
||||
case BZ_BT_DECOR_FAIL:
|
||||
status = BZ_BT_FAIL;
|
||||
break;
|
||||
case BZ_AIBT_DECOR_INVERT:
|
||||
if (inStatus == BZ_AIBT_FAIL)
|
||||
status = BZ_AIBT_SUCCESS;
|
||||
if (inStatus == BZ_AIBT_SUCCESS)
|
||||
status = BZ_AIBT_FAIL;
|
||||
case BZ_BT_DECOR_INVERT:
|
||||
if (inStatus == BZ_BT_FAIL)
|
||||
status = BZ_BT_SUCCESS;
|
||||
if (inStatus == BZ_BT_SUCCESS)
|
||||
status = BZ_BT_FAIL;
|
||||
break;
|
||||
case BZ_AIBT_DECOR_UNTIL_SUCCESS:
|
||||
if (inStatus == BZ_AIBT_SUCCESS)
|
||||
status = BZ_AIBT_SUCCESS;
|
||||
case BZ_BT_DECOR_UNTIL_SUCCESS:
|
||||
if (inStatus == BZ_BT_SUCCESS)
|
||||
status = BZ_BT_SUCCESS;
|
||||
else
|
||||
status = BZ_AIBT_RUNNING;
|
||||
status = BZ_BT_RUNNING;
|
||||
break;
|
||||
case BZ_AIBT_DECOR_UNTIL_FAIL:
|
||||
if (inStatus == BZ_AIBT_FAIL)
|
||||
status = BZ_AIBT_SUCCESS;
|
||||
case BZ_BT_DECOR_UNTIL_FAIL:
|
||||
if (inStatus == BZ_BT_FAIL)
|
||||
status = BZ_BT_SUCCESS;
|
||||
else
|
||||
status = BZ_AIBT_RUNNING;
|
||||
status = BZ_BT_RUNNING;
|
||||
break;
|
||||
case BZ_AIBT_DECOR_REPEAT:
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
BZ_ASSERT(nodeState->node == node);
|
||||
nodeState->as.repeat.iter++;
|
||||
if (nodeState->as.repeat.iter >= node->as.repeat.n) {
|
||||
bzAIBTStatePop(newState, nodeState);
|
||||
bzBTStatePop(newState, nodeState);
|
||||
status = inStatus;
|
||||
break;
|
||||
}
|
||||
status = BZ_AIBT_RUNNING;
|
||||
status = BZ_BT_RUNNING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
static inline BzAIBTStatus bzAIBTExecuteNode(const BzAIBTNode *node, f32 dt,
|
||||
BzAIBTNodeState *nodeState,
|
||||
BzAIBTState *oldState, BzAIBTState *newState) {
|
||||
BzAIBTStatus status = BZ_AIBT_ERROR;
|
||||
static inline BzBTStatus bzBTExecuteNode(const BzBTNode *node, f32 dt,
|
||||
BzBTNodeState *nodeState,
|
||||
BzBTState *oldState, BzBTState *newState) {
|
||||
BzBTStatus status = BZ_BT_ERROR;
|
||||
switch (node->type) {
|
||||
case BZ_AIBT_COMP_SELECTOR:
|
||||
case BZ_AIBT_COMP_SEQUENCE:
|
||||
case BZ_AIBT_COMP_PARALLEL_SELECTOR:
|
||||
case BZ_AIBT_COMP_PARALLEL_SEQUENCE:
|
||||
status = bzAIBTExecuteComposite(node, dt, nodeState, oldState, newState);
|
||||
case BZ_BT_COMP_SELECTOR:
|
||||
case BZ_BT_COMP_SEQUENCE:
|
||||
case BZ_BT_COMP_PARALLEL_SELECTOR:
|
||||
case BZ_BT_COMP_PARALLEL_SEQUENCE:
|
||||
status = bzBTExecuteComposite(node, dt, nodeState, oldState, newState);
|
||||
break;
|
||||
case BZ_AIBT_DECOR_DUMMY:
|
||||
case BZ_AIBT_DECOR_SUCCESS:
|
||||
case BZ_AIBT_DECOR_FAIL:
|
||||
case BZ_AIBT_DECOR_INVERT:
|
||||
case BZ_AIBT_DECOR_UNTIL_SUCCESS:
|
||||
case BZ_AIBT_DECOR_UNTIL_FAIL:
|
||||
case BZ_AIBT_DECOR_REPEAT:
|
||||
case BZ_AIBT_DECOR_DELAY:
|
||||
status = bzAIBTExecuteDecorator(node, dt, nodeState, oldState, newState);
|
||||
case BZ_BT_DECOR_DUMMY:
|
||||
case BZ_BT_DECOR_SUCCESS:
|
||||
case BZ_BT_DECOR_FAIL:
|
||||
case BZ_BT_DECOR_INVERT:
|
||||
case BZ_BT_DECOR_UNTIL_SUCCESS:
|
||||
case BZ_BT_DECOR_UNTIL_FAIL:
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
status = bzBTExecuteDecorator(node, dt, nodeState, oldState, newState);
|
||||
break;
|
||||
case BZ_AIBT_ACTION:
|
||||
case BZ_BT_ACTION:
|
||||
BZ_ASSERT(node->as.action.fn);
|
||||
return node->as.action.fn(oldState->userData);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
BzAIBTStatus bzAIBTExecute(BzAIBTState *state, f32 dt) {
|
||||
BzBTStatus bzBTExecute(BzBTState *state, f32 dt) {
|
||||
BZ_ASSERT(state->nodeStatePool);
|
||||
BZ_ASSERT(bzObjectPoolGetObjectSize(state->nodeStatePool) == bzAIBTGetNodeStateSize());
|
||||
BZ_ASSERT(bzObjectPoolGetObjectSize(state->nodeStatePool) == bzBTGetNodeStateSize());
|
||||
BZ_ASSERT(state);
|
||||
BZ_ASSERT(state->root);
|
||||
|
||||
BzAIBTState newState = {
|
||||
BzBTState newState = {
|
||||
.first = NULL,
|
||||
.last = NULL,
|
||||
};
|
||||
|
||||
BzAIBTNodeState *first = state->first;
|
||||
const BzAIBTNode *firstNode = first ? first->node : state->root;
|
||||
BzAIBTStatus status = bzAIBTExecuteNode(firstNode, dt, first, state, &newState);
|
||||
BzBTNodeState *first = state->first;
|
||||
const BzBTNode *firstNode = first ? first->node : state->root;
|
||||
BzBTStatus status = bzBTExecuteNode(firstNode, dt, first, state, &newState);
|
||||
|
||||
// Release leftover states
|
||||
BzAIBTNodeState *pState = state->first;
|
||||
BzBTNodeState *pState = state->first;
|
||||
while (pState) {
|
||||
BzAIBTNodeState *next = pState->next;
|
||||
bzAIBTStateRelease(state, pState);
|
||||
BzBTNodeState *next = pState->next;
|
||||
bzBTStateRelease(state, pState);
|
||||
pState = next;
|
||||
}
|
||||
state->first = newState.first;
|
||||
|
||||
@@ -3,99 +3,99 @@
|
||||
|
||||
#include "../defines.h"
|
||||
|
||||
typedef struct BzAIBTNode BzAIBTNode;
|
||||
typedef struct BzBTNode BzBTNode;
|
||||
|
||||
typedef enum BzAIBTStatus {
|
||||
BZ_AIBT_RUNNING,
|
||||
BZ_AIBT_SUCCESS,
|
||||
BZ_AIBT_FAIL,
|
||||
BZ_AIBT_ERROR,
|
||||
} BzAIBTStatus;
|
||||
typedef enum BzBTStatus {
|
||||
BZ_BT_RUNNING,
|
||||
BZ_BT_SUCCESS,
|
||||
BZ_BT_FAIL,
|
||||
BZ_BT_ERROR,
|
||||
} BzBTStatus;
|
||||
|
||||
typedef BzAIBTStatus(*BzAIBTActionFn)(void *data);
|
||||
typedef BzBTStatus(*BzBTActionFn)(void *data);
|
||||
|
||||
typedef enum BzAIBTNodeType {
|
||||
typedef enum BzBTNodeType {
|
||||
// Composite
|
||||
BZ_AIBT_COMP_SELECTOR,
|
||||
BZ_AIBT_COMP_SEQUENCE,
|
||||
BZ_AIBT_COMP_PARALLEL_SELECTOR,
|
||||
BZ_AIBT_COMP_PARALLEL_SEQUENCE,
|
||||
BZ_BT_COMP_SELECTOR,
|
||||
BZ_BT_COMP_SEQUENCE,
|
||||
BZ_BT_COMP_PARALLEL_SELECTOR,
|
||||
BZ_BT_COMP_PARALLEL_SEQUENCE,
|
||||
// Decorator
|
||||
BZ_AIBT_DECOR_DUMMY,
|
||||
BZ_AIBT_DECOR_SUCCESS,
|
||||
BZ_AIBT_DECOR_FAIL,
|
||||
BZ_AIBT_DECOR_INVERT,
|
||||
BZ_AIBT_DECOR_UNTIL_SUCCESS,
|
||||
BZ_AIBT_DECOR_UNTIL_FAIL,
|
||||
BZ_AIBT_DECOR_REPEAT,
|
||||
BZ_AIBT_DECOR_DELAY,
|
||||
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_AIBT_ACTION,
|
||||
} BzAIBTNodeType;
|
||||
BZ_BT_ACTION,
|
||||
} BzBTNodeType;
|
||||
|
||||
typedef struct BzObjectPool BzObjectPool;
|
||||
typedef struct BzAIBTNodeState BzAIBTNodeState;
|
||||
typedef struct BzBTNodeState BzBTNodeState;
|
||||
|
||||
typedef struct BzAIBTState {
|
||||
const BzAIBTNode *root;
|
||||
BzAIBTNodeState *first;
|
||||
BzAIBTNodeState *last;
|
||||
typedef struct BzBTState {
|
||||
const BzBTNode *root;
|
||||
BzBTNodeState *first;
|
||||
BzBTNodeState *last;
|
||||
|
||||
BzObjectPool *nodeStatePool;
|
||||
void *userData;
|
||||
} BzAIBTState;
|
||||
} BzBTState;
|
||||
|
||||
typedef struct BzAIBTStateDesc {
|
||||
const BzAIBTNode *root;
|
||||
typedef struct BzBTStateDesc {
|
||||
const BzBTNode *root;
|
||||
|
||||
BzObjectPool *pool;
|
||||
void *userData;
|
||||
} BzAIBTStateDesc;
|
||||
} BzBTStateDesc;
|
||||
|
||||
size_t bzAIBTGetNodeSize();
|
||||
size_t bzAIBTGetNodeStateSize();
|
||||
size_t bzBTGetNodeSize();
|
||||
size_t bzBTGetNodeStateSize();
|
||||
|
||||
const char *bzAIBTNodeTypeToStr(BzAIBTNodeType type);
|
||||
const char *bzBTNodeTypeToStr(BzBTNodeType type);
|
||||
|
||||
BzAIBTNode *bzAIBTMakeRoot(BzObjectPool *nodePool);
|
||||
void bzAIBTDestroyRoot(BzObjectPool *nodePool, BzAIBTNode *node);
|
||||
BzBTNode *bzBTMakeRoot(BzObjectPool *nodePool);
|
||||
void bzBTDestroyRoot(BzObjectPool *nodePool, BzBTNode *node);
|
||||
|
||||
BzAIBTNode *bzAIBTCompSelector(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel);
|
||||
BzAIBTNode *bzAIBTCompSequence(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel);
|
||||
BzBTNode *bzBTCompSelector(BzObjectPool *nodePool, BzBTNode *parent, bool parallel);
|
||||
BzBTNode *bzBTCompSequence(BzObjectPool *nodePool, BzBTNode *parent, bool parallel);
|
||||
|
||||
BzAIBTNode *bzAIBTDecorDummy(BzObjectPool *nodePool, BzAIBTNode *parent);
|
||||
BzAIBTNode *bzAIBTDecorSuccess(BzObjectPool *nodePool, BzAIBTNode *parent);
|
||||
BzAIBTNode *bzAIBTDecorFail(BzObjectPool *nodePool, BzAIBTNode *parent);
|
||||
BzAIBTNode *bzAIBTDecorInvert(BzObjectPool *nodePool, BzAIBTNode *parent);
|
||||
BzAIBTNode *bzAIBTDecorUntilSuccess(BzObjectPool *nodePool, BzAIBTNode *parent);
|
||||
BzAIBTNode *bzAIBTDecorUntilFail(BzObjectPool *nodePool, BzAIBTNode *parent);
|
||||
BzAIBTNode *bzAIBTDecorRepeat(BzObjectPool *nodePool, BzAIBTNode *parent, i32 n);
|
||||
BzAIBTNode *bzAIBTDecorDelay(BzObjectPool *nodePool, BzAIBTNode *parent, f32 ms);
|
||||
BzBTNode *bzBTDecorDummy(BzObjectPool *nodePool, BzBTNode *parent);
|
||||
BzBTNode *bzBTDecorSuccess(BzObjectPool *nodePool, BzBTNode *parent);
|
||||
BzBTNode *bzBTDecorFail(BzObjectPool *nodePool, BzBTNode *parent);
|
||||
BzBTNode *bzBTDecorInvert(BzObjectPool *nodePool, BzBTNode *parent);
|
||||
BzBTNode *bzBTDecorUntilSuccess(BzObjectPool *nodePool, BzBTNode *parent);
|
||||
BzBTNode *bzBTDecorUntilFail(BzObjectPool *nodePool, BzBTNode *parent);
|
||||
BzBTNode *bzBTDecorRepeat(BzObjectPool *nodePool, BzBTNode *parent, i32 n);
|
||||
BzBTNode *bzBTDecorDelay(BzObjectPool *nodePool, BzBTNode *parent, f32 ms);
|
||||
|
||||
BzAIBTNode *bzAIBTAction(BzObjectPool *nodePool, BzAIBTNode *parent, BzAIBTActionFn fn,
|
||||
const char *name);
|
||||
BzBTNode *bzBTAction(BzObjectPool *nodePool, BzBTNode *parent, BzBTActionFn fn,
|
||||
const char *name);
|
||||
|
||||
// Reflection data
|
||||
|
||||
i32 bzAIBTDecorGetRepeat(const BzAIBTNode *node);
|
||||
f32 bzAIBTDecorGetDelay(const BzAIBTNode *node);
|
||||
i32 bzBTDecorGetRepeat(const BzBTNode *node);
|
||||
f32 bzBTDecorGetDelay(const BzBTNode *node);
|
||||
|
||||
BzAIBTActionFn bzAIBTActionGetFn(const BzAIBTNode *node);
|
||||
const char *bzAIBTActionGetName(const BzAIBTNode *node);
|
||||
BzBTActionFn bzBTActionGetFn(const BzBTNode *node);
|
||||
const char *bzBTActionGetName(const BzBTNode *node);
|
||||
|
||||
BzAIBTNodeType bzAIBTGetNodeType(const BzAIBTNode *node);
|
||||
BzAIBTNode *bzAIBTNodeChild(const BzAIBTNode *node);
|
||||
BzAIBTNode *bzAIBTNodeNext(const BzAIBTNode *node);
|
||||
BzBTNodeType bzBTGetNodeType(const BzBTNode *node);
|
||||
BzBTNode *bzBTNodeChild(const BzBTNode *node);
|
||||
BzBTNode *bzBTNodeNext(const BzBTNode *node);
|
||||
|
||||
const BzAIBTNodeState *bzAIBTNodeStateNext(const BzAIBTNodeState *state);
|
||||
bool bzAIBTNodeMatchesState(const BzAIBTNode *node, const BzAIBTNodeState *state);
|
||||
const BzBTNodeState *bzBTNodeStateNext(const BzBTNodeState *state);
|
||||
bool bzBTNodeMatchesState(const BzBTNode *node, const BzBTNodeState *state);
|
||||
|
||||
i32 bzAIBTRepeatStateGetIter(const BzAIBTNodeState *state);
|
||||
f32 bzAIBTDelayStateGetElapsed(const BzAIBTNodeState *state);
|
||||
i32 bzBTRepeatStateGetIter(const BzBTNodeState *state);
|
||||
f32 bzBTDelayStateGetElapsed(const BzBTNodeState *state);
|
||||
|
||||
BzAIBTState bzAIBTCreateState(const BzAIBTStateDesc *desc);
|
||||
void bzAIBTDestroyState(BzAIBTState *state);
|
||||
BzBTState bzBTCreateState(const BzBTStateDesc *desc);
|
||||
void bzBTDestroyState(BzBTState *state);
|
||||
|
||||
BzAIBTStatus bzAIBTExecute(BzAIBTState *state, f32 dt);
|
||||
BzBTStatus bzBTExecute(BzBTState *state, f32 dt);
|
||||
|
||||
#endif //BREEZE_BEHAVIOUR_TREE_H
|
||||
|
||||
@@ -4,39 +4,39 @@
|
||||
BzObjectPool *nodePool = NULL;
|
||||
BzObjectPool *nodeStatePool = NULL;
|
||||
|
||||
BzAIBTNode *printBT = NULL;
|
||||
BzAIBTState agentState;
|
||||
BzBTNode *printBT = NULL;
|
||||
BzBTState agentState;
|
||||
|
||||
BzAIBTStatus printAction(void *data) {
|
||||
BzBTStatus printAction(void *data) {
|
||||
bzLogInfo("Hello, world!");
|
||||
return BZ_AIBT_SUCCESS;
|
||||
return BZ_BT_SUCCESS;
|
||||
}
|
||||
|
||||
bool init(int *game) {
|
||||
rlImGuiSetup(true);
|
||||
nodePool = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
||||
.objectSize = bzAIBTGetNodeSize(),
|
||||
.objectSize = bzBTGetNodeSize(),
|
||||
});
|
||||
nodeStatePool = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
||||
.objectSize = bzAIBTGetNodeStateSize()
|
||||
.objectSize = bzBTGetNodeStateSize()
|
||||
});
|
||||
|
||||
// for 1..5:
|
||||
// seq
|
||||
// delay 1s
|
||||
// print "Hello, world!"
|
||||
printBT = bzAIBTMakeRoot(nodePool);
|
||||
BzAIBTNode *node = bzAIBTDecorRepeat(nodePool, printBT, 5);
|
||||
printBT = bzBTMakeRoot(nodePool);
|
||||
BzBTNode *node = bzBTDecorRepeat(nodePool, printBT, 5);
|
||||
|
||||
BzAIBTNode *seq = bzAIBTCompSequence(nodePool, node, false);
|
||||
BzBTNode *seq = bzBTCompSequence(nodePool, node, false);
|
||||
|
||||
bzAIBTDecorDelay(nodePool, seq, 1.0f);
|
||||
bzAIBTAction(nodePool, seq, printAction, "printAction");
|
||||
bzBTDecorDelay(nodePool, seq, 1.0f);
|
||||
bzBTAction(nodePool, seq, printAction, "printAction");
|
||||
|
||||
agentState = bzAIBTCreateState(&(BzAIBTStateDesc) {
|
||||
.root = printBT,
|
||||
.pool = nodeStatePool,
|
||||
.userData = NULL
|
||||
agentState = bzBTCreateState(&(BzBTStateDesc) {
|
||||
.root = printBT,
|
||||
.pool = nodeStatePool,
|
||||
.userData = NULL
|
||||
});
|
||||
|
||||
return true;
|
||||
@@ -47,60 +47,60 @@ void deinit(int *game) {
|
||||
bzObjectPoolDestroy(nodeStatePool);
|
||||
}
|
||||
|
||||
void igRenderBTNode(const BzAIBTNode *node, const BzAIBTNodeState *state, bool sameLine, i32 depth) {
|
||||
const BzAIBTNode *child = bzAIBTNodeChild(node);
|
||||
BzAIBTNodeType type = bzAIBTGetNodeType(node);
|
||||
void igRenderBTNode(const BzBTNode *node, const BzBTNodeState *state, bool sameLine, i32 depth) {
|
||||
const BzBTNode *child = bzBTNodeChild(node);
|
||||
BzBTNodeType type = bzBTGetNodeType(node);
|
||||
char extraInfo[128];
|
||||
extraInfo[0] = '\0';
|
||||
|
||||
bool hasState = bzAIBTNodeMatchesState(node, state);
|
||||
bool hasState = bzBTNodeMatchesState(node, state);
|
||||
|
||||
switch (type) {
|
||||
case BZ_AIBT_DECOR_REPEAT:
|
||||
case BZ_BT_DECOR_REPEAT:
|
||||
if (hasState) {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%d < %d)",
|
||||
bzAIBTRepeatStateGetIter(state),
|
||||
bzAIBTDecorGetRepeat(node));
|
||||
bzBTRepeatStateGetIter(state),
|
||||
bzBTDecorGetRepeat(node));
|
||||
} else {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%d)", bzAIBTDecorGetRepeat(node));
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%d)", bzBTDecorGetRepeat(node));
|
||||
}
|
||||
break;
|
||||
case BZ_AIBT_DECOR_DELAY:
|
||||
case BZ_BT_DECOR_DELAY:
|
||||
if (hasState) {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%.2f < %.2fms)",
|
||||
bzAIBTDelayStateGetElapsed(state),
|
||||
bzAIBTDecorGetDelay(node));
|
||||
bzBTDelayStateGetElapsed(state),
|
||||
bzBTDecorGetDelay(node));
|
||||
} else {
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%.2fms)", bzAIBTDecorGetDelay(node));
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%.2fms)", bzBTDecorGetDelay(node));
|
||||
}
|
||||
break;
|
||||
case BZ_AIBT_ACTION:
|
||||
case BZ_BT_ACTION:
|
||||
snprintf(extraInfo, sizeof(extraInfo), " (%s:%p)",
|
||||
bzAIBTActionGetName(node),
|
||||
bzAIBTActionGetFn(node));
|
||||
bzBTActionGetName(node),
|
||||
bzBTActionGetFn(node));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (hasState)
|
||||
state = bzAIBTNodeStateNext(state);
|
||||
state = bzBTNodeStateNext(state);
|
||||
|
||||
ImVec4 color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
if (hasState)
|
||||
color = (ImVec4) {1.0f, 1.0f, 0.5f, 1.0f};
|
||||
|
||||
bool hasSingleChild = false;
|
||||
if (child && bzAIBTNodeNext(child) == NULL) hasSingleChild = true;
|
||||
if (child && bzBTNodeNext(child) == NULL) hasSingleChild = true;
|
||||
|
||||
const char *suffix = hasSingleChild ? " > " : ": ";
|
||||
|
||||
if (sameLine) {
|
||||
igTextColored(color, "%s%s%s", bzAIBTNodeTypeToStr(type),
|
||||
igTextColored(color, "%s%s%s", bzBTNodeTypeToStr(type),
|
||||
extraInfo, suffix);
|
||||
} else {
|
||||
igTextColored(color, "%*s%s %s",
|
||||
depth * 2, "",
|
||||
bzAIBTNodeTypeToStr(type), extraInfo, suffix);
|
||||
bzBTNodeTypeToStr(type), extraInfo, suffix);
|
||||
depth++;
|
||||
}
|
||||
|
||||
@@ -109,12 +109,12 @@ void igRenderBTNode(const BzAIBTNode *node, const BzAIBTNodeState *state, bool s
|
||||
while (child) {
|
||||
if (hasSingleChild) igSameLine(0, 0);
|
||||
igRenderBTNode(child, state, hasSingleChild, depth);
|
||||
child = bzAIBTNodeNext(child);
|
||||
child = bzBTNodeNext(child);
|
||||
}
|
||||
}
|
||||
|
||||
void igRenderBT(BzAIBTState *state) {
|
||||
const BzAIBTNode *root = state->root;
|
||||
void igRenderBT(BzBTState *state) {
|
||||
const BzBTNode *root = state->root;
|
||||
if (igBegin("BehaviourTree", NULL, 0)) {
|
||||
igRenderBTNode(root, state->first, false, 0);
|
||||
}
|
||||
@@ -124,7 +124,7 @@ void igRenderBT(BzAIBTState *state) {
|
||||
void render(float dt, int *game) {
|
||||
ClearBackground(WHITE);
|
||||
|
||||
BzAIBTStatus status = bzAIBTExecute(&agentState, dt);
|
||||
BzBTStatus status = bzBTExecute(&agentState, dt);
|
||||
|
||||
rlImGuiBegin();
|
||||
igRenderBT(&agentState);
|
||||
|
||||
Reference in New Issue
Block a user