diff --git a/engine/breeze/ai/behaviour_tree.c b/engine/breeze/ai/behaviour_tree.c index 856c79d..f0f7782 100644 --- a/engine/breeze/ai/behaviour_tree.c +++ b/engine/breeze/ai/behaviour_tree.c @@ -276,6 +276,20 @@ BzBTNodeState *execStatePopFront(BzBTExecState *state) { popped->next = NULL; return popped; } +void execStatePushFront(BzBTExecState *state, BzBTNodeState *nodeState) { + BZ_ASSERT(state); + + nodeState->prev = NULL; + nodeState->next = state->first; + + if (state->first) { + state->first->prev = nodeState; + } else { + state->first = nodeState; + state->last = nodeState; + } + state->first = nodeState; +} void execStatePushBack(BzBTExecState *state, BzBTNodeState *nodeState) { BZ_ASSERT(state); @@ -348,34 +362,31 @@ static void releaseNodeState(BzObjectPool *pool, BzBTNodeState *nodeState) { static inline BzBTExecStatus bzBTExecuteNode(const BzBTNode *node, f32 dt, BzBTExecState *nodeState, BzObjectPool *statePool); -#if 0 static inline BzBTExecStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt, - BzBTExecState *nodeState, BzObjectPool *statePool) { - BzBTNodeState *nextState = getNextNodeState(node, nodeState); - BzBTNode *start = node->first; + BzBTExecState *state, BzObjectPool *statePool) { + BzBTNodeState *nodeState = getNodeState(node, state); + bool isParallel = node->type == BZ_BT_COMP_PARALLEL_SEQUENCE || node->type == BZ_BT_COMP_PARALLEL_SELECTOR; - if (!isParallel && nodeMatchesState(node, nodeState)) + BzBTNode *start = node->first; + if (!isParallel && nodeState) start = nodeState->as.composite.running; - // Always push dummy state - if (nodeMatchesState(node, nodeState)) { - bzBTStateRenew(oldState, newState, nodeState); - } else { - nodeState = bzBTStatePool(oldState, node); - bzBTStateAppend(newState, nodeState); - } i32 numRunning = 0; i32 numSuccessful = 0; i32 numFailed = 0; i32 numChildren = 0; - BzBTStatus status = BZ_BT_ERROR; + BzBTExecStatus status = { .status = BZ_BT_ERROR }; BzBTNode *child = start; for (;child; child = child->next) { - BzBTStatus childStatus = bzBTExecuteNode(child, dt, nextState, oldState, newState); + BzBTExecStatus childStatus = bzBTExecuteNode(child, dt, state, statePool); + if (childStatus.status == BZ_BT_RUNNING) { + execStateMerge(&status.state, &childStatus.state); + } + BZ_ASSERT(childStatus.state.first == NULL); numChildren++; - switch (childStatus) { + switch (childStatus.status) { case BZ_BT_RUNNING: numRunning++; break; @@ -391,21 +402,21 @@ static inline BzBTExecStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt, switch (node->type) { case BZ_BT_COMP_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR: - if (childStatus == BZ_BT_SUCCESS) - status = BZ_BT_SUCCESS; + if (childStatus.status == BZ_BT_SUCCESS) + status.status = BZ_BT_SUCCESS; break; case BZ_BT_COMP_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE: - if (childStatus == BZ_BT_FAIL) - status = BZ_BT_FAIL; + if (childStatus.status == BZ_BT_FAIL) + status.status = BZ_BT_FAIL; break; default: break; } - if (status == BZ_BT_FAIL || status == BZ_BT_SUCCESS) + if (status.status == BZ_BT_FAIL || status.status == BZ_BT_SUCCESS) break; if (numRunning > 0 && !isParallel) { - status = BZ_BT_RUNNING; + status.status = BZ_BT_RUNNING; break; } } @@ -413,34 +424,38 @@ static inline BzBTExecStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt, case BZ_BT_COMP_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR: if (numFailed == numChildren) - status = BZ_BT_FAIL; + status.status = BZ_BT_FAIL; break; case BZ_BT_COMP_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE: if (numSuccessful == numChildren) - status = BZ_BT_SUCCESS; + status.status = BZ_BT_SUCCESS; break; default: break; } - if (status == BZ_BT_ERROR) { - bzBTStateRelease(newState, nodeState); - return BZ_BT_ERROR; + // Propagate ERROR up + if (status.status == BZ_BT_ERROR) { + execStateClear(&status.state, statePool); + status.status = BZ_BT_ERROR; + return status; } - bool finished = status == BZ_BT_SUCCESS || - status == BZ_BT_FAIL; + bool finished = status.status == BZ_BT_SUCCESS || + status.status == BZ_BT_FAIL; if (finished) { - // Dummy state is no longer needed - bzBTStateRelease(newState, nodeState); - } else { - BZ_ASSERT(status == BZ_BT_RUNNING); - nodeState->as.composite.running = child; + BZ_ASSERT(status.state.first == NULL); + if (nodeState) releaseNodeState(statePool, nodeState); + return status; } + BZ_ASSERT(status.status == BZ_BT_RUNNING); + nodeState = ensureValidNodeState(node, statePool, nodeState); + nodeState->as.composite.running = child; + execStatePushFront(&status.state, nodeState); + return status; } -#endif static inline BzBTExecStatus bzBTExecuteDecorator(const BzBTNode *node, f32 dt, BzBTExecState *state, BzObjectPool *statePool) { // Ensure decorator has only one child, if any @@ -544,7 +559,7 @@ static inline BzBTExecStatus bzBTExecuteNode(const BzBTNode *node, f32 dt, case BZ_BT_COMP_SEQUENCE: case BZ_BT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SEQUENCE: - //status = bzBTExecuteComposite(node, dt, nodeState, statePool); + status = bzBTExecuteComposite(node, dt, nodeState, statePool); break; case BZ_BT_DECOR_DUMMY: case BZ_BT_DECOR_SUCCESS: