Skip to content

docs(fulgora): design spec for Voronoi primitive + elevation preview (#27) - #157

Merged
wormeyman merged 2 commits into
mainfrom
docs/fulgora-elevation-design
Aug 5, 2026
Merged

docs(fulgora): design spec for Voronoi primitive + elevation preview (#27)#157
wormeyman merged 2 commits into
mainfrom
docs/fulgora-elevation-design

Conversation

@wormeyman

Copy link
Copy Markdown
Owner

Design record for the first half of #27. Docs only - no code, no behaviour change.

Why #27 is split

#27 asks for Fulgora and a large-island finder. They share nothing: one is noise
reverse-engineering, the other is connected-component analysis over an elevation
field. The finder needs no new primitives and would already run against the Nauvis
island map type. Fulgora goes first; the finder gets its own spec and inherits the
field this one produces.

V1 scope

The VoronoiNoise primitive, the fulgora_elevation chain, the four oil-ocean
tiles against flat land, and Fulgora in the planet dispatch. Road/ruin tiles,
fulgoran-dust, scrap and cliffs are deferred - staged like Vulcanus V1 -> V2 -> V3.

Research before RE, and it paid

  • The 2.1.12 API docs already specify all four voronoi ops semantically, not
    just their signatures, plus the distance enum and jitter meaning.
  • Two doc errata are settled on the forums: the return is a normalised distance
    (tile_distance = grid_size * distance), and minkowski3 takes abs().
  • changelog.txt line 849 puts a behavioural fix in 2.1.7: the voronoi ops used
    to search only a 3x3 cell neighbourhood and missed the nearest point at high
    jitter (forums.factorio.com/130905). Fulgora runs jitter 0.6 / 0.8 / 1.0, so a
    textbook Voronoi would render a plausible-but-wrong Fulgora - this repo's
    recurring failure mode.

That leaves five narrow unknowns rather than a whole primitive.

Attack: oracle-first

sampleExpression() takes an arbitrary expression string, so it can probe a bare
voronoi_cell_id{...} directly. Four independently-falsifiable rungs: jitter = 0
collapses the RNG to closed-form geometry; cell_id exposes the per-cell draw as a
float; spot_noise minima invert back to point positions; constructed 3x3-vs-5x5
probes measure the 2.1.7 fix instead of trusting the changelog. Disasm is a
per-rung backstop, not the plan.

The land/ocean binary is exact

Dropping land tiles from an argmax cost Vulcanus ~3%, so this one carries an
argument: water_base returns -inf above the threshold, and below it the ocean
tiles outscale land tiles by ~1e4. The boundary is exact even with land absent.
The argument is then checked against the game's own get_tile rather than trusted.

Traced, not assumed

44 reachable expression nodes (+ dunes, scrap_medium, water_base). Four nodes
that look central are unreachable and deferred; two that look like M2 material
(fulgora_rock, fulgora_basis_oil) are reachable via sprawl_pyramids and are
in V1 - they are defined in a later data:extend block than their consumer,
exactly what a port-by-reading-order would miss.

Spec: docs/superpowers/specs/2026-08-04-fulgora-elevation-preview-design.md

🤖 Generated with Claude Code

https://claude.ai/code/session_01QZvNS2H4cbaZk46ybA7hbj

…27)

Splits #27 into two projects. Fulgora goes first; the island finder gets
its own spec and inherits the elevation field this one produces.

V1 scope: the VoronoiNoise primitive, the fulgora_elevation chain, the
four oil-ocean tiles against flat land, and Fulgora in the planet
dispatch. Road/ruin tiles, scrap and cliffs are deferred.

Research first, per Eric, and it paid: the 2.1.12 API docs already
specify all four voronoi ops semantically, two doc errata are settled on
the forums, and changelog.txt line 849 puts a behavioural fix in 2.1.7 -
the voronoi ops used to search only a 3x3 cell neighbourhood and missed
the nearest point at high jitter. Fulgora runs jitter 0.6/0.8/1.0, so a
textbook Voronoi would render a plausible-but-wrong Fulgora. That
leaves five narrow unknowns instead of a whole primitive.

Attack is oracle-first: sampleExpression() takes an arbitrary
expression, so jitter=0 collapses the RNG to closed-form geometry,
cell_id exposes the per-cell draw directly, and spot_noise minima invert
back to point positions. Disasm is a per-rung backstop, not the plan.

The land/ocean binary is exact despite dropping land tiles from the
argmax - water_base returns -inf above the threshold and outscales land
tiles ~1e4 below it - and that argument is checked against the game's
own get_tile rather than trusted.
@wormeyman
wormeyman merged commit 6246c4e into main Aug 5, 2026
6 checks passed
@wormeyman
wormeyman deleted the docs/fulgora-elevation-design branch August 5, 2026 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant