@polycode-projects/the-mechanical-code-talker 2.7.12 → 2.7.13
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/corpus/worlds/manifest.json +5 -5
- package/corpus/worlds/shards/ashcombe-hall.jsonl.gz +0 -0
- package/corpus/worlds/src/ashcombe-hall.jsonl +1 -0
- package/package.json +1 -1
- package/src/domain/spider-fly-world.mjs +13 -0
- package/src/domain/sprite-map.mjs +49 -1
- package/src/services/adventure-autoplay.mjs +192 -0
- package/src/services/adventure-viz.mjs +262 -0
- package/src/services/spider-fly-viz.mjs +39 -9
- package/src/services/spider-fly.mjs +236 -68
- package/src/surfaces/web/adventure-browser-entry.mjs +88 -0
- package/src/surfaces/web/memory-ask-browser.bundle.js +1 -0
- package/src/surfaces/web/spider-fly-browser-entry.mjs +10 -8
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// adventure-browser-entry.mjs — the esbuild entry for the adventure's
|
|
2
|
+
// full-screen/home-page pages (public/adventure-browser.bundle.js, built by
|
|
3
|
+
// scripts/build-adventure-bundle.mjs), mirroring
|
|
4
|
+
// spider-fly-browser-entry.mjs's own session-factory shape.
|
|
5
|
+
//
|
|
6
|
+
// Unlike spider-fly's board, Ashcombe Hall's own facts+rules cannot be
|
|
7
|
+
// regenerated in-browser from a pure JS module — its canonical definition is
|
|
8
|
+
// a Node-only JSONL corpus source, read through an fs/gzip provider the
|
|
9
|
+
// browser cannot run. So this session takes the world as data
|
|
10
|
+
// (`worldPayload`, `{ name, facts, rules, opening }`), embedded into the page
|
|
11
|
+
// at build time by scripts/build-demo-site.mjs's own read through the real
|
|
12
|
+
// worlds-pack provider (see adventure-viz.mjs's header for the full
|
|
13
|
+
// rationale) — the bootstrap below then just appends it, exactly the shape
|
|
14
|
+
// openAdventure() itself writes for a real chat session.
|
|
15
|
+
//
|
|
16
|
+
// This session exposes ONLY a raw autoplay tick and a read-only snapshot —
|
|
17
|
+
// no chat dock. Every state-changing command adventure.mjs's own
|
|
18
|
+
// runWorldCommand issues (go/take/open/...) already re-narrates itself
|
|
19
|
+
// through the extractive completions digest on every turn (the
|
|
20
|
+
// "auto-relook"), so this bundle carries the same wink-nlp/completions
|
|
21
|
+
// dependency chain chat.mjs's own runTurn does; a second, lighter path was
|
|
22
|
+
// not available to duck under it. Nothing here calls runTurn, though — the
|
|
23
|
+
// one entry point exercised is adventureTurn itself, via
|
|
24
|
+
// adventure-autoplay.mjs, which is the "auto-play is a caller of the
|
|
25
|
+
// existing interpreter, never a second one" contract this whole feature
|
|
26
|
+
// rests on.
|
|
27
|
+
import {
|
|
28
|
+
createInMemoryStore, appendFacts, appendRule, loadMemory, readFactRows,
|
|
29
|
+
} from "../../adapters/memory/core.mjs";
|
|
30
|
+
import { foldWorldState, worldDigestRows } from "../../services/adventure.mjs";
|
|
31
|
+
import { runAdventureAutoplayTick } from "../../services/adventure-autoplay.mjs";
|
|
32
|
+
import { resolveSpriteForClass, SPRITE_REGISTRY } from "../../domain/sprite-map.mjs";
|
|
33
|
+
|
|
34
|
+
/** A live in-memory adventure this page's ticker drives one auto-play tick
|
|
35
|
+
* at a time. Returns `{ memoryDir, autoplayTick, snapshot }`.
|
|
36
|
+
* `worldPayload.facts`/`.rules` seed the store exactly the way
|
|
37
|
+
* openAdventure() itself does for a real session; `planHolder.state` is set
|
|
38
|
+
* the same way, so adventureTurn treats every subsequent call as a live,
|
|
39
|
+
* already-open world rather than a fresh opening line. */
|
|
40
|
+
export async function createAdventureSession(worldPayload) {
|
|
41
|
+
const memoryDir = createInMemoryStore();
|
|
42
|
+
const tag = `world:${worldPayload.name}`;
|
|
43
|
+
await appendFacts(memoryDir, worldPayload.facts.map((f) => ({
|
|
44
|
+
subject: f.subject, predicate: f.predicate, object: f.object, provenance: tag,
|
|
45
|
+
})));
|
|
46
|
+
for (const rule of worldPayload.rules) {
|
|
47
|
+
await appendRule(memoryDir, { name: rule.name, kind: rule.ruleKind, slots: rule.slots, provenance: tag });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const planHolder = { state: { adventure: { world: worldPayload.name } } };
|
|
51
|
+
const sessionId = globalThis.crypto?.randomUUID?.() ?? String(Date.now());
|
|
52
|
+
let exposedRoomIds = new Set();
|
|
53
|
+
const openingRows = readFactRows(await loadMemory(memoryDir));
|
|
54
|
+
const openingHere = foldWorldState(openingRows).placements.get("player")?.object ?? null;
|
|
55
|
+
if (openingHere) exposedRoomIds = new Set([openingHere]);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
memoryDir,
|
|
59
|
+
|
|
60
|
+
/** One auto-play tick: infer the goal, execute exactly one move through
|
|
61
|
+
* adventureTurn (adventure-autoplay.mjs's own contract), thread the
|
|
62
|
+
* exposed-room set forward. Returns runAdventureAutoplayTick's own
|
|
63
|
+
* `{ turn, goal, plan, done, stalled }` unmodified. */
|
|
64
|
+
async autoplayTick() {
|
|
65
|
+
const result = await runAdventureAutoplayTick(memoryDir, {
|
|
66
|
+
exposedRoomIds, planHolder, sessionId, env: {},
|
|
67
|
+
});
|
|
68
|
+
exposedRoomIds = result.exposedRoomIds;
|
|
69
|
+
return result;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/** A read-only fold of the current room — no engine advance — for the
|
|
73
|
+
* page's own redraw after boot and after every tick. */
|
|
74
|
+
async snapshot() {
|
|
75
|
+
const rows = readFactRows(await loadMemory(memoryDir));
|
|
76
|
+
const state = foldWorldState(rows);
|
|
77
|
+
const here = state.placements.get("player")?.object ?? null;
|
|
78
|
+
return { rows, state, here, turn: state.turnCount };
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Re-exported so the page's own rendering script (adventure-viz.mjs) never
|
|
84
|
+
// has to duplicate sprite resolution or the digest reader — the same posture
|
|
85
|
+
// spider-fly-browser-entry.mjs's own globalThis.tmctSpiderFly re-export takes.
|
|
86
|
+
globalThis.tmctAdventure = {
|
|
87
|
+
createAdventureSession, resolveSpriteForClass, SPRITE_REGISTRY, worldDigestRows,
|
|
88
|
+
};
|
|
@@ -23574,6 +23574,7 @@ ${JSON.stringify(envelope, null, 2)}`;
|
|
|
23574
23574
|
// src/services/spider-fly.mjs
|
|
23575
23575
|
init_planning();
|
|
23576
23576
|
init_core();
|
|
23577
|
+
init_hash();
|
|
23577
23578
|
|
|
23578
23579
|
// src/services/spider-fly-turn.mjs
|
|
23579
23580
|
init_core();
|
|
@@ -52,7 +52,7 @@ import { loadLexicon } from "../../domain/grammar/lexicon.mjs";
|
|
|
52
52
|
import {
|
|
53
53
|
worldFactRows, WORLD_NAME, WORLD_OPENING, cellId, parseCellId, DIRECTION_DELTA, visibleCells,
|
|
54
54
|
} from "../../domain/spider-fly-world.mjs";
|
|
55
|
-
import { foldSpiderFlyState, runSpiderFlyTick, startSpiderFlyGame, DEFAULT_VISION_RADIUS } from "../../services/spider-fly.mjs";
|
|
55
|
+
import { foldSpiderFlyState, runSpiderFlyTick, startSpiderFlyGame, liveWebs, DEFAULT_VISION_RADIUS } from "../../services/spider-fly.mjs";
|
|
56
56
|
import { resolveSpriteForClass, SPRITE_REGISTRY } from "../../domain/sprite-map.mjs";
|
|
57
57
|
|
|
58
58
|
/** A live in-memory game the page's ticker and chat dock can both drive.
|
|
@@ -77,8 +77,8 @@ export async function createSpiderFlySession({ flyCount = 1 } = {}) {
|
|
|
77
77
|
const { facts: startFacts } = await startSpiderFlyGame(memoryDir, { flyCount });
|
|
78
78
|
const initialAgents = {};
|
|
79
79
|
for (const f of startFacts) {
|
|
80
|
-
if (f.predicate
|
|
81
|
-
initialAgents[f.subject] = {
|
|
80
|
+
if (f.predicate === "mgx:currently-in") initialAgents[f.subject] = { ...initialAgents[f.subject], cell: f.object };
|
|
81
|
+
else if (f.predicate === "mgx:mass") initialAgents[f.subject] = { ...initialAgents[f.subject], mass: Number(f.object) };
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
const graph = parseEntities({ individuals: [], objectProperties: [] });
|
|
@@ -93,7 +93,7 @@ export async function createSpiderFlySession({ flyCount = 1 } = {}) {
|
|
|
93
93
|
memoryDir,
|
|
94
94
|
sessionId,
|
|
95
95
|
opening: WORLD_OPENING,
|
|
96
|
-
initial: { turn: 0, agents: initialAgents },
|
|
96
|
+
initial: { turn: 0, agents: initialAgents, activeWebs: [] },
|
|
97
97
|
taxonomyRows,
|
|
98
98
|
|
|
99
99
|
/** Run one real engine turn directly. Returns spider-fly.mjs's own
|
|
@@ -127,16 +127,18 @@ export async function createSpiderFlySession({ flyCount = 1 } = {}) {
|
|
|
127
127
|
|
|
128
128
|
/** A read-only fold of the CURRENT board — no engine advance, no goal
|
|
129
129
|
* lines (see the header comment: only a raw tick() recomputes those).
|
|
130
|
-
* Lets the page resync positions/turn count after a
|
|
130
|
+
* Lets the page resync positions/turn count/mass/active webs after a
|
|
131
|
+
* chat-driven tick. Web individuals are never listed as agents (that's
|
|
132
|
+
* spider-1/fly-1/... only) — they surface only through activeWebs. */
|
|
131
133
|
async snapshot() {
|
|
132
134
|
const rows = readFactRows(await loadMemory(memoryDir));
|
|
133
135
|
const state = foldSpiderFlyState(rows);
|
|
134
136
|
const agents = {};
|
|
135
137
|
for (const [id, place] of state.placements) {
|
|
136
|
-
if (state.removed.has(id)) continue;
|
|
137
|
-
agents[id] = { cell: place.cell };
|
|
138
|
+
if (state.removed.has(id) || /^web-\d+$/.test(id)) continue;
|
|
139
|
+
agents[id] = { cell: place.cell, mass: state.mass.get(id)?.value ?? null };
|
|
138
140
|
}
|
|
139
|
-
return { turn: state.turnCount, agents };
|
|
141
|
+
return { turn: state.turnCount, agents, activeWebs: liveWebs(state.webs, state.turnCount) };
|
|
140
142
|
},
|
|
141
143
|
};
|
|
142
144
|
}
|