Skip to content

resourcePatches carries a systematic ~0.61 offset at every point, and exact-match scoring cannot see it #261

Description

@wormeyman

The measurement

test/resourcePatches.spec.ts grades makeResourcePatches against
oracle-resource-starting.seed123456.json - 4 cases x 3745 positions. After
#260 snapped the sample coordinates onto the game's 1/256 grid, the worst
absolute error dropped from 4.899 / 4.340 / 5.270 / 4.673 to
0.641 / 0.388 / 0.626 / 0.376.

What is left is not noise. It is a systematic ~0.61 absolute offset present at
essentially every point
, including positions that were always on the grid:

position on the 1/256 grid? |error|
idx 0, (-239.5, -239.75) yes 0.6139
idx 1860, (0.5, 0.25) yes 0.6141
idx 3721, (1500.5, 0.25) yes 0.6164

Field values there are near -12,300, so this is ~5e-5 relative.

Exact-match scoring is blind to it: 0 of 14,980 values satisfy
Math.fround(got) === expected, before or after the snap. So the programme in
#256 will not surface this one, and the combined-tolerance gate cannot either -
a point fails only if it busts ABS_TOL and REL_TOL together, and 5e-5
relative is 200x inside the 1e-2 gate.

Why it looks like one term rather than accumulated rounding

Flat ~0.61 across three positions spanning (0.5, 0.25) to (1500.5, 0.25),
on field magnitudes that do not change much, is the signature of a single
additive term being slightly wrong - not of error accumulating with distance or
frequency. Accumulated f32 rounding on a field of ~12,300 would vary with
magnitude and position; this does not appear to.

That is a hypothesis from three points, not a finding. Nobody has decomposed
it
, and this issue exists so the number is on the record rather than living
only in a spec comment - which is exactly how the "f32 coordinate floor"
attributions #260 refuted survived for a year.

Where to start

makeResourcePatches is max(starting, regular). The decomposition that
settled the last residual in this family (see
docs/noise/random-penalty-NOTES.md, the "~1e-3 residual" section) was to split
each field value into spotField + blobTerm and find points sitting exactly on
the basement constant - error there is entirely in the blob term. The same
split should work here. Candidate terms, in rough order of suspicion:

  • the blob amplitude path (regularSpotHeightTypicalAt / startingBlobAmplitude
    in resourceMath.ts), which is where the fastapprox cbrt lives and which
    multiplies a large scalar;
  • the basement constant itself;
  • randomPenalty's contribution - note Snap oracle capture coords to the 1/256 grid the game actually sampled #260 fixed a missing f32 narrowing on its
    return, worth up to 1.19e-7 relative on the product, which is far too small to
    be this but confirms that path had an unmeasured gap.

Do not

ABS_TOL is now 0.7, set just above the measured 0.641. Do not raise it to
make room for a change; a regression here should go red. And do not read the
tolerance passing as evidence the port is right - it was passing at 1.0 with an
error of 5.270 for as long as the fixture has existed.

Found while snapping the capture coordinates for #260.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingnoise-reReverse-engineering Factorio's noise math against the game

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions