@scrolled/nav-graph 0.1.1-dev.7c21e18 → 0.1.1-dev.df34916
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/README.md +12 -7
- package/dist/compile/compileGraph.d.ts.map +1 -1
- package/dist/compile/compileGraph.js +23 -0
- package/dist/compile/compileGraph.js.map +1 -1
- package/dist/dsl/builder.d.ts +41 -8
- package/dist/dsl/builder.d.ts.map +1 -1
- package/dist/dsl/builder.js +26 -4
- package/dist/dsl/builder.js.map +1 -1
- package/dist/dsl/index.d.ts +1 -1
- package/dist/dsl/index.d.ts.map +1 -1
- package/dist/dsl/index.js.map +1 -1
- package/dist/dsl/requirements.d.ts +2 -1
- package/dist/dsl/requirements.d.ts.map +1 -1
- package/dist/dsl/requirements.js +10 -2
- package/dist/dsl/requirements.js.map +1 -1
- package/dist/graphs/starter/index.d.ts.map +1 -1
- package/dist/graphs/starter/index.js +16 -7
- package/dist/graphs/starter/index.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/ir/schema.d.ts +115 -31
- package/dist/ir/schema.d.ts.map +1 -1
- package/dist/ir/schema.js +20 -3
- package/dist/ir/schema.js.map +1 -1
- package/dist/ir/types.d.ts +29 -3
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/types.js +10 -1
- package/dist/ir/types.js.map +1 -1
- package/dist/path/findPath.d.ts +33 -0
- package/dist/path/findPath.d.ts.map +1 -1
- package/dist/path/findPath.js +135 -27
- package/dist/path/findPath.js.map +1 -1
- package/dist/path/index.d.ts +4 -2
- package/dist/path/index.d.ts.map +1 -1
- package/dist/path/index.js +2 -1
- package/dist/path/index.js.map +1 -1
- package/dist/path/unlockables.d.ts +36 -0
- package/dist/path/unlockables.d.ts.map +1 -0
- package/dist/path/unlockables.js +62 -0
- package/dist/path/unlockables.js.map +1 -0
- package/package.json +26 -35
package/dist/path/findPath.js
CHANGED
|
@@ -1,37 +1,79 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Weighted pathfinding: least-time Dijkstra over the compiled adjacency.
|
|
2
|
+
//
|
|
3
|
+
// Two methods cost time — `walk` and `transport` (boats/trains/carpets). Each
|
|
4
|
+
// costs its declared `seconds`, or its method default when untimed, so a graph
|
|
5
|
+
// with no times set still routes sensibly. Every other method (portal, npc,
|
|
6
|
+
// item, skill) is a teleport-like transition, treated as instant.
|
|
7
|
+
//
|
|
8
|
+
// `transport` time is *conditional*: with fast travel enabled (the player holds
|
|
9
|
+
// a fast-travel ticket), every transport hop is instant, so routes prefer boats
|
|
10
|
+
// over long walks; without it, transports cost their ride time and the router
|
|
11
|
+
// may route around them.
|
|
12
|
+
//
|
|
13
|
+
// `scroll` edges (return-to-nearest-town) are *availability*-conditional: they
|
|
14
|
+
// are traversable only when `nearestTownScroll` is set (the player carries
|
|
15
|
+
// return scrolls). They are instant like other teleports when enabled.
|
|
2
16
|
//
|
|
3
17
|
// When an eligibility predicate is supplied:
|
|
4
|
-
// 1. Run
|
|
18
|
+
// 1. Run Dijkstra with the predicate pruning candidate edges.
|
|
5
19
|
// 2. If the destination is reachable that way, return `status: 'found'`.
|
|
6
|
-
// 3. Otherwise run
|
|
7
|
-
// `status: 'unreachable-when-filtered'` with the unfiltered path as
|
|
20
|
+
// 3. Otherwise run Dijkstra again *without* the filter. If a path exists,
|
|
21
|
+
// return `status: 'unreachable-when-filtered'` with the unfiltered path as
|
|
8
22
|
// `fallback` and the step indices the filter blocked. This is FR7 — the
|
|
9
23
|
// app never has to surface a blank "no path" state when the graph itself
|
|
10
24
|
// is connected.
|
|
11
|
-
// 4. If the unfiltered
|
|
25
|
+
// 4. If the unfiltered search also fails, return `status: 'unreachable'`.
|
|
26
|
+
/** Assumed travel time, in seconds, for a walk edge that declares no `seconds`. */
|
|
27
|
+
export const DEFAULT_WALK_SECONDS = 60;
|
|
28
|
+
/**
|
|
29
|
+
* Assumed ride time, in seconds, for a transport edge that declares no
|
|
30
|
+
* `seconds`. Longer than a walk hop: boarding a boat/train means waiting for it.
|
|
31
|
+
*/
|
|
32
|
+
export const DEFAULT_TRANSPORT_SECONDS = 300;
|
|
33
|
+
/**
|
|
34
|
+
* Travel time an edge contributes to a route. `walk` always costs time;
|
|
35
|
+
* `transport` costs its ride time unless `fastTravel` waives it; portal / npc /
|
|
36
|
+
* item / skill transitions teleport the player instantly.
|
|
37
|
+
*/
|
|
38
|
+
export function edgeSeconds(edge, opts = {}) {
|
|
39
|
+
switch (edge.method) {
|
|
40
|
+
case 'walk':
|
|
41
|
+
return edge.seconds ?? DEFAULT_WALK_SECONDS;
|
|
42
|
+
case 'transport':
|
|
43
|
+
return opts.fastTravel ? 0 : (edge.seconds ?? DEFAULT_TRANSPORT_SECONDS);
|
|
44
|
+
default:
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
12
48
|
export function findPath(graph, from, to, opts = {}) {
|
|
13
49
|
assertNodeKnown(graph, from, 'from');
|
|
14
50
|
assertNodeKnown(graph, to, 'to');
|
|
15
51
|
if (from === to)
|
|
16
|
-
return { status: 'found', steps: [] };
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
52
|
+
return { status: 'found', steps: [], totalSeconds: 0 };
|
|
53
|
+
const cost = { fastTravel: opts.fastTravel };
|
|
54
|
+
const allowScroll = opts.nearestTownScroll ?? false;
|
|
55
|
+
const filtered = opts.eligible
|
|
56
|
+
? dijkstra(graph, from, to, cost, allowScroll, opts.eligible)
|
|
57
|
+
: null;
|
|
58
|
+
if (filtered) {
|
|
59
|
+
return { status: 'found', steps: filtered.steps, totalSeconds: filtered.totalSeconds };
|
|
60
|
+
}
|
|
61
|
+
const unfiltered = dijkstra(graph, from, to, cost, allowScroll);
|
|
21
62
|
if (!unfiltered)
|
|
22
|
-
return { status: 'unreachable', steps: [] };
|
|
63
|
+
return { status: 'unreachable', steps: [], totalSeconds: 0 };
|
|
23
64
|
if (!opts.eligible) {
|
|
24
|
-
return { status: 'found', steps: unfiltered };
|
|
65
|
+
return { status: 'found', steps: unfiltered.steps, totalSeconds: unfiltered.totalSeconds };
|
|
25
66
|
}
|
|
26
67
|
const blocked = [];
|
|
27
|
-
unfiltered.forEach((edge, i) => {
|
|
68
|
+
unfiltered.steps.forEach((edge, i) => {
|
|
28
69
|
if (!opts.eligible(edge))
|
|
29
70
|
blocked.push(i);
|
|
30
71
|
});
|
|
31
72
|
return {
|
|
32
73
|
status: 'unreachable-when-filtered',
|
|
33
74
|
steps: [],
|
|
34
|
-
|
|
75
|
+
totalSeconds: 0,
|
|
76
|
+
fallback: { steps: unfiltered.steps, totalSeconds: unfiltered.totalSeconds, blocked },
|
|
35
77
|
};
|
|
36
78
|
}
|
|
37
79
|
function assertNodeKnown(graph, id, label) {
|
|
@@ -39,23 +81,33 @@ function assertNodeKnown(graph, id, label) {
|
|
|
39
81
|
throw new Error(`findPath ${label} references undeclared node "${id}".`);
|
|
40
82
|
}
|
|
41
83
|
}
|
|
42
|
-
function
|
|
84
|
+
function dijkstra(graph, from, to, cost, allowScroll, eligible) {
|
|
85
|
+
const dist = new Map([[from, 0]]);
|
|
43
86
|
const cameFrom = new Map();
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
87
|
+
const settled = new Set();
|
|
88
|
+
const frontier = new MinHeap();
|
|
89
|
+
frontier.push(from, 0);
|
|
90
|
+
while (!frontier.isEmpty()) {
|
|
91
|
+
const node = frontier.pop();
|
|
92
|
+
if (settled.has(node))
|
|
93
|
+
continue; // stale heap entry — already finalized
|
|
48
94
|
if (node === to)
|
|
49
|
-
return reconstruct(cameFrom, from, to);
|
|
50
|
-
|
|
51
|
-
|
|
95
|
+
return { steps: reconstruct(cameFrom, from, to), totalSeconds: dist.get(to) };
|
|
96
|
+
settled.add(node);
|
|
97
|
+
const base = dist.get(node);
|
|
98
|
+
for (const edge of graph.adjacency.get(node) ?? []) {
|
|
99
|
+
if (edge.method === 'scroll' && !allowScroll)
|
|
100
|
+
continue;
|
|
52
101
|
if (eligible && !eligible(edge))
|
|
53
102
|
continue;
|
|
54
|
-
if (
|
|
103
|
+
if (settled.has(edge.to))
|
|
55
104
|
continue;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
105
|
+
const next = base + edgeSeconds(edge, cost);
|
|
106
|
+
if (next < (dist.get(edge.to) ?? Infinity)) {
|
|
107
|
+
dist.set(edge.to, next);
|
|
108
|
+
cameFrom.set(edge.to, edge);
|
|
109
|
+
frontier.push(edge.to, next);
|
|
110
|
+
}
|
|
59
111
|
}
|
|
60
112
|
}
|
|
61
113
|
return null;
|
|
@@ -66,7 +118,7 @@ function reconstruct(cameFrom, from, to) {
|
|
|
66
118
|
while (cursor !== from) {
|
|
67
119
|
const edge = cameFrom.get(cursor);
|
|
68
120
|
if (!edge) {
|
|
69
|
-
// Defensive:
|
|
121
|
+
// Defensive: Dijkstra only stores cameFrom for reachable nodes, so this
|
|
70
122
|
// branch is unreachable in practice — but typing the lookup demands it.
|
|
71
123
|
throw new Error(`Path reconstruction broke at "${cursor}".`);
|
|
72
124
|
}
|
|
@@ -75,4 +127,60 @@ function reconstruct(cameFrom, from, to) {
|
|
|
75
127
|
}
|
|
76
128
|
return steps.reverse();
|
|
77
129
|
}
|
|
130
|
+
// Binary min-heap keyed by tentative distance. Uses lazy deletion — a node can
|
|
131
|
+
// appear more than once and settled entries are skipped on pop.
|
|
132
|
+
class MinHeap {
|
|
133
|
+
nodes = [];
|
|
134
|
+
keys = [];
|
|
135
|
+
isEmpty() {
|
|
136
|
+
return this.nodes.length === 0;
|
|
137
|
+
}
|
|
138
|
+
push(node, key) {
|
|
139
|
+
this.nodes.push(node);
|
|
140
|
+
this.keys.push(key);
|
|
141
|
+
this.bubbleUp(this.nodes.length - 1);
|
|
142
|
+
}
|
|
143
|
+
pop() {
|
|
144
|
+
if (this.nodes.length === 0)
|
|
145
|
+
return undefined;
|
|
146
|
+
const top = this.nodes[0];
|
|
147
|
+
const lastNode = this.nodes.pop();
|
|
148
|
+
const lastKey = this.keys.pop();
|
|
149
|
+
if (this.nodes.length > 0) {
|
|
150
|
+
this.nodes[0] = lastNode;
|
|
151
|
+
this.keys[0] = lastKey;
|
|
152
|
+
this.bubbleDown(0);
|
|
153
|
+
}
|
|
154
|
+
return top;
|
|
155
|
+
}
|
|
156
|
+
bubbleUp(i) {
|
|
157
|
+
while (i > 0) {
|
|
158
|
+
const parent = (i - 1) >> 1;
|
|
159
|
+
if (this.keys[parent] <= this.keys[i])
|
|
160
|
+
break;
|
|
161
|
+
this.swap(i, parent);
|
|
162
|
+
i = parent;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
bubbleDown(i) {
|
|
166
|
+
const n = this.nodes.length;
|
|
167
|
+
for (;;) {
|
|
168
|
+
const left = 2 * i + 1;
|
|
169
|
+
const right = left + 1;
|
|
170
|
+
let smallest = i;
|
|
171
|
+
if (left < n && this.keys[left] < this.keys[smallest])
|
|
172
|
+
smallest = left;
|
|
173
|
+
if (right < n && this.keys[right] < this.keys[smallest])
|
|
174
|
+
smallest = right;
|
|
175
|
+
if (smallest === i)
|
|
176
|
+
break;
|
|
177
|
+
this.swap(i, smallest);
|
|
178
|
+
i = smallest;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
swap(a, b) {
|
|
182
|
+
[this.nodes[a], this.nodes[b]] = [this.nodes[b], this.nodes[a]];
|
|
183
|
+
[this.keys[a], this.keys[b]] = [this.keys[b], this.keys[a]];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
78
186
|
//# sourceMappingURL=findPath.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findPath.js","sourceRoot":"","sources":["../../src/path/findPath.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"findPath.js","sourceRoot":"","sources":["../../src/path/findPath.ts"],"names":[],"mappings":"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"}
|
package/dist/path/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { eligibilityFilter } from './eligibility';
|
|
2
2
|
export type { UserCapability } from './eligibility';
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
3
|
+
export { collectUnlockables, isUnlockable, lockedRequirementsFilter, requirementEntityId, requirementKey, } from './unlockables';
|
|
4
|
+
export type { UnlockableEntry, UnlockableKind, UnlockableRequirement } from './unlockables';
|
|
5
|
+
export { DEFAULT_TRANSPORT_SECONDS, DEFAULT_WALK_SECONDS, edgeSeconds, findPath } from './findPath';
|
|
6
|
+
export type { EdgeCostOptions, FindPathOptions, PathResult } from './findPath';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/path/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/path/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/path/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,wBAAwB,EACxB,mBAAmB,EACnB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACpG,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/path/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { eligibilityFilter } from './eligibility';
|
|
2
|
-
export {
|
|
2
|
+
export { collectUnlockables, isUnlockable, lockedRequirementsFilter, requirementEntityId, requirementKey, } from './unlockables';
|
|
3
|
+
export { DEFAULT_TRANSPORT_SECONDS, DEFAULT_WALK_SECONDS, edgeSeconds, findPath } from './findPath';
|
|
3
4
|
//# sourceMappingURL=index.js.map
|
package/dist/path/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/path/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/path/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,wBAAwB,EACxB,mBAAmB,EACnB,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { NavGraphSource, Requirement, TravelEdge } from '../ir/types';
|
|
2
|
+
export type UnlockableKind = 'item' | 'quest';
|
|
3
|
+
export type UnlockableRequirement = Extract<Requirement, {
|
|
4
|
+
kind: UnlockableKind;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function isUnlockable(req: Requirement): req is UnlockableRequirement;
|
|
7
|
+
/** The opaque entity id a requirement gates on. */
|
|
8
|
+
export declare function requirementEntityId(req: UnlockableRequirement): number;
|
|
9
|
+
/**
|
|
10
|
+
* Stable `${kind}:${id}` key identifying a requirement's unlockable subject.
|
|
11
|
+
* Two edges that require the same item (or quest) share a key, so one toggle
|
|
12
|
+
* governs both.
|
|
13
|
+
*/
|
|
14
|
+
export declare function requirementKey(req: UnlockableRequirement): string;
|
|
15
|
+
/** One distinct unlockable subject referenced somewhere in the graph. */
|
|
16
|
+
export interface UnlockableEntry {
|
|
17
|
+
key: string;
|
|
18
|
+
kind: UnlockableKind;
|
|
19
|
+
id: number;
|
|
20
|
+
/** Author-supplied display name, when any edge naming this subject provides one. */
|
|
21
|
+
name?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Every distinct item/quest requirement referenced by the graph's edges, one
|
|
25
|
+
* entry per `${kind}:${id}` in first-seen order. A named occurrence wins over
|
|
26
|
+
* an anonymous one, so a subject named on any edge surfaces its name.
|
|
27
|
+
*/
|
|
28
|
+
export declare function collectUnlockables(source: NavGraphSource): UnlockableEntry[];
|
|
29
|
+
/**
|
|
30
|
+
* An eligibility predicate for `findPath` that blocks any edge requiring a
|
|
31
|
+
* *locked* item or quest — a subject whose `${kind}:${id}` key is in `locked`.
|
|
32
|
+
* Non-unlockable requirements (meso, level) never block. An empty set passes
|
|
33
|
+
* every edge, matching "all requirements unlocked by default".
|
|
34
|
+
*/
|
|
35
|
+
export declare function lockedRequirementsFilter(locked: ReadonlySet<string>): (edge: TravelEdge) => boolean;
|
|
36
|
+
//# sourceMappingURL=unlockables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unlockables.d.ts","sourceRoot":"","sources":["../../src/path/unlockables.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3E,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9C,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC,CAAC;AAEnF,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,GAAG,IAAI,qBAAqB,CAE3E;AAED,mDAAmD;AACnD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,CAEjE;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,EAAE,CAoB5E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,GAC1B,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAM/B"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// The "requirements you've unlocked" model.
|
|
2
|
+
//
|
|
3
|
+
// Two requirement kinds gate on an opaque game entity id — `item` and `quest`.
|
|
4
|
+
// Those are things a traveller either has unlocked or hasn't, so the navigator
|
|
5
|
+
// lets them declare which ones they hold and routes around the rest. `meso` and
|
|
6
|
+
// `level` are scalar thresholds rather than opaque ids, so they're never gated
|
|
7
|
+
// here and always pass.
|
|
8
|
+
export function isUnlockable(req) {
|
|
9
|
+
return req.kind === 'item' || req.kind === 'quest';
|
|
10
|
+
}
|
|
11
|
+
/** The opaque entity id a requirement gates on. */
|
|
12
|
+
export function requirementEntityId(req) {
|
|
13
|
+
return req.kind === 'item' ? req.itemId : req.questId;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Stable `${kind}:${id}` key identifying a requirement's unlockable subject.
|
|
17
|
+
* Two edges that require the same item (or quest) share a key, so one toggle
|
|
18
|
+
* governs both.
|
|
19
|
+
*/
|
|
20
|
+
export function requirementKey(req) {
|
|
21
|
+
return `${req.kind}:${requirementEntityId(req)}`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Every distinct item/quest requirement referenced by the graph's edges, one
|
|
25
|
+
* entry per `${kind}:${id}` in first-seen order. A named occurrence wins over
|
|
26
|
+
* an anonymous one, so a subject named on any edge surfaces its name.
|
|
27
|
+
*/
|
|
28
|
+
export function collectUnlockables(source) {
|
|
29
|
+
const byKey = new Map();
|
|
30
|
+
for (const edge of source.edges) {
|
|
31
|
+
for (const req of edge.requirements ?? []) {
|
|
32
|
+
if (!isUnlockable(req))
|
|
33
|
+
continue;
|
|
34
|
+
const key = requirementKey(req);
|
|
35
|
+
const existing = byKey.get(key);
|
|
36
|
+
if (!existing) {
|
|
37
|
+
byKey.set(key, {
|
|
38
|
+
key,
|
|
39
|
+
kind: req.kind,
|
|
40
|
+
id: requirementEntityId(req),
|
|
41
|
+
...(req.name ? { name: req.name } : {}),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
else if (!existing.name && req.name) {
|
|
45
|
+
existing.name = req.name;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return [...byKey.values()];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* An eligibility predicate for `findPath` that blocks any edge requiring a
|
|
53
|
+
* *locked* item or quest — a subject whose `${kind}:${id}` key is in `locked`.
|
|
54
|
+
* Non-unlockable requirements (meso, level) never block. An empty set passes
|
|
55
|
+
* every edge, matching "all requirements unlocked by default".
|
|
56
|
+
*/
|
|
57
|
+
export function lockedRequirementsFilter(locked) {
|
|
58
|
+
if (locked.size === 0)
|
|
59
|
+
return () => true;
|
|
60
|
+
return (edge) => (edge.requirements ?? []).every((req) => !isUnlockable(req) || !locked.has(requirementKey(req)));
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=unlockables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unlockables.js","sourceRoot":"","sources":["../../src/path/unlockables.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,wBAAwB;AAQxB,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,OAAO,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC;AACrD,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,mBAAmB,CAAC,GAA0B;IAC5D,OAAO,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAA0B;IACvD,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;AACnD,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAsB;IACvD,MAAM,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;YAC1C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;gBAAE,SAAS;YACjC,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;oBACb,GAAG;oBACH,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,EAAE,EAAE,mBAAmB,CAAC,GAAG,CAAC;oBAC5B,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACxC,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;gBACtC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAA2B;IAE3B,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC;IACzC,OAAO,CAAC,IAAI,EAAE,EAAE,CACd,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,KAAK,CAC7B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAChE,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scrolled/nav-graph",
|
|
3
|
-
"version": "0.1.1-dev.
|
|
3
|
+
"version": "0.1.1-dev.df34916",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Framework-agnostic graph core: IR types + Zod schema, an authoring DSL, a compiler (IR → runtime adjacency), and pathfinding (BFS + eligibility). The engine behind Scrolled Navigator; usable standalone in Node and the browser.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -29,42 +29,25 @@
|
|
|
29
29
|
"README.md",
|
|
30
30
|
"LICENSE"
|
|
31
31
|
],
|
|
32
|
-
"main": "./
|
|
33
|
-
"module": "./
|
|
34
|
-
"types": "./
|
|
32
|
+
"main": "./dist/index.js",
|
|
33
|
+
"module": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
35
|
"exports": {
|
|
36
|
-
".":
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"types": "./dist/index.d.ts",
|
|
48
|
-
"import": "./dist/index.js"
|
|
49
|
-
},
|
|
50
|
-
"./ir": {
|
|
51
|
-
"types": "./dist/ir/index.d.ts",
|
|
52
|
-
"import": "./dist/ir/index.js"
|
|
53
|
-
},
|
|
54
|
-
"./dsl": {
|
|
55
|
-
"types": "./dist/dsl/index.d.ts",
|
|
56
|
-
"import": "./dist/dsl/index.js"
|
|
57
|
-
}
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"import": "./dist/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./ir": {
|
|
41
|
+
"types": "./dist/ir/index.d.ts",
|
|
42
|
+
"import": "./dist/ir/index.js"
|
|
43
|
+
},
|
|
44
|
+
"./dsl": {
|
|
45
|
+
"types": "./dist/dsl/index.d.ts",
|
|
46
|
+
"import": "./dist/dsl/index.js"
|
|
58
47
|
}
|
|
59
48
|
},
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"clean": "rm -rf dist LICENSE",
|
|
63
|
-
"export": "vite-node src/cli/export.ts",
|
|
64
|
-
"test": "vitest run --passWithNoTests",
|
|
65
|
-
"typecheck": "tsc --noEmit",
|
|
66
|
-
"lint": "eslint .",
|
|
67
|
-
"prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run clean && pnpm run build && cp ../../LICENSE LICENSE"
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
68
51
|
},
|
|
69
52
|
"dependencies": {
|
|
70
53
|
"zod": "^3.23.8"
|
|
@@ -74,5 +57,13 @@
|
|
|
74
57
|
"vite": "^5.4.8",
|
|
75
58
|
"vite-node": "^2.1.2",
|
|
76
59
|
"vitest": "^2.1.2"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsc -p tsconfig.build.json",
|
|
63
|
+
"clean": "rm -rf dist LICENSE",
|
|
64
|
+
"export": "vite-node src/cli/export.ts",
|
|
65
|
+
"test": "vitest run --passWithNoTests",
|
|
66
|
+
"typecheck": "tsc --noEmit",
|
|
67
|
+
"lint": "eslint ."
|
|
77
68
|
}
|
|
78
|
-
}
|
|
69
|
+
}
|