Public: anyone can read this; the crew can change it.
forked from trevato/cs · proposes · 4 behind
The grid becomes engine: cells, meshing and A*; de_forge stays the game's #16
Check · Review · Land · Live done — Landed and live in production.
`src/engine/grid.ts` now holds the grid as plain data — `{ width, height, cell, cells: T[] }` for any cell type — along with `inside`, `cellAt`, `worldOf`, `colOf`, `rowOf`, `mergeSolid(grid, match, z0, z1, mat)` and `findPath(grid, passable, from, to)`. Every rule about what is solid or walkable arrives as a predicate, so no `"#"`, no `Cell` and no `MAT` crosses into the engine, and the grid is a…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
src/engine/grid.tsnow holds the grid as plain data —{ width, height, cell, cells: T[] }for any cell type — along withinside,cellAt,worldOf,colOf,rowOf,mergeSolid(grid, match, z0, z1, mat)andfindPath(grid, passable, from, to). Every rule about what is solid or walkable arrives as a predicate, so no"#", noCelland noMATcrosses into the engine, and the grid is always an argument rather than a module-level one, so a second game meshes its own level.src/client/map.tskeeps everything that is Counter-Strike —AREAS,CRATES, the alphabet,MAT, the site slabs, the floor,spawns,sites,siteAt— and exports the same names with the same signatures (plus a newpassable(cell), the predicate it hands the engine), soworld.ts,bots.ts,observe.ts,models.tsandsrc/rl/are untouched;gridis now theGrid<Cell>object rather than the bare array, and nothing imported it.de_forge does not move. I diffed the new map against the old implementation directly: the 50 boxes, the spawns, the sites and 1000 seeded random paths are byte-identical, and
cellAt/walkableagree over the grid and two cells past every edge.map.test.tskeeps its assertions and gains two that pin numbers —boxes.lengthat 50 with the floor at(-2816,-2816,-32)…(2816,2816,0)and the last crate at(1920,-640,0)…(2048,-512,128), and the T-spawn-to-A route at 33 waypoints, 4506.04 units walked against 4141.87 as the crow flies.src/engine/grid.test.tsworks only on grids drawn in the test: a 5×5 with a wall down the middle (the six-step route round the top, hand-checked at 4 + 2 × 1.414 = 6.83 against 4 straight through), a diagonal refused both when both orthogonal neighbours are solid and when one is, an unreachable goal, a goal in the cell you stand in, out-of-bounds at either end, a 3×2 block merging to exactly(-15,-10,0)…(15,10,32), an L splitting into two boxes in reading order, two grids meshing independently, and the corner round-trip ofworldOf/colOf/rowOfincluding the 0.1-unit either side of a cell edge.I did not replace the linear scan of the open set: the algorithm and its tie-breaking are unchanged, which is why the paths are identical, so no equivalence test was needed. What did change is
open.includes(ni)becoming a flag array and the passability predicate being cached one answer per cell per search. 100 searches between random walkable cells, warmed: 0.107 ms each before, 0.104 ms after; cold first pass is 0.19 ms.bun testis 166 pass / 0 fail (151 before, 15 new),boundary.test.tsgreen withgrid.tsinside the engine, and the bundle was rebuilt tostatic/app.876e3fcdf5.js. On the preview, worth checking that bots still walk out of T spawn to both sites and that the level looks unchanged — those are the two things a half-cell of drift would break.🤖 Generated with Claude Code
Closes #11