SOURCE / PINNED RELEASE
Made of little things.
Pursuit PIT
- Release
- 565f4981bdc3…
- Author-recorded commit
- 197afdbed44b…
- License
- LICENSE
- Author’s source reference
- nostr://npub12lm3rxsva8kfempyjkxupt09e02n3fezurkyadyqfejdc5e0r2kscqty6r/wss%3A%2F%2Fgit.napplet.soy%2F/n-951414e7fd7
Archive hash verified: 3b0485589942fd5c…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// City layouts, headless: style spread, lot counts against the renderer's capacities, nothing on
// the highway verge or a slip road, and bridges per city. Run with: bun tools/city-check.ts
import { setRoadSeed } from '../src/game/road.ts';
import { zoneAt } from '../src/game/zones.ts';
import { cityLayout, CITY_STYLES } from '../src/game/cities.ts';
import { ROAD_HALF, rampAt, rampX, MERGE_X, MERGE_LEN, MERGE_TAPER, RAMP_CURVE } from '../src/game/sim.ts';
const styles = new Map<string, number>();
let worst = { lots: 0, streets: 0, low: 0, tall: 0, parks: 0, garages: 0, bridges: 0, maxH: 0 }, cities = 0, problems = 0;
const classes = [12, 24, 45, 80, 130, 200, 300, 420];
const perClassMax = new Array(classes.length).fill(0);
for (const seed of [1, 2, 3, 4, 5, 6]) {
setRoadSeed(seed);
for (let s = 0; s < 120_000;) {
const z = zoneAt(s);
if (z.area === 'city') {
cities++;
const c = cityLayout(z);
styles.set(c.style.name, (styles.get(c.style.name) ?? 0) + 1);
const b = c.lots.filter((l) => l.kind === 'building');
const per = new Array(classes.length).fill(0);
for (const l of b) {
let k = 0;
for (let i = 1; i < classes.length; i++) if (Math.abs(Math.log(classes[i] / l.h)) < Math.abs(Math.log(classes[k] / l.h))) k = i;
per[k]++;
}
per.forEach((n, i) => (perClassMax[i] = Math.max(perClassMax[i], n)));
worst = {
lots: Math.max(worst.lots, c.lots.length), streets: Math.max(worst.streets, c.streets.length),
low: Math.max(worst.low, b.filter((l) => l.h <= 35).length), tall: Math.max(worst.tall, b.filter((l) => l.h > 35).length),
parks: Math.max(worst.parks, c.lots.filter((l) => l.kind === 'park').length), garages: Math.max(worst.garages, c.lots.filter((l) => l.kind === 'garage').length),
bridges: Math.max(worst.bridges, c.bridges.length), maxH: Math.max(worst.maxH, ...b.map((l) => l.h)),
};
for (const l of c.lots) {
if (Math.abs(l.x) - l.w / 2 < ROAD_HALF + 20) problems++; // on the highway's verge
const d = l.s - rampAt(l.s);
if (l.x > 0 && d > -(RAMP_CURVE + 260) && d < MERGE_LEN + MERGE_TAPER) {
const rx = d < 0 ? rampX(-d) : MERGE_X;
if (l.x - l.w / 2 < rx + 8 && l.x + l.w / 2 > rx - 8) problems++; // on the slip road
}
if (!(l.w > 0 && l.d > 0)) problems++;
}
}
s = z.end + 1;
}
}
console.log(`${cities} cities; styles:`, Object.fromEntries(styles));
console.log('worst city:', worst, '| per height class (max):', perClassMax.join(' '));
console.log('problems:', problems, '| styles defined:', CITY_STYLES.length);
