@polycode-projects/the-mechanical-code-talker 4.1.9 → 5.0.1
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 +1 -1
- package/corpus/worlds/index.json.gz +0 -0
- package/corpus/worlds/manifest.json +35 -5
- package/corpus/worlds/shards/town-square-chapel.jsonl.gz +0 -0
- package/corpus/worlds/shards/town-square-market.jsonl.gz +0 -0
- package/corpus/worlds/shards/town-square.jsonl.gz +0 -0
- package/corpus/worlds/src/town-square-chapel.jsonl +929 -0
- package/corpus/worlds/src/town-square-market.jsonl +455 -0
- package/corpus/worlds/src/town-square.jsonl +687 -0
- package/data/mudiii-assets.json +201 -0
- package/package.json +8 -2
- package/src/domain/agent-belief.mjs +96 -0
- package/src/domain/answer-variants.json +1 -1
- package/src/domain/game-config.mjs +65 -0
- package/src/domain/memory/compaction.mjs +2 -0
- package/src/domain/town-square-world.mjs +416 -0
- package/src/services/adventure-editor.mjs +36 -0
- package/src/services/adventure.mjs +45 -15
- package/src/services/chat.mjs +25 -1
- package/src/services/mud-editor.mjs +80 -0
- package/src/services/mudiii-scene.mjs +766 -0
- package/src/services/mudiii-turn.mjs +670 -0
- package/src/services/mudiii-viz.mjs +1247 -0
- package/src/services/pill-complete.mjs +495 -0
- package/src/services/predator-prey.mjs +916 -0
- package/src/services/spider-fly.mjs +14 -64
- package/src/services/world-teach.mjs +214 -0
- package/src/surfaces/web/adventure-browser-entry.mjs +18 -3
- package/src/surfaces/web/memory-ask-browser.bundle.js +126 -121
- package/src/surfaces/web/mudiii-browser-entry.mjs +224 -0
|
@@ -56,6 +56,7 @@ const SNAPSHOT_RE = /^(.+)@turn(\d+)$/;
|
|
|
56
56
|
// elsewhere in the document can never silently retract it.
|
|
57
57
|
const EDITABLE_OTHER_PREDICATES = [
|
|
58
58
|
"rdf:type", "rdfs:subClassOf", "mgx:display-name",
|
|
59
|
+
"mgx:model", "mgx:rotation",
|
|
59
60
|
"mgx:is-container", "mgx:is-predator", "mgx:is-origin",
|
|
60
61
|
"mgx:dig-spawns", "mgx:den-spawns", "mgx:den-resident",
|
|
61
62
|
"mgx:dig-reach", "mgx:dig-spawn-max", "mgx:den-chance-in", "mgx:den-resident-chance-in",
|
|
@@ -68,6 +69,33 @@ const TRUE_ONLY_FLAG_PREDICATES = ["mgx:is-container", "mgx:is-predator", "mgx:i
|
|
|
68
69
|
|
|
69
70
|
// ---- rendering ---------------------------------------------------------------
|
|
70
71
|
|
|
72
|
+
/** A GRID world's folded state in the shape this module's own renderer and
|
|
73
|
+
* differ read. A room world folds a placement into `{ predicate, object }`,
|
|
74
|
+
* because a thing can be carried, hidden or fixed as well as stood in. A grid
|
|
75
|
+
* world folds it into `{ cell, turn, epoch }`: on a board there is one way to
|
|
76
|
+
* be somewhere, and the extra fields carry the (epoch, turn) rank instead.
|
|
77
|
+
*
|
|
78
|
+
* Handed a grid fold directly, `renderMudEditorText` reads `place.predicate`
|
|
79
|
+
* as undefined and renders no placement sentence at all, and
|
|
80
|
+
* `planMudEditorSync` reads every placement line as a change and re-appends
|
|
81
|
+
* it. One translation here keeps both honest, and keeps a second copy of the
|
|
82
|
+
* mapping out of each page that needs it.
|
|
83
|
+
*
|
|
84
|
+
* `masses` comes across too, since a grid fold names it `mass`. There is no
|
|
85
|
+
* openness on a board, so that map is empty. Pure, self-contained (spliced by
|
|
86
|
+
* `.toString()` alongside the two functions it feeds). */
|
|
87
|
+
export function gridWorldEditorState(state) {
|
|
88
|
+
const placements = new Map();
|
|
89
|
+
for (const [subject, place] of (state && state.placements) || new Map()) {
|
|
90
|
+
if (place && place.cell) placements.set(subject, { predicate: "mgx:currently-in", object: place.cell });
|
|
91
|
+
}
|
|
92
|
+
const masses = new Map();
|
|
93
|
+
for (const [subject, mass] of (state && state.mass) || new Map()) {
|
|
94
|
+
if (mass && mass.value !== undefined) masses.set(subject, { value: mass.value });
|
|
95
|
+
}
|
|
96
|
+
return { placements, masses, openness: new Map() };
|
|
97
|
+
}
|
|
98
|
+
|
|
71
99
|
/** The whole burrow's editable facts as plain sentences, one per line, sorted by
|
|
72
100
|
* (subject, predicate, object) so two edits apart produce a reviewable diff
|
|
73
101
|
* rather than a reshuffle. Placement and openness come from the FOLDED state, so
|
|
@@ -125,6 +153,8 @@ export function renderMudEditorText(rows, state) {
|
|
|
125
153
|
if (p === "rdf:type") { push(s, p, o, `${cap(s)} ${typePhraseFor(o)} ${o}.`); continue; }
|
|
126
154
|
if (p === "rdfs:subClassOf") { push(s, p, o, `${cap(s)} is a kind of ${o}.`); continue; }
|
|
127
155
|
if (p === "mgx:display-name") { push(s, p, o, `${cap(s)} is shown as ${o}.`); continue; }
|
|
156
|
+
if (p === "mgx:model") { push(s, p, o, `${cap(s)} is modelled as ${o}.`); continue; }
|
|
157
|
+
if (p === "mgx:rotation") { push(s, p, o, `${cap(s)} is turned ${o} degrees.`); continue; }
|
|
128
158
|
if (p === "mgx:is-container" && o === "true") { push(s, p, o, `${cap(s)} is a container.`); continue; }
|
|
129
159
|
if (p === "mgx:is-predator" && o === "true") { push(s, p, o, `${cap(s)} hunts the other animals.`); continue; }
|
|
130
160
|
if (p === "mgx:is-origin" && o === "true") { push(s, p, o, `${cap(s)} is where the burrow starts.`); continue; }
|
|
@@ -179,6 +209,14 @@ const LINE_PATTERNS = [
|
|
|
179
209
|
build: (m) => ({ subject: LOW(m[1]), predicate: "mgx:hasMass", object: m[2] }) },
|
|
180
210
|
{ re: /^(.+?)\s+is\s+shown\s+as\s+(.+?)\.?$/i,
|
|
181
211
|
build: (m) => ({ subject: LOW(m[1]), predicate: "mgx:display-name", object: LOW(m[2]) }) },
|
|
212
|
+
// The two facts a 3D view needs and no other sentence in this table can
|
|
213
|
+
// say: which mesh draws a thing, and how far round it is turned. Kept
|
|
214
|
+
// apart from "is shown as" (a plain reading name, which every surface uses)
|
|
215
|
+
// because a renderer asking for the mesh must never be handed the name.
|
|
216
|
+
{ re: /^(.+?)\s+is\s+modelled\s+as\s+(.+?)\.?$/i,
|
|
217
|
+
build: (m) => ({ subject: LOW(m[1]), predicate: "mgx:model", object: LOW(m[2]) }) },
|
|
218
|
+
{ re: /^(.+?)\s+is\s+turned\s+(-?[\d.]+)\s+degrees?\.?$/i,
|
|
219
|
+
build: (m) => ({ subject: LOW(m[1]), predicate: "mgx:rotation", object: m[2] }) },
|
|
182
220
|
{ re: /^(.+?)\s+loses\s+([\d.]+)\s+mass\s+a\s+turn\.?$/i,
|
|
183
221
|
build: (m) => ({ subject: LOW(m[1]), predicate: "mgx:mass-drain-per-turn", object: m[2] }) },
|
|
184
222
|
// The dig knobs. "at most N things" is tried before the plain "turns up X" so
|
|
@@ -306,3 +344,45 @@ export function planMudEditorSync(rows, state, triples) {
|
|
|
306
344
|
}
|
|
307
345
|
return { toAppend, toRemoveIds };
|
|
308
346
|
}
|
|
347
|
+
|
|
348
|
+
/** The additive half of planMudEditorSync, for ONE already-parsed triple: the
|
|
349
|
+
* rows a single taught sentence implies, and never a retraction. A whole
|
|
350
|
+
* document says what the world contains, so a fact missing from it has gone;
|
|
351
|
+
* one sentence only ever says what it says, so nothing it leaves out is
|
|
352
|
+
* evidence of anything. Re-asserting a fact the world already holds appends
|
|
353
|
+
* nothing, and `reason` says which of the two happened. Pure. */
|
|
354
|
+
export function planTaughtMudTriple(rows, state, triple) {
|
|
355
|
+
if (!triple?.subject || !triple?.object) return { toAppend: [], reason: "nothing parsed" };
|
|
356
|
+
if (triple.kind === PLACEMENT_KIND) {
|
|
357
|
+
const current = state?.placements?.get(triple.subject);
|
|
358
|
+
if (current && current.predicate === triple.predicate && current.object === triple.object) {
|
|
359
|
+
return { toAppend: [], reason: `${triple.subject} is already ${triple.predicate} ${triple.object}` };
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
toAppend: [triple],
|
|
363
|
+
reason: current
|
|
364
|
+
? `${triple.subject} moves from ${current.object} to ${triple.object}`
|
|
365
|
+
: `${triple.subject} is placed ${triple.predicate} ${triple.object}`,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
if (triple.kind === OPENNESS_KIND) {
|
|
369
|
+
const current = state?.openness?.get(triple.subject);
|
|
370
|
+
const wantOpen = triple.object === "true";
|
|
371
|
+
if (current && current.open === wantOpen) {
|
|
372
|
+
return { toAppend: [], reason: `${triple.subject} is already ${wantOpen ? "open" : "closed"}` };
|
|
373
|
+
}
|
|
374
|
+
return { toAppend: [triple], reason: `${triple.subject} becomes ${wantOpen ? "open" : "closed"}` };
|
|
375
|
+
}
|
|
376
|
+
if (triple.kind === MASS_KIND) {
|
|
377
|
+
const current = state?.masses?.get(triple.subject);
|
|
378
|
+
if (current && Number(current.value) === Number(triple.object)) {
|
|
379
|
+
return { toAppend: [], reason: `${triple.subject} already weighs ${triple.object}` };
|
|
380
|
+
}
|
|
381
|
+
return { toAppend: [triple], reason: `${triple.subject} weighs ${triple.object}` };
|
|
382
|
+
}
|
|
383
|
+
const key = tripleKey(triple);
|
|
384
|
+
if (editableMudOtherRows(rows).some((r) => tripleKey(r) === key)) {
|
|
385
|
+
return { toAppend: [], reason: `the world already says ${key}` };
|
|
386
|
+
}
|
|
387
|
+
return { toAppend: [triple], reason: `the world gains ${key}` };
|
|
388
|
+
}
|