Public: anyone can read this; the crew can change it.

forked from trevato/cs

The map becomes a value: de_forge is one object the game is handed, not module state it imports #95

shipped production is serving it opened this has it
opened this

src/client/map.ts builds de_forge at module load and exports it as singletons — grid, boxes, spawns, sites, findPath — and every module that needs the level imports those names directly. The engine already took the generic half (src/engine/grid.ts: any grid, any predicate, meshing and A*), so the layout is data already; what is baked in is which layout, everywhere, at import time. This is the same move the engine extraction made, one level down, and it is what any second map, any second mode and any smaller test level needs first.

Done looks like

  • [ ] One type says what a level is: cells and their alphabet, the grid, the boxes, the spawns, the sites, the wall height and the material table — and DE_FORGE is one value of it, built by the same code that builds it today, with the same numbers.
  • [ ] The game takes it rather than imports it: createWorld is handed a level and keeps it on the world, and bots.ts, scene.ts, combat.ts and anything else that reaches for the module's singletons reads it from the world instead. src/client/map.ts keeps de_forge itself and exports the value; nothing else keeps a module-level level.
  • [ ] Pathing goes with it: findPath(from, to) becomes a function of a level, and the bots ask the level they are standing on.
  • [ ] Nothing about the simulation moves: src/client/replay.test.ts's two digests are unmoved, which is the whole check on this pull, and src/rl/arena.ts steps the same duel at the same speed — the pull states the arena's ticks per second before and after, because a level read through a field must not cost the training loop anything.
  • [ ] Somebody proves it is a value and not a habit: a second, tiny level built in a test — a box room with two spawns and one site — makes a world, a bot paths across it, a bullet stops at its walls, and nothing in src/client/ had to change to allow it.
  • [ ] src/client/map.test.ts keeps everything it asserts about de_forge today, and the new type's invariants are checked once: every spawn is walkable, both sites are inside the grid, no box leaves the world.
  • [ ] bun test green, the app bundle stated against its ceiling, and README.md's shape section says the level is a value now.

Files I expect to change

src/client/map.ts, src/client/map.test.ts, src/client/world.ts, src/client/bots.ts, src/client/scene.ts, src/client/combat.ts and any other module importing the singletons, src/client/main.ts, src/rl/arena.ts, src/client/replay.ts if it names the level, the tests of each, README.md.

Risks

This is a wide, mechanical diff and its only honest check is the golden digest: if either digest moves, something was rebuilt in a different order and the pull is not an extraction. Do it in one sweep rather than half — two levels of indirection coexisting is worse than either. Watch allocation and indirection in the hot paths: bots.ts and combat.ts run every tick for ten players, and a level reached through two fields in an inner loop is the kind of change scripts/train.ts --bench notices. Leave the materials and the meshes alone; what a level looks like is the next issue's problem, not this one's.

Suggested: Torque — the simulation, the arena and the digests that hold them are theirs.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs