@dreadwood-types/types 0.1.177 → 0.1.179

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.
Files changed (61) hide show
  1. package/dist/areaTransitions.d.ts +11 -1
  2. package/dist/areaTransitions.d.ts.map +1 -1
  3. package/dist/areaTransitions.js +24 -0
  4. package/dist/areaTransitions.js.map +1 -1
  5. package/dist/attackableNpcs.d.ts.map +1 -1
  6. package/dist/attackableNpcs.js +7 -0
  7. package/dist/attackableNpcs.js.map +1 -1
  8. package/dist/bossSignatures.d.ts +1 -1
  9. package/dist/bossSignatures.d.ts.map +1 -1
  10. package/dist/bossSignatures.js +6 -0
  11. package/dist/bossSignatures.js.map +1 -1
  12. package/dist/constants.d.ts +46 -3
  13. package/dist/constants.d.ts.map +1 -1
  14. package/dist/constants.js +34 -1
  15. package/dist/constants.js.map +1 -1
  16. package/dist/cooking.d.ts.map +1 -1
  17. package/dist/cooking.js +7 -0
  18. package/dist/cooking.js.map +1 -1
  19. package/dist/copseQuests.d.ts +58 -0
  20. package/dist/copseQuests.d.ts.map +1 -0
  21. package/dist/copseQuests.js +67 -0
  22. package/dist/copseQuests.js.map +1 -0
  23. package/dist/copseWildlife.d.ts +66 -0
  24. package/dist/copseWildlife.d.ts.map +1 -0
  25. package/dist/copseWildlife.js +80 -0
  26. package/dist/copseWildlife.js.map +1 -0
  27. package/dist/dungeonCharts.d.ts.map +1 -1
  28. package/dist/dungeonCharts.js +12 -0
  29. package/dist/dungeonCharts.js.map +1 -1
  30. package/dist/expandedContracts.d.ts +5 -0
  31. package/dist/expandedContracts.d.ts.map +1 -1
  32. package/dist/expandedContracts.js +17 -3
  33. package/dist/expandedContracts.js.map +1 -1
  34. package/dist/fairFolk.d.ts +7 -1
  35. package/dist/fairFolk.d.ts.map +1 -1
  36. package/dist/fairFolk.js +28 -0
  37. package/dist/fairFolk.js.map +1 -1
  38. package/dist/index.d.ts +3 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +3 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/legacy.d.ts +2 -0
  43. package/dist/legacy.d.ts.map +1 -1
  44. package/dist/legacy.js +2 -0
  45. package/dist/legacy.js.map +1 -1
  46. package/dist/quests.d.ts.map +1 -1
  47. package/dist/quests.js +25 -0
  48. package/dist/quests.js.map +1 -1
  49. package/dist/storyQuests.d.ts +8 -1
  50. package/dist/storyQuests.d.ts.map +1 -1
  51. package/dist/storyQuests.js +169 -0
  52. package/dist/storyQuests.js.map +1 -1
  53. package/dist/westernKingdoms.d.ts +175 -0
  54. package/dist/westernKingdoms.d.ts.map +1 -0
  55. package/dist/westernKingdoms.js +270 -0
  56. package/dist/westernKingdoms.js.map +1 -0
  57. package/dist/westernTrain.d.ts +104 -1
  58. package/dist/westernTrain.d.ts.map +1 -1
  59. package/dist/westernTrain.js +113 -7
  60. package/dist/westernTrain.js.map +1 -1
  61. package/package.json +2 -2
@@ -0,0 +1,270 @@
1
+ /**
2
+ * The Western Kingdoms (James, 2026-10-10): a landmass as big as today's world, drawn WEST of our coast on his marked
3
+ * map (design id `western-kingdoms-vision`), reached only by the dwarven train. Plan:
4
+ * `.cursor/task-plans/2026-10-10-west-land-build-plan.md`, option C2 (James said yes to every recommendation).
5
+ *
6
+ * Where it lives: its own strip of the grid, the grid's last region, east of the Arcane strip (constants.ts
7
+ * WESTERN_ORIGIN_X, WESTERN_CHUNKS_X, WESTERN_STRIP_WIDTH, WESTERN_END_X; worldRegionAt answers 'western'). Nothing in
8
+ * the overworld, the underground or the Arcane strip moved, so no save migrates and WORLD_REVISION is unchanged. The
9
+ * strip is the full grid height (rows are shared across the grid).
10
+ *
11
+ * Phase 0a: the strip exists and is open sea. Phase 1a (this version): the land's OUTLINE, a blockout traced from the
12
+ * marked map, in ZONE-LOCAL tiles with one origin (WESTERN_LAND_X/Z, westernWorld/westernLocal, the Arcane Realms'
13
+ * pattern), so the land can later be moved (a wider strip, or real columns after an x insert) by changing its origin.
14
+ * Any hash a later pass uses must read LOCAL coordinates for the same reason. Backend placeWesternKingdoms lays it as
15
+ * plain ground: grass, the snow of the north-east ice corner, a beach ring; nothing on it yet.
16
+ */
17
+ import { WESTERN_END_X, WESTERN_ORIGIN_X } from './constants.js';
18
+ // Not constants.ts GRID_HEIGHT: that is the generator frame's (1248 rows); the public, final grid is layout 2's.
19
+ import { EXPANDED_WORLD_HEIGHT as GRID_HEIGHT } from './starterExpansion.js';
20
+ export const WESTERN_KINGDOMS_NAME = 'The Western Kingdoms';
21
+ /** The strip's open sea round the land: deep water at height 0, walkable as water is (backend placeWesternKingdoms). */
22
+ export const WESTERN_SEA_HEIGHT = 0;
23
+ /** Is a world tile inside the Western strip (every row of its columns)? */
24
+ export function inWesternStrip(x, z) {
25
+ return x >= WESTERN_ORIGIN_X && x < WESTERN_END_X && z >= 0 && z < GRID_HEIGHT;
26
+ }
27
+ /** A world x as a column of the strip (0 at WESTERN_ORIGIN_X), and back. */
28
+ export function westernStripX(x) {
29
+ return x - WESTERN_ORIGIN_X;
30
+ }
31
+ export function westernWorldX(stripX) {
32
+ return WESTERN_ORIGIN_X + stripX;
33
+ }
34
+ /* ------------------------------------------------------------------ *
35
+ * The land's frame (phase 1a)
36
+ * ------------------------------------------------------------------ */
37
+ /**
38
+ * The land's box in the strip: 560 x 1248 tiles (James drew it about as tall as today's world and a little narrower;
39
+ * the plan's "about 576 x 1250"), local (0, 0) at world (WESTERN_LAND_X, WESTERN_LAND_Z).
40
+ *
41
+ * The margins are open sea: 80 columns on the strip's west side, so the land stays more than three chunks (the
42
+ * server streams two rings and has no region filter on NPCs, audit risk 5) from the Arcane Realms' land, whose east
43
+ * coast is at x 1509; 64 on the east side to the grid's edge, and 64 rows north and south.
44
+ */
45
+ export const WESTERN_LAND_W = 560;
46
+ export const WESTERN_LAND_H = 1248;
47
+ export const WESTERN_LAND_X = WESTERN_ORIGIN_X + 80;
48
+ export const WESTERN_LAND_Z = 64;
49
+ /** The land's ground height (plain, flat for the blockout) and the beach ring's two steps down to the sea. */
50
+ export const WESTERN_GROUND_HEIGHT = 3;
51
+ export const WESTERN_BEACH_HEIGHTS = [1, 2];
52
+ export function westernWorld(lx, lz) {
53
+ return { x: WESTERN_LAND_X + lx, z: WESTERN_LAND_Z + lz };
54
+ }
55
+ export function westernLocal(x, z) {
56
+ return { x: x - WESTERN_LAND_X, z: z - WESTERN_LAND_Z };
57
+ }
58
+ /**
59
+ * The coast, land-local, clockwise from the north-west. A blockout traced from James's marked map
60
+ * (`.cursor/task-plans/2026-10-10-western-kingdoms-island-design/james-vision-marked-map.webp`): one big landmass,
61
+ * roughly the box he drew west of our coast, its long east shore facing our west coast (the impassable join, the red
62
+ * box, is on the paper map, not in the grid). Kept simple and generous; later passes refine it.
63
+ *
64
+ * The one fixed point is the south-east bay (local x 460, z 1040-1076): the train's first stop stands on its west
65
+ * shore (phase 0c's stub, types westernTrain.ts WESTERN_ISLE_*: the platform and rock cap on the land, the causeway
66
+ * running east out into the bay, where the line comes up out of the sea).
67
+ */
68
+ export const WESTERN_LAND_OUTLINE = [
69
+ // North coast.
70
+ [28, 34], [110, 12], [205, 26], [300, 4], [410, 18], [505, 6], [552, 40],
71
+ // East coast, facing our west coast across the sea.
72
+ [560, 150], [544, 290], [558, 430], [538, 560], [556, 700], [540, 830], [552, 950],
73
+ // The south-east bay and the first stop's shore (x 460 from z 1040 to 1076).
74
+ [520, 1010], [470, 1030], [460, 1040], [460, 1076], [486, 1110], [528, 1150], [536, 1200], [500, 1236],
75
+ // South coast.
76
+ [400, 1246], [300, 1232], [190, 1248], [90, 1236], [20, 1210],
77
+ // West coast.
78
+ [8, 1080], [22, 940], [4, 800], [18, 640], [2, 480], [16, 320], [0, 180],
79
+ ];
80
+ /**
81
+ * The ice corner: the land's north-east (beside our Frozen North on the paper map, where James wrote "ice area / huge
82
+ * ice mountain"), a ragged diagonal on its south-west side. Land-local; only the part inside the coast is ice. The
83
+ * mountain itself is a later pass (peak and pass inside this polygon).
84
+ */
85
+ export const WESTERN_ICE = [
86
+ [250, -16], [576, -16], [576, 760], [470, 720], [400, 640], [330, 560], [270, 430], [240, 250],
87
+ ];
88
+ /**
89
+ * The x where each edge of `poly` crosses the line z (the even-odd rule), sorted. Paired up they are the polygon's
90
+ * spans on that line: [x0, x1), [x2, x3), ...
91
+ */
92
+ export function polygonCrossings(poly, z) {
93
+ const xs = [];
94
+ for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
95
+ const [xi, zi] = poly[i];
96
+ const [xj, zj] = poly[j];
97
+ if ((zi > z) !== (zj > z))
98
+ xs.push(xi + ((z - zi) * (xj - xi)) / (zj - zi));
99
+ }
100
+ return xs.sort((a, b) => a - b);
101
+ }
102
+ /** Is the tile (lx, lz) inside `poly`? Tested at the tile's centre, so a vertex on x 460 keeps tile 459 and not 460. */
103
+ export function inWesternPolygon(lx, lz, poly) {
104
+ const cx = lx + 0.5;
105
+ let inside = false;
106
+ for (const x of polygonCrossings(poly, lz + 0.5)) {
107
+ if (x > cx)
108
+ break;
109
+ inside = !inside;
110
+ }
111
+ return inside;
112
+ }
113
+ /**
114
+ * The land's tiles on local row lz, as inclusive [first, last] column runs (tile centres inside the coast). The
115
+ * backend lays the land row by row from these instead of testing 700,000 tiles against the polygon one by one.
116
+ */
117
+ export function westernLandRowSpans(lz) {
118
+ const xs = polygonCrossings(WESTERN_LAND_OUTLINE, lz + 0.5);
119
+ const spans = [];
120
+ for (let k = 0; k + 1 < xs.length; k += 2) {
121
+ const first = Math.max(0, Math.ceil(xs[k] - 0.5));
122
+ const last = Math.min(WESTERN_LAND_W - 1, Math.ceil(xs[k + 1] - 0.5) - 1);
123
+ if (last >= first)
124
+ spans.push([first, last]);
125
+ }
126
+ return spans;
127
+ }
128
+ /** Is a WORLD tile on the land (inside the coast)? */
129
+ export function inWesternLand(x, z) {
130
+ const l = westernLocal(x, z);
131
+ if (l.x < 0 || l.z < 0 || l.x >= WESTERN_LAND_W || l.z >= WESTERN_LAND_H)
132
+ return false;
133
+ return inWesternPolygon(l.x, l.z, WESTERN_LAND_OUTLINE);
134
+ }
135
+ /** Is a WORLD tile in the north-east ice corner (on the land and inside WESTERN_ICE)? */
136
+ export function inWesternIce(x, z) {
137
+ if (!inWesternLand(x, z))
138
+ return false;
139
+ const l = westernLocal(x, z);
140
+ return inWesternPolygon(l.x, l.z, WESTERN_ICE);
141
+ }
142
+ /**
143
+ * Named tiles for the admin Teleport panel and the smokes (world tiles, each a plain ground tile the blockout lays).
144
+ * The first stop's platform is phase 0c's stub (types westernTrain.ts WESTERN_ISLE_STAND).
145
+ */
146
+ export const WESTERN_LANDING_BEACH = westernWorld(466, 1092);
147
+ export const WESTERN_ICE_STAND = westernWorld(470, 300);
148
+ export const WESTERN_HEARTLAND_STAND = westernWorld(200, 640);
149
+ export const WESTERN_WEST_COAST_STAND = westernWorld(40, 700);
150
+ /**
151
+ * The land's discovery zone, in the world frame (types expandedContracts.ts INSERTED_DISCOVERY_ZONES, the same shape
152
+ * as Hope Town's and Ringstone's): the whole land's box, so arriving anywhere on it names the Western Kingdoms on the
153
+ * Discovered card and the far-teleport cover. The places a later phase builds get their own smaller zones listed
154
+ * BEFORE this one (discoveryZoneAt takes the first match).
155
+ */
156
+ export const WESTERN_KINGDOMS_DISCOVERY_ZONE = {
157
+ id: 'western-kingdoms',
158
+ label: WESTERN_KINGDOMS_NAME,
159
+ coordinateFrame: 'world',
160
+ minX: WESTERN_LAND_X,
161
+ maxX: WESTERN_LAND_X + WESTERN_LAND_W - 1,
162
+ minZ: WESTERN_LAND_Z,
163
+ maxZ: WESTERN_LAND_Z + WESTERN_LAND_H - 1,
164
+ };
165
+ /** The land's chart (types dungeonCharts.ts DUNGEON_CHARTS, served by backend /dungeon-maps): the land and a ring of sea. */
166
+ export const WESTERN_CHART_ID = 'western-kingdoms';
167
+ export const WESTERN_CHART_MARGIN = 8;
168
+ /* ------------------------------------------------------------------ *
169
+ * Our side of the join: the broken viaduct (phase 1b, 2026-10-10)
170
+ * ------------------------------------------------------------------ */
171
+ /**
172
+ * James's decision 2 (2026-10-10): the join between our west coast and the Western Kingdoms cannot be crossed on foot,
173
+ * and our own west cliffs SHOW why: the stump of an old dwarven viaduct that once carried the line west, two arches still
174
+ * standing on the Northwest Battlefield's south grass at Calverton's latitude (the red box on his marked map), its last
175
+ * span snapped off over the cliff, and the shattered stones of it on the shore. Beyond the cliff the frontend draws the
176
+ * rest (WesternVista: the broken piers marching out into the sea, the far coast and the ice mountain on the horizon);
177
+ * none of that is tiles.
178
+ *
179
+ * Built from the Sundered Span's Blender kit (quest-workshop spanlib: spanpier, spanbay, spanbrokena and the fallen
180
+ * stones) at WESTERN_BREACH_SCALE, standing east-west (facing 'n', so a piece's `across` runs along x) with its deck at
181
+ * WESTERN_BREACH_DECK_METRES above the sea whatever the ground under it (the client seats it by that, not by the tile).
182
+ * Walkable-safe: the piers and the broken end block their tiles, the deck is never a walk surface (no tile is laid at
183
+ * its height and nothing climbs to it), and the sea cliff's crag rocks (x 2-3, blocked all along our west edge) stay
184
+ * blocked under the broken end, so nothing new can be walked past; the arches' openings stay open ground (walk under
185
+ * them north to south).
186
+ */
187
+ export const WESTERN_BREACH_Z = 650;
188
+ /** The tiles the breach pass clears and dresses (world tiles, overworld). */
189
+ export const WESTERN_BREACH_BOX = { minX: 0, maxX: 26, minZ: 638, maxZ: 662 };
190
+ /**
191
+ * The shattered pass: the rows where our sea cliff's crag rocks (the tall rock wall along x 2-3, blocked all along the
192
+ * west edge) are gone, broken away where the line ran out onto the viaduct, so from the grass the sea and the far shore
193
+ * show through the gap. The cliff's tiles stay blocked: a gap to look through, never a way down.
194
+ */
195
+ export const WESTERN_BREACH_GAP = { minZ: 641, maxZ: 659 };
196
+ /** The cliff's columns (the crag rocks stand on x 2 and 3; x 0-1 is the sea). */
197
+ export const WESTERN_CLIFF_MAX_X = 3;
198
+ /** The span kit is built for a road bridge eleven tiles wide; the line's viaduct is drawn at this share of it. */
199
+ export const WESTERN_BREACH_SCALE = 0.7;
200
+ /** The viaduct's deck above the sea (metres): the kit's piers reach 5.4 below their deck at full size, so its feet are in the ground. */
201
+ export const WESTERN_BREACH_DECK_METRES = 3.7;
202
+ /** The span kit's paving above its model origin at full size (quest-workshop spanlib DECK; the client's spanPaving drop). */
203
+ export const SPAN_KIT_DECK_METRES = 5.4;
204
+ const breachPiece = (id, model, x, z, viaduct = true, facing = 'n') => ({
205
+ id: `western-breach-${id}`,
206
+ style: `${model}-${facing}`,
207
+ x,
208
+ z,
209
+ scale: viaduct ? WESTERN_BREACH_SCALE : 1,
210
+ viaduct,
211
+ });
212
+ /**
213
+ * West to east from the cliff: the snapped-off span over the cliff edge and the sea, then pier, arch, pier, arch, pier,
214
+ * eight tiles between pier centres (the kit's ten at full size, near enough at 0.7 that each arch bears on its piers).
215
+ */
216
+ export const WESTERN_BREACH_PIECES = [
217
+ breachPiece('broken', 'spanbrokena', 2, WESTERN_BREACH_Z),
218
+ breachPiece('pier-1', 'spanpier', 5, WESTERN_BREACH_Z),
219
+ breachPiece('arch-1', 'spanbay', 9, WESTERN_BREACH_Z),
220
+ breachPiece('pier-2', 'spanpier', 13, WESTERN_BREACH_Z),
221
+ breachPiece('arch-2', 'spanbay', 17, WESTERN_BREACH_Z),
222
+ breachPiece('pier-3', 'spanpier', 21, WESTERN_BREACH_Z),
223
+ // The shattered stones: off the broken end and along the shore, clear of the arches' openings.
224
+ breachPiece('stone-large', 'spanstonelarge', 6, 659, false, 'e'),
225
+ breachPiece('keystone', 'spankeystone', 9, 644, false, 'e'),
226
+ breachPiece('stone-medium', 'spanstonemedium', 4, 643, false, 'e'),
227
+ breachPiece('stone-small', 'spanstonesmall', 8, 657, false, 'e'),
228
+ breachPiece('stone-small-2', 'spanstonesmall', 24, 656, false, 'e'),
229
+ // Two of the line's own posts on the landward side: the way west is the train now.
230
+ breachPiece('signpost', 'westsignpost', 17, 661, false, 's'),
231
+ breachPiece('waymarker', 'westwaymarker', 25, 643, false, 's'),
232
+ ];
233
+ /** Is an entity id one of the breach's pieces (the client seats and scales them by WESTERN_BREACH_PIECES)? */
234
+ export function westernBreachPiece(id) {
235
+ return id.startsWith('western-breach-') ? WESTERN_BREACH_PIECES.find((p) => p.id === id) : undefined;
236
+ }
237
+ /** The rows a viaduct piece covers at its scale (the kit's piers and the broken span are 14.46 deep at full size). */
238
+ const BREACH_DEEP_TILES = Math.ceil((14.46 * WESTERN_BREACH_SCALE) / 2);
239
+ /** The kit's widths at full size, along the viaduct (x). */
240
+ const BREACH_ACROSS_METRES = { spanpier: 3.5, spanbrokena: 4.71 };
241
+ /**
242
+ * The tiles the viaduct blocks: under each pier and under the broken span, the rows its depth covers. The arches'
243
+ * spans between the piers stay open ground.
244
+ */
245
+ export const WESTERN_BREACH_BLOCKED = (() => {
246
+ const out = [];
247
+ for (const p of WESTERN_BREACH_PIECES) {
248
+ const model = p.style.split('-')[0];
249
+ const across = BREACH_ACROSS_METRES[model];
250
+ if (!p.viaduct || across === undefined)
251
+ continue;
252
+ const half = (across * p.scale) / 2;
253
+ const cx = p.x + 0.5;
254
+ for (let x = Math.floor(cx - half + 0.25); x <= Math.floor(cx + half - 0.25); x++) {
255
+ for (let z = p.z - BREACH_DEEP_TILES + 1; z <= p.z + BREACH_DEEP_TILES - 1; z++)
256
+ out.push([x, z]);
257
+ }
258
+ }
259
+ return out;
260
+ })();
261
+ /** Where to stand to see it: on the grass south-east of the arches, looking west along them to the sea. */
262
+ export const WESTERN_BREACH_STAND = { x: 16, z: 664 };
263
+ /**
264
+ * The far shore as seen from ours (the frontend's WesternVista, no tiles): it is drawn west of x 0 from anywhere on our
265
+ * west coast between these rows, the Battlefield's snow line to the Hope Beach fields, within this many tiles of the
266
+ * edge.
267
+ */
268
+ export const WESTERN_VISTA_ROWS = { minZ: 470, maxZ: 1120 };
269
+ export const WESTERN_VISTA_REACH_X = 150;
270
+ //# sourceMappingURL=westernKingdoms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"westernKingdoms.js","sourceRoot":"","sources":["../src/westernKingdoms.ts"],"names":[],"mappings":"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"}
@@ -56,8 +56,71 @@ export declare const WESTERN_TUNNEL_STAND: {
56
56
  readonly x: number;
57
57
  readonly z: number;
58
58
  };
