@its-not-rocket-science/ananke 0.1.13 → 0.1.15
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/CHANGELOG.md +46 -0
- package/dist/as/injury.wasm +0 -0
- package/dist/as/injury.wat +382 -0
- package/dist/as/push.wasm +0 -0
- package/dist/as/push.wat +326 -0
- package/dist/as/units.wasm +0 -0
- package/dist/as/units.wat +290 -0
- package/dist/src/campaign-layer.d.ts +1 -0
- package/dist/src/campaign-layer.js +1 -0
- package/dist/src/culture.d.ts +164 -0
- package/dist/src/culture.js +412 -0
- package/dist/src/wasm-kernel.d.ts +58 -0
- package/dist/src/wasm-kernel.js +96 -0
- package/package.json +14 -2
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/wasm-kernel.ts — Node.js loader and host bridge for the AssemblyScript WASM modules.
|
|
2
|
+
//
|
|
3
|
+
// Provides a shadow-mode step that runs as/push.wasm + as/injury.wasm alongside the
|
|
4
|
+
// TypeScript kernel. In shadow mode the WASM outputs are NOT applied to world state;
|
|
5
|
+
// they are returned for the caller to log or validate.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// const kernel = await loadWasmKernel(); // once at startup
|
|
9
|
+
// const report = kernel.shadowStep(world); // after stepWorld() each tick
|
|
10
|
+
// console.log(report.summary);
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { SCALE } from "./units.js";
|
|
14
|
+
// ── Region order shared with as/injury.ts ─────────────────────────────────────
|
|
15
|
+
const REGION_ORDER = ["head", "torso", "leftArm", "rightArm", "leftLeg", "rightLeg"];
|
|
16
|
+
// ── Kernel class ──────────────────────────────────────────────────────────────
|
|
17
|
+
export class WasmKernel {
|
|
18
|
+
push;
|
|
19
|
+
injury;
|
|
20
|
+
// Canonical kernel push tuning (mirrors src/sim/kernel.ts)
|
|
21
|
+
static PUSH_RADIUS_M = Math.trunc(0.45 * SCALE.m); // 4500
|
|
22
|
+
static PUSH_REPEL_MPS2 = Math.trunc(1.5 * SCALE.mps2); // 15000
|
|
23
|
+
constructor(push, injury) {
|
|
24
|
+
this.push = push;
|
|
25
|
+
this.injury = injury;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Run WASM push + injury steps on the current world state (shadow mode — does not
|
|
29
|
+
* mutate world). Returns a per-entity report and a one-line summary string.
|
|
30
|
+
*
|
|
31
|
+
* Call this after stepWorld() each tick for validation / diagnostics.
|
|
32
|
+
*/
|
|
33
|
+
shadowStep(world, tick) {
|
|
34
|
+
const entities = world.entities;
|
|
35
|
+
const pushMax = this.push.MAX_ENTITIES.value;
|
|
36
|
+
const injMax = this.injury.MAX_ENTITIES.value;
|
|
37
|
+
const n = Math.min(entities.length, pushMax, injMax);
|
|
38
|
+
// ── Push pass (position-based repulsion) ──────────────────────────────────
|
|
39
|
+
for (let i = 0; i < n; i++) {
|
|
40
|
+
const e = entities[i];
|
|
41
|
+
this.push.writeEntity(i, e.position_m.x, e.position_m.y, e.injury.dead ? 0 : 1);
|
|
42
|
+
}
|
|
43
|
+
this.push.stepRepulsionPairs(n, WasmKernel.PUSH_RADIUS_M, WasmKernel.PUSH_REPEL_MPS2);
|
|
44
|
+
// ── Injury pass (clotting / bleed / shock / consciousness) ────────────────
|
|
45
|
+
for (let i = 0; i < n; i++) {
|
|
46
|
+
const e = entities[i];
|
|
47
|
+
const suff = e.condition["suffocation"] ?? 0;
|
|
48
|
+
this.injury.writeVitals(i, e.injury.fluidLoss, e.injury.shock, e.injury.consciousness, e.injury.dead ? 1 : 0, e.energy.fatigue, suff);
|
|
49
|
+
for (let r = 0; r < REGION_ORDER.length; r++) {
|
|
50
|
+
const reg = e.injury.byRegion[REGION_ORDER[r]];
|
|
51
|
+
this.injury.writeRegion(i, r, reg?.bleedingRate ?? 0, reg?.structuralDamage ?? 0, reg?.internalDamage ?? 0, reg?.["surfaceDamage"] ?? 0);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
this.injury.stepBleedAndShock(n);
|
|
55
|
+
// ── Build report ──────────────────────────────────────────────────────────
|
|
56
|
+
const reports = [];
|
|
57
|
+
for (let i = 0; i < n; i++) {
|
|
58
|
+
const e = entities[i];
|
|
59
|
+
reports.push({
|
|
60
|
+
entityId: e.id,
|
|
61
|
+
pushDvX: this.push.readDvX(i),
|
|
62
|
+
pushDvY: this.push.readDvY(i),
|
|
63
|
+
projFluidLoss: this.injury.readFluidLoss(i),
|
|
64
|
+
projShock: this.injury.readShock(i),
|
|
65
|
+
projConsciousness: this.injury.readConsciousness(i),
|
|
66
|
+
projDead: this.injury.readDead(i) === 1,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const summary = reports
|
|
70
|
+
.map(r => `e${r.entityId} dv=(${r.pushDvX},${r.pushDvY}) ` +
|
|
71
|
+
`fl=${(r.projFluidLoss / SCALE.Q).toFixed(3)} ` +
|
|
72
|
+
`sh=${(r.projShock / SCALE.Q).toFixed(3)} ` +
|
|
73
|
+
`co=${(r.projConsciousness / SCALE.Q).toFixed(3)}` +
|
|
74
|
+
(r.projDead ? " DEAD" : ""))
|
|
75
|
+
.join(" | ");
|
|
76
|
+
return { tick, entities: reports, ok: true, summary: `[wasm] tick ${tick}: ${summary}` };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ── Factory ───────────────────────────────────────────────────────────────────
|
|
80
|
+
/**
|
|
81
|
+
* Load push.wasm and injury.wasm from dist/as/ (co-located with this compiled module)
|
|
82
|
+
* and return a WasmKernel ready for use.
|
|
83
|
+
*
|
|
84
|
+
* Throws if the WASM files are not found (e.g. npm run build:wasm:all not yet run).
|
|
85
|
+
*/
|
|
86
|
+
export async function loadWasmKernel() {
|
|
87
|
+
// Compiled to dist/src/wasm-kernel.js → WASM files are at ../as/*.wasm
|
|
88
|
+
const base = new URL("../as/", import.meta.url);
|
|
89
|
+
const pushBuf = readFileSync(fileURLToPath(new URL("push.wasm", base)));
|
|
90
|
+
const injuryBuf = readFileSync(fileURLToPath(new URL("injury.wasm", base)));
|
|
91
|
+
const [pushResult, injuryResult] = await Promise.all([
|
|
92
|
+
WebAssembly.instantiate(pushBuf),
|
|
93
|
+
WebAssembly.instantiate(injuryBuf),
|
|
94
|
+
]);
|
|
95
|
+
return new WasmKernel(pushResult.instance.exports, injuryResult.instance.exports);
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@its-not-rocket-science/ananke",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deterministic lockstep-friendly SI-units RPG/physics core (fixed-point TS)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,10 +54,15 @@
|
|
|
54
54
|
"./competence": {
|
|
55
55
|
"import": "./dist/src/competence/index.js",
|
|
56
56
|
"types": "./dist/src/competence/index.d.ts"
|
|
57
|
+
},
|
|
58
|
+
"./wasm-kernel": {
|
|
59
|
+
"import": "./dist/src/wasm-kernel.js",
|
|
60
|
+
"types": "./dist/src/wasm-kernel.d.ts"
|
|
57
61
|
}
|
|
58
62
|
},
|
|
59
63
|
"files": [
|
|
60
64
|
"dist/src",
|
|
65
|
+
"dist/as",
|
|
61
66
|
"docs/project-overview.md",
|
|
62
67
|
"docs/host-contract.md",
|
|
63
68
|
"docs/integration-primer.md",
|
|
@@ -118,12 +123,19 @@
|
|
|
118
123
|
"benchmark-check:strict": "node dist/tools/benchmark-check.js --threshold=0.10",
|
|
119
124
|
"benchmark-check:update": "node dist/tools/benchmark-check.js --update-baseline",
|
|
120
125
|
"benchmark:guide": "node dist/tools/benchmark-guide.js",
|
|
121
|
-
"benchmark:parallel": "node dist/tools/benchmark-parallel.js"
|
|
126
|
+
"benchmark:parallel": "node dist/tools/benchmark-parallel.js",
|
|
127
|
+
"run:renderer-bridge": "node dist/tools/renderer-bridge.js",
|
|
128
|
+
"build:wasm": "asc as/units.ts --outFile dist/as/units.wasm --textFile dist/as/units.wat --runtime stub --optimize",
|
|
129
|
+
"build:wasm:push": "asc as/push.ts --outFile dist/as/push.wasm --textFile dist/as/push.wat --runtime stub --optimize --initialMemory 1",
|
|
130
|
+
"build:wasm:injury": "asc as/injury.ts --outFile dist/as/injury.wasm --textFile dist/as/injury.wat --runtime stub --optimize --initialMemory 1",
|
|
131
|
+
"build:wasm:all": "npm run build:wasm && npm run build:wasm:push && npm run build:wasm:injury",
|
|
132
|
+
"test:wasm": "npm run build:wasm:all && vitest run test/as/"
|
|
122
133
|
},
|
|
123
134
|
"devDependencies": {
|
|
124
135
|
"@eslint/js": "^9.39.3",
|
|
125
136
|
"@types/node": "^20.0.0",
|
|
126
137
|
"@vitest/coverage-v8": "^2.1.8",
|
|
138
|
+
"assemblyscript": "^0.27.37",
|
|
127
139
|
"eslint": "^9.39.3",
|
|
128
140
|
"fast-check": "^4.6.0",
|
|
129
141
|
"typescript": "^5.5.4",
|