docs(mystery): spec for engine prereqs (verbs, disambiguation, ending UI) #1
@@ -29,7 +29,6 @@ export function initialStateFor(world: World): GameState {
|
|||||||
lastNoun: null,
|
lastNoun: null,
|
||||||
pendingDisambiguation: null,
|
pendingDisambiguation: null,
|
||||||
transcript: opening,
|
transcript: opening,
|
||||||
theme: 'amber',
|
|
||||||
endedWith: null,
|
endedWith: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,10 +114,10 @@ function narrate(state: GameState, lines: TranscriptLine[]): DispatchResult {
|
|||||||
|
|
||||||
function handleMeta(state: GameState, verb: 'restart' | 'undo' | 'hint' | 'save' | 'quit' | 'theme'): DispatchResult {
|
function handleMeta(state: GameState, verb: 'restart' | 'undo' | 'hint' | 'save' | 'quit' | 'theme'): DispatchResult {
|
||||||
if (verb === 'save') return narrate(state, [{ kind: 'system', text: '(your progress is saved automatically)' }])
|
if (verb === 'save') return narrate(state, [{ kind: 'system', text: '(your progress is saved automatically)' }])
|
||||||
if (verb === 'theme') {
|
// 'theme' is a UI preference: the terminal intercepts it before dispatch and
|
||||||
const newTheme = state.theme === 'amber' ? 'ansi' : 'amber'
|
// dispatches a 'halfstreet-toggle-theme' DOM event. The engine no-ops here so
|
||||||
return narrate({ ...state, theme: newTheme }, [{ kind: 'system', text: `Theme: ${newTheme}.` }])
|
// typing the verb still produces transcript output if the UI ever misses it.
|
||||||
}
|
if (verb === 'theme') return narrate(state, [{ kind: 'system', text: '(theme)' }])
|
||||||
// restart / undo / hint / quit are handled by the UI layer (state mutations
|
// restart / undo / hint / quit are handled by the UI layer (state mutations
|
||||||
// require coordination with the save layer and route navigation). The
|
// require coordination with the save layer and route navigation). The
|
||||||
// engine acknowledges them with a no-op narration; the UI intercepts before
|
// engine acknowledges them with a no-op narration; the UI intercepts before
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const baseState = (overrides: Partial<GameState> = {}): GameState => ({
|
|||||||
lastNoun: null,
|
lastNoun: null,
|
||||||
pendingDisambiguation: null,
|
pendingDisambiguation: null,
|
||||||
transcript: [],
|
transcript: [],
|
||||||
theme: 'amber',
|
|
||||||
endedWith: null,
|
endedWith: null,
|
||||||
...overrides,
|
...overrides,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ export function loadState(): GameState | null {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Older saves may carry fields no longer in GameState (e.g. `theme` before
|
||||||
|
// it became a UI-only preference). TypeScript ignores extra fields at runtime;
|
||||||
|
// bump SCHEMA_VERSION only when the meaning of an existing field changes.
|
||||||
return parsed as GameState
|
return parsed as GameState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ export type ParsedCommand =
|
|||||||
| { kind: 'unknown'; raw: string; reason: 'unknown-verb' | 'unknown-noun' | 'malformed' }
|
| { kind: 'unknown'; raw: string; reason: 'unknown-verb' | 'unknown-noun' | 'malformed' }
|
||||||
|
|
||||||
export type ResolveLevel = 'steady' | 'shaken' | 'reeling' | 'returning'
|
export type ResolveLevel = 'steady' | 'shaken' | 'reeling' | 'returning'
|
||||||
export type Theme = 'amber' | 'ansi'
|
|
||||||
|
|
||||||
export interface ItemInstance {
|
export interface ItemInstance {
|
||||||
id: ItemId
|
id: ItemId
|
||||||
@@ -68,7 +67,6 @@ export interface GameState {
|
|||||||
pendingDisambiguation: PendingDisambiguation | null
|
pendingDisambiguation: PendingDisambiguation | null
|
||||||
/** Capped at 200 entries; older entries are dropped on append. */
|
/** Capped at 200 entries; older entries are dropped on append. */
|
||||||
transcript: TranscriptLine[]
|
transcript: TranscriptLine[]
|
||||||
theme: Theme
|
|
||||||
/** Set true when the player has reached an ending. UI shows ending screen. */
|
/** Set true when the player has reached an ending. UI shows ending screen. */
|
||||||
endedWith: 'true' | 'wrong' | 'bad' | null
|
endedWith: 'true' | 'wrong' | 'bad' | null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user