feat(engine): read verb narrates item.readableText
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -212,3 +212,43 @@ describe('ambiguous → disambiguation flow', () => {
|
|||||||
expect(result.state.inventory.find((i) => i.id === 'iron-key')).toBeDefined()
|
expect(result.state.inventory.find((i) => i.id === 'iron-key')).toBeDefined()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function readWorld(): World {
|
||||||
|
return {
|
||||||
|
startingRoom: 'r',
|
||||||
|
startingInventory: [],
|
||||||
|
rooms: { r: { id: 'r', title: '[ R ]', descriptions: { firstVisit: '.', revisit: '.', examined: '.' }, exits: {}, items: [] } },
|
||||||
|
items: {
|
||||||
|
letter: { id: 'letter', names: ['letter'], short: 'a letter', long: 'A letter.', initialState: {}, takeable: true, readable: true, readableText: 'You loved Halfstreet, the letter says.' },
|
||||||
|
rock: { id: 'rock', names: ['rock'], short: 'a rock', long: 'A rock.', initialState: {}, takeable: true },
|
||||||
|
},
|
||||||
|
encounters: {},
|
||||||
|
endings: {
|
||||||
|
true: { whenFlags: {}, narration: '' },
|
||||||
|
wrong: { whenFlags: {}, narration: '' },
|
||||||
|
bad: { whenFlags: {}, narration: '' },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('read verb', () => {
|
||||||
|
it('narrates readableText for a readable item in inventory', () => {
|
||||||
|
const world = readWorld()
|
||||||
|
let state = initialStateFor(world)
|
||||||
|
state = { ...state, inventory: [{ id: 'letter', state: {} }] }
|
||||||
|
const result = dispatch(state, {
|
||||||
|
kind: 'verb-target', verb: 'read', target: { canonical: 'letter', raw: 'letter' },
|
||||||
|
}, world)
|
||||||
|
expect(result.appended.at(-1)?.text).toBe('You loved Halfstreet, the letter says.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('errors politely on non-readable items', () => {
|
||||||
|
const world = readWorld()
|
||||||
|
let state = initialStateFor(world)
|
||||||
|
state = { ...state, inventory: [{ id: 'rock', state: {} }] }
|
||||||
|
const result = dispatch(state, {
|
||||||
|
kind: 'verb-target', verb: 'read', target: { canonical: 'rock', raw: 'rock' },
|
||||||
|
}, world)
|
||||||
|
expect(result.appended.at(-1)?.text).toBe("There's nothing to read on it.")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ export function dispatch(state: GameState, command: ParsedCommand, world: World)
|
|||||||
if (command.verb === 'take') return handleTake(stateWithNoun, command.target.canonical, world)
|
if (command.verb === 'take') return handleTake(stateWithNoun, command.target.canonical, world)
|
||||||
if (command.verb === 'drop') return handleDrop(stateWithNoun, command.target.canonical, world)
|
if (command.verb === 'drop') return handleDrop(stateWithNoun, command.target.canonical, world)
|
||||||
if (command.verb === 'examine' || command.verb === 'look') return handleExamine(stateWithNoun, command.target.canonical, world)
|
if (command.verb === 'examine' || command.verb === 'look') return handleExamine(stateWithNoun, command.target.canonical, world)
|
||||||
|
if (command.verb === 'read') return handleRead(stateWithNoun, command.target.canonical, world)
|
||||||
return narrate(stateWithNoun, [{ kind: 'narration', text: `You're not sure how to ${command.verb} that.` }])
|
return narrate(stateWithNoun, [{ kind: 'narration', text: `You're not sure how to ${command.verb} that.` }])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,3 +263,16 @@ function handleExamine(state: GameState, itemId: string, world: World): Dispatch
|
|||||||
if (!visible) return narrate(state, [{ kind: 'narration', text: 'You don\'t see anything like that.' }])
|
if (!visible) return narrate(state, [{ kind: 'narration', text: 'You don\'t see anything like that.' }])
|
||||||
return narrate(state, [{ kind: 'narration', text: item.long }])
|
return narrate(state, [{ kind: 'narration', text: item.long }])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleRead(state: GameState, itemId: string, world: World): DispatchResult {
|
||||||
|
const item = world.items[itemId]
|
||||||
|
if (!item) return narrate(state, [{ kind: 'narration', text: "You don't see anything like that." }])
|
||||||
|
const visible =
|
||||||
|
state.inventory.find((i) => i.id === itemId) ||
|
||||||
|
getItemsInRoom(state, world, state.location).includes(itemId)
|
||||||
|
if (!visible) return narrate(state, [{ kind: 'narration', text: "You don't see anything like that." }])
|
||||||
|
if (!item.readable || !item.readableText) {
|
||||||
|
return narrate(state, [{ kind: 'narration', text: "There's nothing to read on it." }])
|
||||||
|
}
|
||||||
|
return narrate(state, [{ kind: 'narration', text: item.readableText }])
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user