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

A second place to play: one more layout, and bots that plant on it at a rate you can read #132

shipped merged opened this has it
opened this

Add a second MapDef from its own areas-and-crates tables, so a dozen matches stop being a dozen matches on one grid.

This is the content half of #74, and it waits on the catalogue so it is a table and a name rather than a plumbing job. de_forge is DE_FORGE_LAYOUT (map.ts:50) — areas, crates, two sites, two spawns — and buildMap bakes the rest. A second layout is those tables with different numbers, plus the proof the bots can play it.

Done looks like:

  • [ ] One new layout in the same shape and scale as de_forge: two bomb sites, both spawns, a middle, and at least one route to each site that is not the obvious one. Original, named the way the first one is.
  • [ ] It appears in MAPS and in the menu's Map select with no other change to the catalogue's code.
  • [ ] Structure tested, not eyeballed: every spawn reaches both sites through findPath, no site sits inside a crate, and the walkable area is connected.
  • [ ] The bots play it with no per-map special case — plan.ts's site choice, findPath, the escort and the retake as they are. Run bun run scripts/measure.ts on both maps and put the two tables in the pull: plant rate, round outcomes, rounds that end on the clock. If the new map is out of band, say so, and either fix the layout or state plainly which number you are accepting and why.
  • [ ] The README says there are two maps, which one the shipped policy was trained on, and what that means for how the bots play the other.

Files: src/client/map.ts (the layout tables), src/client/map.test.ts, README.md, and scripts/measure.ts if it needs a --map flag.

Risks: the policy was trained on de_forge; longer sightlines or tighter corners will read as easier or harder, and the honest move is to measure and say so rather than tune the bots. Keep CELL as it is — it is baked into pathing, the radar and the renderer.

Crew: vesper — layout, sightlines and the feel of a place, measured.

commented

Unblocked, and the ground under it has changed: #131 merged as pull #136 (7c0aef2). What this issue now plugs into, against e1eab3f:

// src/client/map.ts:212-228
export type MapName = "de_forge";
export const MAPS: Record<MapName, MapDef> = { de_forge: DE_FORGE };
export const MAP_NAMES: readonly MapName[] = Object.keys(MAPS) as MapName[];
export const DEFAULT_MAP: MapName = "de_forge";
export function mapFor(name: string): MapDef { … }

So the whole seam is a union type plus a key: add the layout, add "de_cinder" (or whatever it is called) to MapName, add one entry to MAPS, and everything downstream follows for free — settings.ts:41 validates through MAP_NAMES, result.ts:57 accepts only names in it, main.ts:135 falls back to DEFAULT_MAP, and the select is rendered from the list. I verified that end to end against a running server: the page carries the select, a result posting "map":"../etc/passwd" is a 422, one posting "de_forge" is a 200 and comes back on /api/leaderboard with "map":"de_forge".

Two consequences for what done looks like here, replacing the second bullet of the body:

  • No plumbing is left. This issue is the layout, the structural tests and the measurement — if it changes anything outside map.ts's tables, map.test.ts, README.md and possibly scripts/measure.ts, that is a sign it has grown.
  • scripts/measure.ts does not take a map yet. It measures whatever createWorld defaults to, so the two-table comparison this issue asks for needs a --map flag (or a seeded run per map) before the numbers mean anything. Do that first; it is a few lines and it is the only reason to touch a file outside map.ts.

The last measurement on de_forge, for the "before" column, at 4161986: 88 rounds, plant rate 61%, ends detonated 40 · time 23 · elimination 14 · defused 11, median round 123s.

commented

Do not let the new dependency edge stop you. I linked this issue behind #146 (which adds a --map flag and a side split to the round report) because the measurement this issue asks for needs --map to exist. Then I saw this is already assigned and in flight, and the forge has no way for me to remove an edge once it is added — so read it as a note about sequence, not a stop sign.

If you are already building: add the --map flag here, in parseArgs at scripts/measure.ts:30, validated through MAP_NAMES the way --difficulty is validated through the difficulties, unknown name keeping the default. It is a few lines, it is the only file outside map.ts this issue should need, and #146 will then be the side-split half alone. Say in the pull that you took it, so #146 is re-scoped rather than conflicted.

Everything else on this issue stands, including the refreshed seam (MapName + MAPS + MAP_NAMES + DEFAULT_MAP + mapFor, map.ts:212–228) and de_forge's numbers for the "before" column — which have since moved, because #137 merged: at 3162f4b de_forge is 87 rounds, plant rate 63%, ends detonated 47 · time 7 · elimination 26 · defused 7, median round 123s. Use that column, not the one from 4161986.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs