diff --git a/src/engine/dispatcher.ts b/src/engine/dispatcher.ts index b3f593e..640421f 100644 --- a/src/engine/dispatcher.ts +++ b/src/engine/dispatcher.ts @@ -39,7 +39,7 @@ function append(state: GameState, lines: TranscriptLine[]): GameState { return { ...state, transcript: transcript.slice(-TRANSCRIPT_CAP) } } -function getItemsInRoom(state: GameState, world: World, roomId: string): string[] { +export function getItemsInRoom(state: GameState, world: World, roomId: string): string[] { const baseItems = world.rooms[roomId]?.items ?? [] const dropped = (state.roomState[roomId]?.['droppedItems'] as string[] | undefined) ?? [] const taken = (state.roomState[roomId]?.['takenItems'] as string[] | undefined) ?? [] diff --git a/src/engine/encounters.ts b/src/engine/encounters.ts index 8a7278e..8daa9b3 100644 --- a/src/engine/encounters.ts +++ b/src/engine/encounters.ts @@ -72,7 +72,7 @@ export function applyVerbToEncounter( if (command.kind === 'verb-target') { verb = command.verb targetId = command.target.canonical - } else if (command.kind === 'verb-only' && command.verb !== 'inventory' && command.verb !== 'wait') { + } else if (command.kind === 'verb-only' && command.verb !== 'inventory') { verb = command.verb } else { return null diff --git a/src/ui/chips.test.ts b/src/ui/chips.test.ts index 1c52a0d..0253a42 100644 --- a/src/ui/chips.test.ts +++ b/src/ui/chips.test.ts @@ -19,6 +19,13 @@ describe('computeChips — sample world', () => { expect(chips.find((c) => c.kind === 'item' && c.command === 'take letter')).toBeTruthy() }) + it('removes TAKE chip after item is taken', () => { + let s = initialStateFor(world) + s = dispatch(s, { kind: 'verb-target', verb: 'take', target: { canonical: 'letter', raw: 'letter' } }, world).state + const chips = computeChips(s, world) + expect(chips.find((c) => c.command === 'take letter')).toBeUndefined() + }) + it('adds an encounter verb chip when an encounter is active', () => { let s = initialStateFor(world) s = dispatch(s, { kind: 'go', direction: 'n' }, world).state diff --git a/src/ui/chips.ts b/src/ui/chips.ts index d23cf0c..deff75d 100644 --- a/src/ui/chips.ts +++ b/src/ui/chips.ts @@ -1,5 +1,6 @@ import type { World } from '../world/types' import type { GameState, Direction } from '../engine/types' +import { getItemsInRoom } from '../engine/dispatcher' export type ChipKind = 'direction' | 'item' | 'encounter' | 'meta' @@ -33,10 +34,11 @@ export function computeChips(state: GameState, world: World): Chip[] { } } - // Item chips: TAKE for visible items. - for (const itemId of room.items) { + // Item chips: TAKE for visible items (dynamic list excludes taken items). + for (const itemId of getItemsInRoom(state, world, state.location)) { const item = world.items[itemId] if (!item || !item.takeable) continue + if (state.inventory.find((inst) => inst.id === itemId)) continue // already held out.push({ kind: 'item', label: `TAKE ${item.names[0]?.toUpperCase() ?? itemId.toUpperCase()}`,