A game may give its bots words: they speak as a round opens and when spoken to, remember by notes nobody sees, and read the talk when they move

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric WagonerandClaude Opus 5.5 committed 2026-09-29 12:18:46 -04:00
1 parent 8c99126aee
commit 99a0b23f59
6 files changed
+126 -5

No files matched your search

+40
View File
@@ -124,4 +124,44 @@ describe('rooms', () => {
const host = rooms.create('Ann', 2);
expect(() => rooms.rank(host.room, host.token, ['A'])).toThrow(/asks for no ranking/);
});
it('lets a game give its bots words: when a round opens and when spoken to, with notes kept from every view', () => {
const heard: string[][] = [];
const talking: GameSpec<State, Input> = {
...game,
botInput: (state, seat, press) => {
heard.push((press ?? []).map((l) => l.text));
return game.botInput(state, seat);
},
botPress: (state, seat, press, people, trigger) =>
trigger === 'phase' ? [{ to: people, text: `Round ${game.turn(state)}.`, note: 'secret' }] : [{ to: [press[press.length - 1].id], text: 'I hear you.' }],
parting: (_press, viewer) => [{ id: 'B', text: `Farewell, ${viewer}.` }]
};
const rooms = new Rooms(talking, new Store(dir));
const host = rooms.create('Ann', 3);
rooms.addBot(host.room, host.token);
const cy = rooms.join(host.room, 'Cy');
const room = host.room;
rooms.begin(room, host.token);
rooms.say(room, host.token, 'Psst.', ['B']);
rooms.say(room, cy.token, 'Hello, all.');
const annSees = rooms.view(room, 'A').chat;
expect(annSees.map((l) => l.text)).toEqual(['Round 1.', 'Psst.', 'I hear you.', 'Hello, all.']);
expect(annSees.some((l) => 'note' in l)).toBe(false);
expect(rooms.view(room, 'C').chat.map((l) => l.text)).toEqual(['Round 1.', 'Hello, all.', 'I hear you.']);
expect(rooms.view(room, '').chat.map((l) => l.text)).toEqual(['Hello, all.']);
rooms.submit(room, host.token, { pick: 1 }, 0);
rooms.submit(room, cy.token, { pick: 2 }, 0);
expect(heard[0]).toEqual(['Round 1.', 'Psst.', 'I hear you.', 'Hello, all.', 'I hear you.']);
expect(room.chat.filter((l) => l.note === 'secret').map((l) => l.text)).toEqual(['Round 1.', 'Round 2.']);
expect(rooms.view(room, 'A').parting).toEqual([]);
});
it('refuses private talk to a bot when the game gives bots no words', () => {
const rooms = new Rooms(game, new Store(dir));
const host = rooms.create('Ann', 2);
rooms.addBot(host.room, host.token);
rooms.begin(host.room, host.token);
expect(() => rooms.say(host.room, host.token, 'Psst.', ['B'])).toThrow(/read no private talk/);
});
});