Files
BT411/docs/RADAR_MAP_AUDIT.md
T

111 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Radar/Map Display Drift Audit — binary vs port vs content (2026-08-14)
**What this is:** the AI-facing ledger of the radar/map subsystem audit (3-agent,
full reports preserved at `scratchpad/night17/radar_audit_{bin,port,content}.txt`;
~800k tokens of reads). Trigger: #49 (arena walls missing from radar) + the field
report "many map items aren't showing on radar, like map boundaries."
Companion fix: the static world feed, commit `c2193e2` (#49 CLOSED, operator-verified).
## The architecture, as the machine built it [T1 unless noted]
- ONE radar picture for every map/mech: the 480×640 portrait `BTSEC1.PCX` +
`BTSEC1OV.PCX` baked art (tick ring + crosshair — **no range rings exist**),
with the live `map(` widget in the (366,367) scope rect at (58,229). There is
**no per-map radar art and no map page** — the ModeMapping bit is the
weapon-button CONFIG session, not cartography (aliased ModeNonConfig [T0]).
- **Entity membership** (@004cbfa0, the interest feed): an entity reaches the
scope iff (a) a type-0x12 GaugeImageStream pip exists for its resourceID AND
(b) Mover-derived → moving list, else Terrain-GRAPH-derived → static list.
The derivation graph parents UnscalableTerrain (0x2A), CulturalIcon (0x5E)
and Landmark (0x56) onto Terrain [T0 TERRAIN.cpp:183, CULTURAL.cpp:27] even
though their C++ bases differ.
- **Draw order** (@004c22c4): wedge → static pips → moving pips → name labels,
inside a stroke recorder (erase = replay last frame in bg color).
- **DrawStatic** (@004c25b4): each in-capability static's pip drawn with the
entity's FULL transform — walls/buttes/hills/ridges/buildings/trees rendered
as world-rotated, metre-scaled staticColor(3) outlines. 110 authored GIMs
ship (wall1-3, aw01-05, ab*/ar*/bld*, buttea-e, hillg/dhillg 652-byte
contours, sr1e/n/s/w polar rails, tree, dish, …).
- **DrawMoving** (@004c2788): every mover except the operator, color 7, target
boxed (+4px, hotbox color 1). NO self-blip; NO pipless fallback (every
shipped mech has a pip).
- **DrawNames** (@004c28c4): ≤16 callsign labels (64×16 egg rasters via
playerBitmapIndex); the target's label BLINKS at frame rate.
- **Zoom**: 6-step exponential, RadarRange = 250·2^level (250…8000 m scope
width), SLEWED smoothly; SCALE numeric shows it live. Capability radius =
RadarPercent × 4000 m — radar damage shrinks detection (#105/#121 pending).
- **Wedge**: hardcoded π/8 half-angle (45° total); the config's "180" param
only sizes the DEAD shadow table. (Manual says "60° field of vision" —
print-vs-code drift, the code wins for 4.10 [T1 vs manual].)
## Authenticity verdicts the port must respect
1. **The pure map boundary was INVISIBLE on the shipped machine.** Every
outdoor map places one `wall10k` (collision solids only, ±4100 m ring —
no pip, no video model). Players saw a "boundary" only where visible
wall/ridge ENTITIES formed the perimeter (arena aw*, polar sr1* rails, rav
buttes). Do NOT invent a boundary rectangle. (ExistanceBox type-26 extents:
arena ±700, rav ±1000, others ±7000 — available if a design call ever
wants one.)
2. **BuildRadarShadow (@004c228c) compiled EMPTY** — radar occlusion shading
was cut before ship. The port's empty body is faithful.
3. **Authored pip omissions are design**: floors/sky, wall10k, overhead butte
tops (butteeu), walkways/banners, snow banks have NO pips on purpose.
Never force-draw them.
4. **Missile pips are authored dead content**: lrm/srm/strk/nrk GIMs ship, but
Projectile/Missile are Entity-derived in the graph — they fail both class
tests and never listed on the machine either.
5. **Landmark labels + DropZone blips: dormant/absent** (zero Landmark
instances; DropZones carry rid 1).
## The #49 root cause + fix (2026-08-14, c2193e2)
The port dropped the engine's per-entity interest feed and replaced it with
`GaugeRenderer::RebuildEntityGrid` — which iterated DYNAMIC masters/replicants
only. The 1008 statically-registered UnscalableTerrain instances (every wall,
butte, hill, ridge, big building) never entered the static grid; DrawStatic
(fully transcribed and working) had nothing to draw. Dynamic-registering
CulturalIcon props (e.g. grass's 313 trees) were the only statics that ever
showed. Fix: a third RebuildEntityGrid pass files non-dynamic Terrain-graph
entities from `HostManager::AllEntityIterator`; pipless ones no-op at the pip
lookup exactly as on the machine. Receipts: `[map-grid] worldStatics=` census +
capped per-static `[map] static ent/cls/rid/pip/dsq` dump (BT_MAP_LOG).
Benched grass (hill cls=42 rid=2190 pip=1 drawing + trees) and arena1
(126 world statics, aw walls rid 1918/1915 drawing, unpipped props skipped);
operator-verified visually on arena1.
## Known port deviations (deliberate, inventoried)
- Three visible-radius culls (DrawStatic/DrawMoving/DrawNames) drop contacts
between scope radius and capability radius instead of the binary's
draw-and-clip — justified by the shared gauge surface (out-of-port draws
land on neighbors). Revisit only with a real GraphicsView clip.
- Cross-blip fallback for pipless movers (dev content insurance; dead in the
field — every shipped mech has a pip).
- Dead-mover (state 2/9) radar drop: the wreck-blip removal. The binary's
uninteresting-notification presumably did the same [T4 — unverified whether
a pod wreck kept its blip].
- Per-frame O(all-entities) rebuild vs the authentic event-driven feed —
acceptable at shipped populations; restoring the notify feed retires it.
## Stale notes corrected by this audit
- `mech.cpp` "SetTargetRange is stubbed" — FALSE since the zoom work
(btstubs.cpp body + the mapper slew); comment swept 2026-08-14.
- `btl4rdr.cpp` header "Make has no exported caller" — stale; @004c1b4c IS in
the 2026-08-06 re-export.
- `docs/GAUGE_COMPOSITE.md` row 24 "cross-blip stand-in" — stale; pips are the
live path since dd27238.
## Open follow-ups
- ERA QUESTION (for the group): what did the ARENA EDGE look like on the pod's
scope — just the wall outlines, or anything more? (Guards against inventing
a boundary ring; the code says wall outlines only.)
- #105/#121: RadarPercent is pinned 1.0 until sensor damage lands — the
capability-shrink lane is authored and waiting.
- The 45°-wedge vs the manual's "60° field of vision" — flag to testers
comparing against memory; the 4.10 code hardcodes π/8·2.
- Overlay-plane compositing into the dev sec cell (SECTOR/SCALE readouts) —
existing polish item, unchanged.