Remove AI prefix from behaviour_tree

This commit is contained in:
2024-01-10 07:36:05 +01:00
parent c4c2b7610d
commit 113ac72181
3 changed files with 319 additions and 319 deletions

View File

@@ -5,16 +5,16 @@
//#define GET_NODE(idx) ((BzAIBTNode *) bzObjectPoolGetObject(bt->nodePool, idx)) //#define GET_NODE(idx) ((BzAIBTNode *) bzObjectPoolGetObject(bt->nodePool, idx))
struct BzAIBTNode { struct BzBTNode {
BzAIBTNode *parent; BzBTNode *parent;
// Children // Children
BzAIBTNode *first; BzBTNode *first;
BzAIBTNode *last; BzBTNode *last;
// Siblings // Siblings
BzAIBTNode *prev; BzBTNode *prev;
BzAIBTNode *next; BzBTNode *next;
BzAIBTNodeType type; BzBTNodeType type;
union { union {
struct { struct {
i32 n; i32 n;
@@ -23,21 +23,21 @@ struct BzAIBTNode {
f32 ms; f32 ms;
} delay; } delay;
struct { struct {
BzAIBTActionFn fn; BzBTActionFn fn;
const char *name; const char *name;
} action; } action;
} as; } as;
}; };
struct BzAIBTNodeState { struct BzBTNodeState {
const BzAIBTNode *node; const BzBTNode *node;
BzAIBTNodeState *next; BzBTNodeState *next;
BzAIBTNodeState *prev; BzBTNodeState *prev;
union { union {
struct { struct {
BzAIBTNode *running; BzBTNode *running;
} composite; } composite;
struct { struct {
i32 iter; i32 iter;
@@ -49,48 +49,48 @@ struct BzAIBTNodeState {
}; };
size_t bzAIBTGetNodeSize() { size_t bzBTGetNodeSize() {
return sizeof(BzAIBTNode); return sizeof(BzBTNode);
} }
size_t bzAIBTGetNodeStateSize() { size_t bzBTGetNodeStateSize() {
return sizeof(BzAIBTNodeState); return sizeof(BzBTNodeState);
} }
const char *bzAIBTNodeTypeToStr(BzAIBTNodeType type) { const char *bzBTNodeTypeToStr(BzBTNodeType type) {
switch (type) { switch (type) {
case BZ_AIBT_COMP_SELECTOR: case BZ_BT_COMP_SELECTOR:
return "SELECTOR"; return "SELECTOR";
case BZ_AIBT_COMP_SEQUENCE: case BZ_BT_COMP_SEQUENCE:
return "SEQUENCE"; return "SEQUENCE";
case BZ_AIBT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR:
return "PARALLEL_SELECTOR"; return "PARALLEL_SELECTOR";
case BZ_AIBT_COMP_PARALLEL_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE:
return "PARALLEL_SEQUENCE"; return "PARALLEL_SEQUENCE";
case BZ_AIBT_DECOR_DUMMY: case BZ_BT_DECOR_DUMMY:
return "DUMMY"; return "DUMMY";
case BZ_AIBT_DECOR_SUCCESS: case BZ_BT_DECOR_SUCCESS:
return "SUCCESS"; return "SUCCESS";
case BZ_AIBT_DECOR_FAIL: case BZ_BT_DECOR_FAIL:
return "FAIL"; return "FAIL";
case BZ_AIBT_DECOR_INVERT: case BZ_BT_DECOR_INVERT:
return "INVERT"; return "INVERT";
case BZ_AIBT_DECOR_UNTIL_SUCCESS: case BZ_BT_DECOR_UNTIL_SUCCESS:
return "UNTIL_SUCCESS"; return "UNTIL_SUCCESS";
case BZ_AIBT_DECOR_UNTIL_FAIL: case BZ_BT_DECOR_UNTIL_FAIL:
return "UNTIL_FAIL"; return "UNTIL_FAIL";
case BZ_AIBT_DECOR_REPEAT: case BZ_BT_DECOR_REPEAT:
return "REPEAT"; return "REPEAT";
case BZ_AIBT_DECOR_DELAY: case BZ_BT_DECOR_DELAY:
return "DELAY"; return "DELAY";
case BZ_AIBT_ACTION: case BZ_BT_ACTION:
return "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(nodePool);
BZ_ASSERT(bzObjectPoolGetObjectSize(nodePool) == bzAIBTGetNodeSize()); BZ_ASSERT(bzObjectPoolGetObjectSize(nodePool) == bzBTGetNodeSize());
BzAIBTNode *node = bzObjectPool(nodePool); BzBTNode *node = bzObjectPool(nodePool);
bzMemSet(node, 0, sizeof(*node)); bzMemSet(node, 0, sizeof(*node));
node->type = type; node->type = type;
@@ -108,123 +108,123 @@ static BzAIBTNode *bzAIBTNodeMake(BzObjectPool *nodePool, BzAIBTNode *parent, Bz
return node; return node;
} }
BzAIBTNode *bzAIBTMakeRoot(BzObjectPool *nodePool) { BzBTNode *bzBTMakeRoot(BzObjectPool *nodePool) {
return bzAIBTNodeMake(nodePool, NULL, BZ_AIBT_DECOR_DUMMY); return bzBTNodeMake(nodePool, NULL, BZ_BT_DECOR_DUMMY);
} }
void bzAIBTDestroyRoot(BzObjectPool *nodePool, BzAIBTNode *node) { void bzBTDestroyRoot(BzObjectPool *nodePool, BzBTNode *node) {
BZ_ASSERT(node); BZ_ASSERT(node);
BzAIBTNode *pNode = node; BzBTNode *pNode = node;
while (pNode) { while (pNode) {
BzAIBTNode *next = pNode->next; BzBTNode *next = pNode->next;
bzAIBTDestroyRoot(nodePool, pNode); bzBTDestroyRoot(nodePool, pNode);
pNode = next; pNode = next;
} }
bzObjectPoolRelease(nodePool, node); bzObjectPoolRelease(nodePool, node);
} }
BzAIBTNode *bzAIBTCompSelector(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel) { BzBTNode *bzBTCompSelector(BzObjectPool *nodePool, BzBTNode *parent, bool parallel) {
BzAIBTNodeType type = parallel ? BzBTNodeType type = parallel ?
BZ_AIBT_COMP_PARALLEL_SELECTOR : BZ_BT_COMP_PARALLEL_SELECTOR :
BZ_AIBT_COMP_SELECTOR; BZ_BT_COMP_SELECTOR;
return bzAIBTNodeMake(nodePool, parent, type); return bzBTNodeMake(nodePool, parent, type);
} }
BzAIBTNode *bzAIBTCompSequence(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel) { BzBTNode *bzBTCompSequence(BzObjectPool *nodePool, BzBTNode *parent, bool parallel) {
BzAIBTNodeType type = parallel ? BzBTNodeType type = parallel ?
BZ_AIBT_COMP_PARALLEL_SEQUENCE : BZ_BT_COMP_PARALLEL_SEQUENCE :
BZ_AIBT_COMP_SEQUENCE; BZ_BT_COMP_SEQUENCE;
return bzAIBTNodeMake(nodePool, parent, type); return bzBTNodeMake(nodePool, parent, type);
} }
BzAIBTNode *bzAIBTDecorDummy(BzObjectPool *nodePool, BzAIBTNode *parent) { BzBTNode *bzBTDecorDummy(BzObjectPool *nodePool, BzBTNode *parent) {
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_DUMMY); return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_DUMMY);
} }
BzAIBTNode *bzAIBTDecorSuccess(BzObjectPool *nodePool, BzAIBTNode *parent) { BzBTNode *bzBTDecorSuccess(BzObjectPool *nodePool, BzBTNode *parent) {
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_SUCCESS); return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_SUCCESS);
} }
BzAIBTNode *bzAIBTDecorFail(BzObjectPool *nodePool, BzAIBTNode *parent) { BzBTNode *bzBTDecorFail(BzObjectPool *nodePool, BzBTNode *parent) {
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_FAIL); return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_FAIL);
} }
BzAIBTNode *bzAIBTDecorInvert(BzObjectPool *nodePool, BzAIBTNode *parent) { BzBTNode *bzBTDecorInvert(BzObjectPool *nodePool, BzBTNode *parent) {
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_INVERT); return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_INVERT);
} }
BzAIBTNode *bzAIBTDecorUntilSuccess(BzObjectPool *nodePool, BzAIBTNode *parent) { BzBTNode *bzBTDecorUntilSuccess(BzObjectPool *nodePool, BzBTNode *parent) {
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_UNTIL_SUCCESS); return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_UNTIL_SUCCESS);
} }
BzAIBTNode *bzAIBTDecorUntilFail(BzObjectPool *nodePool, BzAIBTNode *parent) { BzBTNode *bzBTDecorUntilFail(BzObjectPool *nodePool, BzBTNode *parent) {
return bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_UNTIL_FAIL); return bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_UNTIL_FAIL);
} }
BzAIBTNode *bzAIBTDecorRepeat(BzObjectPool *nodePool, BzAIBTNode *parent, i32 n) { BzBTNode *bzBTDecorRepeat(BzObjectPool *nodePool, BzBTNode *parent, i32 n) {
BzAIBTNode *node = bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_REPEAT); BzBTNode *node = bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_REPEAT);
node->as.repeat.n = n; node->as.repeat.n = n;
return node; return node;
} }
BzAIBTNode *bzAIBTDecorDelay(BzObjectPool *nodePool, BzAIBTNode *parent, f32 ms) { BzBTNode *bzBTDecorDelay(BzObjectPool *nodePool, BzBTNode *parent, f32 ms) {
BzAIBTNode *node = bzAIBTNodeMake(nodePool, parent, BZ_AIBT_DECOR_DELAY); BzBTNode *node = bzBTNodeMake(nodePool, parent, BZ_BT_DECOR_DELAY);
node->as.delay.ms = ms; node->as.delay.ms = ms;
return node; return node;
} }
BzAIBTNode *bzAIBTAction(BzObjectPool *nodePool, BzAIBTNode *parent, BzAIBTActionFn fn, BzBTNode *bzBTAction(BzObjectPool *nodePool, BzBTNode *parent, BzBTActionFn fn,
const char *name) { const char *name) {
BzAIBTNode *node = bzAIBTNodeMake(nodePool, parent, BZ_AIBT_ACTION); BzBTNode *node = bzBTNodeMake(nodePool, parent, BZ_BT_ACTION);
node->as.action.fn = fn; node->as.action.fn = fn;
node->as.action.name = name; node->as.action.name = name;
return node; return node;
} }
i32 bzAIBTDecorGetRepeat(const BzAIBTNode *node) { i32 bzBTDecorGetRepeat(const BzBTNode *node) {
BZ_ASSERT(node->type == BZ_AIBT_DECOR_REPEAT); BZ_ASSERT(node->type == BZ_BT_DECOR_REPEAT);
return node->as.repeat.n; return node->as.repeat.n;
} }
f32 bzAIBTDecorGetDelay(const BzAIBTNode *node) { f32 bzBTDecorGetDelay(const BzBTNode *node) {
BZ_ASSERT(node->type == BZ_AIBT_DECOR_DELAY); BZ_ASSERT(node->type == BZ_BT_DECOR_DELAY);
return node->as.delay.ms; return node->as.delay.ms;
} }
BzAIBTActionFn bzAIBTActionGetFn(const BzAIBTNode *node) { BzBTActionFn bzBTActionGetFn(const BzBTNode *node) {
BZ_ASSERT(node->type == BZ_AIBT_ACTION); BZ_ASSERT(node->type == BZ_BT_ACTION);
return node->as.action.fn; return node->as.action.fn;
} }
const char *bzAIBTActionGetName(const BzAIBTNode *node) { const char *bzBTActionGetName(const BzBTNode *node) {
BZ_ASSERT(node->type == BZ_AIBT_ACTION); BZ_ASSERT(node->type == BZ_BT_ACTION);
return node->as.action.name; return node->as.action.name;
} }
BzAIBTNodeType bzAIBTGetNodeType(const BzAIBTNode *node) { BzBTNodeType bzBTGetNodeType(const BzBTNode *node) {
return node->type; return node->type;
} }
BzAIBTNode *bzAIBTNodeChild(const BzAIBTNode *node) { BzBTNode *bzBTNodeChild(const BzBTNode *node) {
return node->first; return node->first;
} }
BzAIBTNode *bzAIBTNodeNext(const BzAIBTNode *node) { BzBTNode *bzBTNodeNext(const BzBTNode *node) {
return node->next; return node->next;
} }
const BzAIBTNodeState *bzAIBTNodeStateNext(const BzAIBTNodeState *state) { const BzBTNodeState *bzBTNodeStateNext(const BzBTNodeState *state) {
BZ_ASSERT(state); BZ_ASSERT(state);
return state->next; return state->next;
} }
bool bzAIBTNodeMatchesState(const BzAIBTNode *node, const BzAIBTNodeState *state) { bool bzBTNodeMatchesState(const BzBTNode *node, const BzBTNodeState *state) {
return state && state->node == node; return state && state->node == node;
} }
i32 bzAIBTRepeatStateGetIter(const BzAIBTNodeState *state) { i32 bzBTRepeatStateGetIter(const BzBTNodeState *state) {
BZ_ASSERT(state->node && state->node->type == BZ_AIBT_DECOR_REPEAT); BZ_ASSERT(state->node && state->node->type == BZ_BT_DECOR_REPEAT);
return state->as.repeat.iter; return state->as.repeat.iter;
} }
f32 bzAIBTDelayStateGetElapsed(const BzAIBTNodeState *state) { f32 bzBTDelayStateGetElapsed(const BzBTNodeState *state) {
BZ_ASSERT(state->node && state->node->type == BZ_AIBT_DECOR_DELAY); BZ_ASSERT(state->node && state->node->type == BZ_BT_DECOR_DELAY);
return state->as.delay.elapsed; return state->as.delay.elapsed;
} }
BzAIBTState bzAIBTCreateState(const BzAIBTStateDesc *desc) { BzBTState bzBTCreateState(const BzBTStateDesc *desc) {
BZ_ASSERT(desc->pool); BZ_ASSERT(desc->pool);
BZ_ASSERT(bzObjectPoolGetObjectSize(desc->pool) == bzAIBTGetNodeStateSize()); BZ_ASSERT(bzObjectPoolGetObjectSize(desc->pool) == bzBTGetNodeStateSize());
BZ_ASSERT(desc->root); BZ_ASSERT(desc->root);
return (BzAIBTState) { return (BzBTState) {
.root = desc->root, .root = desc->root,
.first = NULL, .first = NULL,
.last = NULL, .last = NULL,
@@ -232,17 +232,17 @@ BzAIBTState bzAIBTCreateState(const BzAIBTStateDesc *desc) {
.userData = desc->userData .userData = desc->userData
}; };
} }
void bzAIBTDestroyState(BzAIBTState *state) { void bzBTDestroyState(BzBTState *state) {
BzAIBTNodeState *pNodeState = state->first; BzBTNodeState *pNodeState = state->first;
while (pNodeState) { while (pNodeState) {
BzAIBTNodeState *next = pNodeState->next; BzBTNodeState *next = pNodeState->next;
bzObjectPoolRelease(state->nodeStatePool, pNodeState); bzObjectPoolRelease(state->nodeStatePool, pNodeState);
pNodeState = next; pNodeState = next;
} }
bzMemSet(state, 0, sizeof(*state)); bzMemSet(state, 0, sizeof(*state));
} }
void bzAIBTStateAppend(BzAIBTState *state, BzAIBTNodeState *nodeState) { void bzBTStateAppend(BzBTState *state, BzBTNodeState *nodeState) {
nodeState->next = NULL; nodeState->next = NULL;
nodeState->prev = state->last; nodeState->prev = state->last;
if (state->last) if (state->last)
@@ -251,11 +251,11 @@ void bzAIBTStateAppend(BzAIBTState *state, BzAIBTNodeState *nodeState) {
state->first = nodeState; state->first = nodeState;
state->last = 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->first == nodeState) state->first = nodeState->next;
if (state->last == nodeState) state->last = nodeState->prev; if (state->last == nodeState) state->last = nodeState->prev;
BzAIBTNodeState *next = nodeState->next; BzBTNodeState *next = nodeState->next;
BzAIBTNodeState *prev = nodeState->prev; BzBTNodeState *prev = nodeState->prev;
if (nodeState->prev) if (nodeState->prev)
nodeState->prev->next = next; nodeState->prev->next = next;
if (nodeState->next) if (nodeState->next)
@@ -263,155 +263,155 @@ void bzAIBTStatePop(BzAIBTState *state, BzAIBTNodeState *nodeState) {
nodeState->next = NULL; nodeState->next = NULL;
nodeState->prev = 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 // Pop nodeState and transfer it to the back
bzAIBTStatePop(oldState, nodeState); bzBTStatePop(oldState, nodeState);
bzAIBTStateAppend(newState, nodeState); bzBTStateAppend(newState, nodeState);
} }
BzAIBTNodeState *bzAIBTStatePool(BzAIBTState *state, const BzAIBTNode *node) { BzBTNodeState *bzBTStatePool(BzBTState *state, const BzBTNode *node) {
BzAIBTNodeState *nodeState = bzObjectPool(state->nodeStatePool); BzBTNodeState *nodeState = bzObjectPool(state->nodeStatePool);
nodeState->next = NULL; nodeState->next = NULL;
nodeState->prev = NULL; nodeState->prev = NULL;
nodeState->node = node; nodeState->node = node;
return nodeState; return nodeState;
} }
void bzAIBTStateRelease(BzAIBTState *state, BzAIBTNodeState *nodeState) { void bzBTStateRelease(BzBTState *state, BzBTNodeState *nodeState) {
bzObjectPoolRelease(state->nodeStatePool, nodeState); bzObjectPoolRelease(state->nodeStatePool, nodeState);
} }
bool nodeMatchesState(const BzAIBTNode *node, const BzAIBTNodeState *state) { bool nodeMatchesState(const BzBTNode *node, const BzBTNodeState *state) {
return bzAIBTNodeMatchesState(node, state); return bzBTNodeMatchesState(node, state);
} }
BzAIBTNodeState *getNextNodeState(const BzAIBTNode *node, BzAIBTNodeState *nodeState) { BzBTNodeState *getNextNodeState(const BzBTNode *node, BzBTNodeState *nodeState) {
if (nodeState && nodeMatchesState(node, nodeState)) if (nodeState && nodeMatchesState(node, nodeState))
return nodeState->next; return nodeState->next;
return nodeState; return nodeState;
} }
static inline BzAIBTStatus bzAIBTExecuteNode(const BzAIBTNode *node, f32 dt, static inline BzBTStatus bzBTExecuteNode(const BzBTNode *node, f32 dt,
BzAIBTNodeState *nodeState, BzBTNodeState *nodeState,
BzAIBTState *oldState, BzAIBTState *newState); BzBTState *oldState, BzBTState *newState);
static inline BzAIBTStatus bzAIBTExecuteComposite(const BzAIBTNode *node, f32 dt, static inline BzBTStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt,
BzAIBTNodeState *nodeState, BzBTNodeState *nodeState,
BzAIBTState *oldState, BzAIBTState *newState) { BzBTState *oldState, BzBTState *newState) {
BzAIBTNodeState *nextState = getNextNodeState(node, nodeState); BzBTNodeState *nextState = getNextNodeState(node, nodeState);
BzAIBTNode *start = node->first; BzBTNode *start = node->first;
bool isParallel = node->type == BZ_AIBT_COMP_PARALLEL_SEQUENCE || bool isParallel = node->type == BZ_BT_COMP_PARALLEL_SEQUENCE ||
node->type == BZ_AIBT_COMP_PARALLEL_SELECTOR; node->type == BZ_BT_COMP_PARALLEL_SELECTOR;
if (!isParallel && nodeMatchesState(node, nodeState)) if (!isParallel && nodeMatchesState(node, nodeState))
start = nodeState->as.composite.running; start = nodeState->as.composite.running;
// Always push dummy state // Always push dummy state
if (nodeMatchesState(node, nodeState)) { if (nodeMatchesState(node, nodeState)) {
bzAIBTStateRenew(oldState, newState, nodeState); bzBTStateRenew(oldState, newState, nodeState);
} else { } else {
nodeState = bzAIBTStatePool(oldState, node); nodeState = bzBTStatePool(oldState, node);
bzAIBTStateAppend(newState, nodeState); bzBTStateAppend(newState, nodeState);
} }
i32 numRunning = 0; i32 numRunning = 0;
i32 numSuccessful = 0; i32 numSuccessful = 0;
i32 numFailed = 0; i32 numFailed = 0;
i32 numChildren = 0; i32 numChildren = 0;
BzAIBTStatus status = BZ_AIBT_ERROR; BzBTStatus status = BZ_BT_ERROR;
BzAIBTNode *child = start; BzBTNode *child = start;
for (;child; child = child->next) { for (;child; child = child->next) {
BzAIBTStatus childStatus = bzAIBTExecuteNode(child, dt, nextState, oldState, newState); BzBTStatus childStatus = bzBTExecuteNode(child, dt, nextState, oldState, newState);
numChildren++; numChildren++;
switch (childStatus) { switch (childStatus) {
case BZ_AIBT_RUNNING: case BZ_BT_RUNNING:
numRunning++; numRunning++;
break; break;
case BZ_AIBT_SUCCESS: case BZ_BT_SUCCESS:
numSuccessful++; numSuccessful++;
break; break;
case BZ_AIBT_FAIL: case BZ_BT_FAIL:
numFailed++; numFailed++;
break; break;
default: default:
break; break;
} }
switch (node->type) { switch (node->type) {
case BZ_AIBT_COMP_SELECTOR: case BZ_BT_COMP_SELECTOR:
case BZ_AIBT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR:
if (childStatus == BZ_AIBT_SUCCESS) if (childStatus == BZ_BT_SUCCESS)
status = BZ_AIBT_SUCCESS; status = BZ_BT_SUCCESS;
break; break;
case BZ_AIBT_COMP_SEQUENCE: case BZ_BT_COMP_SEQUENCE:
case BZ_AIBT_COMP_PARALLEL_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE:
if (childStatus == BZ_AIBT_FAIL) if (childStatus == BZ_BT_FAIL)
status = BZ_AIBT_FAIL; status = BZ_BT_FAIL;
break; break;
default: default:
break; break;
} }
if (status == BZ_AIBT_FAIL || status == BZ_AIBT_SUCCESS) if (status == BZ_BT_FAIL || status == BZ_BT_SUCCESS)
break; break;
if (numRunning > 0 && !isParallel) { if (numRunning > 0 && !isParallel) {
status = BZ_AIBT_RUNNING; status = BZ_BT_RUNNING;
break; break;
} }
} }
switch (node->type) { switch (node->type) {
case BZ_AIBT_COMP_SELECTOR: case BZ_BT_COMP_SELECTOR:
case BZ_AIBT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR:
if (numFailed == numChildren) if (numFailed == numChildren)
status = BZ_AIBT_FAIL; status = BZ_BT_FAIL;
break; break;
case BZ_AIBT_COMP_SEQUENCE: case BZ_BT_COMP_SEQUENCE:
case BZ_AIBT_COMP_PARALLEL_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE:
if (numSuccessful == numChildren) if (numSuccessful == numChildren)
status = BZ_AIBT_SUCCESS; status = BZ_BT_SUCCESS;
break; break;
default: default:
break; break;
} }
if (status == BZ_AIBT_ERROR) { if (status == BZ_BT_ERROR) {
bzAIBTStatePop(newState, nodeState); bzBTStatePop(newState, nodeState);
return BZ_AIBT_ERROR; return BZ_BT_ERROR;
} }
bool finished = status == BZ_AIBT_SUCCESS || bool finished = status == BZ_BT_SUCCESS ||
status == BZ_AIBT_FAIL; status == BZ_BT_FAIL;
if (finished) { if (finished) {
// Dummy state is no longer needed // Dummy state is no longer needed
bzAIBTStatePop(newState, nodeState); bzBTStatePop(newState, nodeState);
} else { } else {
BZ_ASSERT(status == BZ_AIBT_RUNNING); BZ_ASSERT(status == BZ_BT_RUNNING);
nodeState->as.composite.running = child; nodeState->as.composite.running = child;
} }
return status; return status;
} }
static inline BzAIBTStatus bzAIBTExecuteDecorator(const BzAIBTNode *node, f32 dt, static inline BzBTStatus bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
BzAIBTNodeState *nodeState, BzBTNodeState *nodeState,
BzAIBTState *oldState, BzAIBTState *newState) { BzBTState *oldState, BzBTState *newState) {
// Ensure decorator has only one child, if any // Ensure decorator has only one child, if any
BZ_ASSERT(!node->first || node->first == node->last); BZ_ASSERT(!node->first || node->first == node->last);
BzAIBTNodeState *nextState = getNextNodeState(node, nodeState); BzBTNodeState *nextState = getNextNodeState(node, nodeState);
switch (node->type) { switch (node->type) {
case BZ_AIBT_DECOR_REPEAT: case BZ_BT_DECOR_REPEAT:
if (!nodeMatchesState(node, nodeState)) { if (!nodeMatchesState(node, nodeState)) {
BzAIBTNodeState *newNodeState = bzAIBTStatePool(oldState, node); BzBTNodeState *newNodeState = bzBTStatePool(oldState, node);
newNodeState->as.repeat.iter = 0; newNodeState->as.repeat.iter = 0;
bzAIBTStateAppend(newState, newNodeState); bzBTStateAppend(newState, newNodeState);
nodeState = newNodeState; nodeState = newNodeState;
} else { } else {
bzAIBTStateRenew(oldState, newState, nodeState); bzBTStateRenew(oldState, newState, nodeState);
} }
break; break;
case BZ_AIBT_DECOR_DELAY: case BZ_BT_DECOR_DELAY:
if (!nodeMatchesState(node, nodeState)) { if (!nodeMatchesState(node, nodeState)) {
BzAIBTNodeState *newNodeState = bzAIBTStatePool(oldState, node); BzBTNodeState *newNodeState = bzBTStatePool(oldState, node);
newNodeState->as.delay.elapsed = dt; newNodeState->as.delay.elapsed = dt;
bzAIBTStateAppend(newState, newNodeState); bzBTStateAppend(newState, newNodeState);
return BZ_AIBT_RUNNING; return BZ_BT_RUNNING;
} }
nodeState->as.delay.elapsed += dt; nodeState->as.delay.elapsed += dt;
if (nodeState->as.delay.elapsed < node->as.delay.ms) { if (nodeState->as.delay.elapsed < node->as.delay.ms) {
bzAIBTStateRenew(oldState, newState, nodeState); bzBTStateRenew(oldState, newState, nodeState);
return BZ_AIBT_RUNNING; return BZ_BT_RUNNING;
} }
break; break;
default: default:
@@ -419,109 +419,109 @@ static inline BzAIBTStatus bzAIBTExecuteDecorator(const BzAIBTNode *node, f32 dt
} }
// Implicit success, if no children are present // Implicit success, if no children are present
BzAIBTStatus inStatus = BZ_AIBT_SUCCESS; BzBTStatus inStatus = BZ_BT_SUCCESS;
if (node->first) if (node->first)
inStatus = bzAIBTExecuteNode(node->first, dt, nextState, oldState, newState); inStatus = bzBTExecuteNode(node->first, dt, nextState, oldState, newState);
// Propagate ERROR, RUNNING up // Propagate ERROR, RUNNING up
if (inStatus == BZ_AIBT_ERROR) if (inStatus == BZ_BT_ERROR)
return BZ_AIBT_ERROR; return BZ_BT_ERROR;
if (inStatus == BZ_AIBT_RUNNING) if (inStatus == BZ_BT_RUNNING)
return BZ_AIBT_RUNNING; return BZ_BT_RUNNING;
BzAIBTStatus status = BZ_AIBT_ERROR; BzBTStatus status = BZ_BT_ERROR;
switch (node->type) { switch (node->type) {
case BZ_AIBT_DECOR_DUMMY: case BZ_BT_DECOR_DUMMY:
case BZ_AIBT_DECOR_DELAY: // Delay already handled case BZ_BT_DECOR_DELAY: // Delay already handled
status = inStatus; status = inStatus;
break; break;
case BZ_AIBT_DECOR_SUCCESS: case BZ_BT_DECOR_SUCCESS:
status = BZ_AIBT_SUCCESS; status = BZ_BT_SUCCESS;
break; break;
case BZ_AIBT_DECOR_FAIL: case BZ_BT_DECOR_FAIL:
status = BZ_AIBT_FAIL; status = BZ_BT_FAIL;
break; break;
case BZ_AIBT_DECOR_INVERT: case BZ_BT_DECOR_INVERT:
if (inStatus == BZ_AIBT_FAIL) if (inStatus == BZ_BT_FAIL)
status = BZ_AIBT_SUCCESS; status = BZ_BT_SUCCESS;
if (inStatus == BZ_AIBT_SUCCESS) if (inStatus == BZ_BT_SUCCESS)
status = BZ_AIBT_FAIL; status = BZ_BT_FAIL;
break; break;
case BZ_AIBT_DECOR_UNTIL_SUCCESS: case BZ_BT_DECOR_UNTIL_SUCCESS:
if (inStatus == BZ_AIBT_SUCCESS) if (inStatus == BZ_BT_SUCCESS)
status = BZ_AIBT_SUCCESS; status = BZ_BT_SUCCESS;
else else
status = BZ_AIBT_RUNNING; status = BZ_BT_RUNNING;
break; break;
case BZ_AIBT_DECOR_UNTIL_FAIL: case BZ_BT_DECOR_UNTIL_FAIL:
if (inStatus == BZ_AIBT_FAIL) if (inStatus == BZ_BT_FAIL)
status = BZ_AIBT_SUCCESS; status = BZ_BT_SUCCESS;
else else
status = BZ_AIBT_RUNNING; status = BZ_BT_RUNNING;
break; break;
case BZ_AIBT_DECOR_REPEAT: case BZ_BT_DECOR_REPEAT:
BZ_ASSERT(nodeState->node == node); BZ_ASSERT(nodeState->node == node);
nodeState->as.repeat.iter++; nodeState->as.repeat.iter++;
if (nodeState->as.repeat.iter >= node->as.repeat.n) { if (nodeState->as.repeat.iter >= node->as.repeat.n) {
bzAIBTStatePop(newState, nodeState); bzBTStatePop(newState, nodeState);
status = inStatus; status = inStatus;
break; break;
} }
status = BZ_AIBT_RUNNING; status = BZ_BT_RUNNING;
break; break;
default: default:
break; break;
} }
return status; return status;
} }
static inline BzAIBTStatus bzAIBTExecuteNode(const BzAIBTNode *node, f32 dt, static inline BzBTStatus bzBTExecuteNode(const BzBTNode *node, f32 dt,
BzAIBTNodeState *nodeState, BzBTNodeState *nodeState,
BzAIBTState *oldState, BzAIBTState *newState) { BzBTState *oldState, BzBTState *newState) {
BzAIBTStatus status = BZ_AIBT_ERROR; BzBTStatus status = BZ_BT_ERROR;
switch (node->type) { switch (node->type) {
case BZ_AIBT_COMP_SELECTOR: case BZ_BT_COMP_SELECTOR:
case BZ_AIBT_COMP_SEQUENCE: case BZ_BT_COMP_SEQUENCE:
case BZ_AIBT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR:
case BZ_AIBT_COMP_PARALLEL_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE:
status = bzAIBTExecuteComposite(node, dt, nodeState, oldState, newState); status = bzBTExecuteComposite(node, dt, nodeState, oldState, newState);
break; break;
case BZ_AIBT_DECOR_DUMMY: case BZ_BT_DECOR_DUMMY:
case BZ_AIBT_DECOR_SUCCESS: case BZ_BT_DECOR_SUCCESS:
case BZ_AIBT_DECOR_FAIL: case BZ_BT_DECOR_FAIL:
case BZ_AIBT_DECOR_INVERT: case BZ_BT_DECOR_INVERT:
case BZ_AIBT_DECOR_UNTIL_SUCCESS: case BZ_BT_DECOR_UNTIL_SUCCESS:
case BZ_AIBT_DECOR_UNTIL_FAIL: case BZ_BT_DECOR_UNTIL_FAIL:
case BZ_AIBT_DECOR_REPEAT: case BZ_BT_DECOR_REPEAT:
case BZ_AIBT_DECOR_DELAY: case BZ_BT_DECOR_DELAY:
status = bzAIBTExecuteDecorator(node, dt, nodeState, oldState, newState); status = bzBTExecuteDecorator(node, dt, nodeState, oldState, newState);
break; break;
case BZ_AIBT_ACTION: case BZ_BT_ACTION:
BZ_ASSERT(node->as.action.fn); BZ_ASSERT(node->as.action.fn);
return node->as.action.fn(oldState->userData); return node->as.action.fn(oldState->userData);
} }
return status; return status;
} }
BzAIBTStatus bzAIBTExecute(BzAIBTState *state, f32 dt) { BzBTStatus bzBTExecute(BzBTState *state, f32 dt) {
BZ_ASSERT(state->nodeStatePool); BZ_ASSERT(state->nodeStatePool);
BZ_ASSERT(bzObjectPoolGetObjectSize(state->nodeStatePool) == bzAIBTGetNodeStateSize()); BZ_ASSERT(bzObjectPoolGetObjectSize(state->nodeStatePool) == bzBTGetNodeStateSize());
BZ_ASSERT(state); BZ_ASSERT(state);
BZ_ASSERT(state->root); BZ_ASSERT(state->root);
BzAIBTState newState = { BzBTState newState = {
.first = NULL, .first = NULL,
.last = NULL, .last = NULL,
}; };
BzAIBTNodeState *first = state->first; BzBTNodeState *first = state->first;
const BzAIBTNode *firstNode = first ? first->node : state->root; const BzBTNode *firstNode = first ? first->node : state->root;
BzAIBTStatus status = bzAIBTExecuteNode(firstNode, dt, first, state, &newState); BzBTStatus status = bzBTExecuteNode(firstNode, dt, first, state, &newState);
// Release leftover states // Release leftover states
BzAIBTNodeState *pState = state->first; BzBTNodeState *pState = state->first;
while (pState) { while (pState) {
BzAIBTNodeState *next = pState->next; BzBTNodeState *next = pState->next;
bzAIBTStateRelease(state, pState); bzBTStateRelease(state, pState);
pState = next; pState = next;
} }
state->first = newState.first; state->first = newState.first;

View File

@@ -3,99 +3,99 @@
#include "../defines.h" #include "../defines.h"
typedef struct BzAIBTNode BzAIBTNode; typedef struct BzBTNode BzBTNode;
typedef enum BzAIBTStatus { typedef enum BzBTStatus {
BZ_AIBT_RUNNING, BZ_BT_RUNNING,
BZ_AIBT_SUCCESS, BZ_BT_SUCCESS,
BZ_AIBT_FAIL, BZ_BT_FAIL,
BZ_AIBT_ERROR, BZ_BT_ERROR,
} BzAIBTStatus; } BzBTStatus;
typedef BzAIBTStatus(*BzAIBTActionFn)(void *data); typedef BzBTStatus(*BzBTActionFn)(void *data);
typedef enum BzAIBTNodeType { typedef enum BzBTNodeType {
// Composite // Composite
BZ_AIBT_COMP_SELECTOR, BZ_BT_COMP_SELECTOR,
BZ_AIBT_COMP_SEQUENCE, BZ_BT_COMP_SEQUENCE,
BZ_AIBT_COMP_PARALLEL_SELECTOR, BZ_BT_COMP_PARALLEL_SELECTOR,
BZ_AIBT_COMP_PARALLEL_SEQUENCE, BZ_BT_COMP_PARALLEL_SEQUENCE,
// Decorator // Decorator
BZ_AIBT_DECOR_DUMMY, BZ_BT_DECOR_DUMMY,
BZ_AIBT_DECOR_SUCCESS, BZ_BT_DECOR_SUCCESS,
BZ_AIBT_DECOR_FAIL, BZ_BT_DECOR_FAIL,
BZ_AIBT_DECOR_INVERT, BZ_BT_DECOR_INVERT,
BZ_AIBT_DECOR_UNTIL_SUCCESS, BZ_BT_DECOR_UNTIL_SUCCESS,
BZ_AIBT_DECOR_UNTIL_FAIL, BZ_BT_DECOR_UNTIL_FAIL,
BZ_AIBT_DECOR_REPEAT, BZ_BT_DECOR_REPEAT,
BZ_AIBT_DECOR_DELAY, BZ_BT_DECOR_DELAY,
// Action/Task // Action/Task
BZ_AIBT_ACTION, BZ_BT_ACTION,
} BzAIBTNodeType; } BzBTNodeType;
typedef struct BzObjectPool BzObjectPool; typedef struct BzObjectPool BzObjectPool;
typedef struct BzAIBTNodeState BzAIBTNodeState; typedef struct BzBTNodeState BzBTNodeState;
typedef struct BzAIBTState { typedef struct BzBTState {
const BzAIBTNode *root; const BzBTNode *root;
BzAIBTNodeState *first; BzBTNodeState *first;
BzAIBTNodeState *last; BzBTNodeState *last;
BzObjectPool *nodeStatePool; BzObjectPool *nodeStatePool;
void *userData; void *userData;
} BzAIBTState; } BzBTState;
typedef struct BzAIBTStateDesc { typedef struct BzBTStateDesc {
const BzAIBTNode *root; const BzBTNode *root;
BzObjectPool *pool; BzObjectPool *pool;
void *userData; void *userData;
} BzAIBTStateDesc; } BzBTStateDesc;
size_t bzAIBTGetNodeSize(); size_t bzBTGetNodeSize();
size_t bzAIBTGetNodeStateSize(); size_t bzBTGetNodeStateSize();
const char *bzAIBTNodeTypeToStr(BzAIBTNodeType type); const char *bzBTNodeTypeToStr(BzBTNodeType type);
BzAIBTNode *bzAIBTMakeRoot(BzObjectPool *nodePool); BzBTNode *bzBTMakeRoot(BzObjectPool *nodePool);
void bzAIBTDestroyRoot(BzObjectPool *nodePool, BzAIBTNode *node); void bzBTDestroyRoot(BzObjectPool *nodePool, BzBTNode *node);
BzAIBTNode *bzAIBTCompSelector(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel); BzBTNode *bzBTCompSelector(BzObjectPool *nodePool, BzBTNode *parent, bool parallel);
BzAIBTNode *bzAIBTCompSequence(BzObjectPool *nodePool, BzAIBTNode *parent, bool parallel); BzBTNode *bzBTCompSequence(BzObjectPool *nodePool, BzBTNode *parent, bool parallel);
BzAIBTNode *bzAIBTDecorDummy(BzObjectPool *nodePool, BzAIBTNode *parent); BzBTNode *bzBTDecorDummy(BzObjectPool *nodePool, BzBTNode *parent);
BzAIBTNode *bzAIBTDecorSuccess(BzObjectPool *nodePool, BzAIBTNode *parent); BzBTNode *bzBTDecorSuccess(BzObjectPool *nodePool, BzBTNode *parent);
BzAIBTNode *bzAIBTDecorFail(BzObjectPool *nodePool, BzAIBTNode *parent); BzBTNode *bzBTDecorFail(BzObjectPool *nodePool, BzBTNode *parent);
BzAIBTNode *bzAIBTDecorInvert(BzObjectPool *nodePool, BzAIBTNode *parent); BzBTNode *bzBTDecorInvert(BzObjectPool *nodePool, BzBTNode *parent);
BzAIBTNode *bzAIBTDecorUntilSuccess(BzObjectPool *nodePool, BzAIBTNode *parent); BzBTNode *bzBTDecorUntilSuccess(BzObjectPool *nodePool, BzBTNode *parent);
BzAIBTNode *bzAIBTDecorUntilFail(BzObjectPool *nodePool, BzAIBTNode *parent); BzBTNode *bzBTDecorUntilFail(BzObjectPool *nodePool, BzBTNode *parent);
BzAIBTNode *bzAIBTDecorRepeat(BzObjectPool *nodePool, BzAIBTNode *parent, i32 n); BzBTNode *bzBTDecorRepeat(BzObjectPool *nodePool, BzBTNode *parent, i32 n);
BzAIBTNode *bzAIBTDecorDelay(BzObjectPool *nodePool, BzAIBTNode *parent, f32 ms); BzBTNode *bzBTDecorDelay(BzObjectPool *nodePool, BzBTNode *parent, f32 ms);
BzAIBTNode *bzAIBTAction(BzObjectPool *nodePool, BzAIBTNode *parent, BzAIBTActionFn fn, BzBTNode *bzBTAction(BzObjectPool *nodePool, BzBTNode *parent, BzBTActionFn fn,
const char *name); const char *name);
// Reflection data // Reflection data
i32 bzAIBTDecorGetRepeat(const BzAIBTNode *node); i32 bzBTDecorGetRepeat(const BzBTNode *node);
f32 bzAIBTDecorGetDelay(const BzAIBTNode *node); f32 bzBTDecorGetDelay(const BzBTNode *node);
BzAIBTActionFn bzAIBTActionGetFn(const BzAIBTNode *node); BzBTActionFn bzBTActionGetFn(const BzBTNode *node);
const char *bzAIBTActionGetName(const BzAIBTNode *node); const char *bzBTActionGetName(const BzBTNode *node);
BzAIBTNodeType bzAIBTGetNodeType(const BzAIBTNode *node); BzBTNodeType bzBTGetNodeType(const BzBTNode *node);
BzAIBTNode *bzAIBTNodeChild(const BzAIBTNode *node); BzBTNode *bzBTNodeChild(const BzBTNode *node);
BzAIBTNode *bzAIBTNodeNext(const BzAIBTNode *node); BzBTNode *bzBTNodeNext(const BzBTNode *node);
const BzAIBTNodeState *bzAIBTNodeStateNext(const BzAIBTNodeState *state); const BzBTNodeState *bzBTNodeStateNext(const BzBTNodeState *state);
bool bzAIBTNodeMatchesState(const BzAIBTNode *node, const BzAIBTNodeState *state); bool bzBTNodeMatchesState(const BzBTNode *node, const BzBTNodeState *state);
i32 bzAIBTRepeatStateGetIter(const BzAIBTNodeState *state); i32 bzBTRepeatStateGetIter(const BzBTNodeState *state);
f32 bzAIBTDelayStateGetElapsed(const BzAIBTNodeState *state); f32 bzBTDelayStateGetElapsed(const BzBTNodeState *state);
BzAIBTState bzAIBTCreateState(const BzAIBTStateDesc *desc); BzBTState bzBTCreateState(const BzBTStateDesc *desc);
void bzAIBTDestroyState(BzAIBTState *state); void bzBTDestroyState(BzBTState *state);
BzAIBTStatus bzAIBTExecute(BzAIBTState *state, f32 dt); BzBTStatus bzBTExecute(BzBTState *state, f32 dt);
#endif //BREEZE_BEHAVIOUR_TREE_H #endif //BREEZE_BEHAVIOUR_TREE_H

View File

@@ -4,39 +4,39 @@
BzObjectPool *nodePool = NULL; BzObjectPool *nodePool = NULL;
BzObjectPool *nodeStatePool = NULL; BzObjectPool *nodeStatePool = NULL;
BzAIBTNode *printBT = NULL; BzBTNode *printBT = NULL;
BzAIBTState agentState; BzBTState agentState;
BzAIBTStatus printAction(void *data) { BzBTStatus printAction(void *data) {
bzLogInfo("Hello, world!"); bzLogInfo("Hello, world!");
return BZ_AIBT_SUCCESS; return BZ_BT_SUCCESS;
} }
bool init(int *game) { bool init(int *game) {
rlImGuiSetup(true); rlImGuiSetup(true);
nodePool = bzObjectPoolCreate(&(BzObjectPoolDesc) { nodePool = bzObjectPoolCreate(&(BzObjectPoolDesc) {
.objectSize = bzAIBTGetNodeSize(), .objectSize = bzBTGetNodeSize(),
}); });
nodeStatePool = bzObjectPoolCreate(&(BzObjectPoolDesc) { nodeStatePool = bzObjectPoolCreate(&(BzObjectPoolDesc) {
.objectSize = bzAIBTGetNodeStateSize() .objectSize = bzBTGetNodeStateSize()
}); });
// for 1..5: // for 1..5:
// seq // seq
// delay 1s // delay 1s
// print "Hello, world!" // print "Hello, world!"
printBT = bzAIBTMakeRoot(nodePool); printBT = bzBTMakeRoot(nodePool);
BzAIBTNode *node = bzAIBTDecorRepeat(nodePool, printBT, 5); BzBTNode *node = bzBTDecorRepeat(nodePool, printBT, 5);
BzAIBTNode *seq = bzAIBTCompSequence(nodePool, node, false); BzBTNode *seq = bzBTCompSequence(nodePool, node, false);
bzAIBTDecorDelay(nodePool, seq, 1.0f); bzBTDecorDelay(nodePool, seq, 1.0f);
bzAIBTAction(nodePool, seq, printAction, "printAction"); bzBTAction(nodePool, seq, printAction, "printAction");
agentState = bzAIBTCreateState(&(BzAIBTStateDesc) { agentState = bzBTCreateState(&(BzBTStateDesc) {
.root = printBT, .root = printBT,
.pool = nodeStatePool, .pool = nodeStatePool,
.userData = NULL .userData = NULL
}); });
return true; return true;
@@ -47,60 +47,60 @@ void deinit(int *game) {
bzObjectPoolDestroy(nodeStatePool); bzObjectPoolDestroy(nodeStatePool);
} }
void igRenderBTNode(const BzAIBTNode *node, const BzAIBTNodeState *state, bool sameLine, i32 depth) { void igRenderBTNode(const BzBTNode *node, const BzBTNodeState *state, bool sameLine, i32 depth) {
const BzAIBTNode *child = bzAIBTNodeChild(node); const BzBTNode *child = bzBTNodeChild(node);
BzAIBTNodeType type = bzAIBTGetNodeType(node); BzBTNodeType type = bzBTGetNodeType(node);
char extraInfo[128]; char extraInfo[128];
extraInfo[0] = '\0'; extraInfo[0] = '\0';
bool hasState = bzAIBTNodeMatchesState(node, state); bool hasState = bzBTNodeMatchesState(node, state);
switch (type) { switch (type) {
case BZ_AIBT_DECOR_REPEAT: case BZ_BT_DECOR_REPEAT:
if (hasState) { if (hasState) {
snprintf(extraInfo, sizeof(extraInfo), " (%d < %d)", snprintf(extraInfo, sizeof(extraInfo), " (%d < %d)",
bzAIBTRepeatStateGetIter(state), bzBTRepeatStateGetIter(state),
bzAIBTDecorGetRepeat(node)); bzBTDecorGetRepeat(node));
} else { } else {
snprintf(extraInfo, sizeof(extraInfo), " (%d)", bzAIBTDecorGetRepeat(node)); snprintf(extraInfo, sizeof(extraInfo), " (%d)", bzBTDecorGetRepeat(node));
} }
break; break;
case BZ_AIBT_DECOR_DELAY: case BZ_BT_DECOR_DELAY:
if (hasState) { if (hasState) {
snprintf(extraInfo, sizeof(extraInfo), " (%.2f < %.2fms)", snprintf(extraInfo, sizeof(extraInfo), " (%.2f < %.2fms)",
bzAIBTDelayStateGetElapsed(state), bzBTDelayStateGetElapsed(state),
bzAIBTDecorGetDelay(node)); bzBTDecorGetDelay(node));
} else { } else {
snprintf(extraInfo, sizeof(extraInfo), " (%.2fms)", bzAIBTDecorGetDelay(node)); snprintf(extraInfo, sizeof(extraInfo), " (%.2fms)", bzBTDecorGetDelay(node));
} }
break; break;
case BZ_AIBT_ACTION: case BZ_BT_ACTION:
snprintf(extraInfo, sizeof(extraInfo), " (%s:%p)", snprintf(extraInfo, sizeof(extraInfo), " (%s:%p)",
bzAIBTActionGetName(node), bzBTActionGetName(node),
bzAIBTActionGetFn(node)); bzBTActionGetFn(node));
break; break;
default: default:
break; break;
} }
if (hasState) if (hasState)
state = bzAIBTNodeStateNext(state); state = bzBTNodeStateNext(state);
ImVec4 color = {1.0f, 1.0f, 1.0f, 1.0f}; ImVec4 color = {1.0f, 1.0f, 1.0f, 1.0f};
if (hasState) if (hasState)
color = (ImVec4) {1.0f, 1.0f, 0.5f, 1.0f}; color = (ImVec4) {1.0f, 1.0f, 0.5f, 1.0f};
bool hasSingleChild = false; bool hasSingleChild = false;
if (child && bzAIBTNodeNext(child) == NULL) hasSingleChild = true; if (child && bzBTNodeNext(child) == NULL) hasSingleChild = true;
const char *suffix = hasSingleChild ? " > " : ": "; const char *suffix = hasSingleChild ? " > " : ": ";
if (sameLine) { if (sameLine) {
igTextColored(color, "%s%s%s", bzAIBTNodeTypeToStr(type), igTextColored(color, "%s%s%s", bzBTNodeTypeToStr(type),
extraInfo, suffix); extraInfo, suffix);
} else { } else {
igTextColored(color, "%*s%s %s", igTextColored(color, "%*s%s %s",
depth * 2, "", depth * 2, "",
bzAIBTNodeTypeToStr(type), extraInfo, suffix); bzBTNodeTypeToStr(type), extraInfo, suffix);
depth++; depth++;
} }
@@ -109,12 +109,12 @@ void igRenderBTNode(const BzAIBTNode *node, const BzAIBTNodeState *state, bool s
while (child) { while (child) {
if (hasSingleChild) igSameLine(0, 0); if (hasSingleChild) igSameLine(0, 0);
igRenderBTNode(child, state, hasSingleChild, depth); igRenderBTNode(child, state, hasSingleChild, depth);
child = bzAIBTNodeNext(child); child = bzBTNodeNext(child);
} }
} }
void igRenderBT(BzAIBTState *state) { void igRenderBT(BzBTState *state) {
const BzAIBTNode *root = state->root; const BzBTNode *root = state->root;
if (igBegin("BehaviourTree", NULL, 0)) { if (igBegin("BehaviourTree", NULL, 0)) {
igRenderBTNode(root, state->first, false, 0); igRenderBTNode(root, state->first, false, 0);
} }
@@ -124,7 +124,7 @@ void igRenderBT(BzAIBTState *state) {
void render(float dt, int *game) { void render(float dt, int *game) {
ClearBackground(WHITE); ClearBackground(WHITE);
BzAIBTStatus status = bzAIBTExecute(&agentState, dt); BzBTStatus status = bzBTExecute(&agentState, dt);
rlImGuiBegin(); rlImGuiBegin();
igRenderBT(&agentState); igRenderBT(&agentState);