import type { UnlockDef, UnlockState } from "../game/unlocks.js"; export interface TechNodeDef extends UnlockDef { requires?: readonly string[]; cost?: Readonly>; grants?: readonly string[]; recipe?: string; } export type TechState = UnlockState; export type TechRejection = { reason: "unknown-node"; } | { reason: "already-unlocked"; } | { reason: "missing-prerequisites"; missing: readonly string[]; }; export type TechCheck = { ok: true; } | ({ ok: false; } & TechRejection); /** @internal */ export declare function techPrerequisitesMet(state: TechState, node: TechNodeDef): boolean; /** @internal */ export declare function missingPrerequisites(state: TechState, node: TechNodeDef): string[]; /** @internal */ export declare function canUnlockTech(defs: readonly TechNodeDef[], state: TechState, id: string): TechCheck; /** @internal */ export declare function grantTech(state: TechState, node: TechNodeDef): string[]; /** * Research/tech nodes gated by prerequisites that unlock recipes and capabilities as they are granted. * * @capability tech-tree research nodes with prerequisites that unlock recipes * @internal */ export declare function availableTech(defs: readonly TechNodeDef[], state: TechState): TechNodeDef[]; /** @internal */ export declare function unlockedRecipes(defs: readonly TechNodeDef[], state: TechState): string[]; export interface TechTree { has(userId: string, id: string): boolean; canUnlock(userId: string, id: string): TechCheck; unlock(userId: string, id: string): TechCheck; available(userId: string): TechNodeDef[]; recipes(userId: string): string[]; list(userId: string): string[]; tree(categoryId: string): UnlockDef[]; node(id: string): TechNodeDef | null; snapshot(userId: string): string[]; hydrate(userId: string, ids: string[]): void; } /** @internal */ export declare function createTechTree(defs?: readonly TechNodeDef[]): TechTree;