@dreadwood-types/types 0.1.103 → 0.1.104

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,207 @@
1
+ export declare const AQUARIUM_NAME = "The Great Aquarium";
2
+ /** The NPC's display name (NpcKind `curator`). */
3
+ export declare const AQUARIUM_CURATOR_NAME = "Curator Elowen Vane";
4
+ /** The Live Brown Crab (sheet A's new item): a crab cage now and then comes up with the crab alive. */
5
+ export declare const LIVE_CRAB_KIND = "livecrab";
6
+ /** Share of crab cage hauls that bring the crab up alive instead of as crab meat. */
7
+ export declare const LIVE_CRAB_CHANCE = 0.2;
8
+ /** Sheet E: a Live Brown Crab can be prepared into crab meat from the bag ("Prepare -> Crab Meat"). */
9
+ export declare const LIVE_CRAB_PREPARES_INTO = "crabmeat";
10
+ export type AquariumHabitat = 'pond' | 'plants' | 'lake' | 'sea' | 'frozen';
11
+ export type AquariumSkill = 'fishing' | 'foraging';
12
+ export type AquariumHabitatInfo = {
13
+ id: AquariumHabitat;
14
+ label: string;
15
+ /** The tank's Blender model (CAPITAL_BUILDING_MODELS), placed as kind `aquariumtank`, style `<model>-<facing>`. */
16
+ model: string;
17
+ /** Paid once, when the tank's last species is donated. */
18
+ completeXp: number;
19
+ completeSkill: AquariumSkill;
20
+ };
21
+ /** In the book's order (sheet D: Pond Life, Water Plants, Lake Fish, Coastal & Sea, Frozen Waters). */
22
+ export declare const AQUARIUM_HABITATS: readonly AquariumHabitatInfo[];
23
+ export type AquariumSpecies = {
24
+ /** The item a player donates: the raw catch, never a cooked one. */
25
+ kind: string;
26
+ label: string;
27
+ habitat: AquariumHabitat;
28
+ /** The level it is caught at (Fishing, or Foraging for a plant), shown in the book. */
29
+ level: number;
30
+ /** The skill its XP trains. */
31
+ skill: AquariumSkill;
32
+ /** The first donation of the species, once per character. */
33
+ firstXp: number;
34
+ /** Explorer XP for discovering the species (paid with the first donation). */
35
+ explorerXp: number;
36
+ /** Each later donation: about one catch's XP (world.ts's catch XP), capped by AQUARIUM_REPEATS_PER_WINDOW. */
37
+ repeatXp: number;
38
+ /** Only members can catch it (the Smugglers' Strand's conger), so only members may donate it. */
39
+ members?: boolean;
40
+ /** Where to find it, one line for the book. */
41
+ where: string;
42
+ };
43
+ /**
44
+ * The thirteen species of the book. Sheet E (James, 2026-10-03) prints four payouts: Frog and Snail 55 Fishing + 15
45
+ * Explorer, Tadpole 320 Fishing + 60 Explorer, Pond Weed 55 Foraging + 15 Explorer. The rest follow the same line,
46
+ * firstXp = 55 + 19 x (level - 1) and explorerXp = 15 + 3.2 x (level - 1), rounded to fives, so the two level-1 Fishing
47
+ * species together (110) take a brand new character from Fishing 1 almost to 3 (121; xp.ts) and a Sea Bass pays 800.
48
+ */
49
+ export declare const AQUARIUM_SPECIES: readonly AquariumSpecies[];
50
+ /** Repeat donations (any species already in the book) a character may make in one window. Sheet D: "17 / 20". */
51
+ export declare const AQUARIUM_REPEATS_PER_WINDOW = 20;
52
+ /** The window: it opens at the first repeat donation and lasts an hour, then the count starts again. */
53
+ export declare const AQUARIUM_REPEAT_WINDOW_MS: number;
54
+ /** The whole book: a title and a last payout. */
55
+ export declare const AQUARIUM_COMPLETE_TITLE = "Keeper of the Waters";
56
+ export declare const AQUARIUM_COMPLETE_FISHING_XP = 2500;
57
+ export declare const AQUARIUM_COMPLETE_EXPLORER_XP = 500;
58
+ /** How close (Chebyshev tiles) a donor must stand to the curator, a tank or the lectern. */
59
+ export declare const AQUARIUM_DONATE_RANGE = 4;
60
+ /** One click's "Donate all" can never take more than this many of a kind. */
61
+ export declare const AQUARIUM_DONATE_MAX = 100;
62
+ export declare function aquariumSpecies(kind: unknown): AquariumSpecies | null;
63
+ export declare function aquariumHabitat(id: unknown): AquariumHabitatInfo | null;
64
+ export declare function aquariumHabitatSpecies(habitat: AquariumHabitat): AquariumSpecies[];
65
+ /** The habitat whose tank a model id draws (`aqtankpond` -> 'pond'), from an `aquariumtank` style. */
66
+ export declare function aquariumHabitatForStyle(style: string | undefined): AquariumHabitat | null;
67
+ /**
68
+ * A character's collection, stored on the character document (backend db/characters.ts) so the first-donation flags,
69
+ * the window and its count survive restarts and deploys. Times are absolute epoch ms, never relative to a boot.
70
+ */
71
+ export type AquariumState = {
72
+ /** How many of each species kind this character has donated. A kind is in the book once it is 1 or more. */
73
+ donated: Record<string, number>;
74
+ /** When the current repeat window opened (0 = none open). */
75
+ windowStart: number;
76
+ /** Repeat donations made in that window. */
77
+ windowCount: number;
78
+ /** Habitats whose tank is complete (their bonus has been paid). */
79
+ tanks: AquariumHabitat[];
80
+ /** The whole book is complete (the title has been paid). */
81
+ complete: boolean;
82
+ };
83
+ export declare function emptyAquariumState(): AquariumState;
84
+ /** Whatever the database held, made safe: unknown kinds and habitats dropped, counts whole and positive. */
85
+ export declare function normalizeAquariumState(raw: unknown): AquariumState;
86
+ export declare function aquariumHasSpecies(state: AquariumState, kind: string): boolean;
87
+ /** Species in the book so far, of all thirteen. */
88
+ export declare function aquariumSpeciesCount(state: AquariumState): number;
89
+ /** Repeat donations left in the window at `now`. */
90
+ export declare function aquariumRepeatsLeft(state: AquariumState, now: number): number;
91
+ /** When the window closes and the count starts again (0 when none is open). */
92
+ export declare function aquariumWindowEndsAt(state: AquariumState, now: number): number;
93
+ export type AquariumXp = {
94
+ skill: AquariumSkill | 'explorer';
95
+ amount: number;
96
+ };
97
+ export type AquariumDonationPlan = {
98
+ ok: false;
99
+ reason: string;
100
+ } | {
101
+ ok: true;
102
+ kind: string;
103
+ /** How many items leave the bag. */
104
+ give: number;
105
+ /** This donation puts the species in the book. */
106
+ first: boolean;
107
+ /** Of `give`, how many count against the window. */
108
+ repeats: number;
109
+ xp: AquariumXp[];
110
+ /** Tanks this donation completes, and whether it completes the book. */
111
+ tanksCompleted: AquariumHabitat[];
112
+ bookCompleted: boolean;
113
+ /** The state after the donation. */
114
+ next: AquariumState;
115
+ };
116
+ /**
117
+ * What donating `want` of `kind` does, from a bag holding `have` of it, at `now`. Pure: the server applies the plan
118
+ * (takes `give`, pays `xp`, stores `next`) as one step or refuses everything, and the client shows the same numbers.
119
+ *
120
+ * The first one of a species always goes in (it is the discovery, not a repeat); every other one counts against the
121
+ * window, so a "Donate all" of a new species gives one plus whatever the window has left.
122
+ */
123
+ export declare function planAquariumDonation(state: AquariumState, kind: unknown, want: unknown, have: number, now: number, opts?: {
124
+ member?: boolean;
125
+ }): AquariumDonationPlan;
126
+ export declare const AQUARIUM_X: number;
127
+ /** The arch's row, on the sand: its two posts stand at AQUARIUM_X +- 2. */
128
+ export declare const AQUARIUM_ARCH_Z: number;
129
+ export type AquariumPiece = {
130
+ model: string;
131
+ x: number;
132
+ z: number;
133
+ };
134
+ /** The walkway, landward first: centre tiles of the 3 x 3 pieces (all facing north, `<model>-n`). */
135
+ export declare const AQUARIUM_WALKWAY: readonly AquariumPiece[];
136
+ export declare const AQUARIUM_WALKWAY_HALF_W = 1;
137
+ /** First and last rows of the walkway (the first is the beach row of the start piece). */
138
+ export declare const AQUARIUM_WALKWAY_MIN_Z: number;
139
+ export declare const AQUARIUM_WALKWAY_MAX_Z: number;
140
+ export declare const AQUARIUM_PLATFORM: {
141
+ readonly model: "aqplatform";
142
+ readonly x: number;
143
+ readonly z: number;
144
+ readonly halfX: 7;
145
+ readonly halfZ: 6;
146
+ };
147
+ export declare const AQUARIUM_HALL: {
148
+ readonly model: "aquariumhall";
149
+ readonly x: number;
150
+ readonly z: number;
151
+ readonly halfX: 5;
152
+ readonly halfZ: 4;
153
+ };
154
+ export type AquariumFacing = 'n' | 'e' | 's' | 'w';
155
+ export type AquariumTankPlace = {
156
+ habitat: AquariumHabitat;
157
+ x: number;
158
+ z: number;
159
+ facing: AquariumFacing;
160
+ };
161
+ /**
162
+ * The tanks inside the hall, each 3 x 1 against a wall, its glass facing into the room: Pond Life and Water Plants
163
+ * on the west wall, Lake Fish and Frozen Waters on the east, Coastal & Sea at the back behind the curator.
164
+ */
165
+ export declare const AQUARIUM_TANKS: readonly AquariumTankPlace[];
166
+ /** The curator's desk (3 x 1, front to the door) and where she stands behind it. */
167
+ export declare const AQUARIUM_DESK: {
168
+ model: string;
169
+ x: number;
170
+ z: number;
171
+ facing: AquariumFacing;
172
+ };
173
+ export declare const AQUARIUM_CURATOR_SPOT: {
174
+ x: number;
175
+ z: number;
176
+ };
177
+ /** The Collection Book on its lectern, to the left of the walk in. */
178
+ export declare const AQUARIUM_LECTERN: {
179
+ model: string;
180
+ x: number;
181
+ z: number;
182
+ facing: AquariumFacing;
183
+ };
184
+ /** Kinds the aquarium's clickable pieces are placed as. */
185
+ export declare const AQUARIUM_TANK_KIND = "aquariumtank";
186
+ export declare const AQUARIUM_LECTERN_KIND = "aquariumlectern";
187
+ /**
188
+ * The tank's water, in the tank model's own frame (three.js, before the facing turn: x across, y up, z towards the
189
+ * glass front), where the game swims the species a player has donated (quest-workshop aquarium_v001.py).
190
+ */
191
+ export declare const AQUARIUM_TANK_INTERIOR: {
192
+ readonly halfX: 1.2;
193
+ readonly y0: 1;
194
+ readonly y1: 1.72;
195
+ readonly z0: -0.18;
196
+ readonly z1: 0.2;
197
+ };
198
+ /** Is (x, z) on the aquarium's decks: the walkway or the platform (hall included)? */
199
+ export declare function onAquariumDeck(x: number, z: number): boolean;
200
+ /**
201
+ * Every tile the aquarium authors: the decks, the arch's row and the two rows of sand in front of it it keeps clear.
202
+ * The beach's own passes (litter, finds, treasure digs, the beach regression smoke) leave these alone.
203
+ */
204
+ export declare function onAquariumSite(x: number, z: number): boolean;
205
+ /** Inside the hall's walls (the walkable room, not the ring the walls stand on). */
206
+ export declare function inAquariumHall(x: number, z: number): boolean;
207
+ //# sourceMappingURL=aquarium.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aquarium.d.ts","sourceRoot":"","sources":["../src/aquarium.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,279 @@
1
+ /**
2
+ * THE GREAT AQUARIUM (James, 2026-10-03: "a giant aquarium somewhere and we store things like tadpole for lots of xp ...
3
+ * I want early players to be able to benefit"). His four concept sheets are filed in the backend's design-references
4
+ * (`great-aquarium`, `aquariumcurator`, `livecrab`); the plan is `.cursor/task-plans/2026-10-03-great-aquarium.md`.
5
+ *
6
+ * Phase 1 is on Hope Beach, open from level 1: a pier of its own west of the Long Pier (a glass floor down its middle)
7
+ * out to a platform with a glass hall on it. Inside, Curator Elowen Vane keeps one collection book per character: donate
8
+ * a live catch or a water plant and its tank shows it swimming, the first of each species pays a big one-time XP, later
9
+ * ones a catch's worth (capped per hour), a full tank pays a bonus and the whole book a title. Phase 2, the grand hall in
10
+ * the Capital's King's Harbour, opens the same book (backend NEXT_STEPS.md).
11
+ *
12
+ * Every number James may want to tune is here: the species table, the XP, the hourly cap, the bonuses. The donation
13
+ * rules are pure functions here too, so the server applies exactly what the client previews.
14
+ */
15
+ import { BEACH_GATE_X, OCEAN_START_Z } from './constants.js';
16
+ import { FROG_KIND, POND_WEED_KIND, ROACH_KIND, SNAIL_KIND, TADPOLE_KIND } from './pondFishing.js';
17
+ import { RAW_CONGER_KIND } from './smugglersStrand.js';
18
+ import { RAW_SMELT_KIND, RAW_TROUT_KIND } from './woodwork.js';
19
+ export const AQUARIUM_NAME = 'The Great Aquarium';
20
+ /** The NPC's display name (NpcKind `curator`). */
21
+ export const AQUARIUM_CURATOR_NAME = 'Curator Elowen Vane';
22
+ /** The Live Brown Crab (sheet A's new item): a crab cage now and then comes up with the crab alive. */
23
+ export const LIVE_CRAB_KIND = 'livecrab';
24
+ /** Share of crab cage hauls that bring the crab up alive instead of as crab meat. */
25
+ export const LIVE_CRAB_CHANCE = 0.2;
26
+ /** Sheet E: a Live Brown Crab can be prepared into crab meat from the bag ("Prepare -> Crab Meat"). */
27
+ export const LIVE_CRAB_PREPARES_INTO = 'crabmeat';
28
+ /** In the book's order (sheet D: Pond Life, Water Plants, Lake Fish, Coastal & Sea, Frozen Waters). */
29
+ export const AQUARIUM_HABITATS = [
30
+ { id: 'pond', label: 'Pond Life', model: 'aqtankpond', completeXp: 150, completeSkill: 'fishing' },
31
+ { id: 'plants', label: 'Water Plants', model: 'aqtankplants', completeXp: 40, completeSkill: 'foraging' },
32
+ { id: 'lake', label: 'Lake Fish', model: 'aqtanklake', completeXp: 600, completeSkill: 'fishing' },
33
+ { id: 'sea', label: 'Coastal & Sea', model: 'aqtanksea', completeXp: 1200, completeSkill: 'fishing' },
34
+ { id: 'frozen', label: 'Frozen Waters', model: 'aqtankfrozen', completeXp: 500, completeSkill: 'fishing' },
35
+ ];
36
+ /**
37
+ * The thirteen species of the book. Sheet E (James, 2026-10-03) prints four payouts: Frog and Snail 55 Fishing + 15
38
+ * Explorer, Tadpole 320 Fishing + 60 Explorer, Pond Weed 55 Foraging + 15 Explorer. The rest follow the same line,
39
+ * firstXp = 55 + 19 x (level - 1) and explorerXp = 15 + 3.2 x (level - 1), rounded to fives, so the two level-1 Fishing
40
+ * species together (110) take a brand new character from Fishing 1 almost to 3 (121; xp.ts) and a Sea Bass pays 800.
41
+ */
42
+ export const AQUARIUM_SPECIES = [
43
+ { kind: FROG_KIND, label: 'Frog', habitat: 'pond', level: 1, skill: 'fishing', firstXp: 55, explorerXp: 15, repeatXp: 8, where: 'Scooped with a net at Henson Pond.' },
44
+ { kind: SNAIL_KIND, label: 'Snail', habitat: 'pond', level: 1, skill: 'fishing', firstXp: 55, explorerXp: 15, repeatXp: 6, where: 'Clings to a net at Henson Pond.' },
45
+ { kind: TADPOLE_KIND, label: 'Tadpole', habitat: 'pond', level: 15, skill: 'fishing', firstXp: 320, explorerXp: 60, repeatXp: 12, where: 'Henson Pond, in the net, from Fishing 15.' },
46
+ { kind: ROACH_KIND, label: 'Roach', habitat: 'pond', level: 20, skill: 'fishing', firstXp: 415, explorerXp: 75, repeatXp: 18, where: 'Henson Pond, in the net, from Fishing 20.' },
47
+ { kind: POND_WEED_KIND, label: 'Pond Weed', habitat: 'plants', level: 1, skill: 'foraging', firstXp: 55, explorerXp: 15, repeatXp: 4, where: 'Trails from a net at Henson Pond.' },
48
+ { kind: 'rawperch', label: 'Perch', habitat: 'lake', level: 7, skill: 'fishing', firstXp: 170, explorerXp: 35, repeatXp: 22, where: 'A rod and bait at the lake spots.' },
49
+ { kind: 'rawtench', label: 'Tench', habitat: 'lake', level: 20, skill: 'fishing', firstXp: 415, explorerXp: 75, repeatXp: 45, where: 'A rod and earth worms, from Fishing 20.' },
50
+ { kind: RAW_TROUT_KIND, label: 'Trout', habitat: 'lake', level: 30, skill: 'fishing', firstXp: 605, explorerXp: 110, repeatXp: 90, where: 'The Trout Fishery, on the fly.' },
51
+ { kind: LIVE_CRAB_KIND, label: 'Live Brown Crab', habitat: 'sea', level: 3, skill: 'fishing', firstXp: 95, explorerXp: 20, repeatXp: 14, where: 'Now and then a crab cage off the Long Pier comes up with one alive.' },
52
+ { kind: RAW_SMELT_KIND, label: 'Smelt', habitat: 'sea', level: 10, skill: 'fishing', firstXp: 225, explorerXp: 45, repeatXp: 26, where: 'Off the Long Pier with a spinning rod.' },
53
+ { kind: RAW_CONGER_KIND, label: 'Conger Eel', habitat: 'sea', level: 30, skill: 'fishing', firstXp: 605, explorerXp: 110, repeatXp: 110, members: true, where: "Among the rocks of the Smugglers' Strand (members)." },
54
+ { kind: 'rawbass', label: 'Sea Bass', habitat: 'sea', level: 40, skill: 'fishing', firstXp: 800, explorerXp: 140, repeatXp: 160, where: 'Off the far end of the Long Pier.' },
55
+ { kind: 'rawfrostpike', label: 'Frost Pike', habitat: 'frozen', level: 35, skill: 'fishing', firstXp: 700, explorerXp: 125, repeatXp: 60, where: 'Through the ice holes of the Frozen Lake.' },
56
+ ];
57
+ /** Repeat donations (any species already in the book) a character may make in one window. Sheet D: "17 / 20". */
58
+ export const AQUARIUM_REPEATS_PER_WINDOW = 20;
59
+ /** The window: it opens at the first repeat donation and lasts an hour, then the count starts again. */
60
+ export const AQUARIUM_REPEAT_WINDOW_MS = 60 * 60 * 1000;
61
+ /** The whole book: a title and a last payout. */
62
+ export const AQUARIUM_COMPLETE_TITLE = 'Keeper of the Waters';
63
+ export const AQUARIUM_COMPLETE_FISHING_XP = 2500;
64
+ export const AQUARIUM_COMPLETE_EXPLORER_XP = 500;
65
+ /** How close (Chebyshev tiles) a donor must stand to the curator, a tank or the lectern. */
66
+ export const AQUARIUM_DONATE_RANGE = 4;
67
+ /** One click's "Donate all" can never take more than this many of a kind. */
68
+ export const AQUARIUM_DONATE_MAX = 100;
69
+ const SPECIES_BY_KIND = new Map(AQUARIUM_SPECIES.map((s) => [s.kind, s]));
70
+ export function aquariumSpecies(kind) {
71
+ return typeof kind === 'string' ? SPECIES_BY_KIND.get(kind) ?? null : null;
72
+ }
73
+ export function aquariumHabitat(id) {
74
+ return AQUARIUM_HABITATS.find((h) => h.id === id) ?? null;
75
+ }
76
+ export function aquariumHabitatSpecies(habitat) {
77
+ return AQUARIUM_SPECIES.filter((s) => s.habitat === habitat);
78
+ }
79
+ /** The habitat whose tank a model id draws (`aqtankpond` -> 'pond'), from an `aquariumtank` style. */
80
+ export function aquariumHabitatForStyle(style) {
81
+ const model = (style ?? '').split('-')[0];
82
+ return AQUARIUM_HABITATS.find((h) => h.model === model)?.id ?? null;
83
+ }
84
+ export function emptyAquariumState() {
85
+ return { donated: {}, windowStart: 0, windowCount: 0, tanks: [], complete: false };
86
+ }
87
+ /** Whatever the database held, made safe: unknown kinds and habitats dropped, counts whole and positive. */
88
+ export function normalizeAquariumState(raw) {
89
+ const out = emptyAquariumState();
90
+ if (!raw || typeof raw !== 'object')
91
+ return out;
92
+ const r = raw;
93
+ if (r.donated && typeof r.donated === 'object') {
94
+ for (const [kind, n] of Object.entries(r.donated)) {
95
+ if (!SPECIES_BY_KIND.has(kind) || typeof n !== 'number' || !Number.isFinite(n) || n < 1)
96
+ continue;
97
+ out.donated[kind] = Math.floor(n);
98
+ }
99
+ }
100
+ if (typeof r.windowStart === 'number' && Number.isFinite(r.windowStart) && r.windowStart > 0)
101
+ out.windowStart = r.windowStart;
102
+ if (typeof r.windowCount === 'number' && Number.isFinite(r.windowCount) && r.windowCount > 0) {
103
+ out.windowCount = Math.min(AQUARIUM_REPEATS_PER_WINDOW, Math.floor(r.windowCount));
104
+ }
105
+ if (Array.isArray(r.tanks)) {
106
+ out.tanks = AQUARIUM_HABITATS.map((h) => h.id).filter((id) => r.tanks.includes(id));
107
+ }
108
+ out.complete = r.complete === true;
109
+ return out;
110
+ }
111
+ export function aquariumHasSpecies(state, kind) {
112
+ return (state.donated[kind] ?? 0) > 0;
113
+ }
114
+ /** Species in the book so far, of all thirteen. */
115
+ export function aquariumSpeciesCount(state) {
116
+ return AQUARIUM_SPECIES.filter((s) => aquariumHasSpecies(state, s.kind)).length;
117
+ }
118
+ /** Is the window still open at `now`? A clock that went backwards (or a window from the future) counts as closed. */
119
+ function windowOpen(state, now) {
120
+ return state.windowStart > 0 && now >= state.windowStart && now - state.windowStart < AQUARIUM_REPEAT_WINDOW_MS;
121
+ }
122
+ /** Repeat donations left in the window at `now`. */
123
+ export function aquariumRepeatsLeft(state, now) {
124
+ return windowOpen(state, now) ? Math.max(0, AQUARIUM_REPEATS_PER_WINDOW - state.windowCount) : AQUARIUM_REPEATS_PER_WINDOW;
125
+ }
126
+ /** When the window closes and the count starts again (0 when none is open). */
127
+ export function aquariumWindowEndsAt(state, now) {
128
+ return windowOpen(state, now) ? state.windowStart + AQUARIUM_REPEAT_WINDOW_MS : 0;
129
+ }
130
+ function addXp(list, skill, amount) {
131
+ if (amount <= 0)
132
+ return;
133
+ const at = list.find((x) => x.skill === skill);
134
+ if (at)
135
+ at.amount += amount;
136
+ else
137
+ list.push({ skill, amount });
138
+ }
139
+ /**
140
+ * What donating `want` of `kind` does, from a bag holding `have` of it, at `now`. Pure: the server applies the plan
141
+ * (takes `give`, pays `xp`, stores `next`) as one step or refuses everything, and the client shows the same numbers.
142
+ *
143
+ * The first one of a species always goes in (it is the discovery, not a repeat); every other one counts against the
144
+ * window, so a "Donate all" of a new species gives one plus whatever the window has left.
145
+ */
146
+ export function planAquariumDonation(state, kind, want, have, now, opts = {}) {
147
+ const species = aquariumSpecies(kind);
148
+ if (!species)
149
+ return { ok: false, reason: 'The curator only takes live catches and water plants for the tanks.' };
150
+ if (species.members && !opts.member)
151
+ return { ok: false, reason: `Only members can donate the ${species.label}.` };
152
+ const asked = typeof want === 'number' && Number.isFinite(want) ? Math.floor(want) : 0;
153
+ if (asked < 1)
154
+ return { ok: false, reason: 'Donate how many?' };
155
+ const held = Math.max(0, Math.floor(have));
156
+ if (held < 1)
157
+ return { ok: false, reason: `You have no ${species.label} to donate.` };
158
+ const first = !aquariumHasSpecies(state, species.kind);
159
+ const left = aquariumRepeatsLeft(state, now);
160
+ const cap = Math.min(asked, held, AQUARIUM_DONATE_MAX);
161
+ const firstGive = first ? 1 : 0;
162
+ const repeats = Math.max(0, Math.min(cap - firstGive, left));
163
+ const give = firstGive + repeats;
164
+ if (give < 1) {
165
+ const ends = aquariumWindowEndsAt(state, now);
166
+ const mins = ends ? Math.max(1, Math.ceil((ends - now) / 60000)) : 60;
167
+ return {
168
+ ok: false,
169
+ reason: `The tanks are full for now: that's your ${AQUARIUM_REPEATS_PER_WINDOW} this hour. Come back in ${mins} minute${mins === 1 ? '' : 's'}.`,
170
+ };
171
+ }
172
+ const next = {
173
+ donated: { ...state.donated, [species.kind]: (state.donated[species.kind] ?? 0) + give },
174
+ windowStart: state.windowStart,
175
+ windowCount: state.windowCount,
176
+ tanks: [...state.tanks],
177
+ complete: state.complete,
178
+ };
179
+ if (repeats > 0) {
180
+ if (!windowOpen(state, now)) {
181
+ next.windowStart = now;
182
+ next.windowCount = 0;
183
+ }
184
+ next.windowCount += repeats;
185
+ }
186
+ const xp = [];
187
+ if (first) {
188
+ addXp(xp, species.skill, species.firstXp);
189
+ addXp(xp, 'explorer', species.explorerXp);
190
+ }
191
+ addXp(xp, species.skill, species.repeatXp * repeats);
192
+ const tanksCompleted = [];
193
+ if (first) {
194
+ const habitat = aquariumHabitat(species.habitat);
195
+ const full = aquariumHabitatSpecies(species.habitat).every((s) => (next.donated[s.kind] ?? 0) > 0);
196
+ if (full && !next.tanks.includes(habitat.id)) {
197
+ tanksCompleted.push(habitat.id);
198
+ next.tanks = AQUARIUM_HABITATS.map((h) => h.id).filter((id) => id === habitat.id || next.tanks.includes(id));
199
+ addXp(xp, habitat.completeSkill, habitat.completeXp);
200
+ }
201
+ }
202
+ let bookCompleted = false;
203
+ if (!next.complete && AQUARIUM_SPECIES.every((s) => (next.donated[s.kind] ?? 0) > 0)) {
204
+ bookCompleted = true;
205
+ next.complete = true;
206
+ addXp(xp, 'fishing', AQUARIUM_COMPLETE_FISHING_XP);
207
+ addXp(xp, 'explorer', AQUARIUM_COMPLETE_EXPLORER_XP);
208
+ }
209
+ return { ok: true, kind: species.kind, give, first, repeats, xp, tanksCompleted, bookCompleted, next };
210
+ }
211
+ /* --- Where it stands on Hope Beach ------------------------------------------
212
+ *
213
+ * West of the Long Pier, on the open sand between the beach gate and the pier (sheets A-D's maps). World tiles. The
214
+ * walkway is three wide down x AQUARIUM_X, five 3 x 3 Blender pieces from the beach out to a 15 x 13 platform; the
215
+ * 11 x 9 hall stands on the platform one row south of its centre, door north, a forecourt of three rows in front.
216
+ * Water tiles under the decks become SurfaceType.Boards at height 1 (the Long Pier is Path at 1); the start piece's
217
+ * landward row stays beach and its boards ramp up. The arch stands one row further landward, on the sand.
218
+ */
219
+ export const AQUARIUM_X = BEACH_GATE_X + 7;
220
+ /** The arch's row, on the sand: its two posts stand at AQUARIUM_X +- 2. */
221
+ export const AQUARIUM_ARCH_Z = OCEAN_START_Z - 2;
222
+ /** The walkway, landward first: centre tiles of the 3 x 3 pieces (all facing north, `<model>-n`). */
223
+ export const AQUARIUM_WALKWAY = [
224
+ { model: 'aqpierstart', x: AQUARIUM_X, z: OCEAN_START_Z },
225
+ { model: 'aqpiermiddle', x: AQUARIUM_X, z: OCEAN_START_Z + 3 },
226
+ { model: 'aqpierglass', x: AQUARIUM_X, z: OCEAN_START_Z + 6 },
227
+ { model: 'aqpiermiddle', x: AQUARIUM_X, z: OCEAN_START_Z + 9 },
228
+ { model: 'aqpierglass', x: AQUARIUM_X, z: OCEAN_START_Z + 12 },
229
+ ];
230
+ export const AQUARIUM_WALKWAY_HALF_W = 1;
231
+ /** First and last rows of the walkway (the first is the beach row of the start piece). */
232
+ export const AQUARIUM_WALKWAY_MIN_Z = OCEAN_START_Z - 1;
233
+ export const AQUARIUM_WALKWAY_MAX_Z = OCEAN_START_Z + 13;
234
+ export const AQUARIUM_PLATFORM = { model: 'aqplatform', x: AQUARIUM_X, z: OCEAN_START_Z + 20, halfX: 7, halfZ: 6 };
235
+ export const AQUARIUM_HALL = { model: 'aquariumhall', x: AQUARIUM_X, z: OCEAN_START_Z + 21, halfX: 5, halfZ: 4 };
236
+ /**
237
+ * The tanks inside the hall, each 3 x 1 against a wall, its glass facing into the room: Pond Life and Water Plants
238
+ * on the west wall, Lake Fish and Frozen Waters on the east, Coastal & Sea at the back behind the curator.
239
+ */
240
+ export const AQUARIUM_TANKS = [
241
+ { habitat: 'pond', x: AQUARIUM_HALL.x - 4, z: AQUARIUM_HALL.z - 1, facing: 'e' },
242
+ { habitat: 'plants', x: AQUARIUM_HALL.x - 4, z: AQUARIUM_HALL.z + 2, facing: 'e' },
243
+ { habitat: 'lake', x: AQUARIUM_HALL.x + 4, z: AQUARIUM_HALL.z - 1, facing: 'w' },
244
+ { habitat: 'frozen', x: AQUARIUM_HALL.x + 4, z: AQUARIUM_HALL.z + 2, facing: 'w' },
245
+ { habitat: 'sea', x: AQUARIUM_HALL.x, z: AQUARIUM_HALL.z + 3, facing: 'n' },
246
+ ];
247
+ /** The curator's desk (3 x 1, front to the door) and where she stands behind it. */
248
+ export const AQUARIUM_DESK = { model: 'aqdesk', x: AQUARIUM_HALL.x, z: AQUARIUM_HALL.z + 1, facing: 'n' };
249
+ export const AQUARIUM_CURATOR_SPOT = { x: AQUARIUM_HALL.x, z: AQUARIUM_HALL.z + 2 };
250
+ /** The Collection Book on its lectern, to the left of the walk in. */
251
+ export const AQUARIUM_LECTERN = { model: 'aqlectern', x: AQUARIUM_HALL.x - 2, z: AQUARIUM_HALL.z, facing: 'n' };
252
+ /** Kinds the aquarium's clickable pieces are placed as. */
253
+ export const AQUARIUM_TANK_KIND = 'aquariumtank';
254
+ export const AQUARIUM_LECTERN_KIND = 'aquariumlectern';
255
+ /**
256
+ * The tank's water, in the tank model's own frame (three.js, before the facing turn: x across, y up, z towards the
257
+ * glass front), where the game swims the species a player has donated (quest-workshop aquarium_v001.py).
258
+ */
259
+ export const AQUARIUM_TANK_INTERIOR = { halfX: 1.2, y0: 1.0, y1: 1.72, z0: -0.18, z1: 0.2 };
260
+ /** Is (x, z) on the aquarium's decks: the walkway or the platform (hall included)? */
261
+ export function onAquariumDeck(x, z) {
262
+ if (Math.abs(x - AQUARIUM_X) <= AQUARIUM_WALKWAY_HALF_W && z >= AQUARIUM_WALKWAY_MIN_Z && z <= AQUARIUM_WALKWAY_MAX_Z)
263
+ return true;
264
+ return Math.abs(x - AQUARIUM_PLATFORM.x) <= AQUARIUM_PLATFORM.halfX && Math.abs(z - AQUARIUM_PLATFORM.z) <= AQUARIUM_PLATFORM.halfZ;
265
+ }
266
+ /**
267
+ * Every tile the aquarium authors: the decks, the arch's row and the two rows of sand in front of it it keeps clear.
268
+ * The beach's own passes (litter, finds, treasure digs, the beach regression smoke) leave these alone.
269
+ */
270
+ export function onAquariumSite(x, z) {
271
+ if (onAquariumDeck(x, z))
272
+ return true;
273
+ return Math.abs(x - AQUARIUM_X) <= AQUARIUM_WALKWAY_HALF_W + 1 && z >= AQUARIUM_ARCH_Z - 2 && z < AQUARIUM_WALKWAY_MIN_Z;
274
+ }
275
+ /** Inside the hall's walls (the walkable room, not the ring the walls stand on). */
276
+ export function inAquariumHall(x, z) {
277
+ return Math.abs(x - AQUARIUM_HALL.x) < AQUARIUM_HALL.halfX && Math.abs(z - AQUARIUM_HALL.z) < AQUARIUM_HALL.halfZ;
278
+ }
279
+ //# sourceMappingURL=aquarium.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aquarium.js","sourceRoot":"","sources":["../src/aquarium.ts"],"names":[],"mappings":"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"}
@@ -149,11 +149,11 @@ export type EntityKind = 'tree' | 'rock' | 'shell' | 'seaweed' | 'wormcast' | 'b
149
149
  /** One tile of the Hope Beach pier deck. See HOPE_PIER_X in landmarks.ts. */
