feat(bt): implement subtree status clearing in TaskRunner
Introduce `clearSubtree` to recursively reset status for an entity and all its descendants. This ensures that when a task reaches a terminal state, its entire branch is properly reset. Also refactor the Tetris example to use a sequential task node within the behavior tree.
This commit is contained in:
parent
c3c24d2350
commit
efa92be5ab
|
|
@ -55,6 +55,9 @@ world.add(game, TickTimer);
|
||||||
// Create blessed UI
|
// Create blessed UI
|
||||||
const ui = createUI();
|
const ui = createUI();
|
||||||
|
|
||||||
|
// Spawn the first piece
|
||||||
|
spawnPiece();
|
||||||
|
|
||||||
// ── Command handlers ─────────────────────────────────
|
// ── Command handlers ─────────────────────────────────
|
||||||
const commands = new CommandQueue(world);
|
const commands = new CommandQueue(world);
|
||||||
|
|
||||||
|
|
@ -186,24 +189,29 @@ const runner = new TaskRunner(world);
|
||||||
|
|
||||||
// Build the BT structure:
|
// Build the BT structure:
|
||||||
// root (repeat)
|
// root (repeat)
|
||||||
// ├── handleInput (leaf)
|
// └── seq (sequential)
|
||||||
// ├── gravityTick (leaf)
|
// ├── handleInput (leaf)
|
||||||
// └── render (leaf)
|
// ├── gravityTick (leaf)
|
||||||
|
// └── render (leaf)
|
||||||
|
|
||||||
const root = world.spawn();
|
const root = world.spawn();
|
||||||
world.add(root, Task, { kind: "repeat" });
|
world.add(root, Task, { kind: "repeat" });
|
||||||
|
|
||||||
|
const seq = world.spawn();
|
||||||
|
world.add(seq, Task, { kind: "sequential" });
|
||||||
|
world.relate(seq, ChildOf, root);
|
||||||
|
|
||||||
const handleInputTask = world.spawn();
|
const handleInputTask = world.spawn();
|
||||||
world.add(handleInputTask, Task, { kind: "leaf" });
|
world.add(handleInputTask, Task, { kind: "leaf" });
|
||||||
world.relate(handleInputTask, ChildOf, root);
|
world.relate(handleInputTask, ChildOf, seq);
|
||||||
|
|
||||||
const gravityTask = world.spawn();
|
const gravityTask = world.spawn();
|
||||||
world.add(gravityTask, Task, { kind: "leaf" });
|
world.add(gravityTask, Task, { kind: "leaf" });
|
||||||
world.relate(gravityTask, ChildOf, root);
|
world.relate(gravityTask, ChildOf, seq);
|
||||||
|
|
||||||
const renderTask = world.spawn();
|
const renderTask = world.spawn();
|
||||||
world.add(renderTask, Task, { kind: "leaf" });
|
world.add(renderTask, Task, { kind: "leaf" });
|
||||||
world.relate(renderTask, ChildOf, root);
|
world.relate(renderTask, ChildOf, seq);
|
||||||
|
|
||||||
// ── Leaf handlers ────────────────────────────────────
|
// ── Leaf handlers ────────────────────────────────────
|
||||||
runner.onLeaf = (_w, entity) => {
|
runner.onLeaf = (_w, entity) => {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,14 @@ function clearStatus(world: World, entity: Entity): void {
|
||||||
if (world.has(entity, Running)) world.remove(entity, Running);
|
if (world.has(entity, Running)) world.remove(entity, Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Recursively clear status from an entity and all its descendants. */
|
||||||
|
function clearSubtree(world: World, entity: Entity): void {
|
||||||
|
clearStatus(world, entity);
|
||||||
|
for (const child of childrenOf(world, entity)) {
|
||||||
|
clearSubtree(world, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function childrenOf(world: World, parent: Entity): Entity[] {
|
function childrenOf(world: World, parent: Entity): Entity[] {
|
||||||
return world.getRelatedTo(parent, ChildOf);
|
return world.getRelatedTo(parent, ChildOf);
|
||||||
}
|
}
|
||||||
|
|
@ -258,9 +266,9 @@ export class TaskRunner {
|
||||||
|
|
||||||
const child = children[0];
|
const child = children[0];
|
||||||
|
|
||||||
// If child reached a terminal, reset it and schedule again
|
// If child reached a terminal, reset the entire subtree and schedule again
|
||||||
if (isTerminal(this._world, child)) {
|
if (isTerminal(this._world, child)) {
|
||||||
clearStatus(this._world, child);
|
clearSubtree(this._world, child);
|
||||||
this._world.add(child, Scheduled);
|
this._world.add(child, Scheduled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue