1/** Shared types for gamesapp test harnesses and scenarios */ 3export type GameAction = { 8 descriptionText?: string 9 finishedTrails?: object[] 10 assignedStackName?: string 11 isAiGenerated?: boolean 12 [key: string]: unknown 15// eslint-disable-next-line @typescript-eslint/no-explicit-any 16export type ApplyActionResult = { ok: boolean, gameState?: any, error?: unknown } 18export type GameState = { 21 isEphemeralGame?: boolean 22 gameActionHistA?: GameAction[] 23 pendingAiActionHistA?: GameAction[] 24 playerStates?: Record<string, PlayerState> 25 hiddenState?: { paperStacks?: Record<string, PaperStack> } 26 settings?: GameSettings 27 needsAiDrawings?: boolean 28 [key: string]: unknown 31export type PlayerState = { 37 assignedStackName?: string 38 hasBeenKicked?: boolean 39 [key: string]: unknown 42export type PaperStack = { 43 responses: StackResponse[] 46export type StackResponse = { 48 lastDescription?: string 49 lastFinishedTrails?: object[] 50 lastImageDataUrl?: string 52 isAiGenerated?: boolean 53 [key: string]: unknown 56export type GameSettings = { 57 maxHumPlayers?: number 58 aiDescriptEnabled?: boolean 59 aiDrawEnabled?: boolean 60 aiDrawingAfterFirstHumanDescript?: boolean 61 aiDrawerUsername?: string | null 65export type TestHarness = { 66 applyAction: (action: GameAction) => Promise<ApplyActionResult> 67 getState: () => GameState 68 getActivePlayers: () => Array<{ sessId: string } & PlayerState> 69 getPlayer: (sessId: string) => PlayerState | undefined 70 getPaperStacks: () => Record<string, PaperStack> 71 setGameActiveAt: (sessId: string, gameActiveAtMs: number) => void 72 triggerTimeoutCheck: (sessId: string) => Promise<{ kicked: boolean, overdueSec?: number, remainingSec?: number }> 73 setPlayerIp: (sessId: string, ip: string) => void 74 resetBlockedIps: () => void 75 cleanup?: () => Promise<void> 78export type TestAgent = { 81 chooseAction: (gameState: GameState) => GameAction | null 84export type CreateHarnessOpts = { 92// eslint-disable-next-line @typescript-eslint/no-explicit-any 93export type CreateHarnessFn = (opts?: CreateHarnessOpts) => any 95export type RunAgentsOpts = { 99 onRound?: (info: { round: number, actionsThisRound: number, isGameFin?: boolean }) => void 102export type RunAgentsResult = { 105 gameIdChanged?: boolean 106 reachedMaxRounds: boolean 109export type OnRoundFn = (info: { round: number, actionsThisRound: number, isGameFin?: boolean }) => void 111export type ScenarioOpts = { 112 createHarness?: CreateHarnessFn 117export type TestResult = { passed: boolean, message: string, details?: unknown }