150
150
  | 'pier' | 'abandonedboat' | 'ship' | 'campfire'
151
151
  /** Cast-iron range: the cooking spot indoors, where an open fire has no business being. */
152
- | 'stove' | 'cookedcrab' | 'cookedrabbit' | 'cookedchicken' | 'lugworm' | 'maggot' | 'earthworm' | 'earthwormcast' | 'rottenmeat' | 'fishingline' | 'fishinghook' | 'fishingfloat' | 'coins' | 'lilypad' | 'reeds' | 'jetty' | 'rawbass' | 'cookedbass' | 'rawperch' | 'cookedperch' | 'rawtench' | 'cookedtench' | 'frog' | 'cookedfroglegs' | 'rawroach' | 'tadpole' | 'pondweed' | 'snail' | 'grilledfish' | 'simplelure' | 'crops' | 'smallfishingrod' | 'mudhut' | 'fortwall' | 'archertower' | 'barbedwire' | 'barricade' | 'haybale' | 'horse' | 'trough' | 'barrel' | 'well' | 'farmcart' | 'scarecrow' | 'logpile' | 'flowers' | 'lantern' | 'bench' | 'compost' | 'farmtool' | 'ranchgate' | 'milestone' | 'tent' | 'cargo' | 'bush' | 'workbench' | 'workshop' | 'nettles' | 'sharprock' | 'storagehut' | 'bankchest' | 'birchwood' | 'woodenclub' | 'livoniapineclub' | 'leatherboots' | 'poplarhelmet' | 'poplarbody' | 'poplarlegs' | 'poplarspear' | 'pineshield' | 'hay' | 'caveentrance' | 'rattail' | 'ratteeth' | 'brokensaw' | 'bronzechest' | 'bronzechestkey' | 'goblincavekey' | 'goblinprisonkey' | 'blacksmithinghammer' | 'blacksmithingtongs' | 'anvil' | 'furnace' | 'bronzebar' | 'ironbar' | 'bronzedagger' | 'bronzesword' | 'bronzeshield' | 'bronzehelmet' | 'bronzebody' | 'bronzelegs' | 'bronzegauntlets' | 'bronzeboots' | 'irondagger' | 'ironpickaxe' | 'ironsword' | 'ironshield' | 'ironhelmet' | 'ironbody' | 'ironlegs' | 'irongauntlets' | 'ironboots' | 'steelsword' | 'steelshield' | 'steelhelmet' | 'steelbody' | 'steellegs' | 'steelgauntlets' | 'steelboots' | 'copper' | 'tin' | 'iron' | 'bridge' | 'hatchet' | 'ironhatchet' | 'steelhatchet' | 'foldingsaw' | 'woolygloves' | 'woolyboots' | 'peasantclothes' | 'rangerclothes' | 'carvingknife' | 'pinebow' | 'apple' | 'wheat' | 'poplarwood' | 'pinewood' | 'sprucewood' | 'bircharrow' | 'sprucearrow' | 'stone' | 'grapes' | 'orange' | 'dungeondoor' | 'bones' | 'unlitbirchtorch' | 'litbirchtorch' | 'ratnest' | 'glowfungus' | 'silo' | 'grainmill' | 'pumpwindmill' | 'watertower' | 'packbarn' | 'packcoop' | 'packstable' | 'foxtracks' | 'foxtail' | 'rabbithutch' | 'bountyboard' | 'smallsatchel'
152
+ | 'stove' | 'cookedcrab' | 'cookedrabbit' | 'cookedchicken' | 'lugworm' | 'maggot' | 'earthworm' | 'earthwormcast' | 'rottenmeat' | 'fishingline' | 'fishinghook' | 'fishingfloat' | 'coins' | 'lilypad' | 'reeds' | 'jetty' | 'rawbass' | 'cookedbass' | 'rawperch' | 'cookedperch' | 'rawtench' | 'cookedtench' | 'frog' | 'cookedfroglegs' | 'rawroach' | 'tadpole' | 'pondweed' | 'snail' | 'grilledfish' | 'simplelure' | 'livecrab' | 'crops' | 'smallfishingrod' | 'mudhut' | 'fortwall' | 'archertower' | 'barbedwire' | 'barricade' | 'haybale' | 'horse' | 'trough' | 'barrel' | 'well' | 'farmcart' | 'scarecrow' | 'logpile' | 'flowers' | 'lantern' | 'bench' | 'compost' | 'farmtool' | 'ranchgate' | 'milestone' | 'tent' | 'cargo' | 'bush' | 'workbench' | 'workshop' | 'nettles' | 'sharprock' | 'storagehut' | 'bankchest' | 'birchwood' | 'woodenclub' | 'livoniapineclub' | 'leatherboots' | 'poplarhelmet' | 'poplarbody' | 'poplarlegs' | 'poplarspear' | 'pineshield' | 'hay' | 'caveentrance' | 'rattail' | 'ratteeth' | 'brokensaw' | 'bronzechest' | 'bronzechestkey' | 'goblincavekey' | 'goblinprisonkey' | 'blacksmithinghammer' | 'blacksmithingtongs' | 'anvil' | 'furnace' | 'bronzebar' | 'ironbar' | 'bronzedagger' | 'bronzesword' | 'bronzeshield' | 'bronzehelmet' | 'bronzebody' | 'bronzelegs' | 'bronzegauntlets' | 'bronzeboots' | 'irondagger' | 'ironpickaxe' | 'ironsword' | 'ironshield' | 'ironhelmet' | 'ironbody' | 'ironlegs' | 'irongauntlets' | 'ironboots' | 'steelsword' | 'steelshield' | 'steelhelmet' | 'steelbody' | 'steellegs' | 'steelgauntlets' | 'steelboots' | 'copper' | 'tin' | 'iron' | 'bridge' | 'hatchet' | 'ironhatchet' | 'steelhatchet' | 'foldingsaw' | 'woolygloves' | 'woolyboots' | 'peasantclothes' | 'rangerclothes' | 'carvingknife' | 'pinebow' | 'apple' | 'wheat' | 'poplarwood' | 'pinewood' | 'sprucewood' | 'bircharrow' | 'sprucearrow' | 'stone' | 'grapes' | 'orange' | 'dungeondoor' | 'bones' | 'unlitbirchtorch' | 'litbirchtorch' | 'ratnest' | 'glowfungus' | 'silo' | 'grainmill' | 'pumpwindmill' | 'watertower' | 'packbarn' | 'packcoop' | 'packstable' | 'foxtracks' | 'foxtail' | 'rabbithutch' | 'bountyboard' | 'smallsatchel'
153
153
  /** Dropped by a twigling shaken out of a felled tree; opens to coins. */
