The template's bots move once the player's request is answered: a slow bot no longer holds up the reply to the move it is answering

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx
This commit is contained in:
Eric WagonerandClaude Fable 5.1 committed 2026-10-26 17:32:23 -04:00
1 parent dcd2293b42
commit 62cb00be33
2 files changed
+39 -9

No files matched your search

+16 -5
View File
@@ -16,6 +16,9 @@ afterEach(() => {
rmSync(dir, { recursive: true, force: true });
});
/** The bots move once the request that made their move due has been answered: after this tick. */
const settled = () => new Promise<void>((r) => setImmediate(r));
/** A table of the demo game: Ann, who opened it, Bo, and Cy when asked for, the game begun. */
function table(spec: GameSpec<State, Input> = game, withCy = false) {
const rooms = new Rooms(spec, new Store(dir));
@@ -161,7 +164,7 @@ describe('rooms', () => {
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', () => {
it('lets a game give its bots words: when a round opens and when spoken to, with notes kept from every view', async () => {
const heard: string[][] = [];
const talking: GameSpec<State, Input> = {
...game,
@@ -179,6 +182,7 @@ describe('rooms', () => {
const cy = rooms.join(host.room, 'Cy');
const room = host.room;
rooms.begin(room, host.token);
await settled();
rooms.say(room, host.token, 'Psst.', ['B']);
rooms.say(room, cy.token, 'Hello, all.');
const annSees = rooms.view(room, 'A').chat;
@@ -188,6 +192,7 @@ describe('rooms', () => {
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);
await settled();
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([]);
@@ -229,6 +234,7 @@ describe('rooms', () => {
rooms.addBot(host.room, host.token);
rooms.begin(host.room, host.token);
const room = host.room;
vi.runOnlyPendingTimers();
expect(room.state!.n).toBe(4);
expect(rooms.view(room, 'A').playingOn).toBe(true);
vi.advanceTimersByTime(2000);
@@ -243,16 +249,18 @@ describe('rooms', () => {
});
describe('the host and the other seats', () => {
it("gives a person's seat to a bot, which plays it at once, and the person's token opens nothing", () => {
it("gives a person's seat to a bot, which plays it at once, and the person's token opens nothing", async () => {
const { rooms, room, ann, bo } = table();
rooms.submit(room, ann, { pick: 5 }, 0);
rooms.standIn(room, ann, 'B');
// The round waited on Bo alone; the bot played it.
// The round waited on Bo alone; the bot plays it as soon as the host has been answered.
await settled();
expect(room.resolved).toBe(1);
expect(rooms.waitingOn(room)).toEqual(['A']);
expect(() => rooms.seatOf(room, bo)).toThrow(/gave your seat to a bot/);
expect(rooms.view(room, 'A').seats[1]).toEqual({ id: 'B', name: 'Bo', bot: true, standIn: true });
rooms.submit(room, ann, { pick: 3 }, 1);
await settled();
expect(room.resolved).toBe(2);
});
@@ -305,12 +313,15 @@ describe('the host and the other seats', () => {
expect(() => rooms.hostPhrase(withBot.room, withBot.token, bot.id)).toThrow(/No other person/);
});
it('voids a phrase for the seat once a bot stands in, and holds the person\'s seat at a rematch without the stand-in', () => {
it('voids a phrase for the seat once a bot stands in, and holds the person\'s seat at a rematch without the stand-in', async () => {
const { rooms, room, ann } = table();
const { phrase } = rooms.hostPhrase(room, ann, 'B');
rooms.standIn(room, ann, 'B');
expect(() => rooms.claim(phrase)).toThrow(/unknown or has expired/);
while (!game.over(room.state!)) rooms.submit(room, ann, { pick: 5 }, room.resolved);
while (!game.over(room.state!)) {
rooms.submit(room, ann, { pick: 5 }, room.resolved);
await settled();
}
const next = rooms.get(rooms.rematch(room, ann).roomId);
expect(next.expected).toEqual(['Bo']);
expect(next.seats.map((s) => s.name)).toEqual(['Ann']);