create-siltrun 0.1.0
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/index.mjs +98 -0
- package/package.json +18 -0
- package/templates/mass-grid/AGENTS.md +106 -0
- package/templates/mass-grid/README.md +59 -0
- package/templates/mass-grid/_gitignore +4 -0
- package/templates/mass-grid/index.html +22 -0
- package/templates/mass-grid/package.json +31 -0
- package/templates/mass-grid/room.test.ts +214 -0
- package/templates/mass-grid/room.ts +530 -0
- package/templates/mass-grid/skills/authoritative-tick.md +116 -0
- package/templates/mass-grid/skills/compact-snapshots.md +110 -0
- package/templates/mass-grid/skills/demo-room-lifecycle.md +145 -0
- package/templates/mass-grid/skills/genre-lane-mapping.md +88 -0
- package/templates/mass-grid/skills/territory-capture.md +115 -0
- package/templates/mass-grid/src/Game.tsx +174 -0
- package/templates/mass-grid/src/main.tsx +9 -0
- package/templates/mass-grid/tsconfig.json +15 -0
- package/templates/mass-grid/vite.config.ts +9 -0
- package/templates/minimal/README.md +39 -0
- package/templates/minimal/_gitignore +4 -0
- package/templates/minimal/index.html +15 -0
- package/templates/minimal/package.json +30 -0
- package/templates/minimal/room.ts +30 -0
- package/templates/minimal/src/Game.tsx +71 -0
- package/templates/minimal/src/main.tsx +9 -0
- package/templates/minimal/tsconfig.json +15 -0
- package/templates/minimal/vite.config.ts +7 -0
- package/templates/tower-defense/AGENTS.md +132 -0
- package/templates/tower-defense/README.md +53 -0
- package/templates/tower-defense/_gitignore +4 -0
- package/templates/tower-defense/index.html +15 -0
- package/templates/tower-defense/package.json +31 -0
- package/templates/tower-defense/room.test.ts +159 -0
- package/templates/tower-defense/room.ts +321 -0
- package/templates/tower-defense/skills/authoritative-tick.md +96 -0
- package/templates/tower-defense/skills/demo-room-lifecycle.md +145 -0
- package/templates/tower-defense/skills/state-budget.md +79 -0
- package/templates/tower-defense/skills/two-lanes.md +66 -0
- package/templates/tower-defense/skills/waves-and-timing.md +79 -0
- package/templates/tower-defense/src/Game.tsx +227 -0
- package/templates/tower-defense/src/main.tsx +9 -0
- package/templates/tower-defense/tsconfig.json +15 -0
- package/templates/tower-defense/vite.config.ts +7 -0
- package/templates/turn-based-grid/AGENTS.md +183 -0
- package/templates/turn-based-grid/README.md +72 -0
- package/templates/turn-based-grid/_gitignore +4 -0
- package/templates/turn-based-grid/index.html +15 -0
- package/templates/turn-based-grid/package.json +30 -0
- package/templates/turn-based-grid/room.ts +309 -0
- package/templates/turn-based-grid/skills/play.md +97 -0
- package/templates/turn-based-grid/src/App.tsx +141 -0
- package/templates/turn-based-grid/src/GraphicsView.tsx +148 -0
- package/templates/turn-based-grid/src/brains.ts +112 -0
- package/templates/turn-based-grid/src/main.tsx +8 -0
- package/templates/turn-based-grid/src/stubAgent.ts +82 -0
- package/templates/turn-based-grid/src/substrate/ascii.ts +87 -0
- package/templates/turn-based-grid/src/substrate/map.ts +104 -0
- package/templates/turn-based-grid/src/substrate/types.ts +59 -0
- package/templates/turn-based-grid/src/view.ts +94 -0
- package/templates/turn-based-grid/tsconfig.json +15 -0
- package/templates/turn-based-grid/vite.config.ts +7 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// view.ts — the AGENT's perception parser. Input is the rendered ASCII string (and
|
|
2
|
+
// nothing else); output is structured data a brain can reason over. This is the
|
|
3
|
+
// concrete demonstration that the ASCII projection is a SUFFICIENT sensorium: a brain
|
|
4
|
+
// turns text into a decision here, never touching the server State object.
|
|
5
|
+
|
|
6
|
+
import type { Dir, Pos } from "./substrate/types.ts";
|
|
7
|
+
|
|
8
|
+
export type View = {
|
|
9
|
+
w: number;
|
|
10
|
+
h: number;
|
|
11
|
+
grid: string[]; // just the map rows
|
|
12
|
+
selfGlyph: string | null;
|
|
13
|
+
self: Pos | null;
|
|
14
|
+
pellets: Pos[];
|
|
15
|
+
others: { glyph: string; pos: Pos }[];
|
|
16
|
+
isWall: (x: number, y: number) => boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** Parse the perception string produced by renderAscii(state, selfId). */
|
|
20
|
+
export function readView(ascii: string): View {
|
|
21
|
+
const lines = ascii.split("\n");
|
|
22
|
+
// the grid is the leading block of equal-width rows made only of map glyphs.
|
|
23
|
+
const grid: string[] = [];
|
|
24
|
+
for (const line of lines) {
|
|
25
|
+
if (/^[#.\*A-Za-z]+$/.test(line) && (grid.length === 0 || line.length === grid[0].length)) {
|
|
26
|
+
grid.push(line);
|
|
27
|
+
} else if (grid.length > 0) {
|
|
28
|
+
break; // grid ended
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const h = grid.length;
|
|
32
|
+
const w = h ? grid[0].length : 0;
|
|
33
|
+
|
|
34
|
+
const selfLine = lines.find((l) => l.startsWith("you are: "));
|
|
35
|
+
const selfGlyph = selfLine ? (selfLine.match(/you are:\s*([A-Za-z])\b/)?.[1] ?? null) : null;
|
|
36
|
+
|
|
37
|
+
const pellets: Pos[] = [];
|
|
38
|
+
const others: { glyph: string; pos: Pos }[] = [];
|
|
39
|
+
let self: Pos | null = null;
|
|
40
|
+
for (let y = 0; y < h; y++) {
|
|
41
|
+
for (let x = 0; x < w; x++) {
|
|
42
|
+
const c = grid[y][x];
|
|
43
|
+
if (c === "*") pellets.push({ x, y });
|
|
44
|
+
else if (/[A-Za-z]/.test(c)) {
|
|
45
|
+
if (c === selfGlyph) self = { x, y };
|
|
46
|
+
else others.push({ glyph: c, pos: { x, y } });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const isWall = (x: number, y: number) => {
|
|
52
|
+
if (y < 0 || y >= h || x < 0 || x >= w) return true;
|
|
53
|
+
return grid[y][x] === "#";
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return { w, h, grid, selfGlyph, self, pellets, others, isWall };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const DIRS: { dir: Exclude<Dir, "stay">; dx: number; dy: number }[] = [
|
|
60
|
+
{ dir: "up", dx: 0, dy: -1 },
|
|
61
|
+
{ dir: "down", dx: 0, dy: 1 },
|
|
62
|
+
{ dir: "left", dx: -1, dy: 0 },
|
|
63
|
+
{ dir: "right", dx: 1, dy: 0 },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* BFS from `self` over floor cells to the nearest pellet; return the first step's
|
|
68
|
+
* direction. Treats other players' cells as blocked. Null if none reachable. This is
|
|
69
|
+
* the "greedy pathfinder" a real agent would run over its parsed perception.
|
|
70
|
+
*/
|
|
71
|
+
export function stepTowardNearestPellet(view: View): Dir | null {
|
|
72
|
+
if (!view.self || view.pellets.length === 0) return null;
|
|
73
|
+
const pelletSet = new Set(view.pellets.map((p) => `${p.x},${p.y}`));
|
|
74
|
+
const blocked = new Set(view.others.map((o) => `${o.pos.x},${o.pos.y}`));
|
|
75
|
+
const start = view.self;
|
|
76
|
+
|
|
77
|
+
// BFS, recording the first-step direction taken from start on each shortest path.
|
|
78
|
+
const seen = new Set<string>([`${start.x},${start.y}`]);
|
|
79
|
+
type Node = { x: number; y: number; first: Dir | null };
|
|
80
|
+
const queue: Node[] = [{ x: start.x, y: start.y, first: null }];
|
|
81
|
+
while (queue.length) {
|
|
82
|
+
const node = queue.shift()!;
|
|
83
|
+
if (pelletSet.has(`${node.x},${node.y}`) && node.first) return node.first;
|
|
84
|
+
for (const { dir, dx, dy } of DIRS) {
|
|
85
|
+
const nx = node.x + dx;
|
|
86
|
+
const ny = node.y + dy;
|
|
87
|
+
const key = `${nx},${ny}`;
|
|
88
|
+
if (seen.has(key) || view.isWall(nx, ny) || blocked.has(key)) continue;
|
|
89
|
+
seen.add(key);
|
|
90
|
+
queue.push({ x: nx, y: ny, first: node.first ?? dir });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"noEmit": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src", "room.ts", "vite.config.ts"]
|
|
15
|
+
}
|