ugly-game 0.5.0 → 0.5.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/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './dmath';
2
2
  export * from './mat4';
3
3
  export * from './noise';
4
4
  export * from './moat';
5
+ export * from './stateIR';
5
6
  export * from './gpuShadow';
6
7
  export * from './input/resolve';
7
8
  export * from './input/browserBackend';
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ export * from './dmath';
4
4
  export * from './mat4';
5
5
  export * from './noise';
6
6
  export * from './moat';
7
+ export * from './stateIR';
7
8
  export * from './gpuShadow';
8
9
  export * from './input/resolve';
9
10
  export * from './input/browserBackend';
@@ -0,0 +1,30 @@
1
+ /** A sim/scene that can explain itself to an agent from structured state (not pixels). */
2
+ export interface AgentDebuggable<Snap> {
3
+ /** Typed, JSON-able structured snapshot of the current state (a pure read). */
4
+ snapshot(): Snap;
5
+ /** One-screen play-by-play of the current state, highlighting the actionable "why" (built with Narrator). */
6
+ describe(): string;
7
+ }
8
+ /** Accumulates a readable, sectioned report with FIRST-CLASS warnings — the "why isn't it working?" view.
9
+ * Warnings are recorded both inline (so they appear in the narration) and separately (so an agent can
10
+ * branch on `warnings` without re-parsing the text). Chainable. */
11
+ export declare class Narrator {
12
+ private lines;
13
+ private warns;
14
+ /** Append a raw line. */
15
+ line(text: string): this;
16
+ /** A compact "label: k1 v1 · k2 v2 · …" status line. */
17
+ status(label: string, kv: Record<string, string | number>): this;
18
+ /** A ⚠ warning: shown inline AND collected in `warnings` so an agent can act on it programmatically. */
19
+ warn(text: string): this;
20
+ /** Warn only when `cond` holds. Returns this for chaining either way. */
21
+ warnIf(cond: boolean, text: string): this;
22
+ /** The bare warning strings (no ⚠ prefix), for agent branching. */
23
+ get warnings(): string[];
24
+ /** Was any warning raised? (a quick "is something wrong?" for an agent loop). */
25
+ get healthy(): boolean;
26
+ /** Render the whole report as one string. */
27
+ toString(): string;
28
+ }
29
+ /** Tally names into a "3 miner, 2 smelter" style histogram string, preserving first-seen order. */
30
+ export declare function histogram(names: Iterable<string>): string;
@@ -0,0 +1,43 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // ugly-game STATE IR — "debug from state, not screenshots"
3
+ //
4
+ // A general helper for turning ANY deterministic sim's CURRENT state into (a) a typed, JSON-able
5
+ // structured snapshot and (b) a one-screen, sectioned, WARNING-annotated narration that surfaces the
6
+ // actionable "why isn't it working?" — the view an AI (or a human) reads to diagnose without a picture.
7
+ //
8
+ // Complements the replay IR (ir.ts): that reconstructs state over TIME by re-running the sim; this
9
+ // explains a SINGLE state readably, right now. A game exposes `AgentDebuggable` (snapshot + describe);
10
+ // `Narrator` + `histogram` are the tools its describe() is built from. Graduated from the Cogsworth
11
+ // factory game, where it caught starved crafters, unpowered machines, and idle logistics at a glance.
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ /** Accumulates a readable, sectioned report with FIRST-CLASS warnings — the "why isn't it working?" view.
14
+ * Warnings are recorded both inline (so they appear in the narration) and separately (so an agent can
15
+ * branch on `warnings` without re-parsing the text). Chainable. */
16
+ export class Narrator {
17
+ lines = [];
18
+ warns = [];
19
+ /** Append a raw line. */
20
+ line(text) { this.lines.push(text); return this; }
21
+ /** A compact "label: k1 v1 · k2 v2 · …" status line. */
22
+ status(label, kv) {
23
+ this.lines.push(`${label}: ${Object.entries(kv).map(([k, v]) => `${k} ${v}`).join(' · ')}`);
24
+ return this;
25
+ }
26
+ /** A ⚠ warning: shown inline AND collected in `warnings` so an agent can act on it programmatically. */
27
+ warn(text) { this.warns.push(text); this.lines.push(`⚠ ${text}`); return this; }
28
+ /** Warn only when `cond` holds. Returns this for chaining either way. */
29
+ warnIf(cond, text) { return cond ? this.warn(text) : this; }
30
+ /** The bare warning strings (no ⚠ prefix), for agent branching. */
31
+ get warnings() { return this.warns.slice(); }
32
+ /** Was any warning raised? (a quick "is something wrong?" for an agent loop). */
33
+ get healthy() { return this.warns.length === 0; }
34
+ /** Render the whole report as one string. */
35
+ toString() { return this.lines.join('\n'); }
36
+ }
37
+ /** Tally names into a "3 miner, 2 smelter" style histogram string, preserving first-seen order. */
38
+ export function histogram(names) {
39
+ const m = new Map();
40
+ for (const n of names)
41
+ m.set(n, (m.get(n) ?? 0) + 1);
42
+ return [...m].map(([k, v]) => `${v} ${k}`).join(', ');
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugly-game",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {