The drake moves once the player has been answered, so a move lands at once and the reply follows

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:30:11 -04:00
1 parent 7545985d98
commit 2ef7682dbd
2 files changed
+34 -13

No files matched your search

+16 -9
View File
@@ -21,6 +21,9 @@ afterEach(() => {
const GOLD_OPENS: Input = { from: square('2c2'), to: square('2c3') };
const SCARLET_ANSWERS: Input = { from: square('2c7'), to: square('2c6') };
/** 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 two: Ann, who opened it and plays Gold, and Bo, the game begun. */
function table(spec: GameSpec<State, Input> = game) {
const rooms = new Rooms(spec, new Store(dir));
@@ -124,18 +127,19 @@ describe('rooms', () => {
expect(() => rooms.say(room, bo, 'Anyone?', ['Q'])).toThrow(/Nobody at this table/);
});
it('seats the host on the side they chose, and a drake across from them', () => {
it('seats the host on the side they chose, and a drake across from them, which moves once the host has been answered', async () => {
const rooms = new Rooms(game, new Store(dir));
const host = rooms.create('Ann', 2, { side: 'scarlet', setup: 'shifted' });
const bot = rooms.addBot(host.room, host.token);
expect(game.botNames).toContain(bot.name);
rooms.begin(host.room, host.token);
const s = host.room.state!;
expect(s.players.A.side).toBe('scarlet');
expect(s.players.B.side).toBe('gold');
expect(s.setup).toBe('shifted');
// Gold moves first, and Gold is the drake: it has already moved.
expect(s.moves).toHaveLength(1);
expect(host.room.state!.players.A.side).toBe('scarlet');
expect(host.room.state!.players.B.side).toBe('gold');
expect(host.room.state!.setup).toBe('shifted');
// Gold moves first, and Gold is the drake: it moves once the host's request has been answered, not inside it.
expect(host.room.state!.moves).toHaveLength(0);
await settled();
expect(host.room.state!.moves).toHaveLength(1);
expect(rooms.waitingOn(host.room)).toEqual(['A']);
});
@@ -181,6 +185,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);
@@ -195,16 +200,18 @@ describe('rooms', () => {
});
describe('the host and the other seats', () => {
it("gives a person's seat to a drake, which plays it at once, and the person's token opens nothing", () => {
it("gives a person's seat to a drake, which plays it at once, and the person's token opens nothing", async () => {
const { rooms, room, ann, bo } = table();
rooms.submit(room, ann, GOLD_OPENS, 0);
rooms.standIn(room, ann, 'B');
// The move was Bo's; the drake made it.
// The move was Bo's; the drake makes it as soon as the host has been answered.
await settled();
expect(room.resolved).toBe(2);
expect(rooms.waitingOn(room)).toEqual(['A']);
expect(() => rooms.seatOf(room, bo)).toThrow(/gave your seat to a drake/);
expect(rooms.view(room, 'A').seats[1]).toEqual({ id: 'B', name: 'Bo', bot: true, standIn: true });
rooms.submit(room, ann, { from: square('2d2'), to: square('2d3') }, 2);
await settled();
expect(room.resolved).toBe(4);
});