feat(bt)!: Remove legacy tree definition format
The `LegacyTreeDef` type and its normalization path have been removed. All tree definitions must now use the factory functions (`leaf`, `sequential`, `parallel`, `selector`, `random`, `repeat`). The `TreeDef` type is now simply `TaskEntityDef`.
This commit is contained in:
+35
-42
@@ -23,7 +23,13 @@
|
||||
// npx tsx examples/blackjack/main.ts
|
||||
|
||||
import { World } from "../../src/index";
|
||||
import { buildTree } from "../../src/bt/index";
|
||||
import {
|
||||
buildTree,
|
||||
leaf,
|
||||
parallel,
|
||||
repeat,
|
||||
sequential,
|
||||
} from "../../src/bt/index";
|
||||
import { CommandQueue } from "../../src/commands/index";
|
||||
|
||||
import {
|
||||
@@ -63,50 +69,37 @@ const commands = new CommandQueue(world);
|
||||
registerCommands(world, commands, cards);
|
||||
|
||||
// ── Behaviour Tree ───────────────────────────────────
|
||||
const runner = buildTree(world, {
|
||||
kind: "parallel",
|
||||
children: [
|
||||
{
|
||||
kind: "leaf",
|
||||
*run() {
|
||||
while (true) {
|
||||
const dt: number = yield;
|
||||
const phase = world.getSingleton(GamePhase);
|
||||
if (phase.phase !== "dealerTurn") continue;
|
||||
const runner = buildTree(
|
||||
world,
|
||||
parallel([
|
||||
leaf(function* dealerPlay() {
|
||||
while (true) {
|
||||
yield;
|
||||
const phase = world.getSingleton(GamePhase);
|
||||
if (phase.phase !== "dealerTurn") continue;
|
||||
|
||||
if (dealerShouldHit(cards.getHand(InDealerHand))) {
|
||||
const cardEntity = cards.drawCard();
|
||||
if (cardEntity) {
|
||||
cards.dealTo(cardEntity, InDealerHand);
|
||||
}
|
||||
} else {
|
||||
resolveRound(world, cards);
|
||||
if (dealerShouldHit(cards.getHand(InDealerHand))) {
|
||||
const cardEntity = cards.drawCard();
|
||||
if (cardEntity) {
|
||||
cards.dealTo(cardEntity, InDealerHand);
|
||||
}
|
||||
} else {
|
||||
resolveRound(world, cards);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "repeat",
|
||||
child: {
|
||||
kind: "sequential",
|
||||
children: [
|
||||
{
|
||||
kind: "leaf",
|
||||
run: () => {
|
||||
commands.execute();
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "leaf",
|
||||
run: () => {
|
||||
render(world, ui);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}),
|
||||
repeat(
|
||||
sequential([
|
||||
leaf(() => {
|
||||
commands.execute();
|
||||
}),
|
||||
leaf(() => {
|
||||
render(world, ui);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
// ── Input → Command mapping ──────────────────────────
|
||||
const keyToCommand: Partial<Record<Key, typeof Hit>> = {
|
||||
|
||||
+41
-48
@@ -20,7 +20,13 @@
|
||||
// npx tsx examples/tetris/main.ts
|
||||
|
||||
import { World } from "../../src/index";
|
||||
import { buildTree } from "../../src/bt/index";
|
||||
import {
|
||||
buildTree,
|
||||
leaf,
|
||||
parallel,
|
||||
repeat,
|
||||
sequential,
|
||||
} from "../../src/bt/index";
|
||||
import { CommandQueue } from "../../src/commands/index";
|
||||
|
||||
import {
|
||||
@@ -64,56 +70,43 @@ registerCommands(world, commands, pieces);
|
||||
pieces.spawnPiece();
|
||||
|
||||
// ── Behaviour Tree ───────────────────────────────────
|
||||
const runner = buildTree(world, {
|
||||
kind: "parallel",
|
||||
children: [
|
||||
{
|
||||
kind: "leaf",
|
||||
*run() {
|
||||
while (true) {
|
||||
const dt: number = yield;
|
||||
if (world.hasSingleton(GameOver) || world.hasSingleton(Paused)) {
|
||||
continue;
|
||||
}
|
||||
const timer = world.getSingleton(TickTimer);
|
||||
timer.accumulator += dt;
|
||||
if (timer.accumulator >= timer.interval) {
|
||||
timer.accumulator -= timer.interval;
|
||||
if (world.hasSingleton(Piece)) {
|
||||
const piece = world.getSingleton(Piece);
|
||||
const board = world.getSingleton(Board);
|
||||
if (!collides(board.grid, piece.shape, piece.x, piece.y + 1)) {
|
||||
piece.y++;
|
||||
} else {
|
||||
pieces.lockAndSpawn();
|
||||
}
|
||||
const runner = buildTree(
|
||||
world,
|
||||
parallel([
|
||||
leaf(function* gravityTick() {
|
||||
while (true) {
|
||||
const dt: number = yield;
|
||||
if (world.hasSingleton(GameOver) || world.hasSingleton(Paused)) {
|
||||
continue;
|
||||
}
|
||||
const timer = world.getSingleton(TickTimer);
|
||||
timer.accumulator += dt;
|
||||
if (timer.accumulator >= timer.interval) {
|
||||
timer.accumulator -= timer.interval;
|
||||
if (world.hasSingleton(Piece)) {
|
||||
const piece = world.getSingleton(Piece);
|
||||
const board = world.getSingleton(Board);
|
||||
if (!collides(board.grid, piece.shape, piece.x, piece.y + 1)) {
|
||||
piece.y++;
|
||||
} else {
|
||||
pieces.lockAndSpawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "repeat",
|
||||
child: {
|
||||
kind: "sequential",
|
||||
children: [
|
||||
{
|
||||
kind: "leaf",
|
||||
run: () => {
|
||||
commands.execute();
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "leaf",
|
||||
run: () => {
|
||||
render(world, ui);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}),
|
||||
repeat(
|
||||
sequential([
|
||||
leaf(() => {
|
||||
commands.execute();
|
||||
}),
|
||||
leaf(() => {
|
||||
render(world, ui);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
// ── Input → Command mapping ──────────────────────────
|
||||
const keyToCommand: Partial<Record<Key, typeof MoveLeft>> = {
|
||||
|
||||
Reference in New Issue
Block a user