@rpgm-tools/neo-angband-content 0.11.0
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.
- package/LICENSE.md +43 -0
- package/README.md +65 -0
- package/dist/compile.d.ts +10 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +42 -0
- package/dist/compile.js.map +1 -0
- package/dist/data-exactness.reader.d.ts +105 -0
- package/dist/data-exactness.reader.d.ts.map +1 -0
- package/dist/data-exactness.reader.js +547 -0
- package/dist/data-exactness.reader.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.d.ts +70 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +365 -0
- package/dist/parser.js.map +1 -0
- package/dist/records.d.ts +101 -0
- package/dist/records.d.ts.map +1 -0
- package/dist/records.js +244 -0
- package/dist/records.js.map +1 -0
- package/dist/specs/generate.d.ts +12 -0
- package/dist/specs/generate.d.ts.map +1 -0
- package/dist/specs/generate.js +57 -0
- package/dist/specs/generate.js.map +1 -0
- package/dist/specs/index.d.ts +9 -0
- package/dist/specs/index.d.ts.map +1 -0
- package/dist/specs/index.js +60 -0
- package/dist/specs/index.js.map +1 -0
- package/dist/specs/init.d.ts +23 -0
- package/dist/specs/init.d.ts.map +1 -0
- package/dist/specs/init.js +305 -0
- package/dist/specs/init.js.map +1 -0
- package/dist/specs/misc.d.ts +33 -0
- package/dist/specs/misc.d.ts.map +1 -0
- package/dist/specs/misc.js +146 -0
- package/dist/specs/misc.js.map +1 -0
- package/dist/specs/mon-init.d.ts +22 -0
- package/dist/specs/mon-init.d.ts.map +1 -0
- package/dist/specs/mon-init.js +157 -0
- package/dist/specs/mon-init.js.map +1 -0
- package/dist/specs/obj-init.d.ts +19 -0
- package/dist/specs/obj-init.d.ts.map +1 -0
- package/dist/specs/obj-init.js +219 -0
- package/dist/specs/obj-init.js.map +1 -0
- package/dist/specs/ui-entry.d.ts +22 -0
- package/dist/specs/ui-entry.d.ts.map +1 -0
- package/dist/specs/ui-entry.js +69 -0
- package/dist/specs/ui-entry.js.map +1 -0
- package/dist/specs/visuals.d.ts +26 -0
- package/dist/specs/visuals.d.ts.map +1 -0
- package/dist/specs/visuals.js +35 -0
- package/dist/specs/visuals.js.map +1 -0
- package/pack/activation.json +3340 -0
- package/pack/artifact.json +5146 -0
- package/pack/blow_effects.json +370 -0
- package/pack/blow_methods.json +286 -0
- package/pack/body.json +59 -0
- package/pack/brand.json +100 -0
- package/pack/chest_trap.json +117 -0
- package/pack/class.json +5501 -0
- package/pack/constants.json +470 -0
- package/pack/curse.json +580 -0
- package/pack/dungeon_profile.json +836 -0
- package/pack/ego_item.json +2900 -0
- package/pack/flavor.json +1541 -0
- package/pack/hints.json +303 -0
- package/pack/history.json +1656 -0
- package/pack/manifest.json +52 -0
- package/pack/monster.json +29392 -0
- package/pack/monster_base.json +688 -0
- package/pack/monster_spell.json +2735 -0
- package/pack/names.json +1204 -0
- package/pack/object.json +11877 -0
- package/pack/object_base.json +364 -0
- package/pack/object_property.json +2034 -0
- package/pack/p_race.json +447 -0
- package/pack/pain.json +150 -0
- package/pack/pit.json +617 -0
- package/pack/player_property.json +519 -0
- package/pack/player_timed.json +1321 -0
- package/pack/projection.json +664 -0
- package/pack/quest.json +18 -0
- package/pack/realm.json +34 -0
- package/pack/room_template.json +9571 -0
- package/pack/shape.json +263 -0
- package/pack/slay.json +116 -0
- package/pack/store.json +675 -0
- package/pack/summon.json +143 -0
- package/pack/terrain.json +511 -0
- package/pack/trap.json +1483 -0
- package/pack/ui_entry.json +382 -0
- package/pack/ui_entry_base.json +60 -0
- package/pack/ui_entry_renderer.json +43 -0
- package/pack/ui_knowledge.json +302 -0
- package/pack/vault.json +4355 -0
- package/pack/visuals.json +680 -0
- package/pack/world.json +1030 -0
- package/package.json +67 -0
- package/src/compile.ts +55 -0
- package/src/data-exactness.reader.ts +559 -0
- package/src/index.ts +31 -0
- package/src/parser.ts +406 -0
- package/src/records.ts +341 -0
- package/src/specs/generate.ts +61 -0
- package/src/specs/index.ts +103 -0
- package/src/specs/init.ts +322 -0
- package/src/specs/misc.ts +153 -0
- package/src/specs/mon-init.ts +165 -0
- package/src/specs/obj-init.ts +230 -0
- package/src/specs/ui-entry.ts +74 -0
- package/src/specs/visuals.ts +37 -0
package/src/records.ts
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record assembly: turns a parsed gamedata file into JSON records.
|
|
3
|
+
*
|
|
4
|
+
* A FileSpec mirrors one upstream init_parse_* registration set. Records
|
|
5
|
+
* begin at the record-start directive; other directives attach to the
|
|
6
|
+
* current record. Directives marked `repeat` accumulate into arrays (in
|
|
7
|
+
* file order). Directives marked `childOf` attach to the most recent
|
|
8
|
+
* instance of one of their parent directives, replicating the upstream
|
|
9
|
+
* "walk to the last effect/book/spell/level" parsing idiom; when no parent
|
|
10
|
+
* instance exists yet in the record they attach to the record itself
|
|
11
|
+
* (upstream treats that as "human, not parser error") unless the directive
|
|
12
|
+
* is marked `requireParent`, where upstream instead reports
|
|
13
|
+
* PARSE_ERROR_MISSING_RECORD_HEADER. A repeat of a non-`repeat` directive is
|
|
14
|
+
* otherwise silently overwrite the previous value, matching the usual
|
|
15
|
+
* upstream handler behavior. Only explicitly marked directives reject a
|
|
16
|
+
* repeat with PARSE_ERROR_REPEATED_DIRECTIVE.
|
|
17
|
+
*
|
|
18
|
+
* Output key order is spec order (the upstream registration order), not
|
|
19
|
+
* encounter order, so records diff cleanly against the .txt sources.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { ParseError, parseLine, parseSignature } from "./parser.js";
|
|
23
|
+
import type { DirectiveSignature } from "./parser.js";
|
|
24
|
+
|
|
25
|
+
export interface DirectiveDef {
|
|
26
|
+
/** The exact upstream parser_reg() format string. */
|
|
27
|
+
readonly fmt: string;
|
|
28
|
+
/** Accumulate repeated occurrences into an array. */
|
|
29
|
+
readonly repeat?: boolean;
|
|
30
|
+
/** Attach to the most recent instance of one of these directives. */
|
|
31
|
+
readonly childOf?: readonly string[];
|
|
32
|
+
/** Preserve encounter order for a cross-directive repeated list. */
|
|
33
|
+
readonly orderKey?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Reject a repeated occurrence. This models the two upstream handlers
|
|
36
|
+
* that explicitly test already-initialized state: parse_feat_name
|
|
37
|
+
* (init.c:2059-2060) and parse_class_magic (init.c:3714-3716).
|
|
38
|
+
*/
|
|
39
|
+
readonly rejectRepeated?: (prior: JsonValue) => boolean;
|
|
40
|
+
/**
|
|
41
|
+
* This directive is an ERROR when none of its `childOf` parents has been
|
|
42
|
+
* seen yet, rather than attaching to the enclosing record. Upstream is
|
|
43
|
+
* split on this: class.txt, object.txt and trap.txt treat an orphan
|
|
44
|
+
* effect detail as "human, not parser, error" and return
|
|
45
|
+
* PARSE_ERROR_NONE, but player-timed.c's four effect-* handlers return
|
|
46
|
+
* PARSE_ERROR_MISSING_RECORD_HEADER when `ps->e` is NULL
|
|
47
|
+
* (player-timed.c L473-560, asserted by ptimed.c test_missing_effect0).
|
|
48
|
+
*/
|
|
49
|
+
readonly requireParent?: boolean;
|
|
50
|
+
/** Error returned when no `childOf` parent has been seen. */
|
|
51
|
+
readonly orphanError?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Handler-specific state validation that is expressible from already
|
|
54
|
+
* assembled records. This deliberately cannot see runtime registries.
|
|
55
|
+
*/
|
|
56
|
+
readonly validate?: (context: DirectiveValidationContext) => string | undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface DirectiveValidationContext {
|
|
60
|
+
readonly record: JsonObject;
|
|
61
|
+
readonly target: JsonObject;
|
|
62
|
+
readonly values: Readonly<Record<string, string | number>>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface FileSpec {
|
|
66
|
+
/** Gamedata file stem, e.g. "monster" for lib/gamedata/monster.txt. */
|
|
67
|
+
readonly name: string;
|
|
68
|
+
/** Upstream C sources that register this file's parser. */
|
|
69
|
+
readonly upstream: readonly string[];
|
|
70
|
+
/** Directive that begins a record; null for singleton files (constants). */
|
|
71
|
+
readonly recordStart: string | null;
|
|
72
|
+
/** Directives collected before the first record (e.g. object_base defaults). */
|
|
73
|
+
readonly header?: readonly string[];
|
|
74
|
+
readonly directives: readonly DirectiveDef[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export type JsonPrimitive = string | number | boolean;
|
|
78
|
+
export type JsonValue = JsonPrimitive | JsonValue[] | { [key: string]: JsonValue };
|
|
79
|
+
export type JsonObject = { [key: string]: JsonValue };
|
|
80
|
+
|
|
81
|
+
export interface CompiledFile {
|
|
82
|
+
file: string;
|
|
83
|
+
source: string;
|
|
84
|
+
header?: JsonObject;
|
|
85
|
+
records: JsonObject[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** A container node: a directive instance that other directives attach to. */
|
|
89
|
+
class Node {
|
|
90
|
+
readonly fields: Array<readonly [string, JsonPrimitive]> = [];
|
|
91
|
+
readonly children = new Map<string, Slot>();
|
|
92
|
+
readonly orderGroups = new Map<string, string[]>();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
type Value = JsonPrimitive | JsonObject | Node;
|
|
96
|
+
type Slot = Value | Value[];
|
|
97
|
+
|
|
98
|
+
interface CompiledDirective {
|
|
99
|
+
readonly def: DirectiveDef;
|
|
100
|
+
readonly sig: DirectiveSignature;
|
|
101
|
+
readonly isContainer: boolean;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface Instance {
|
|
105
|
+
readonly node: Node;
|
|
106
|
+
readonly seq: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function buildTable(spec: FileSpec): Map<string, CompiledDirective> {
|
|
110
|
+
const parents = new Set<string>();
|
|
111
|
+
for (const def of spec.directives) {
|
|
112
|
+
for (const parent of def.childOf ?? []) {
|
|
113
|
+
parents.add(parent);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const table = new Map<string, CompiledDirective>();
|
|
117
|
+
for (const def of spec.directives) {
|
|
118
|
+
const sig = parseSignature(def.fmt);
|
|
119
|
+
if (table.has(sig.directive)) {
|
|
120
|
+
throw new Error(`${spec.name}: duplicate directive spec "${sig.directive}"`);
|
|
121
|
+
}
|
|
122
|
+
table.set(sig.directive, { def, sig, isContainer: parents.has(sig.directive) });
|
|
123
|
+
}
|
|
124
|
+
for (const parent of parents) {
|
|
125
|
+
if (!table.has(parent)) {
|
|
126
|
+
throw new Error(`${spec.name}: childOf refers to unknown directive "${parent}"`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return table;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function makeValue(cd: CompiledDirective, values: Readonly<Record<string, string | number>>): Value {
|
|
133
|
+
const entries: Array<readonly [string, JsonPrimitive]> = [];
|
|
134
|
+
for (const field of cd.sig.fields) {
|
|
135
|
+
const v = values[field.name];
|
|
136
|
+
if (v !== undefined) {
|
|
137
|
+
entries.push([field.name, v]);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (cd.isContainer) {
|
|
141
|
+
const node = new Node();
|
|
142
|
+
node.fields.push(...entries);
|
|
143
|
+
return node;
|
|
144
|
+
}
|
|
145
|
+
if (cd.sig.fields.length === 1) {
|
|
146
|
+
const only = entries[0];
|
|
147
|
+
/* A lone optional field that is absent leaves a bare presence marker. */
|
|
148
|
+
return only === undefined ? true : only[1];
|
|
149
|
+
}
|
|
150
|
+
const obj: JsonObject = {};
|
|
151
|
+
for (const [k, v] of entries) {
|
|
152
|
+
obj[k] = v;
|
|
153
|
+
}
|
|
154
|
+
return obj;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function finalizeValue(v: Value, spec: FileSpec, table: Map<string, CompiledDirective>): JsonValue {
|
|
158
|
+
return v instanceof Node ? finalizeNode(v, spec, table) : v;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function finalizeNode(
|
|
162
|
+
node: Node,
|
|
163
|
+
spec: FileSpec,
|
|
164
|
+
table: Map<string, CompiledDirective>,
|
|
165
|
+
): JsonObject {
|
|
166
|
+
const out: JsonObject = {};
|
|
167
|
+
for (const [k, v] of node.fields) {
|
|
168
|
+
out[k] = v;
|
|
169
|
+
}
|
|
170
|
+
/* Emit child directives in spec (upstream registration) order. */
|
|
171
|
+
for (const def of spec.directives) {
|
|
172
|
+
const directive = def.fmt.split(" ", 1)[0];
|
|
173
|
+
if (directive === undefined) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const slot = node.children.get(directive);
|
|
177
|
+
if (slot === undefined) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
out[directive] = Array.isArray(slot)
|
|
181
|
+
? slot.map((v) => finalizeValue(v, spec, table))
|
|
182
|
+
: finalizeValue(slot, spec, table);
|
|
183
|
+
}
|
|
184
|
+
for (const [key, order] of node.orderGroups) out[key] = [...order];
|
|
185
|
+
return out;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Compile the text of one gamedata file into JSON records.
|
|
190
|
+
* Throws on any line the upstream parser would reject. Non-repeating
|
|
191
|
+
* directives overwrite their previous value unless their spec explicitly
|
|
192
|
+
* models an upstream repeated-directive error.
|
|
193
|
+
*
|
|
194
|
+
* This is the port's `parse_file` (datafile.c:87) plus the `fp->run` half of
|
|
195
|
+
* `run_parser` (datafile.c:45): one line-at-a-time loop over the file feeding
|
|
196
|
+
* `parseLine` (upstream `parser_parse`). Two deliberate differences, both
|
|
197
|
+
* unobservable on shipped 4.2.6 data (W1-CAVE-SAVE-DATA.md, datafile section):
|
|
198
|
+
* - Upstream tries ANGBAND_DIR_USER/<name>.txt before ANGBAND_DIR_GAMEDATA
|
|
199
|
+
* (datafile.c:96-105); user data-file overriding is the mod substrate's job
|
|
200
|
+
* here, and the compiler reads only reference/lib/gamedata.
|
|
201
|
+
* - Upstream logs up to get_parser_error_limit() parse errors and returns the
|
|
202
|
+
* FIRST (datafile.c:113-141); this throws on the first. `parse_file_quit_
|
|
203
|
+
* not_found` (datafile.c:71) is the readFileSync throw in compile.ts.
|
|
204
|
+
*/
|
|
205
|
+
export function compileGamedata(text: string, spec: FileSpec): CompiledFile {
|
|
206
|
+
const table = buildTable(spec);
|
|
207
|
+
const lookup = (directive: string): DirectiveSignature | undefined =>
|
|
208
|
+
table.get(directive)?.sig;
|
|
209
|
+
|
|
210
|
+
const records: Node[] = [];
|
|
211
|
+
const headerNode = spec.header !== undefined ? new Node() : null;
|
|
212
|
+
let current: Node | null = null;
|
|
213
|
+
if (spec.recordStart === null) {
|
|
214
|
+
current = new Node();
|
|
215
|
+
records.push(current);
|
|
216
|
+
}
|
|
217
|
+
let lastInstance = new Map<string, Instance>();
|
|
218
|
+
let seq = 0;
|
|
219
|
+
|
|
220
|
+
const lines = text.split("\n");
|
|
221
|
+
for (let i = 0; i < lines.length; i++) {
|
|
222
|
+
let raw = lines[i] ?? "";
|
|
223
|
+
if (raw.endsWith("\r")) {
|
|
224
|
+
raw = raw.slice(0, -1);
|
|
225
|
+
}
|
|
226
|
+
if (i === 0 && raw.charCodeAt(0) === 0xfeff) {
|
|
227
|
+
raw = raw.slice(1);
|
|
228
|
+
}
|
|
229
|
+
const where = `${spec.name}.txt:${i + 1}`;
|
|
230
|
+
let parsed;
|
|
231
|
+
try {
|
|
232
|
+
parsed = parseLine(raw, lookup);
|
|
233
|
+
} catch (err) {
|
|
234
|
+
if (err instanceof ParseError) {
|
|
235
|
+
throw new Error(`${where}: ${err.code}: ${err.message}`);
|
|
236
|
+
}
|
|
237
|
+
throw err;
|
|
238
|
+
}
|
|
239
|
+
if (parsed === null) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const cd = table.get(parsed.directive);
|
|
243
|
+
if (cd === undefined) {
|
|
244
|
+
/* parseLine already resolved the directive, so this cannot happen. */
|
|
245
|
+
throw new Error(`${where}: unregistered directive "${parsed.directive}"`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (spec.recordStart !== null && parsed.directive === spec.recordStart) {
|
|
249
|
+
current = new Node();
|
|
250
|
+
records.push(current);
|
|
251
|
+
lastInstance = new Map();
|
|
252
|
+
seq = 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
let root: Node;
|
|
256
|
+
if (current !== null) {
|
|
257
|
+
root = current;
|
|
258
|
+
} else if (headerNode !== null && (spec.header ?? []).includes(parsed.directive)) {
|
|
259
|
+
root = headerNode;
|
|
260
|
+
} else {
|
|
261
|
+
throw new Error(`${where}: directive "${parsed.directive}" before first record`);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const value = makeValue(cd, parsed.values);
|
|
265
|
+
|
|
266
|
+
/* Resolve the attachment target. */
|
|
267
|
+
let target = root;
|
|
268
|
+
if (cd.def.childOf !== undefined) {
|
|
269
|
+
let best: Instance | null = null;
|
|
270
|
+
for (const parent of cd.def.childOf) {
|
|
271
|
+
const inst = lastInstance.get(parent);
|
|
272
|
+
if (inst !== undefined && (best === null || inst.seq > best.seq)) {
|
|
273
|
+
best = inst;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (best !== null) {
|
|
277
|
+
target = best.node;
|
|
278
|
+
} else if (cd.def.requireParent === true || cd.def.orphanError !== undefined) {
|
|
279
|
+
const code = cd.def.orphanError ?? "MISSING_RECORD_HEADER";
|
|
280
|
+
throw new Error(
|
|
281
|
+
`${where}: ${code}: "${parsed.directive}" before any ` +
|
|
282
|
+
`${cd.def.childOf.join(" / ")}`,
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const validation = cd.def.validate?.({
|
|
288
|
+
record: finalizeNode(root, spec, table),
|
|
289
|
+
target: finalizeNode(target, spec, table),
|
|
290
|
+
values: parsed.values,
|
|
291
|
+
});
|
|
292
|
+
if (validation !== undefined) {
|
|
293
|
+
throw new Error(`${where}: ${validation}: rejected by upstream handler`);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (cd.def.repeat === true) {
|
|
297
|
+
const slot = target.children.get(parsed.directive);
|
|
298
|
+
const occurrence = slot === undefined ? 0 : Array.isArray(slot) ? slot.length : 0;
|
|
299
|
+
if (slot === undefined) {
|
|
300
|
+
target.children.set(parsed.directive, [value]);
|
|
301
|
+
} else if (Array.isArray(slot)) {
|
|
302
|
+
slot.push(value);
|
|
303
|
+
} else {
|
|
304
|
+
throw new Error(`${where}: repeat directive "${parsed.directive}" collided with a single value`);
|
|
305
|
+
}
|
|
306
|
+
if (cd.def.orderKey !== undefined) {
|
|
307
|
+
const order = target.orderGroups.get(cd.def.orderKey) ?? [];
|
|
308
|
+
order.push(`${parsed.directive}:${occurrence}`);
|
|
309
|
+
target.orderGroups.set(cd.def.orderKey, order);
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
const prior = target.children.get(parsed.directive);
|
|
313
|
+
if (
|
|
314
|
+
prior !== undefined &&
|
|
315
|
+
!Array.isArray(prior) &&
|
|
316
|
+
cd.def.rejectRepeated?.(finalizeValue(prior, spec, table))
|
|
317
|
+
) {
|
|
318
|
+
throw new Error(
|
|
319
|
+
`${where}: duplicate directive "${parsed.directive}" (rejected by upstream handler)`,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
target.children.set(parsed.directive, value);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (value instanceof Node) {
|
|
326
|
+
lastInstance.set(parsed.directive, { node: value, seq: ++seq });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const finalized = records.map((r) => finalizeNode(r, spec, table));
|
|
331
|
+
const source = `lib/gamedata/${spec.name}.txt`;
|
|
332
|
+
if (headerNode !== null && headerNode.children.size > 0) {
|
|
333
|
+
return {
|
|
334
|
+
file: spec.name,
|
|
335
|
+
source,
|
|
336
|
+
header: finalizeNode(headerNode, spec, table),
|
|
337
|
+
records: finalized,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
return { file: spec.name, source, records: finalized };
|
|
341
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Specs for the gamedata files whose upstream parsers live in
|
|
3
|
+
* src/generate.c: dungeon_profile (profile_parser), room_template
|
|
4
|
+
* (room_parser), vault (vault_parser).
|
|
5
|
+
*
|
|
6
|
+
* Format strings are copied verbatim from the parser_reg() calls.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { FileSpec } from "../records.js";
|
|
10
|
+
|
|
11
|
+
export const dungeonProfileSpec: FileSpec = {
|
|
12
|
+
name: "dungeon_profile",
|
|
13
|
+
upstream: ["src/generate.c"],
|
|
14
|
+
recordStart: "name",
|
|
15
|
+
directives: [
|
|
16
|
+
{ fmt: "name str name" },
|
|
17
|
+
{ fmt: "params int block int rooms int unusual int rarity" },
|
|
18
|
+
{ fmt: "tunnel int rnd int chg int con int pen int jct" },
|
|
19
|
+
{ fmt: "streamer int den int rng int mag int mc int qua int qc" },
|
|
20
|
+
{
|
|
21
|
+
fmt: "room sym name int rating int height int width int level int pit int rarity int cutoff",
|
|
22
|
+
repeat: true,
|
|
23
|
+
},
|
|
24
|
+
{ fmt: "min-level int min" },
|
|
25
|
+
{ fmt: "alloc int alloc" },
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const roomTemplateSpec: FileSpec = {
|
|
30
|
+
name: "room_template",
|
|
31
|
+
upstream: ["src/generate.c"],
|
|
32
|
+
recordStart: "name",
|
|
33
|
+
directives: [
|
|
34
|
+
{ fmt: "name str name" },
|
|
35
|
+
{ fmt: "type uint type" },
|
|
36
|
+
{ fmt: "rating int rating" },
|
|
37
|
+
{ fmt: "rows uint height" },
|
|
38
|
+
{ fmt: "columns uint width" },
|
|
39
|
+
{ fmt: "doors uint doors" },
|
|
40
|
+
{ fmt: "tval sym tval" },
|
|
41
|
+
{ fmt: "flags str flags", repeat: true },
|
|
42
|
+
{ fmt: "D str text", repeat: true },
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const vaultSpec: FileSpec = {
|
|
47
|
+
name: "vault",
|
|
48
|
+
upstream: ["src/generate.c"],
|
|
49
|
+
recordStart: "name",
|
|
50
|
+
directives: [
|
|
51
|
+
{ fmt: "name str name" },
|
|
52
|
+
{ fmt: "type str type" },
|
|
53
|
+
{ fmt: "rating int rating" },
|
|
54
|
+
{ fmt: "rows uint height" },
|
|
55
|
+
{ fmt: "columns uint width" },
|
|
56
|
+
{ fmt: "min-depth uint min_lev" },
|
|
57
|
+
{ fmt: "max-depth uint max_lev" },
|
|
58
|
+
{ fmt: "flags str flags", repeat: true },
|
|
59
|
+
{ fmt: "D str text", repeat: true },
|
|
60
|
+
],
|
|
61
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The full set of compiled gamedata files, in compile (and manifest) order.
|
|
3
|
+
*
|
|
4
|
+
* Deferred (not compiled): old_class.txt (retired data kept upstream for
|
|
5
|
+
* reference only).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { FileSpec } from "../records.js";
|
|
9
|
+
import {
|
|
10
|
+
bodySpec,
|
|
11
|
+
classSpec,
|
|
12
|
+
constantsSpec,
|
|
13
|
+
flavorSpec,
|
|
14
|
+
hintsSpec,
|
|
15
|
+
historySpec,
|
|
16
|
+
namesSpec,
|
|
17
|
+
pRaceSpec,
|
|
18
|
+
playerPropertySpec,
|
|
19
|
+
realmSpec,
|
|
20
|
+
shapeSpec,
|
|
21
|
+
terrainSpec,
|
|
22
|
+
trapSpec,
|
|
23
|
+
worldSpec,
|
|
24
|
+
} from "./init.js";
|
|
25
|
+
import {
|
|
26
|
+
activationSpec,
|
|
27
|
+
artifactSpec,
|
|
28
|
+
brandSpec,
|
|
29
|
+
curseSpec,
|
|
30
|
+
egoItemSpec,
|
|
31
|
+
objectBaseSpec,
|
|
32
|
+
objectPropertySpec,
|
|
33
|
+
objectSpec,
|
|
34
|
+
projectionSpec,
|
|
35
|
+
slaySpec,
|
|
36
|
+
} from "./obj-init.js";
|
|
37
|
+
import {
|
|
38
|
+
blowEffectsSpec,
|
|
39
|
+
blowMethodsSpec,
|
|
40
|
+
monsterBaseSpec,
|
|
41
|
+
monsterSpec,
|
|
42
|
+
monsterSpellSpec,
|
|
43
|
+
painSpec,
|
|
44
|
+
pitSpec,
|
|
45
|
+
} from "./mon-init.js";
|
|
46
|
+
import { dungeonProfileSpec, roomTemplateSpec, vaultSpec } from "./generate.js";
|
|
47
|
+
import {
|
|
48
|
+
chestTrapSpec,
|
|
49
|
+
playerTimedSpec,
|
|
50
|
+
questSpec,
|
|
51
|
+
storeSpec,
|
|
52
|
+
summonSpec,
|
|
53
|
+
uiKnowledgeSpec,
|
|
54
|
+
} from "./misc.js";
|
|
55
|
+
import { uiEntryBaseSpec, uiEntryRendererSpec, uiEntrySpec } from "./ui-entry.js";
|
|
56
|
+
import { visualsSpec } from "./visuals.js";
|
|
57
|
+
|
|
58
|
+
export const gamedataSpecs: readonly FileSpec[] = [
|
|
59
|
+
constantsSpec,
|
|
60
|
+
objectBaseSpec,
|
|
61
|
+
objectPropertySpec,
|
|
62
|
+
projectionSpec,
|
|
63
|
+
terrainSpec,
|
|
64
|
+
objectSpec,
|
|
65
|
+
monsterBaseSpec,
|
|
66
|
+
monsterSpellSpec,
|
|
67
|
+
blowMethodsSpec,
|
|
68
|
+
blowEffectsSpec,
|
|
69
|
+
monsterSpec,
|
|
70
|
+
egoItemSpec,
|
|
71
|
+
artifactSpec,
|
|
72
|
+
curseSpec,
|
|
73
|
+
brandSpec,
|
|
74
|
+
slaySpec,
|
|
75
|
+
activationSpec,
|
|
76
|
+
pRaceSpec,
|
|
77
|
+
classSpec,
|
|
78
|
+
playerPropertySpec,
|
|
79
|
+
playerTimedSpec,
|
|
80
|
+
shapeSpec,
|
|
81
|
+
bodySpec,
|
|
82
|
+
historySpec,
|
|
83
|
+
namesSpec,
|
|
84
|
+
flavorSpec,
|
|
85
|
+
painSpec,
|
|
86
|
+
pitSpec,
|
|
87
|
+
roomTemplateSpec,
|
|
88
|
+
vaultSpec,
|
|
89
|
+
dungeonProfileSpec,
|
|
90
|
+
storeSpec,
|
|
91
|
+
questSpec,
|
|
92
|
+
summonSpec,
|
|
93
|
+
trapSpec,
|
|
94
|
+
chestTrapSpec,
|
|
95
|
+
realmSpec,
|
|
96
|
+
worldSpec,
|
|
97
|
+
hintsSpec,
|
|
98
|
+
uiEntryRendererSpec,
|
|
99
|
+
uiEntryBaseSpec,
|
|
100
|
+
uiEntrySpec,
|
|
101
|
+
uiKnowledgeSpec,
|
|
102
|
+
visualsSpec,
|
|
103
|
+
];
|