154
154
  | 'coinpurse' | 'beachfind' | 'treasuredig' | 'oddjobsboard' | 'haretracks' | 'rumourboard' | 'appletree'
155
155
  /** A rock pool on the Smugglers' Strand (smugglersStrand.ts), searched for sea glass and pearls. */
156
- | 'rockpool' | 'ciderpress' | 'herbpatch' | 'cauldron' | 'stonehouse' | 'townwall' | 'towngate' | 'marketstall' | 'fishingpeg' | 'waterfall' | 'ashwood' | 'flyfishingrod' | 'spinningrod' | 'heavybeachcastingrod'
156
+ | 'rockpool' | 'ciderpress' | 'aquariumtank' | 'aquariumlectern' | 'herbpatch' | 'cauldron' | 'stonehouse' | 'townwall' | 'towngate' | 'marketstall' | 'fishingpeg' | 'waterfall' | 'ashwood' | 'flyfishingrod' | 'spinningrod' | 'heavybeachcastingrod'
157
157
  /** Salt & Sand Tackle: sea line, pre-tied rig, and a spinner lure. */
158
158
  | 'sealine' | 'searig' | 'seaspinner' | 'flyhook' | 'rawtrout' | 'cookedtrout' | 'cobweb' | 'webveil' | 'spideregg' | 'spidersilk' | 'wolffang'
