ship: index-less brg/eng/sld parts never matched their GN frame — 34 ships assembled without a bridge
Tier 3 matched a part to its hardpoint by trailing index, so `e105_brg` compared "01" == "" against GN_Bridge_01 and fell through silently. The runtime capture is what exposed it: the game draws the bridge and places it at [0, 70, -1850] rel e105_bdy_01, and assemble_ship emitted nothing there. With no index to match on, take the lowest-numbered frame of the category. Diffing assemble_ship part counts across every container: 34 (stage, ship) entries gain parts — e102 +2 (bridge and engine), e104 +1, e105 +1, Stages 02-29. ship_audit is unchanged, so nothing regressed, and the capture now agrees to dT 0.03 / dR 0.000. Also fixes the diff itself: correlate_frames compared static against a rotation sampled from the first block, which can belong to another INSTANCE of the class. Scoped to the position-agreeing cluster, e105_eng_01 goes 1.711 -> 0.000 and both e106 nacelles to 0.000. The one remaining rotation delta (e106_wep_02_01, 0.134) is a turret whose rotation varies by 0.182 between blocks that agree on its position — the runtime disagrees with itself more than with the assembler. The new rotVar column makes that distinction visible. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,9 +15,12 @@ and to 0.000 in rotation for every part that does not move; see
|
||||
[`ship-placement-capture-generalisation.md`](ship-placement-capture-generalisation.md)
|
||||
§4. So look at **the viewer**: first that it passes `include_external = true`
|
||||
(`iso_loader.rs:4012` — with `false` an e106 loses its bridge and both nacelles,
|
||||
5 parts instead of 11), then its own transform stack. Two narrow format-side leftovers
|
||||
remain: `e105_brg` is never produced by `assemble_ship`, and `e105_eng_01`'s rotation
|
||||
differs by 1.711.
|
||||
5 parts instead of 11), then its own transform stack.
|
||||
|
||||
One real format-side bug was found on the way and is **fixed**: index-less parts
|
||||
(`e105_brg`) never matched their `GN_Bridge_01` hardpoint, so 34 (stage, ship) entries
|
||||
— `e102`, `e104`, `e105` across Stages 02–29 — assembled without a bridge. The other
|
||||
apparent exception (`e105_eng_01` rotation) was an aggregation artefact and is 0.000.
|
||||
|
||||
The original report and its reasoning follow.
|
||||
|
||||
|
||||
@@ -192,16 +192,32 @@ for, and it is the opposite of the assumption in it: `assemble_ship` is right, s
|
||||
viewer's "capital ships assemble wrong" is the viewer's own transform stack (the
|
||||
backlog's own "worth ruling out first, cheaply").
|
||||
|
||||
Two real exceptions, both narrow:
|
||||
Both first-pass exceptions were chased down, and neither survives as an open question:
|
||||
|
||||
- **`e105_brg` is never produced by `assemble_ship`**, at either `include_external`
|
||||
setting, although the runtime draws it and places it at `[0.0, 70.0, -1850.0]`
|
||||
relative to `e105_bdy_01` (4/4 blocks, spread ≤0.13). ❔ A genuine missing part.
|
||||
- **Rotation differs only on parts that move**: `e106_wep_02_01` (turret, dR 0.093),
|
||||
`e106_eng_01`/`eng_02` (dR ~0.097) and `e105_eng_01` (dR **1.711**). A turret aiming
|
||||
and a nacelle gimballing at capture time is expected and is not an assembly error;
|
||||
1.711 on `e105_eng_01` is too large for that and is ❔ **unexplained — NEEDS-HUMAN**
|
||||
(either a static rotation bug on that one part, or the part is articulated).
|
||||
- ✅ **`e105_brg` was genuinely missing — a real assembler bug, now fixed.** Tier 3
|
||||
matched a part to its `GN_*` hardpoint by trailing index, so an index-less part
|
||||
(`e105_brg`) compared `"01" == ""` against `GN_Bridge_01` and fell through silently.
|
||||
With no index to match on, take the lowest-numbered frame of the category. The
|
||||
runtime is the check: `e105_brg` now assembles at `[0.0, 70.0, -1850.0]` relative to
|
||||
`e105_bdy_01`, **dT 0.03, dR 0.000** against the capture.
|
||||
Reach measured by diffing `assemble_ship` part counts over all containers before and
|
||||
after: **34 (stage, ship) entries gain parts** — `e102` +2 (bridge *and* engine),
|
||||
`e104` +1, `e105` +1, across Stages 02–29. Every one of those ships was assembling
|
||||
without its bridge. `ship_audit` is unchanged (still exactly the `f002_bdy_05`
|
||||
outlier), so nothing regressed.
|
||||
- ✅ **The rotation deltas were an artefact of my own aggregation, plus one real
|
||||
articulation.** The static diff was comparing against a rotation taken from the
|
||||
first sampled block, which can belong to *another instance* of the class; scoping it
|
||||
to the position-agreeing cluster drops `e105_eng_01` from dR 1.711 to **0.000** and
|
||||
both `e106` nacelles to **0.000**. What remains is `e106_wep_02_01` at dR 0.134 — and
|
||||
that part's rotation varies by **0.182 between blocks that agree on its position**,
|
||||
i.e. the runtime disagrees with itself more than it disagrees with the assembler.
|
||||
It is a turret aiming, not an assembly error. `correlate_frames` now prints that
|
||||
`rotVar` column precisely so "the part moved" cannot be mistaken for "the rotation
|
||||
is wrong".
|
||||
|
||||
Final numbers, three classes, 21 parts: **worst dT 0.43, worst dR 0.000** for every
|
||||
part that is not articulating.
|
||||
|
||||
`include_external` matters and is a caller-side trap: with `false` an `e106` assembles
|
||||
as **5** parts and with `true` as **11** — the engine cluster, the bridge and the
|
||||
@@ -223,7 +239,9 @@ bridge — which looks exactly like "assembles wrong".
|
||||
frames. The `e106`-derived rules generalise; the MULTIKEY hypothesis in §1 is *not*
|
||||
needed to explain anything observed so far (`f105` has 2 multikey tracks and still
|
||||
matches exactly).
|
||||
- ❌ Still open, both narrow and both evidenced: `e105_brg` is missing from
|
||||
`assemble_ship`, and `e105_eng_01`'s rotation differs by 1.711 — NEEDS-HUMAN.
|
||||
- ▶ Next: chase those two, and point the viewer investigation at the viewer
|
||||
(`include_external`, node-instance recursion), not at the format layer.
|
||||
- ✅ One real assembler bug found and fixed by this route: index-less `brg`/`eng`/`sld`
|
||||
parts never matched their `GN_*` frame, so **34 (stage, ship) entries** assembled
|
||||
without a bridge (and `e102` also without its engine). Verified against the capture.
|
||||
- ▶ Next: the viewer itself (`include_external`, node-instance recursion) — the format
|
||||
layer is now measured, not assumed. A per-ship regression table over the checked-in
|
||||
captures would keep it that way.
|
||||
|
||||
Reference in New Issue
Block a user