Checkpoint Eibenreith ink architecture

This commit is contained in:
2026-05-24 09:09:41 +02:00
parent beac5a2be3
commit d42540f29d
35 changed files with 12015 additions and 54 deletions
+17 -2
View File
@@ -21,6 +21,18 @@ The production client must tolerate speech being unavailable. The safe TTS provi
- `scripts/`: project utility scripts. Currently used: `check-node-version.js` and `run-engine.js`.
- `templates/`: not present in the current repository and not used.
## Text Encoding
Ink source files and game UI localization files must be saved as UTF-8 and must contain the real written characters. German text uses full umlauts and special characters directly, for example `ä`, `ö`, `ü`, `Ä`, `Ö`, `Ü`, `ß`, and German quotation marks `„…“`. Do not transliterate German into `ae`, `oe`, `ue`, or `ss` as an encoding workaround.
## Ink Authoring State
Use Ink's built-in visit state for simple facts such as "this knot has been shown". Do not create parallel boolean flags for knot visits. Use explicit LIST-based state chains only when the state has semantic order or knowledge progression, such as character-generation dependencies, relationship frames, evidence chains, or episode progress.
## Choice Text Perspective
Choice text must describe the player character's intention before the action is taken. Do not write choices from a post-hoc author perspective that reveals what the branch will discover. For example, use "try the door" before the destination is known, not "go to the second-class cars"; use automatic or hidden events for things the player character cannot control, such as the train entering a tunnel.
## Engine Selection And Commands
`DEFAULT_GAME_ENGINE` in `.env` selects the engine used by:
@@ -107,10 +119,10 @@ The YAML engine is no longer the architectural default; it is one engine beside
- Config: `config/engines/ink.json`
- Server: `src/server-ink.ts`
- Engine: `src/engine/ink-engine.ts`
- Source: `data/ink-src/eibenreith.ink` plus included chapter files.
- Source: `data/ink-src/eibenreith/main.ink` plus included chapter files.
- Compiled output: `data/ink/eibenreith.ink.json`
The Ink server compiles source at startup using `inkjs/full`, then runs the compiled story with `inkjs`. Ink choices become `ChoiceResult` objects. Ink tags become shared `StoryTag` objects. Choice preview tags support `#key`, `#letter`, `#optional`, `#action`, `#gated`, and `#sort`.
The Ink server compiles source at startup using `inkjs/full`, then runs the compiled story with `inkjs`. Ink choices become `ChoiceResult` objects. Ink tags become shared `StoryTag` objects. Choice preview tags support `#key`, `#letter`, `#optional`, `#action`, `#gated`, `#sort`, and `#auto`.
The server keeps only ephemeral per-socket InkEngine instances. Browser IndexedDB owns durable Ink saves and the current autosave. If the socket reconnects or the page reloads, the browser sends the autosaved Ink state to `resumeGame()` and restores rendered history locally.
@@ -223,10 +235,13 @@ Choice tags:
- `#letter[x]`
- `#optional`
- `#action[name]`
- `#auto`, `#auto(2)`, `#auto[keyword]`, `#auto[keyword](2)`
The active choice UI is one list. Explicit keys are reserved first, then remaining choices receive `1` through `0`, then `A` through `Z`.
Before key assignment, choices are ordered by invisible `#action` groups. The first appearance of each action group in the authored list determines group order. Choices inside each group are randomized for presentation. Choices without an action group form one final group shown last. Group labels are not displayed.
`#auto` marks an ordinary Ink choice that should not be rendered as a visible button. The browser selects the first ready auto choice when the choice surface becomes ready. Ink still owns availability and once-only behavior through normal choice syntax and conditions. A numeric parameter delays the trigger by UI choice turns since the last matching auto trigger. Without a keyword the delay is global; with a keyword it applies only to that keyword. Use global `#auto(n)` when different auto events must not happen back-to-back, and keyworded `#auto[name](n)` when only repeated events of the same class should be spaced out.
TTS instruction tags are paragraph/block metadata. They are ignored by renderers and by providers that do not support per-request reading instructions. Providerless `#tts[...]` and `#tts(...)` are the default authoring forms; provider-specific forms are optional filters for provider overrides. OpenAI consumes matching instructions only for `gpt-4o-mini-tts`, where they are sent as the Speech API `instructions` field. Instructions should describe delivery, such as tone, emotion, intonation, pace, accent, whispering, humming, or singing style.
Markdown emphasis: