Two Keys: co-op mystery games for couples. Eight games on four engines (story, defuse, sync, labyrinth), two-device and couch play, mobile-first UI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
41 lines
1.6 KiB
TypeScript
41 lines
1.6 KiB
TypeScript
import { loadGames } from '../src/content/loader';
|
|
import type { DefuseGame, Game, LabyrinthGame, StoryGame, SyncGame } from '../src/content/schemas';
|
|
import { initEngine } from '../src/engines/index';
|
|
import { createCtx } from '../src/engines/types';
|
|
import { RoomStore, type Room } from '../src/rooms/store';
|
|
|
|
export const games = loadGames();
|
|
|
|
export function getGame<E extends Game['engine']>(id: string, engine: E): Extract<Game, { engine: E }> {
|
|
const game = games.get(id);
|
|
if (!game || game.engine !== engine) throw new Error(`no ${engine} game "${id}"`);
|
|
return game as Extract<Game, { engine: E }>;
|
|
}
|
|
|
|
export const storyGames = [...games.values()].filter((g): g is StoryGame => g.engine === 'story');
|
|
export const defuse = () => getGame('tick-tock-together', 'defuse') as DefuseGame;
|
|
export const sync = () => getGame('in-sync', 'sync') as SyncGame;
|
|
export const labyrinth = () => getGame('labyrinth-of-lanterns', 'labyrinth') as LabyrinthGame;
|
|
|
|
/** A room that is already in the `playing` phase for the given game. */
|
|
export function playingRoom(game: Game, startedAt = 1_000_000): Room {
|
|
const { room } = new RoomStore(null).create(game.id, 'duo', startedAt);
|
|
room.players[0].seat = 'A';
|
|
room.players.push({ token: 'b', seat: 'B', ready: true, viewing: null });
|
|
room.phase = 'playing';
|
|
room.startedAt = startedAt;
|
|
room.engine = initEngine(game);
|
|
return room;
|
|
}
|
|
|
|
/** A clock for tests: every call to `ctx()` is 3 seconds later, clear of the rate limit. */
|
|
export function clock(room: Room, start = 1_000_000) {
|
|
let now = start;
|
|
return {
|
|
ctx: (advanceMs = 3000) => createCtx(room, (now += advanceMs)),
|
|
get now() {
|
|
return now;
|
|
},
|
|
};
|
|
}
|