2026-05-09 00:18:25 -05:00
|
|
|
import { describe, it, expect } from 'vitest'
|
|
|
|
|
import { computeChips } from './chips'
|
|
|
|
|
import { world } from '../world'
|
|
|
|
|
import { initialStateFor } from '../engine/dispatcher'
|
|
|
|
|
import { dispatch } from '../engine/dispatcher'
|
|
|
|
|
|
|
|
|
|
describe('computeChips — sample world', () => {
|
|
|
|
|
it('shows valid exits as direction chips with the dim flag for invalid ones', () => {
|
|
|
|
|
const s = initialStateFor(world)
|
|
|
|
|
const chips = computeChips(s, world)
|
|
|
|
|
const directions = chips.filter((c) => c.kind === 'direction')
|
|
|
|
|
expect(directions.find((c) => c.label.includes('N'))?.disabled).toBe(false)
|
|
|
|
|
expect(directions.find((c) => c.label.includes('S'))?.disabled).toBe(true)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('adds TAKE chips for visible takeable items', () => {
|
2026-05-09 21:51:12 -05:00
|
|
|
let s = initialStateFor(world)
|
|
|
|
|
s = dispatch(s, { kind: 'go', direction: 'n' }, world).state
|
|
|
|
|
s = dispatch(s, { kind: 'go', direction: 'n' }, world).state
|
2026-05-09 00:18:25 -05:00
|
|
|
const chips = computeChips(s, world)
|
2026-05-09 21:51:12 -05:00
|
|
|
expect(chips.find((c) => c.kind === 'item' && c.command === 'take lamp')).toBeTruthy()
|
2026-05-09 00:18:25 -05:00
|
|
|
})
|
|
|
|
|
|
2026-05-09 00:37:45 -05:00
|
|
|
it('removes TAKE chip after item is taken', () => {
|
|
|
|
|
let s = initialStateFor(world)
|
2026-05-09 21:51:12 -05:00
|
|
|
s = dispatch(s, { kind: 'go', direction: 'n' }, world).state
|
|
|
|
|
s = dispatch(s, { kind: 'go', direction: 'n' }, world).state
|
|
|
|
|
s = dispatch(s, { kind: 'verb-target', verb: 'take', target: { canonical: 'lamp', raw: 'lamp' } }, world).state
|
2026-05-09 00:37:45 -05:00
|
|
|
const chips = computeChips(s, world)
|
2026-05-09 21:51:12 -05:00
|
|
|
expect(chips.find((c) => c.command === 'take lamp')).toBeUndefined()
|
2026-05-09 00:37:45 -05:00
|
|
|
})
|
|
|
|
|
|
2026-05-09 00:18:25 -05:00
|
|
|
it('adds an encounter verb chip when an encounter is active', () => {
|
|
|
|
|
let s = initialStateFor(world)
|
|
|
|
|
s = dispatch(s, { kind: 'go', direction: 'n' }, world).state
|
2026-05-09 21:51:12 -05:00
|
|
|
s = dispatch(s, { kind: 'go', direction: 'n' }, world).state
|
2026-05-09 00:18:25 -05:00
|
|
|
s = dispatch(s, { kind: 'go', direction: 'e' }, world).state
|
|
|
|
|
const chips = computeChips(s, world)
|
2026-05-10 05:53:32 -05:00
|
|
|
expect(chips.find((c) => c.kind === 'encounter' && c.label === 'ATTACK RAT' && c.command === 'attack rat')).toBeTruthy()
|
2026-05-09 00:18:25 -05:00
|
|
|
})
|
|
|
|
|
|
2026-05-10 07:56:31 -05:00
|
|
|
it('always includes LOOK, INV, USE, WAIT, and HELP', () => {
|
2026-05-09 00:18:25 -05:00
|
|
|
const s = initialStateFor(world)
|
|
|
|
|
const chips = computeChips(s, world)
|
|
|
|
|
expect(chips.find((c) => c.command === 'look')).toBeTruthy()
|
|
|
|
|
expect(chips.find((c) => c.command === 'inventory')).toBeTruthy()
|
2026-05-10 05:53:32 -05:00
|
|
|
expect(chips.find((c) => c.label === 'USE' && c.command === 'use ')).toBeTruthy()
|
2026-05-10 07:56:31 -05:00
|
|
|
expect(chips.find((c) => c.command === 'wait')).toBeTruthy()
|
2026-05-09 21:51:12 -05:00
|
|
|
expect(chips.find((c) => c.command === 'help')).toBeTruthy()
|
2026-05-09 00:18:25 -05:00
|
|
|
})
|
2026-05-12 19:44:18 -05:00
|
|
|
|
|
|
|
|
it('shows only confirmation chips while a dangerous command is pending', () => {
|
|
|
|
|
const s = {
|
|
|
|
|
...initialStateFor(world),
|
|
|
|
|
pendingConfirmation: {
|
|
|
|
|
command: { kind: 'verb-target' as const, verb: 'attack' as const, target: { canonical: 'rat', raw: 'rat' } },
|
|
|
|
|
prompt: 'Are you sure?',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
const chips = computeChips(s, world)
|
|
|
|
|
expect(chips).toEqual([
|
|
|
|
|
{ kind: 'meta', label: 'YES', command: 'yes', disabled: false },
|
|
|
|
|
{ kind: 'meta', label: 'NO', command: 'no', disabled: false },
|
|
|
|
|
])
|
|
|
|
|
})
|
2026-05-09 00:18:25 -05:00
|
|
|
})
|