Split The code is public; the app answers only to the crew.

The geometry nothing tests: `trace.ts` gets its first test, and reports the exit fraction it already computes #78

shipped merged opened this has it
opened this

Every bullet, every sight line, every grenade's line of sight and every bot's decision to shoot goes through src/client/trace.ts, and it is the only headless module in the client with no test file next to it.

This is a test issue with one small production change in it: rayBox computes tMax — where the ray leaves the box — and throws it away. Returning it costs nothing, changes no caller, and is the one number a penetrable crate will need.

Done looks like

  • [ ] src/client/trace.test.ts exists, and bun test fails if the slab loop in rayBox is altered.
  • [ ] rayBox: a segment entering a box returns t in 0..1 and the entry face's normal, checked on all six faces with both signs.
  • [ ] rayBox: the axis-parallel branch (Math.abs(d) < 1e-9) is covered both ways — parallel and outside the slab is null, parallel and inside the slab is not.
  • [ ] rayBox: a segment that stops short returns null; a ray starting inside the box is covered, and the test records what the code does today (tMin never moves, so the normal is the axis-0 face) rather than inventing what it ought to do.
  • [ ] traceWorld returns the nearest of several boxes on one ray, and what is the box object itself.
  • [ ] visible is false through a wall and true down an open corridor, using the real map.boxes and two named points from map.ts (one per site), so a map edit that closes a sightline fails here first.
  • [ ] rayBox returns the exit fraction as well as the entry one, with a test for it, and no existing caller changes behaviour: traceWorld, traceBullet, visible, the bots' sight and grenades.ts all answer exactly what they answer today.

Files I expect to change

src/client/trace.ts (one extra field on the return), src/client/trace.test.ts (new). Nothing else.

Risks

  • The return of rayBox is read in combat.ts and through traceWorld in several places. Widen it; do not rename or reorder what is there.
  • visible()'s answer is a contract: the bots' 32 observation inputs and the shipped policy's weights were trained against exactly it. A test may pin it; nothing here may change it.

Brief that fits: scout — small, sharp, entirely headless, nothing to render.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs