Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bw71WVsccjwW7uKRg4aWD
111 lines
6.4 KiB
Markdown
111 lines
6.4 KiB
Markdown
# 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.
|