Refactor behaviour tree composites

This commit is contained in:
2024-01-10 21:34:08 +01:00
parent 93b665b290
commit eb14bc8b2a

View File

@@ -276,6 +276,20 @@ BzBTNodeState *execStatePopFront(BzBTExecState *state) {
popped->next = NULL; popped->next = NULL;
return popped; 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) { void execStatePushBack(BzBTExecState *state, BzBTNodeState *nodeState) {
BZ_ASSERT(state); BZ_ASSERT(state);
@@ -348,34 +362,31 @@ static void releaseNodeState(BzObjectPool *pool, BzBTNodeState *nodeState) {
static inline BzBTExecStatus bzBTExecuteNode(const BzBTNode *node, f32 dt, static inline BzBTExecStatus bzBTExecuteNode(const BzBTNode *node, f32 dt,
BzBTExecState *nodeState, BzObjectPool *statePool); BzBTExecState *nodeState, BzObjectPool *statePool);
#if 0
static inline BzBTExecStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt, static inline BzBTExecStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt,
BzBTExecState *nodeState, BzObjectPool *statePool) { BzBTExecState *state, BzObjectPool *statePool) {
BzBTNodeState *nextState = getNextNodeState(node, nodeState); BzBTNodeState *nodeState = getNodeState(node, state);
BzBTNode *start = node->first;
bool isParallel = node->type == BZ_BT_COMP_PARALLEL_SEQUENCE || bool isParallel = node->type == BZ_BT_COMP_PARALLEL_SEQUENCE ||
node->type == BZ_BT_COMP_PARALLEL_SELECTOR; node->type == BZ_BT_COMP_PARALLEL_SELECTOR;
if (!isParallel && nodeMatchesState(node, nodeState)) BzBTNode *start = node->first;
if (!isParallel && nodeState)
start = nodeState->as.composite.running; 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 numRunning = 0;
i32 numSuccessful = 0; i32 numSuccessful = 0;
i32 numFailed = 0; i32 numFailed = 0;
i32 numChildren = 0; i32 numChildren = 0;
BzBTStatus status = BZ_BT_ERROR; BzBTExecStatus status = { .status = BZ_BT_ERROR };
BzBTNode *child = start; BzBTNode *child = start;
for (;child; child = child->next) { 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++; numChildren++;
switch (childStatus) { switch (childStatus.status) {
case BZ_BT_RUNNING: case BZ_BT_RUNNING:
numRunning++; numRunning++;
break; break;
@@ -391,21 +402,21 @@ static inline BzBTExecStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt,
switch (node->type) { switch (node->type) {
case BZ_BT_COMP_SELECTOR: case BZ_BT_COMP_SELECTOR:
case BZ_BT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR:
if (childStatus == BZ_BT_SUCCESS) if (childStatus.status == BZ_BT_SUCCESS)
status = BZ_BT_SUCCESS; status.status = BZ_BT_SUCCESS;
break; break;
case BZ_BT_COMP_SEQUENCE: case BZ_BT_COMP_SEQUENCE:
case BZ_BT_COMP_PARALLEL_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE:
if (childStatus == BZ_BT_FAIL) if (childStatus.status == BZ_BT_FAIL)
status = BZ_BT_FAIL; status.status = BZ_BT_FAIL;
break; break;
default: default:
break; break;
} }
if (status == BZ_BT_FAIL || status == BZ_BT_SUCCESS) if (status.status == BZ_BT_FAIL || status.status == BZ_BT_SUCCESS)
break; break;
if (numRunning > 0 && !isParallel) { if (numRunning > 0 && !isParallel) {
status = BZ_BT_RUNNING; status.status = BZ_BT_RUNNING;
break; break;
} }
} }
@@ -413,34 +424,38 @@ static inline BzBTExecStatus bzBTExecuteComposite(const BzBTNode *node, f32 dt,
case BZ_BT_COMP_SELECTOR: case BZ_BT_COMP_SELECTOR:
case BZ_BT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR:
if (numFailed == numChildren) if (numFailed == numChildren)
status = BZ_BT_FAIL; status.status = BZ_BT_FAIL;
break; break;
case BZ_BT_COMP_SEQUENCE: case BZ_BT_COMP_SEQUENCE:
case BZ_BT_COMP_PARALLEL_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE:
if (numSuccessful == numChildren) if (numSuccessful == numChildren)
status = BZ_BT_SUCCESS; status.status = BZ_BT_SUCCESS;
break; break;
default: default:
break; break;
} }
if (status == BZ_BT_ERROR) { // Propagate ERROR up
bzBTStateRelease(newState, nodeState); if (status.status == BZ_BT_ERROR) {
return BZ_BT_ERROR; execStateClear(&status.state, statePool);
status.status = BZ_BT_ERROR;
return status;
} }
bool finished = status == BZ_BT_SUCCESS || bool finished = status.status == BZ_BT_SUCCESS ||
status == BZ_BT_FAIL; status.status == BZ_BT_FAIL;
if (finished) { if (finished) {
// Dummy state is no longer needed BZ_ASSERT(status.state.first == NULL);
bzBTStateRelease(newState, nodeState); if (nodeState) releaseNodeState(statePool, nodeState);
} else { return status;
BZ_ASSERT(status == BZ_BT_RUNNING);
nodeState->as.composite.running = child;
} }
BZ_ASSERT(status.status == BZ_BT_RUNNING);
nodeState = ensureValidNodeState(node, statePool, nodeState);
nodeState->as.composite.running = child;
execStatePushFront(&status.state, nodeState);
return status; return status;
} }
#endif
static inline BzBTExecStatus bzBTExecuteDecorator(const BzBTNode *node, f32 dt, static inline BzBTExecStatus bzBTExecuteDecorator(const BzBTNode *node, f32 dt,
BzBTExecState *state, BzObjectPool *statePool) { BzBTExecState *state, BzObjectPool *statePool) {
// Ensure decorator has only one child, if any // 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_SEQUENCE:
case BZ_BT_COMP_PARALLEL_SELECTOR: case BZ_BT_COMP_PARALLEL_SELECTOR:
case BZ_BT_COMP_PARALLEL_SEQUENCE: case BZ_BT_COMP_PARALLEL_SEQUENCE:
//status = bzBTExecuteComposite(node, dt, nodeState, statePool); status = bzBTExecuteComposite(node, dt, nodeState, statePool);
break; break;
case BZ_BT_DECOR_DUMMY: case BZ_BT_DECOR_DUMMY:
case BZ_BT_DECOR_SUCCESS: case BZ_BT_DECOR_SUCCESS: