export declare const AQUARIUM_NAME = "The Great Aquarium"; /** The NPC's display name (NpcKind `curator`). */ export declare const AQUARIUM_CURATOR_NAME = "Curator Elowen Vane"; /** The Live Brown Crab (sheet A's new item): a crab cage now and then comes up with the crab alive. */ export declare const LIVE_CRAB_KIND = "livecrab"; /** Share of crab cage hauls that bring the crab up alive instead of as crab meat. */ export declare const LIVE_CRAB_CHANCE = 0.2; /** Sheet E: a Live Brown Crab can be prepared into crab meat from the bag ("Prepare -> Crab Meat"). */ export declare const LIVE_CRAB_PREPARES_INTO = "crabmeat"; export type AquariumHabitat = 'pond' | 'plants' | 'lake' | 'river' | 'sea' | 'frozen' | 'deep'; export type AquariumSkill = 'fishing' | 'foraging'; export type AquariumHabitatInfo = { id: AquariumHabitat; label: string; /** The tank's Blender model (CAPITAL_BUILDING_MODELS), placed as kind `aquariumtank`, style `-`. */ model: string; /** Paid once, when the tank's last species is donated. */ completeXp: number; completeSkill: AquariumSkill; }; /** In the book's order (sheet D: Pond Life, Water Plants, Lake Fish, Coastal & Sea, Frozen Waters). */ export declare const AQUARIUM_HABITATS: readonly AquariumHabitatInfo[]; export type AquariumSpecies = { /** The item a player donates: the raw catch, never a cooked one. */ kind: string; label: string; habitat: AquariumHabitat; /** The level it is caught at (Fishing, or Foraging for a plant), shown in the book. */ level: number; /** The skill its XP trains. */ skill: AquariumSkill; /** The first donation of the species, once per character. */ firstXp: number; /** Explorer XP for discovering the species (paid with the first donation). */ explorerXp: number; /** Each later donation: about one catch's XP (world.ts's catch XP), capped by AQUARIUM_REPEATS_PER_WINDOW. */ repeatXp: number; /** * Only members can catch it (the Smugglers' Strand's conger), so only members may donate it. A bonus specimen: no * tank and not the book waits for it (aquariumRequiredSpecies). */ members?: boolean; /** Where to find it, one line for the book. */ where: string; }; /** * The species of the book. Sheet E (James, 2026-10-03) prints four payouts: Frog and Snail 55 Fishing + 15 * Explorer, Tadpole 320 Fishing + 60 Explorer, Pond Weed 55 Foraging + 15 Explorer. The rest follow the same line, * firstXp = 55 + 19 x (level - 1) and explorerXp = 15 + 3.2 x (level - 1), rounded to fives, so the two level-1 Fishing * species together (110) take a brand new character from Fishing 1 almost to 3 (121; xp.ts) and a Sea Bass pays 800. */ export declare const AQUARIUM_SPECIES: readonly AquariumSpecies[]; /** Repeat donations (any species already in the book) a character may make in one window. Sheets D and E: "17 / 20". */ export declare const AQUARIUM_REPEATS_PER_WINDOW = 20; /** The window: it opens at the first repeat donation and lasts an hour, then the count starts again. */ export declare const AQUARIUM_REPEAT_WINDOW_MS: number; /** The whole book (its free species: aquariumRequiredSpecies): a title and a last payout. */ export declare const AQUARIUM_COMPLETE_TITLE = "Keeper of the Waters"; export declare const AQUARIUM_COMPLETE_FISHING_XP = 2500; export declare const AQUARIUM_COMPLETE_EXPLORER_XP = 500; /** How close (Chebyshev tiles) a donor must stand to the curator, a tank or the lectern. */ export declare const AQUARIUM_DONATE_RANGE = 4; /** One click's "Donate all" can never take more than this many of a kind. */ export declare const AQUARIUM_DONATE_MAX = 100; export declare function aquariumSpecies(kind: unknown): AquariumSpecies | null; export declare function aquariumHabitat(id: unknown): AquariumHabitatInfo | null; export declare function aquariumHabitatSpecies(habitat: AquariumHabitat): AquariumSpecies[]; /** * The species a full tank (with `habitat`) or the whole book (without) needs: every one a free player can catch. The * members-only ones are bonus specimens (W-070, James 2026-10-03). */ export declare function aquariumRequiredSpecies(habitat?: AquariumHabitat): AquariumSpecies[]; /** * What fills a habitat's tank: its free species, or, for a page that has none (the Deep Sea, deepSea.ts: every fish on it * is a members' catch), its members' species. Only a member can donate those, so only a member ever completes such a * tank; the book and its title still ask for the free species alone. */ export declare function aquariumTankNeeds(habitat: AquariumHabitat): AquariumSpecies[]; /** * The habitat whose tank a model id draws (`aqtankpond` -> 'pond'), from an `aquariumtank` style: Hope Beach's tanks * and the Capital Aquarium's big ones (`capaqtankpond`, capitalAquarium.ts) alike. */ export declare function aquariumHabitatForStyle(style: string | undefined): AquariumHabitat | null; /** * A character's collection, stored on the character document (backend db/characters.ts) so the first-donation flags, * the window and its count survive restarts and deploys. Times are absolute epoch ms, never relative to a boot. */ export type AquariumState = { /** How many of each species kind this character has donated. A kind is in the book once it is 1 or more. */ donated: Record; /** When the current repeat window opened (0 = none open). */ windowStart: number; /** Repeat donations made in that window. */ windowCount: number; /** Habitats whose tank is complete (their bonus has been paid). */ tanks: AquariumHabitat[]; /** The whole book is complete (the title has been paid). */ complete: boolean; }; export declare function emptyAquariumState(): AquariumState; /** Whatever the database held, made safe: unknown kinds and habitats dropped, counts whole and positive. */ export declare function normalizeAquariumState(raw: unknown): AquariumState; export declare function aquariumHasSpecies(state: AquariumState, kind: string): boolean; /** Species in the book so far, of all thirteen (bonus specimens included). */ export declare function aquariumSpeciesCount(state: AquariumState): number; /** Of the species the book needs (aquariumRequiredSpecies, optionally one habitat's), how many are in it: the "x / 12". */ export declare function aquariumRequiredCount(state: AquariumState, habitat?: AquariumHabitat): number; /** Repeat donations left in the window at `now`. */ export declare function aquariumRepeatsLeft(state: AquariumState, now: number): number; /** When the window closes and the count starts again (0 when none is open). */ export declare function aquariumWindowEndsAt(state: AquariumState, now: number): number; export type AquariumXp = { skill: AquariumSkill | 'explorer'; amount: number; }; export type AquariumDonationPlan = { ok: false; reason: string; } | { ok: true; kind: string; /** How many items leave the bag. */ give: number; /** This donation puts the species in the book. */ first: boolean; /** Of `give`, how many count against the window. */ repeats: number; xp: AquariumXp[]; /** Tanks this donation completes, and whether it completes the book. */ tanksCompleted: AquariumHabitat[]; bookCompleted: boolean; /** The state after the donation. */ next: AquariumState; }; /** * What donating `want` of `kind` does, from a bag holding `have` of it, at `now`. Pure: the server applies the plan * (takes `give`, pays `xp`, stores `next`) as one step or refuses everything, and the client shows the same numbers. * * The first one of a species always goes in (it is the discovery, not a repeat); every other one counts against the * window, so a "Donate all" of a new species gives one plus whatever the window has left. */ export declare function planAquariumDonation(state: AquariumState, kind: unknown, want: unknown, have: number, now: number, opts?: { member?: boolean; }): AquariumDonationPlan; export declare const AQUARIUM_X: number; /** The arch's row, on the sand: its two posts stand at AQUARIUM_X +- 2. */ export declare const AQUARIUM_ARCH_Z: number; export type AquariumPiece = { model: string; x: number; z: number; }; /** The walkway, landward first: centre tiles of the 3 x 3 pieces (all facing north, `-n`). */ export declare const AQUARIUM_WALKWAY: readonly AquariumPiece[]; export declare const AQUARIUM_WALKWAY_HALF_W = 1; /** First and last rows of the walkway (the first is the beach row of the start piece). */ export declare const AQUARIUM_WALKWAY_MIN_Z: number; export declare const AQUARIUM_WALKWAY_MAX_Z: number; export declare const AQUARIUM_PLATFORM: { readonly model: "aqplatform"; readonly x: number; readonly z: number; readonly halfX: 7; readonly halfZ: 7; }; export declare const AQUARIUM_HALL: { readonly model: "aquariumhall"; readonly x: number; readonly z: number; readonly halfX: 5; readonly halfZ: 5; }; /** n/e/s/w, or a diagonal for a tank on one of the octagon's angled walls (types constants buildingDiagonalFront). */ export type AquariumFacing = 'n' | 'e' | 's' | 'w' | 'ne' | 'nw' | 'se' | 'sw'; export type AquariumTankPlace = { habitat: AquariumHabitat; x: number; z: number; facing: AquariumFacing; }; /** * The tanks inside the octagon, each 3 long against a wall with its glass to the room (sheet E): Pond Life on the west * wall and Water Plants on the south-west one, Lake Fish on the east and Frozen Waters on the south-east, Coastal & Sea on * the back wall behind the curator. The two on the angled walls stand at 45 degrees along their diagonal's three tiles. * The angled walls either side of the door hold the water system (west) and the trophy display (east). */ export declare const AQUARIUM_TANKS: readonly AquariumTankPlace[]; /** The curator's desk (3 x 1, front to the door) and where she stands behind it, in front of the Coastal & Sea tank. */ export declare const AQUARIUM_DESK: { model: string; x: number; z: number; facing: AquariumFacing; }; export declare const AQUARIUM_CURATOR_SPOT: { x: number; z: number; }; /** The Collection Book on its lectern in the middle of the room, on the fish rug, the book open to the door (sheet E). */ export declare const AQUARIUM_LECTERN: { model: string; x: number; z: number; facing: AquariumFacing; }; /** Kinds the aquarium's clickable pieces are placed as. */ export declare const AQUARIUM_TANK_KIND = "aquariumtank"; export declare const AQUARIUM_LECTERN_KIND = "aquariumlectern"; /** * The tank's water, in the tank model's own frame (three.js, before the facing turn: x across, y up, z towards the * glass front), where the game swims the species a player has donated (quest-workshop aquarium_v001.py). */ export declare const AQUARIUM_TANK_INTERIOR: { readonly halfX: 1.2; readonly y0: 1; readonly y1: 1.72; readonly z0: -0.18; readonly z1: 0.2; }; export type AquariumTankInterior = { readonly halfX: number; readonly y0: number; readonly y1: number; readonly z0: number; readonly z1: number; }; /** The water a tank's style swims its species in: Hope Beach's 3 x 1 tank, or the Capital Aquarium's 5 x 1 big tank. */ export declare function aquariumTankInterior(style: string | undefined): AquariumTankInterior; /** * The water under each glass floor piece of the walkway (aqpierglass, quest-workshop aquarium_v003.py), in the piece's * own frame (three.js: x across the walkway, y up from the deck tile, z along it): where the game swims the marine life * a player has given the Coastal & Sea tank, seen through the panes (sheet E: "collected marine life can appear in the * glass panels"). It is a thin layer between the painted seabed (y 0.042) and the panes (y 0.07), because the deck tile * under it is drawn as boards; the creatures are flattened to it (`flatten`, their height's scale), which from the game * camera, looking down, reads as fish swimming under the glass. */ export declare const AQUARIUM_GLASS_WELL: { readonly halfX: 0.48; readonly halfZ: 1.3; readonly y0: 0.046; readonly y1: 0.066; readonly flatten: 0.1; }; export declare const AQUARIUM_GLASS_WELL_HABITAT: AquariumHabitat; /** Is (x, z) on the aquarium's decks: the walkway or the platform (hall included)? */ export declare function onAquariumDeck(x: number, z: number): boolean; /** * Every tile the aquarium authors: the decks, the arch's row and the two rows of sand in front of it it keeps clear. * The beach's own passes (litter, finds, treasure digs, the beach regression smoke) leave these alone. */ export declare function onAquariumSite(x: number, z: number): boolean; /** * Inside the hall's walls: the octagon's room, not the walls nor the open corners outside them (the same measure as the * collision, types constants buildingOctagonRadius). */ export declare function inHopeAquariumHall(x: number, z: number): boolean; /** * Inside an aquarium, where the donate panel, the book and the tanks are in reach: the Hope Beach hall, or anywhere * indoors in the Capital Aquarium (its Main Hall and its three wings, capitalAquarium.ts). The one collection book opens * in either. */ export declare function inAquariumHall(x: number, z: number): boolean; //# sourceMappingURL=aquarium.d.ts.map