159
159
  /** A snow wolf's winter coat. Fenwick at the Northern Gate buys them. */
@@ -284,7 +284,9 @@ export type NpcKind = 'seagull' | 'crab'
284
284
  /** The sheet's tougher red crab, at the foot of the Long Pier (2026-09-24). */
285
285
  | 'redcrab'
286
286
  /** The sheet's larger rock crab, green, along the Blood River in the Dreadwoods. */
287
- | 'greencrab' | 'seabass' | 'beagle' | 'trader' | 'woody' | 'rabbit' | 'petrabbit' | 'forbes' | 'jobless' | 'driver' | 'duck' | 'angler' | 'wilson' | 'pig' | 'cow' | 'chicken' | 'sheep'
287
+ | 'greencrab' | 'seabass' | 'beagle' | 'trader' | 'woody' | 'rabbit' | 'petrabbit' | 'forbes' | 'jobless' | 'driver' | 'duck' | 'angler'
288
+ /** Curator Elowen Vane, who keeps the Great Aquarium on Hope Beach (aquarium.ts). */
289
+ | 'curator' | 'wilson' | 'pig' | 'cow' | 'chicken' | 'sheep'
288
290
  /**
289
291
  * The farm's sheep gone feral, out in the woodland between the farm gate and
290
292
  * the beach path. A separate kind from `sheep` on purpose: the pen animals at
@@ -630,6 +632,11 @@ export type CapitalBuildingModel = {
630
632
  readonly open?: boolean;
631
633
  /** Floor you walk across: a deck. Nothing in its footprint blocks, whatever its size. */
632
634
  readonly walkable?: boolean;
635
+ /**
636
+ * Stands on its own tile's height, not the smoothed height the client gives props (a deck out over the sea: smoothed,
637
+ * its open-water neighbours drag it down into the water, the Long Pier's trap).
638
+ */
639
+ readonly rawHeight?: boolean;
633
640
  readonly frontProps?: ReadonlyArray<readonly [number, number]>;
634
641
  };
635
642
  export declare const CAPITAL_BUILDING_MODELS: Readonly<Record<string, CapitalBuildingModel>>;