59
+ /**
60
+ * PHASE 0c SPIKE (2026-10-10, plan `.cursor/task-plans/2026-10-10-western-phase0c.md`; parent
61
+ * `2026-10-10-west-land-build-plan.md`): a stub of the Western Isle's halt in the Western Kingdoms' strip, to measure
62
+ * the train's jump into a new region. NOT the designed first stop: a copy of the home station's layout translated into
63
+ * the strip's open sea (the platform, the gap row with its step plates, the sea kerb, the line, the portal in a rock
64
+ * cap), with a short causeway straight off its east end into the sea. The train's third leg ('isle') runs from the
65
+ * causeway's sea end west past the platform into the cap, then wraps to the home causeway's sea end.
66
+ *
67
+ * Because the stub is the docked layout moved by (WESTERN_ISLE_SHIFT_X, WESTERN_ISLE_SHIFT_Z), a train standing at
68
+ * the isle stop has every docked tile exactly that far from its world tile: the step plates, doorways and platform
69
+ * edge tiles line up as at home (westernStopSteps maps them through the leg, so a later stop need not be a copy).
70
+ */
71
+ export declare const WESTERN_ISLE_SHIFT_X = 1970;
72
+ export declare const WESTERN_ISLE_SHIFT_Z = -32;
73
+ export declare const WESTERN_ISLE_TRACK_Z: number;
74
+ /** The stub's causeway, the last 22 tiles of the line, stepping down to the waterline (its sea end the leg's x0). */
75
+ export declare const WESTERN_ISLE_SEA_END_X = 2097;
76
+ export declare const WESTERN_ISLE_CAUSEWAY: {
77
+ readonly minX: number;
78
+ readonly maxX: 2097;
79
+ readonly minZ: number;
80
+ readonly maxZ: number;
81
+ };
82
+ export declare function westernIsleCausewayHeight(x: number): number;
83
+ type Box = {
84
+ minX: number;
85
+ maxX: number;
86
+ minZ: number;
87
+ maxZ: number;
88
+ };
89
+ export declare const WESTERN_ISLE_PLATFORM: Box;
90
+ export declare const WESTERN_ISLE_PLATFORM_PIECES: (readonly [number, number])[];
91
+ export declare const WESTERN_ISLE_GAP_ROW: {
92
+ readonly minX: number;
93
+ readonly maxX: number;
94
+ readonly z: number;
95
+ };
96
+ export declare const WESTERN_ISLE_SEA_KERB: {
97
+ readonly minX: number;
98
+ readonly maxX: number;
99
+ readonly z: number;
100
+ };
101
+ /** The rock cap the line runs into (the home knoll's box, moved), and the portal on its east face. */
102
+ export declare const WESTERN_ISLE_KNOLL: Box;
103
+ export declare const WESTERN_ISLE_MOUTH: {
104
+ readonly x: number;
105
+ readonly z: number;
106
+ readonly style: "westportal-e";
107
+ };
108
+ export declare const WESTERN_ISLE_MOUTH_ID = "western-isle-spike-mouth";
109
+ /** The stub's ground: the knoll's west foot to the causeway's start, a few rows round the station (all laid on the strip's sea). */
110
+ export declare const WESTERN_ISLE_LAND: {
111
+ readonly minX: number;
112
+ readonly maxX: number;
113
+ readonly minZ: number;
114
+ readonly maxZ: number;
115
+ };
116
+ /** Where an admin /tp lands on the stub: the platform's middle. */
117
+ export declare const WESTERN_ISLE_STAND: {
118
+ readonly x: number;
119
+ readonly z: number;
120
+ };
121
+ export declare function inWesternIsleStub(x: number, z: number): boolean;
59
122
  export type WesternTrainSegment = {
60
- id: 'surface' | 'tunnel';
123
+ id: 'surface' | 'tunnel' | 'isle';
61
124
  /** The first c on this leg and how many tiles it runs. */
62
125
  c0: number;
63
126
  length: number;
@@ -68,6 +131,8 @@ export type WesternTrainSegment = {
68
131
  dz: number;
69
132
  };
70
133
  export declare const WESTERN_TRAIN_SEGMENTS: readonly WesternTrainSegment[];
134
+ /** c of the nose when the train stands at the isle stub (the nose on the platform's west end, as at home). */
135
+ export declare const WESTERN_ISLE_STOP_C: number;
71
136
  export declare const WESTERN_TRAIN_CIRCUIT_LENGTH: number;
72
137
  /** c of the nose when the train stands at the platform (loco's nose at x 30). */
73
138
  export declare const WESTERN_TRAIN_PLATFORM_C: number;
@@ -133,6 +198,11 @@ export declare const WESTERN_TRAIN_ALIGHT_MOVING_TEXT = "The train is moving. Wa
133
198
  * platform in the strip on this bore, reached from the city by a stair or lift (a cave entrance in the city's south
134
199
  * quarter, the way the Rat Tunnel is reached), placed when that stair is built.
135
200
  */
201
+ /**
202
+ * `steps`: the stop has its own step plates on its own platform (westernStopSteps): riders step off there and people
203
+ * on that platform board there, while the train stands with its doors open. The home platform's plates are the docked
204
+ * rake's own (WESTERN_STEPS) and need no flag.
205
+ */
136
206
  export type WesternTrainStop = {
137
207
  id: string;
138
208
  name: string;
@@ -140,6 +210,7 @@ export type WesternTrainStop = {
140
210
  dwellMs: number;
141
211
  enabled: boolean;
142
212
  note: string;
213
+ steps?: boolean;
143
214
  };
144
215
  export declare const WESTERN_TRAIN_STOPS: readonly WesternTrainStop[];
145
216
  /** Duration (ms) of a run of D tiles from a stop to a stop: up to speed, cruise, slow to a stand. */
@@ -206,4 +277,36 @@ export declare function westernPlatformTileNear(x: number): {
206
277
  x: number;
207
278
  y: number;
208
279
  };
280
+ /**
281
+ * One step plate of a stop with its own platform: the home plate's docked tiles carried by the leg to where the train
282
+ * stands at that stop. `x`/`z` the plate's world tile, `platform` the world tile a rider steps down to, `doorway` the
283
+ * DOCKED tile someone boarding there is put on (their tile is always kept in the docked frame aboard).
284
+ */
285
+ export type WesternStopStep = {
286
+ stopId: string;
287
+ car: string;
288
+ id: string;
289
+ x: number;
290
+ z: number;
291
+ platform: {
292
+ x: number;
293
+ y: number;
294
+ };
295
+ doorway: {
296
+ x: number;
297
+ y: number;
298
+ };
299
+ };
300
+ export declare function westernStopSteps(stop: WesternTrainStop): WesternStopStep[];
301
+ /** Every running stop's own plates (not the home platform's). */
302
+ export declare const WESTERN_STOP_STEPS: readonly WesternStopStep[];
303
+ export declare function westernStopStepAt(x: number, z: number): WesternStopStep | null;
304
+ export declare function westernStopStepById(id: string | undefined): WesternStopStep | null;
305
+ /** The train standing at a stop (not the home platform) at `nowMs`, or null. */
306
+ export declare function westernTrainAtStop(nowMs: number, stopId: string): WesternTrainState | null;
307
+ /** The train at a stop with its doors open (more than the shut time to go), or null. */
308
+ export declare function westernStopDoorsOpen(nowMs: number, stopId: string): WesternTrainState | null;
309
+ /** Why a stop's plates refuse at `nowMs`. */
310
+ export declare function westernStopNoBoardingText(nowMs: number, stopId: string): string;
311
+ export {};
209
312
  //# sourceMappingURL=westernTrain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"westernTrain.d.ts","sourceRoot":"","sources":["../src/westernTrain.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"westernTrain.d.ts","sourceRoot":"","sources":["../src/westernTrain.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,8 @@
15
15
  * THE CIRCUIT is one track coordinate `c` (tiles), in the order the train runs it:
16
16
  * - the SURFACE leg: c 0 at the sea end of the line (x 199) west along z 1153 to the tunnel mouth (c 173 is x 26);
17
17
  * - the TUNNEL leg: c 174 on in a straight tunnel cut in the underground strip (dark, lit by wall sconces), heading south;
18
+ * - the ISLE leg (phase 0c spike, c 730 on): up out of the sea in the Western Kingdoms' strip, along a stub platform where
19
+ * the train stands (WESTERN_ISLE_STOP_C), into a rock cap (see WESTERN_ISLE_SHIFT_X);
18
20
  * - at c = WESTERN_TRAIN_CIRCUIT_LENGTH it wraps to 0: the train comes up out of the sea at the causeway again.
19
21
  * The nose leads; a piece `u` tiles behind the nose (its docked x minus the nose's docked x) is at c - u.
20
22
  *
@@ -24,7 +26,7 @@
24
26
  * places are built; switching one on adds its dwell to the cycle.
25
27
  */
26
28
  import { CAPITAL_BUILDING_MODELS, HEIGHT_STEP, UNDERGROUND_END_X } from './constants.js';
27
- import { WESTERN_CARS, WESTERN_GANGWAYS, WESTERN_JOINTS, WESTERN_KIT_DECK_METRES, WESTERN_PRECINCT_HEIGHT, WESTERN_RAKE_SLOTS, WESTERN_SEA_END, WESTERN_STEPS, WESTERN_TRACK, WESTERN_TRACK_Z, westernCausewayHeight, } from './westernEntrance.js';
29
+ import { WESTERN_CARS, WESTERN_CAUSEWAY, WESTERN_GANGWAYS, WESTERN_GAP_ROW, WESTERN_JOINTS, WESTERN_KIT_DECK_METRES, WESTERN_KNOLL, WESTERN_PLATFORM, WESTERN_PLATFORM_PIECES, WESTERN_PRECINCT_HEIGHT, WESTERN_RAKE_SLOTS, WESTERN_SEA_END, WESTERN_SEA_KERB, WESTERN_STEPS, WESTERN_TRACK, WESTERN_TRACK_Z, WESTERN_TUNNEL_MOUTH, westernCausewayHeight, } from './westernEntrance.js';
28
30
  /* ------------------------------------------------------------------ *
29
31
  * The docked rake (the cart-local frame).
30
32
  * ------------------------------------------------------------------ */
@@ -102,11 +104,63 @@ export function inWesternTunnel(x, z) {
102
104
  export const WESTERN_TUNNEL_SCONCE_EVERY = 14;
103
105
  /** The /tp into the tunnel (admins): its north end, beside the line. */
104
106
  export const WESTERN_TUNNEL_STAND = { x: WESTERN_TUNNEL_X - WESTERN_TUNNEL_HALF_WIDTH, z: WESTERN_TUNNEL_START_Z + 6 };
107
+ /**
108
+ * PHASE 0c SPIKE (2026-10-10, plan `.cursor/task-plans/2026-10-10-western-phase0c.md`; parent
109
+ * `2026-10-10-west-land-build-plan.md`): a stub of the Western Isle's halt in the Western Kingdoms' strip, to measure
110
+ * the train's jump into a new region. NOT the designed first stop: a copy of the home station's layout translated into
111
+ * the strip's open sea (the platform, the gap row with its step plates, the sea kerb, the line, the portal in a rock
112
+ * cap), with a short causeway straight off its east end into the sea. The train's third leg ('isle') runs from the
113
+ * causeway's sea end west past the platform into the cap, then wraps to the home causeway's sea end.
114
+ *
115
+ * Because the stub is the docked layout moved by (WESTERN_ISLE_SHIFT_X, WESTERN_ISLE_SHIFT_Z), a train standing at
116
+ * the isle stop has every docked tile exactly that far from its world tile: the step plates, doorways and platform
117
+ * edge tiles line up as at home (westernStopSteps maps them through the leg, so a later stop need not be a copy).
118
+ */
119
+ export const WESTERN_ISLE_SHIFT_X = 1970;
120
+ export const WESTERN_ISLE_SHIFT_Z = -32;
121
+ export const WESTERN_ISLE_TRACK_Z = WESTERN_TRACK_Z + WESTERN_ISLE_SHIFT_Z;
122
+ /** The stub's causeway, the last 22 tiles of the line, stepping down to the waterline (its sea end the leg's x0). */
123
+ export const WESTERN_ISLE_SEA_END_X = 2097;
124
+ const ISLE_CAUSEWAY_SHIFT = WESTERN_ISLE_SEA_END_X - WESTERN_SEA_END.x;
125
+ export const WESTERN_ISLE_CAUSEWAY = {
126
+ minX: WESTERN_CAUSEWAY.minX + ISLE_CAUSEWAY_SHIFT, maxX: WESTERN_ISLE_SEA_END_X,
127
+ minZ: WESTERN_ISLE_TRACK_Z - 1, maxZ: WESTERN_ISLE_TRACK_Z + 1,
128
+ };
129
+ export function westernIsleCausewayHeight(x) {
130
+ return westernCausewayHeight(x - ISLE_CAUSEWAY_SHIFT);
131
+ }
132
+ const shiftBox = (b) => ({ minX: b.minX + WESTERN_ISLE_SHIFT_X, maxX: b.maxX + WESTERN_ISLE_SHIFT_X, minZ: b.minZ + WESTERN_ISLE_SHIFT_Z, maxZ: b.maxZ + WESTERN_ISLE_SHIFT_Z });
133
+ export const WESTERN_ISLE_PLATFORM = shiftBox(WESTERN_PLATFORM);
134
+ export const WESTERN_ISLE_PLATFORM_PIECES = WESTERN_PLATFORM_PIECES.map(([x, z]) => [x + WESTERN_ISLE_SHIFT_X, z + WESTERN_ISLE_SHIFT_Z]);
135
+ export const WESTERN_ISLE_GAP_ROW = { minX: WESTERN_GAP_ROW.minX + WESTERN_ISLE_SHIFT_X, maxX: WESTERN_GAP_ROW.maxX + WESTERN_ISLE_SHIFT_X, z: WESTERN_GAP_ROW.z + WESTERN_ISLE_SHIFT_Z };
136
+ export const WESTERN_ISLE_SEA_KERB = { minX: WESTERN_SEA_KERB.minX + WESTERN_ISLE_SHIFT_X, maxX: WESTERN_SEA_KERB.maxX + WESTERN_ISLE_SHIFT_X, z: WESTERN_SEA_KERB.z + WESTERN_ISLE_SHIFT_Z };
137
+ /** The rock cap the line runs into (the home knoll's box, moved), and the portal on its east face. */
138
+ export const WESTERN_ISLE_KNOLL = shiftBox(WESTERN_KNOLL);
139
+ export const WESTERN_ISLE_MOUTH = { x: WESTERN_TUNNEL_MOUTH.x + WESTERN_ISLE_SHIFT_X, z: WESTERN_ISLE_TRACK_Z, style: WESTERN_TUNNEL_MOUTH.style };
140
+ export const WESTERN_ISLE_MOUTH_ID = 'western-isle-spike-mouth';
141
+ /** The stub's ground: the knoll's west foot to the causeway's start, a few rows round the station (all laid on the strip's sea). */
142
+ export const WESTERN_ISLE_LAND = {
143
+ minX: WESTERN_ISLE_KNOLL.minX - 2, maxX: WESTERN_ISLE_CAUSEWAY.minX - 1,
144
+ minZ: WESTERN_ISLE_KNOLL.minZ - 2, maxZ: WESTERN_ISLE_KNOLL.maxZ + 2,
145
+ };
146
+ /** Where an admin /tp lands on the stub: the platform's middle. */
147
+ export const WESTERN_ISLE_STAND = { x: WESTERN_ISLE_PLATFORM.minX + 20, z: WESTERN_ISLE_PLATFORM.minZ + 1 };
148
+ export function inWesternIsleStub(x, z) {
149
+ const b = WESTERN_ISLE_LAND;
150
+ return (x >= b.minX && x <= b.maxX && z >= b.minZ && z <= b.maxZ) ||
151
+ (x >= WESTERN_ISLE_CAUSEWAY.minX && x <= WESTERN_ISLE_CAUSEWAY.maxX && z >= WESTERN_ISLE_CAUSEWAY.minZ && z <= WESTERN_ISLE_CAUSEWAY.maxZ);
152
+ }
105
153
  const SURFACE_LENGTH = WESTERN_SEA_END.x - (WESTERN_TRACK.minX - 1) + 1; // x 199 to x 26 (the mouth tile): 174
154
+ /** The spike's third leg: the isle causeway's sea end west to the tile in front of the stub's portal (102 tiles). */
155
+ const ISLE_LENGTH = WESTERN_ISLE_SEA_END_X - (WESTERN_ISLE_MOUTH.x + 1) + 1;
156
+ const ISLE_C0 = SURFACE_LENGTH + WESTERN_TUNNEL_LENGTH;
106
157
  export const WESTERN_TRAIN_SEGMENTS = [
107
158
  { id: 'surface', c0: 0, length: SURFACE_LENGTH, x0: WESTERN_SEA_END.x, z0: WESTERN_TRACK_Z, dx: -1, dz: 0 },
108
159
  { id: 'tunnel', c0: SURFACE_LENGTH, length: WESTERN_TUNNEL_LENGTH, x0: WESTERN_TUNNEL_X, z0: WESTERN_TUNNEL_START_Z, dx: 0, dz: 1 },
160
+ { id: 'isle', c0: ISLE_C0, length: ISLE_LENGTH, x0: WESTERN_ISLE_SEA_END_X, z0: WESTERN_ISLE_TRACK_Z, dx: -1, dz: 0 },
109
161
  ];
162
+ /** c of the nose when the train stands at the isle stub (the nose on the platform's west end, as at home). */
163
+ export const WESTERN_ISLE_STOP_C = ISLE_C0 + (WESTERN_ISLE_SEA_END_X - WESTERN_ISLE_PLATFORM.minX);
110
164
  export const WESTERN_TRAIN_CIRCUIT_LENGTH = WESTERN_TRAIN_SEGMENTS.reduce((n, s) => n + s.length, 0);
111
165
  /** c of the nose when the train stands at the platform (loco's nose at x 30). */
112
166
  export const WESTERN_TRAIN_PLATFORM_C = WESTERN_SEA_END.x - WESTERN_TRAIN_NOSE_X;
@@ -146,10 +200,15 @@ export function westernTrainGroundHeight(seg, c) {
146
200
  if (seg.id === 'tunnel')
147
201
  return WESTERN_TUNNEL_FLOOR_HEIGHT;
148
202
  const x = seg.x0 + seg.dx * (c - seg.c0);
149
- if (x > WESTERN_SEA_END.x)
150
- return -(x - WESTERN_SEA_END.x) * 1.4; // under the sea past the line's end
203
+ // Both open-air legs come up out of the sea at their x0 and climb a causeway to the station's ground.
204
+ const isle = seg.id === 'isle';
205
+ const seaEnd = isle ? WESTERN_ISLE_SEA_END_X : WESTERN_SEA_END.x;
206
+ const causewayFrom = isle ? WESTERN_ISLE_CAUSEWAY.minX : WESTERN_CAUSEWAY.minX;
207
+ const causeway = isle ? westernIsleCausewayHeight : westernCausewayHeight;
208
+ if (x > seaEnd)
209
+ return -(x - seaEnd) * 1.4; // under the sea past the line's end
151
210
  const lo = Math.floor(x), t = x - lo;
152
- const h = (xi) => (xi >= 178 ? westernCausewayHeight(Math.min(xi, WESTERN_SEA_END.x)) : WESTERN_PRECINCT_HEIGHT);
211
+ const h = (xi) => (xi >= causewayFrom ? causeway(Math.min(xi, seaEnd)) : WESTERN_PRECINCT_HEIGHT);
153
212
  return h(lo) * (1 - t) + h(lo + 1) * t;
154
213
  }
155
214
  /** Metres: the deck a rider stands on at c (the ground plus the kit's deck height). */
@@ -204,7 +263,8 @@ export const WESTERN_TRAIN_ABOARD_COMBAT_TEXT = 'There is no fighting aboard the
204
263
  export const WESTERN_TRAIN_ALIGHT_MOVING_TEXT = 'The train is moving. Wait until it stops at the platform.';
205
264
  export const WESTERN_TRAIN_STOPS = [
206
265
  { id: 'platform', name: 'The Western Entrance', c: WESTERN_TRAIN_PLATFORM_C, dwellMs: 60_000, enabled: true, note: 'The platform on the headland: boarding by the step plates.' },
207
- { id: 'western-isle', name: 'The Western Isle', c: SURFACE_LENGTH + 150, dwellMs: 45_000, enabled: false, note: 'The island to the west is not built yet: a halt, a platform and a way up to the island are needed.' },
266
+ // Phase 0c spike: switched on in the branch, at the stub platform in the Western Kingdoms' strip (the 'isle' leg).
267
+ { id: 'western-isle', name: 'The Western Isle', c: WESTERN_ISLE_STOP_C, dwellMs: 30_000, enabled: true, steps: true, note: 'SPIKE (phase 0c): a stub platform in the Western Kingdoms strip, a copy of the home station moved into the sea; the designed first stop replaces it in phase 1b.' },
208
268
  { id: 'dwarf-hold', name: 'The Dwarf Hold', c: SURFACE_LENGTH + 300, dwellMs: 45_000, enabled: false, note: 'An underground dwarf dungeon beside the bore; its exit is blocked for now.' },
209
269
  { id: 'capital', name: 'The Capital', c: SURFACE_LENGTH + 450, dwellMs: 60_000, enabled: false, note: 'Not reachable by a surface line (the city is ~900 rows north); needs an underground halt on this bore and a stair or lift from the city.' },
210
270
  ];
@@ -271,9 +331,12 @@ export function westernTrainAt(nowMs, train = 0, timetable = TIMETABLE) {
271
331
  msToPlatform: leg.stop.id === 'platform' ? 0 : msToPlatform, cycleMs: t,
272
332
  };
273
333
  }
274
- const noseC = wrapWesternC(leg.stop.c + westernTrainRunTiles(leg.runTiles, t - leg.departMs));
334
+ const ran = westernTrainRunTiles(leg.runTiles, t - leg.departMs);
335
+ const noseC = wrapWesternC(leg.stop.c + ran);
275
336
  const onSurface = rakeOnSurface(noseC);
276
- const phase = !onSurface ? 'away' : noseC < WESTERN_TRAIN_PLATFORM_C ? 'approaching' : 'departing';
337
+ // The last instant of a run into the platform is still the approach (its noseC lands exactly on the platform's c).
338
+ const arriving = leg.runTiles - ran < 0.5;
339
+ const phase = !onSurface ? 'away' : noseC < WESTERN_TRAIN_PLATFORM_C || arriving ? 'approaching' : 'departing';
277
340
  return { train, noseC, noseStep: Math.floor(noseC), moving: true, phase, stopId: null, msToDepart: null, msToPlatform, cycleMs: t };
278
341
  }
279
342
  // Rounding at the cycle's very end: treat as the first leg's start.
@@ -353,4 +416,47 @@ export function westernPlatformTileNear(x) {
353
416
  best = s;
354
417
  return { x: best.platform[0], y: best.platform[1] };
355
418
  }
419
+ export function westernStopSteps(stop) {
420
+ return WESTERN_STEPS.map((s) => {
421
+ const plate = westernRiderWorldTile(stop.c, s.x, s.z);
422
+ return {
423
+ stopId: stop.id,
424
+ car: s.car,
425
+ id: `${stop.id}-spike-step-${s.car}`,
426
+ x: plate.x,
427
+ z: plate.y,
428
+ platform: westernRiderWorldTile(stop.c, s.platform[0], s.platform[1]),
429
+ doorway: { x: s.doorway[0], y: s.doorway[1] },
430
+ };
431
+ });
432
+ }
433
+ /** Every running stop's own plates (not the home platform's). */
434
+ export const WESTERN_STOP_STEPS = WESTERN_TRAIN_STOPS.filter((s) => s.enabled && s.steps).flatMap(westernStopSteps);
435
+ export function westernStopStepAt(x, z) {
436
+ return WESTERN_STOP_STEPS.find((s) => s.x === x && s.z === z) ?? null;
437
+ }
438
+ export function westernStopStepById(id) {
439
+ return WESTERN_STOP_STEPS.find((s) => s.id === id) ?? null;
440
+ }
441
+ /** The train standing at a stop (not the home platform) at `nowMs`, or null. */
442
+ export function westernTrainAtStop(nowMs, stopId) {
443
+ for (let i = 0; i < WESTERN_TRAIN_COUNT; i++) {
444
+ const s = westernTrainAt(nowMs, i);
445
+ if (!s.moving && s.stopId === stopId)
446
+ return s;
447
+ }
448
+ return null;
449
+ }
450
+ /** The train at a stop with its doors open (more than the shut time to go), or null. */
451
+ export function westernStopDoorsOpen(nowMs, stopId) {
452
+ const s = westernTrainAtStop(nowMs, stopId);
453
+ return s && (s.msToDepart ?? 0) > WESTERN_TRAIN_DOORS_SHUT_BEFORE_MS ? s : null;
454
+ }
455
+ /** Why a stop's plates refuse at `nowMs`. */
456
+ export function westernStopNoBoardingText(nowMs, stopId) {
457
+ if (westernTrainAtStop(nowMs, stopId))
458
+ return WESTERN_TRAIN_DOORS_SHUT_TEXT;
459
+ const stop = WESTERN_TRAIN_STOPS.find((s) => s.id === stopId);
460
+ return `No train stands at ${stop?.name ?? 'this platform'}.`;
461
+ }
356
462
  //# sourceMappingURL=westernTrain.js.map