2026-07-01 15:44:37 +08:00
|
|
|
import type { World } from "../../src/index";
|
|
|
|
|
import {
|
|
|
|
|
action,
|
|
|
|
|
buildTree,
|
|
|
|
|
sequential,
|
|
|
|
|
wait,
|
|
|
|
|
whilst,
|
|
|
|
|
type TaskControl,
|
|
|
|
|
type TaskRunner,
|
|
|
|
|
} from "../../src/bt/index";
|
|
|
|
|
import { allPlayersSelected, hasWinner } from "./components";
|
2026-07-01 16:25:41 +08:00
|
|
|
import {
|
|
|
|
|
beginSelectionPhase,
|
|
|
|
|
chantPhase,
|
|
|
|
|
exchangePhase,
|
|
|
|
|
fetchWaterPhase,
|
|
|
|
|
drinkPhase,
|
|
|
|
|
endOfRoundPhase,
|
|
|
|
|
prepareNextRound,
|
|
|
|
|
} from "./rules";
|
2026-07-01 15:44:37 +08:00
|
|
|
|
|
|
|
|
export interface ThreeMonksFlow {
|
|
|
|
|
runner: TaskRunner;
|
|
|
|
|
start(): void;
|
|
|
|
|
notifySelectionChanged(): void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function createThreeMonksFlow(world: World): ThreeMonksFlow {
|
|
|
|
|
let selectionControl: TaskControl | null = null;
|
|
|
|
|
|
|
|
|
|
const completeSelectionIfReady = () => {
|
|
|
|
|
if (selectionControl && allPlayersSelected(world)) {
|
|
|
|
|
const control = selectionControl;
|
|
|
|
|
selectionControl = null;
|
|
|
|
|
control.succeed();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const runner = buildTree(
|
|
|
|
|
world,
|
|
|
|
|
whilst(
|
|
|
|
|
(world) => !hasWinner(world),
|
|
|
|
|
sequential([
|
|
|
|
|
action((world) => beginSelectionPhase(world)),
|
|
|
|
|
wait((world, _entity, control) => {
|
|
|
|
|
selectionControl = control;
|
|
|
|
|
if (allPlayersSelected(world)) {
|
|
|
|
|
selectionControl = null;
|
|
|
|
|
control.succeed();
|
|
|
|
|
}
|
|
|
|
|
}),
|
2026-07-01 16:25:41 +08:00
|
|
|
action((world) => chantPhase(world)),
|
|
|
|
|
action((world) => fetchWaterPhase(world)),
|
|
|
|
|
action((world) => exchangePhase(world)),
|
|
|
|
|
action((world) => drinkPhase(world)),
|
|
|
|
|
action((world) => endOfRoundPhase(world)),
|
2026-07-01 15:44:37 +08:00
|
|
|
action((world) => prepareNextRound(world)),
|
|
|
|
|
]),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
runner,
|
|
|
|
|
start() {
|
|
|
|
|
runner.schedule(runner.root!);
|
|
|
|
|
},
|
|
|
|
|
notifySelectionChanged() {
|
|
|
|
|
completeSelectionIfReady();
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|