From a89aac9c2156b72be0c426983a7be87d9615870c Mon Sep 17 00:00:00 2001 From: hypercross Date: Sat, 4 Apr 2026 01:03:12 +0800 Subject: [PATCH] docs: update docs --- AGENTS.md | 13 +++++++------ README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 06fda2b..b9f5157 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,13 +48,13 @@ tests/ # Mirrors src/ structure with *.test.ts files - Trailing commas in multi-line objects/arrays ### Naming Conventions -- **Types/Interfaces**: `PascalCase` — `Part`, `Region`, `Command`, `IGameContext` -- **Classes**: `PascalCase` — `MutableSignal`, `AsyncQueue`, `Mulberry32RNG` -- **Functions**: `camelCase`, verb-first — `createGameContext`, `parseCommand`, `isValidMove` +- **Types/Interfaces**: `PascalCase` — `Part`, `Region`, `Command`, `IGameContext`, `GameHost` +- **Classes**: `PascalCase` — `MutableSignal`, `AsyncQueue`, `Mulberry32RNG`, `GameHost` +- **Functions**: `camelCase`, verb-first — `createGameContext`, `createGameHost`, `parseCommand`, `isValidMove` - **Variables**: `camelCase` - **Constants**: `UPPER_SNAKE_CASE` — `BOARD_SIZE`, `WINNING_LINES` - **Test files**: `*.test.ts` mirroring `src/` structure under `tests/` -- **Factory functions**: prefix with `create` or `mutable` — `createGameContext`, `mutableSignal` +- **Factory functions**: prefix with `create` or `mutable` — `createGameContext`, `createGameHost`, `mutableSignal` ### Types - **Strict TypeScript** is enabled — no `any` @@ -84,9 +84,10 @@ tests/ # Mirrors src/ structure with *.test.ts files - **Reactivity**: `MutableSignal` extends Preact Signal — access state via `.value`, mutate via `.produce(draft => ...)` - **Command system**: CLI-style parsing with schema validation via `inline-schema` -- **Prompt system**: Commands prompt for input via `PromptEvent` with `resolve`/`reject`; `tryCommit` accepts `Command | string` and validates against schema before custom validator +- **Prompt system**: Commands prompt for input via `PromptEvent` with `resolve`/`reject`; `tryCommit` accepts `Command | string` and validates against schema before custom validator; `promptEnd` event fires when prompt completes (success or cancel) +- **GameHost**: Lifecycle manager for game sessions — provides `setup()`, `onInput()`, `dispose()`, reactive `state`/`status`/`activePromptSchema` signals - **Barrel exports**: `src/index.ts` is the single public API surface -- **Game modules**: export `registry` and `createInitialState` for use with `createGameContextFromModule` +- **Game modules**: export `registry` and `createInitialState` for use with `createGameContextFromModule` or `createGameHost` - **Region system**: plain `Region` type with `createRegion()` factory; `parts` are stored as `Record` keyed by ID, with `partMap` in regions mapping position keys to part IDs - **Part collections**: Game state uses `Record>` (not arrays) for O(1) lookup by ID. Use `Object.values(parts)` when iteration is needed, `Object.keys(parts)` for count/IDs - **Mutative**: used for immutable state updates inside `MutableSignal.produce()` diff --git a/README.md b/README.md index 5f0d1ab..62d4f7d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Build turn-based board games with reactive state, entity collections, spatial re - **Type Safe**: Full TypeScript support with strict mode and generic context extension - **Region System**: Spatial management with multi-axis positioning, alignment, and shuffling - **Command System**: CLI-style command parsing with schema validation, type coercion, and prompt support +- **Game Lifecycle Management**: `GameHost` class provides clean setup/reset/dispose lifecycle for game sessions - **Deterministic RNG**: Seeded pseudo-random number generator (Mulberry32) for reproducible game states ## Installation @@ -124,6 +125,52 @@ If the player needs to cancel instead of committing: promptEvent.cancel('player quit'); ``` +### Managing Game Lifecycle with GameHost + +For a cleaner game lifecycle (setup, reset, dispose), use `GameHost`: + +```ts +import { createGameHost } from 'boardgame-core'; +import { registry, createInitialState } from './my-game'; + +// Create a game host with a setup command +const host = createGameHost( + { registry, createInitialState }, + 'setup' // command to run when setting up/resetting the game +); + +// Reactive state — use in effects or computed values +console.log(host.state.value.currentPlayer); +console.log(host.status.value); // 'created' | 'running' | 'disposed' + +// Check if a prompt is active and what schema it expects +const schema = host.activePromptSchema.value; +if (schema) { + console.log('Waiting for:', schema.name, schema.params); +} + +// Submit player input to the active prompt +const error = host.onInput('play X 1 2'); +if (error) { + console.log('Invalid move:', error); +} + +// Reset the game (cancels active prompt, resets state, runs setup) +await host.setup('setup'); + +// Dispose when done (cleans up listeners, cancels active prompts) +host.dispose(); +``` + +The `GameHost` provides: +- **`state`**: `ReadonlySignal` — reactive game state +- **`status`**: `ReadonlySignal<'created' | 'running' | 'disposed'>` — lifecycle status +- **`activePromptSchema`**: `ReadonlySignal` — reactive current prompt schema +- **`onInput(input)`**: Submit input to active prompt, returns error or null +- **`setup(command)`**: Reset and reinitialize the game +- **`dispose()`**: Clean up all resources +- **`on(event, listener)`**: Listen to `'setup'` or `'dispose'` events + ## Sample Games ### Tic-Tac-Toe @@ -189,6 +236,10 @@ rng.setSeed(999); // reseed | `IGameContext` | Base interface for the game context (state, commands) | | `createGameContext(registry, initialState?)` | Create a game context instance. `initialState` can be an object or factory function | | `createGameCommandRegistry()` | Create a command registry with fluent `.add()` API | +| `GameHost` | Game lifecycle manager class with setup/reset/dispose | +| `createGameHost(module, setupCommand, options?)` | Create a GameHost instance from a game module | +| `GameHostStatus` | Type: `'created' \| 'running' \| 'disposed'` | +| `GameHostOptions` | Options: `{ autoStart?: boolean }` | ### Parts @@ -239,6 +290,7 @@ rng.setSeed(999); // reseed | `runCommandParsed(registry, context, command)` | Run a pre-parsed command | | `createCommandRunnerContext(registry, context)` | Create a command runner context | | `PromptEvent` | Event dispatched when a command prompts for input | +| `CommandRunnerEvents` | Event types: `prompt` (when prompt starts), `promptEnd` (when prompt completes) | ### Utilities