Everything on Nauvis (morganc fork)

by morganc

Moves all resources to Nauvis. Removes other planets.

Content
6 days ago
2.0
529
Factorio: Space Age Icon Space Age Mod

Changelog

Version: 0.1.17
Date: 2026-09-XX
  Changes:
Version: 0.1.16
Date: 2026-10-13
  Changes:
    - eon-nauvis2-clone: the dummy primary surface (nauvis) is now shrunk to
      a 32x32-tile single-chunk stub at runtime, the same trick biter-battles applies to its
      default surface (map_gen_settings width/height = 32 + delete every
      chunk), so the swap-staging surface costs nothing to exist, generate or
      reset. The data stage cannot do this -- the engine clamps a planet's
      map_gen_settings size up to the 2,000,000 maximum (probe-verified), so
      the shrink lives in control.lua (on_init, on_configuration_changed for
      old saves, on_surface_cleared for in-place resets) and is saved with
      the game. Only when eon-nauvis2-clone is on; without it nauvis IS the
      map.
    - eon-nauvis2-clone: a player who died on a space platform respawned on
      the dummy primary surface (the engine respawns platform deaths on the
      force's default spawn surface, which with the clone live is the 32x32
      staging stub) instead of the round. on_player_changed_surface now
      catches the ghost before it respawns and teleports it to the clone's
      round surface at the force spawn there -- the same event/condition pair
      any-planet-start applies to its multi-planet starts. Only when
      eon-nauvis2-clone is on; without it the primary IS the map.
    - New pistol-start enemy tier: tiny pentapods (tiny-wriggler 15 HP / 1.5+1.5
      dmg, tiny-strafer 75 HP / 25.2 explosion, tiny-stomper 150 HP / 7 stomp,
      2.7-tile radius), built from space-age's make_wriggler/make_strafer/
      make_stomper factories reusing small-pentapod graphics and icons. They
      own the 0.0-0.4 evolution band on both gleba-spawner and
      gleba-spawner-small (small pushed to 0.2, medium to 0.3 so tier onset stays
      in-order tiny→small→medium→big; tiny appended after big so the
      big tier keeps indices [7,8,9] and coexists with behemoth-enemies
      regardless of load order), with gleba-spawner-small capped at 3 owned
      units so near-spawn wriggler nests can swarm at pistol start. Spores
      -> pollution absorptions auto-apply via pollution.lua. Gated by the
      `eon-tiny-pentapods` startup setting (default on); disabling removes the tiny
      tier and reverts the small/medium spawn windows to vanilla. Adds locale keys for
      all tiny pentapod entities (wriggler/strafer/stomper, premature, corpses, shell)
      so they display proper names in Factoriopedia instead of raw prototype ids. Band
      names use the canonical wriggler-pentapod spelling (matching space-age's
      make_wriggler prefix) so set_spawn_band lookups resolve correctly.
Version: 0.1.15
Date: 2026-10-07
  Changes:
    - eon-nauvis2-clone: the rocket silo refused to launch on the clone
      ("nauvis2 is not unlocked") -- the engine only starts the vanilla
      "nauvis" unlocked per force, and there is no planet prototype flag for
      it -- every space-platform stop read "inaccessible from current
      position" because the space-connections still started at the dummy
      nauvis while platforms orbit the clone, and the dummy nauvis itself
      showed up as a droppable planet while the restored space-locations
      stayed locked forever (their discovery technologies are hidden). The
      solar system unlock state is now fixed for every force at game start /
      save upgrade / force creation, and again after any force.reset() (which
      wipes script-set unlock state, probe-verified; handled via
      on_force_reset so scenario resets need no cooperation): nauvis2 and the
      restored vulcanus/gleba/fulgora/aquilo + solar-system-edge are
      unlocked, the dummy nauvis is locked (control.lua), and every
      space-connection that touched nauvis is rewired onto nauvis2 (data
      stage, both eon-restore-space-locations modes).
Version: 0.1.14
Date: 2026-09-XX
  Changes:
    - eon-nauvis2-clone (off): the dummy original nauvis planet is now stripped
      to a vanilla default map (its map_gen_settings are nilled AFTER the clone
      deepcopy takes the merged map). The primary surface only exists as a swap
      staging area, so generating the full merged program there is wasted cost;
      world creation safely falls back to the engine default map when the
      settings are absent (probe-verified 2.0.77: --create succeeds, surface 1
      tile = grass-1, planet still associated). The live cloned surface is
      unaffected -- the deepcopy already carried the merged settings.
    - New startup setting eon-restore-space-locations (on by default): instead of
      deleting Vulcanus, Fulgora, Gleba and Aquilo, they come back as unlandable
      SPACE LOCATIONS -- the same prototype as the solar system edge and the
      shattered planet. The vanilla trip graph is restored (nauvis ->
      vulcanus/gleba/fulgora -> aquilo -> solar-system-edge, with every planet's
      asteroid field), so the first voyage is the normal easy kind instead of the
      old straight nauvis->edge slog (edge-grade asteroids from day one), while no
      surface exists anywhere but Nauvis so landing is impossible everywhere else
      and play stays on Nauvis. The planet prototypes are deleted in the on state
      (less data loaded; nothing but the discovery/removal machinery referenced
      them); the off state keeps the old behavior (only Nauvis, solo trip to the
      edge, aquilo-solar-system-edge.from = nauvis). Interacts with
      eon-nauvis2-clone: the clone's edge rewire is skipped while the setting is
      on, so the restored progression wins.
    - Territory state is stored PER SURFACE (storage keyed by surface.name), not in one
      shared marker table: a reset that replaces the map (clear in place, or a fresh
      surface run alongside the old one) now gets clean state per surface, and an old
      surface that survives a round keeps its own. A surface is "the map" when ITS OWN
      map_gen_settings carry the merged map (the vulcanus_volcanism autoplace control),
      planet or no planet -- so a second surface created to pre-generate the next map
      in the background is claimed during pre-generation, and a pre-generated chunk
      never re-fires on_chunk_generated, so that is the only timing that works. Note:
      the PRIMARY surface (index 1, nauvis) is never deletable (LuaSurface.deletable is
      false, hardcoded in the engine, probe-verified), so the planet can never lose its
      surface and associate_surface can never move it to a runtime surface; the
      deleted-surface path exists for created surfaces only. State
      is cleared per surface on on_surface_cleared and on_pre_surface_deleted (the old
      global wipe is gone). Old saves' single marker table is hoisted under the
      surface name on first use, so claims survive an upgrade.
    - New startup setting eon-nauvis2-clone (off by default): adds a second planet,
      nauvis2, an exact deep-copied clone of the merged Nauvis, for scenario
      map-swaps. The primary surface can never be deleted (see above), so the only
      legal swap is to run the game on the clone: LuaPlanet::create_surface
      materialises its surface (which IS deletable), the mod claims it through the
      same settings-based identity (is_merged_map), and the scenario can delete and
      re-create it freely. The clone is deep-copied in data-final-fixes AFTER the
      whole map merge, so it carries identical map_gen_settings; the
      aquilo-solar-system-edge space connection is rewired to point at it, the
      original nauvis planet is hidden (it is the dummy), and every
      default_import_location is swept onto the clone (remove-planets.lua had
      pointed them at nauvis). Off by default: vanilla freeplay games keep a single
      Nauvis.
    - Fix: quantum-processor could not be crafted on Nauvis. Its surface condition is
      a max only (pressure <= 600, Aquilo's value; Nauvis is 1000), and the rewrite
      only relaxed conditions that carry a positive minimum, so the ceiling survived
      and Nauvis failed it. Max-only conditions are now dropped too; the
      min = 0 / max = 0 platform-exclusive shape (crusher, thruster, space-science-pack,
      ...) is untouched, so space platform restrictions stay exactly as they were.
    - A BIG VOLCANO CARRIES TWO GUARDS. The claim is cut in two with one straight cut
      through the cone's own centre -- a wedge of some fraction of the disc and the
      rest of it -- and each piece becomes its own territory with its own patrol loop
      and its own demolisher, so a big volcano is walked by a big guard and a medium
      one at the same time. Why a cut through the centre: each piece then contains the
      apex, so both guards stand on the middle of the volcano rather than one of them
      patrolling a rim fragment. Why ONE cut and not two: three pieces of a circle are
      ~120 degree sectors, whose largest inscribed circle is 0.16 of the disc against
      0.41 for a quadrant -- the angles get too sharp to carry a guard's body.
    - The cut is clamped to a 90-180 degree wedge (a quarter to a half of the disc);
      the other side is the remainder, since two pieces of a disc cut through its centre
      cannot both be halves without a third piece between them. What the clamp costs is
      the size mix: medium+big becomes a narrow band of the largest cones rather than
      the common case, and sliver slices (which used to carry a guard that walked a pin)
      are gone.
    - The two guards are ONE SIZE STEP apart (small+medium, medium+big, and
      big+behemoth with a modded fourth rung), never small+big. The sizes are not
      chosen here: a slice with a fraction f of the area has a size fraction of
      sqrt(f) times the cone's, and the cut is the one that lands the two sides on
      adjacent rungs of the existing ladder (volcano-demolisher.lua), taken from the
      middle of the range of cuts that qualify rather than off one edge of it. A cone
      that no cut can do is left WHOLE, and says so in the log with the reason --
      usually that it already carries the smallest guard, or that it is too small to
      cut. On the vanilla ladder that leaves mostly small+medium and medium+big only
      on the very largest cones: a cone sitting just above a tier boundary is already
      one rung from the one below, so halving it drops it two.
    - The two guards of one volcano no longer meet in the middle of it. Wedges closed at
      the apex put both patrol loops through the same point, so the two guards converged
      on the centre and walked each other's ground (measured: 0 tiles between the two
      loops). Each loop now closes on an INNER ARC -- the volcano's own ground curve
      scaled in, so it runs around the lava roughly where the lava is -- and the two of
      them are two rings around the same middle. The claim is not cut back: a caldera of
      unclaimed ground there was tried and dropped, because it is a hole in a volcano
      and it made the claim something other than the mirror's chunk list.
    - The inner arc does not hug the claim's edge, and it does not jitter. It used to
      follow the claim's own inner edge, which is chunk-quantised, so it stepped 32 tiles
      between neighbouring directions and the guard turned through a corner at every step;
      the playtest saw both ("hugging it too closely", "jitter in the inner path"). It is
      now a smooth curve at a fixed fraction of the volcano's ground radius, and its span
      is narrower than the outer arc's so it keeps clear of the cut lines, because
      membership is decided by the chunk centre. The sharpest corner anywhere over three
      seeds and three frequencies, and not one point of either loop stands on the other
      slice's ground.
    - The two joins where a loop's legs meet its arcs are RIGHT ANGLES again, and
      nothing is corner-cut. Both arcs share one span, so a leg is radial and a circle's
      tangent is perpendicular to its radius; the guard rounds it itself, because its
      patrolling turning radius is a whole radian per tile and the arcs stop well short
      of the cuts, leaving it open ground to do that in. Giving the inner arc its own
      narrower span -- which is what this did first -- made the leg run back across the
      arc, and the join came out at 134-177 degrees: a hairpin no body can follow.
      Corner cutting is worse than the corner it smooths, since a fillet is a list of
      short edges each demanding a turn the body cannot make.
    - The inner arc now follows the LAVA, which took finding where the lava is: the
      expressions resolve to a lava pool at 0.060 of a cone's width with a lava-hot ring
      out to 0.083 and nothing beyond 0.106, so the whole lava complex is inside a tenth
      of the width -- and the arc was walking at 0.158, outside all of it. It is now at
      0.115, just past the lava, and because the lava comes from the same spot field the
      outer arc does, it follows the pool's rough outline for free. The wedge shrank with
      it (a chunk's clearance from the cut is a fixed number of tiles, and the rim is now
      near the middle), and every point of a loop must have a quarter-chunk of claim under
      it in all four directions or the cut is refused: a point inside the claim is not
      enough when the guard is a tile wide and the line between two of its points is not
      the claim.
    - The two guards of one volcano are kept a CHUNK apart, and it is measured rather
      than hoped for: the arcs end a chunk clear of the cut lines, and the plan re-checks
      the closest approach between the two finished loops and refuses the cut if it is
      under a chunk. The one way it failed was a patrol point the walk moved, which is
      how 19-tile passes were found. A cone whose rim cannot spare a chunk is left
      whole: there is no room for two loops on it.
    - FIX: both of a slice's legs joined the SAME end of its outer arc, so the guard
      U-turned there and backtracked over ground it had already walked. One stray line
      was appending the outer arc's radius to the inner arc's point list as well, which
      made the outline the outer arc out, the inner arc in, and the outer arc again.
      Every other measurement was happy with it -- every point on claimed ground, the
      loop long enough for the guard, the sharpest corner 9.9 degrees -- so the check is
      a new one: the bearing from the volcano's centre around the loop turns one way all
      the way round except once at each of the two legs, and a backtrack shows up as
      four. It had been costing cuts as well: a doubled outer arc has chords that span
      twice as much ground, so they crossed a neighbour's dent and came back off the
      claim (measured: 11-27 volcanoes cut per map before, 22-33 after, and the two
      loops went from touching to 12-64 tiles apart).
    - A slice is only claimed when BOTH guards fit, and each patrol path is a
      PIE-SLICE OUTLINE of its piece: the arc the whole volcano would have walked
      (the same radius curve, restricted to the wedge's directions), two legs running in
      along the cuts, and their tip. A half-disc slice is a half circle with a diameter.
      The corners where a leg meets the arc are right angles -- which a demolisher's body
      cannot walk -- so they are rounded; the sharpest corner anywhere is 10 degrees. A
      side that cannot carry even the smallest demolisher, or that comes back from the
      ladder stepped down from what its own area asked for, means no cut at all. A cut volcano is also decided slice by
      slice, each by a chunk of its OWN, because every list handed to
      create_territory needs a generated chunk and the chunk that woke the mod
      satisfies one of them at most; the other waits for the next chunk event that
      carries one of its own. The cut is a pure function of the map (the bearing is a
      hash of the cone's own id), so both pieces are identical on every load in either
      generation order, and the pieces are DISJOINT because the cut test is TOTAL --
      every chunk takes a side, with no third outcome. That is proved, not assumed:
      create_territory settles an overlap silently by taking the chunk from whoever
      held it, so an overlap would make the two pieces depend on which was built first
      with nothing in the log. The apex chunk, the one the two cut lines meet in, goes
      to one side like any other (both loops stay 23+ tiles from it); excluding it
      instead would put an unclaimed hole in the middle of every cut volcano.
Version: 0.1.13
Date: 2026-09-XX
  Changes:
    - Volcano (demolisher) territories are built at RUNTIME from a spot mirror, not
      from a noise-expression index -- and the index is gone, so there is no setting
      to choose. Why: spot_noise returns a cone HEIGHT and never says which of its
      selected spots produced it (features/upstream-spot-noise-owner-id.feature), so an
      expression could only claim chunks by cell id plus a field threshold and could
      not name a volcano. The mirror recovers the identity: a cone's centre is the
      first dart-throw-accepted candidate of its region's taus88 stream -- integer
      RNG, exact -- and its width is the engine's own effective radius. noise-mirror/
      never touches Factorio and is tested without it.
    - A chunk's owner is the NEAREST CENTRE among the cones whose ground covers it,
      measured at the displaced point because that is where the engine reads the
      field. It is recomputed every time from two or three cones; nothing is
      materialised to answer it and nothing is kept. Overlapping cones therefore yield
      DISJOINT chunk sets, decided up front, so whichever territory is created second
      cannot take ground from the first and generation order cannot change the answer.
      The engine's own MAX-of-cones field rule is not used for a claim: it lets a small
      cone beside a big one win a bite out of the middle of the big one's disc
      (measured on a 3-series: the big cone came out a 31%-wide crescent and the
      middle cone got no territory at all).
    - CONEXISTENCE is computed, not asked of the tiles. The engine's own spot density
      (volcano_area / volcanism^2 * spawn gate) is ported into noise-mirror/density.lua,
      so a cone exists or does not as a pure function of position. Chunks are
      generated one at a time, so no per-chunk or per-tile test can see a whole
      volcano: every tile-based gate was a function of what the player had revealed,
      which is what made claims appear late, vanish when more ground arrived, and
      need an audit to take them back. Verified against the shipped expression at the
      candidate centres the gate asks at (100% sign agreement, 3.8e-4 worst relative)
      and against the engine's own spot selection through the Rust oracle (240/240
      region decisions agree).
    - A cone is decided when a chunk of ITS OWN is generated. The chunk that woke the
      mod is generated by definition, so create_territory's "at least one generated
      chunk" precondition is met by construction, and the shipped path asks the
      engine about the map NOWHERE -- no is_chunk_generated, no get_tile. That
      replaced a walk of every waiting cone's whole share calling the engine: 0.48 us
      a call, 241,840 calls over a 1681-chunk reveal at 100% volcanism and 611,762 at
      600%. The old rule could also decide a cone on a chunk belonging to a neighbour;
      that cannot happen now.
    - Each volcano is ONE create_territory call carrying the cone's whole share,
      including chunks that do not exist yet (create_territory holds them and they
      join on arrival). Membership is geometric -- the cone's core disc, 0.42 of its
      width, tested at each chunk's CENTRE -- so a claim never depends on what the
      player has walked past. Sampling the engine's top-left corner instead leaves the
      claimed area about half a chunk down-right of the volcano; the 16px-shifted
      "_at16" expressions existed only to cancel that bias and are gone with it.
    - The PATROL PATH is ours, from the cone's geometry: 0.78 of the core radius,
      DENTED where a neighbouring cone takes the ground away, so an untouched volcano
      gets a plain circle and a squashed one gives ground up only where it must. Its
      points are sized to the ground available -- about one every 6 tiles, 8 to 32 --
      and every point must land in the cone's own chunks or there is no claim at all,
      because a territory with no units does not appear on the player's map. The
      radius on each direction is the first-order inverse of the engine's
      displacement rather than a search for it: one noise evaluation per direction,
      where the previous root find marched 76 samples per direction for the last
      crossing (2,432 noise evaluations and 16 ms per volcano).
    - Demolishers are placed explicitly, in the same pass that creates the
      territory: one per volcano, sized by the cone's rendered width, and created
      WHOLE with body_nodes laid along its own patrol path at one-tile spacing, up to
      the prototype's segment_engine.max_body_nodes (106 big / 81 medium / 55 small --
      the API docs say 63 for all three and are stale). Previously the engine spawned
      the head only and grew the body as it crawled.
    - body_nodes are laid one node per TILE crossed, bounded at the prototype's node
      budget -- a node past the budget is dropped by the engine, which is the cropped
      tail seen from the other end. Spacing by path SEGMENT instead of by tile puts a
      demolisher's body in a spiral around its own route rather than along it, so the
      walk counts distance crossed, not nodes emitted. Measured live: 106/106 nodes at
      1.00-tile spacing on a 475-wide volcano, 42/42 segments placed at spawn, and
      unchanged after the unit walks 60 tiles.
    - FIX: two volcanoes could be placed on top of each other, structurally rather
      than by a mistuned number. The spots were TWO spot_noise calls merged with
      max() -- a dense small-seed one and a sparse big-seed one -- to "merge into
      varied sizes". Each call has its own candidate placement and its own
      suggested_minimum_candidate_point_spacing, and nothing coordinates them, so a
      big and a small cone can land on the same spot, with no way to say "not where
      the other one is" across two calls. Measured on a real map (seed 1096463296,
      600% volcanism, 113 cones): the closest pair sat 64 tiles apart with radii of
      192 and 134, and 11 of 6328 pairs were closer than half their combined reach.
      It is now ONE call, with the size varying per candidate through
      eon_volcano_size_dist, which already varied and the two classes were masking.
      Two calls also cost map generation: the field ran two full candidate systems
      at every point.
    - Sizes were uniform after that, and the cause was measurable: the ramp x noise
      x gate product in eon_volcano_size_dist was capped at 1.0 and 55% of candidate
      centres landed EXACTLY on that cap. Raising the cap would not have helped --
      the engine clamps to maximum_spot_basement_radius, so overshooting cones would
      all clamp to the same size -- so the product now varies below 1 (0% at the cap,
      7 distinct buckets) with size_mult 1.3, a continuous spread bracketing the old
      two classes: 0.35 / 0.55 / 0.74 / 0.87 / 1.11. 1.3 is a measured ceiling, not
      a preference: 1.4 makes cones big enough that the patrol circle stops fitting
      inside a claim a neighbour has trimmed.
    - Map reset (surface.clear() plus a new map seed -- the Legendary Deathworld
      scenario's /reset) drops the territory state instead of inheriting it. A cone
      id is "seed<stream>@<region>:<region>" and does NOT contain the map seed, so
      the new map's cones come back under the SAME ids pointing somewhere else
      entirely, and every one of them would have been skipped as already decided.
    - The load path is empty: on_chunk_generated is the only thing that feeds the
      builder, and on_load does one thing, which is drop the cached builder -- which
      is also how a new map seed is picked up. The load-time scan of already-generated
      chunks it replaces only ever migrated saves from builds predating this path.
    - There is no audit, no priority pass, no lens refill, no once-a-minute
      re-assertion and no remotes. Each existed because the split was once computed
      against cones that had not resolved yet; existence is computed, the split is
      settled up front from geometry, and a placed cone is recognised by its marker.
      Every volcano logs one line, which is the only channel a test has and what a
      playtest is read from: "[eon] volcano <id>: centre ... width ... -> territory
      of N chunks, patrol 32 points, demolishers 1 [...]".
    - Per-chunk cost of the whole feature at 600% volcanism: 0.13 ms, from two hash
      lookups and a handful of distance tests.
    - Dead noise expressions are deleted (tests/dead_expressions.py: 910 defined, 0
      unreachable) and the noise-dedup work that found them is gone with it. The
      data stage keeps no expression the mirror makes unnecessary.
    - The gate is hermetic and separate from the live rcon loop: run_spot_mirror_tests.py
      runs the mirror's own self test against game-captured vectors, the claim path
      against a fake surface (no Factorio), a patrol-turn-radius test, the
      duplicate-function and dead-expression checks, density and field parity against
      the shipped expressions, four spot-selection parity configurations, and two
      headless end-to-end runs (100% and 600% volcanism). tools/noise-sandbox/ holds
      the analysis side: a Python evaluator for the shipped noise expressions, the
      Rust noise oracle, a complexity reporter, and the calibration scripts that set
      the constants above.
    - The requirements live in features/lua-territory.feature (AC-1..AC-15, each with
      the probe that proves it) and the working agreements in AGENTS.md: no fallbacks
      that change behaviour, no swallowed errors, nothing raised on a per-chunk path,
      one Lua dialect (5.2), and measure rather than assume.
Version: 0.1.12
Date: 2026-09-25
  Changes:
    - Demolisher territories SPLIT: medium+ volcanoes get two territories
      (west half + east half) instead of one, small volcanoes stay whole, and
      overlapping/merged volcanoes no longer collapse into a single territory.
      The cut is anchored by the volcano FIELD GRADIENT, not any world lattice:
      the territory index compares the volcano spot field at x+32 vs x-32, whose
      sign flips exactly at the deployed peak column (probe-verified: lossless
      partition of the mask, cut within ~1 column of the lava centroid, immune
      to the spot-deployment jitter that broke lattice-anchored cuts). Small
      cones (size_dist < 0.55) are exempt so tiny halves never drop under the
      territory floor (unguarded seams). Residual: the corner of a big cone
      that pokes into a neighbouring voronoi cell keeps its own small territory
      (~1-2 per map, guarded) -- the alternative is an unguarded gap.
    - Demolisher SIZE now scales with volcano size, not distance: tier by
      eon_volcano_size_dist (small < 0.55, medium 0.55-0.8, big >= 0.8), plus a
      per-territory nudge (0/1) so the two halves of a split cone are adjacent
      size classes (small+medium / medium+big, never small+big). Small-only
      cones cap at medium.
    - Probe tooling: territory grouping is now verifiable headless via
      LuaTerritory.get_chunks()/get_segmented_units() (tests/eon-probe-grouping,
      tests/probe_split_grouping.py - the dedicated territory E2E; unguarded-lava
      quota + leak guard).
    - Volcanoes are real cones now: the surface elevation property carries the
      FFF-390 cone profile (min(x, P - x)) -- tiles rise from the folds foot to
      a crest at the lava edge and drop back toward the center, so the lava
      sits in a visible caldera bowl below the rim instead of a flat disc
      wearing cliff rings. Cliff rings staircase only the climb side and
      plateau from the crest inward, so the top ring is outward-facing and no
      rings descend into the lava (probe: zero cliffs on lava tiles). Ring
      spacing stays uniform across volcano sizes: the 300-unit relief amplitude
      scales with the distance-driven size growth and big-spot-system dominance
      (bigger cone, higher peak, same slope).
    - Volcano size vs distance: ramps from 0.30 near spawn to full by 4000
      tiles, so the nearest cones are small and can never swallow spawn (old
      0.8-bottom ramp + ~424px base radius let big-system cones reach it).
      Per-volcano random size was attempted but rejected: spot_noise parameters
      must be compile-time constants, and a random term in the spot radius
      broke map-gen compilation (surfaced as "Expected a constant: spotNoise[3]"
      on unrelated early-compiled expressions like barnacles-decal).
    - Volcano frequency is a pure density control again: vanilla couples it
      into eon_volcanism as a divider (cranking frequency shrank every volcano
      -- at 600% ~129px radius vs 300), decoupled, and the density curve rescaled
      so the highest slider setting yields ~2x the volcanoes (11 vs 5 per 3.2km
      square at 100%, ~linear in frequency past the GUI max). Volcano spawn
      protection halved (candidates may form from ~425 tiles out) so volcanoes
      can sit close to spawn -- no harm in nearby volcanoes.
    - Sulfuric acid geysers: gated to the inner volcano core (eon_vulcano_coverage,
      the per-tile form of the demolisher-territory signals), with a per-volcano
      presence lottery driven by the geyser frequency slider (roughly 20% of
      volcanoes at the bottom, ~half at default, all of them by 350%). Cluster
      geometry reuses the same helper/grid as calcite (offset 0 on the shared
      span-3 sub-grid, so calcite and acid never stack -- measured zero calcite
      within 30px of a geyser); tile density is vanilla's 0.025 with a capped
      per-geyser richness (no size-slider inverse, so shrinking size no longer
      makes each remaining geyser 16x richer). Baseline acid total sits ~1.5-2x
      crude-oil at default settings.
    - Sulfur puddles and stains follow the geysers (same core + hash gate)
      instead of a feathered volcano band; the old mask_volcano_fade rendered
      them on plain ground outside the rim.
    - Scrap is fixed in the holmium-off config: vanilla scrap's probability is
      0 (it only spawned via Fulgora's per-planet overrides) and the old branch
      wrapped that dead 0, so scrap never rendered. It is now rebuilt as a real
      nauvis ore (same params holmium-ore uses) with its own resource-autoplace
      patch-set index, masked like every other ore -- off volcano ground, off
      aquilo/ammonia/gleba -- so it can't stack on calcite (volcano-anchored) or
      the base ores (measured zero scrap within 25px of iron).
    - Calcite ore grows at volcanoes (vanilla Vulcanus behavior) instead of as
      plain Nauvis scatter: spots anchor on a smoothed volcano spot field via
      vanilla's vulcanus_place_non_metal_spots, so each volcano carries roughly
      1-2 compact patches (the candidate lottery leaves some volcanoes bare and
      some with a couple more, which map-gen noise and water rims naturally
      shuffle). Patches may spill a few tiles past the volcano rim onto plain
      ground and outside demolisher territory (a breadcrumb pointing at the
      volcano), but never drift far from one; richness is flat in distance like
      vanilla and capped at tungsten's per-tile scale (2500), so calcite is
      never richer than tungsten. This replaces the dead
      vulcanus_calcite_probability override (nothing referenced it) and the
      nauvis-scatter richness that silently vetoed volcano patches.
    - Sulfuric acid puddles and geysers are gated tight to volcano terrain (no
      feather band): their vanilla region is positive over the broad pre-biome
      around a volcano, so the old mask_volcano_fade band rendered them on
      plain ground just outside the rim.
    - Volcano/gleba/aquilo boundary masks renamed *_early -> *_fade (the
      consistent suffix for the eon_fade boundary family); no behavior change.
    - Ashland and flaming ashland trees grow on volcano terrain.
    - Gleba starts with a translated starting area instead of a lone frontier: vanilla's own yumako+jellynut patch pair (same starting_spot_at_angle formula, radii and wobbles) moved to just below the transition, with vanilla's starting_aux/starting_radius gradient translated to the same spot so gleba_biome_mask_green/red split the start into a yumako side and a jellynut side instead of reading the province lottery (previously one fruit dominated and the other needed deep exploration). Both fruits ~400 tiles apart at gleba landfall; deep south stays regular vanilla Gleba with shared fruit/ore provinces.
    - Gleba's desert-province flora restored: vanilla Gleba grows ~15 shared base-prototype decoratives (desert bushes, pitas, croton, mud/lichen/shroom decals, green carpet/hairy grass) via its own property_expression_names. The merged map now evaluates those same vanilla gleba formulas in gleba territory (nauvis-side behavior untouched); the red/purple/cream nerve-roots-veins decoratives (referenced by wrong unprefixed names in the original mod so they never placed) are registered and masked like the other gleba natives. Measured vs a vanilla-gleba baseline in the same box: all species within ~1-10% in the deep south, cliffs 1.0x vanilla.
    - One transition field only, no wide variant: moisture/aux/elevation/cliffiness all morph on a clean few-hundred-tile ramp around eon_gleba_south_offset (0 north of line-100, 1 by line+400; the territory LINE keeps its wobble character). A wide/slow moisture morph and a wobble-laden blend input both silently shifted the deep-south decoration provinces (measured 3-4x swings on aux-selective species); the aux gardening at the translated start is gated by a tight anisotropic box (full only across the patch pair, zero by |x|=330 / y=1450) so it cannot tilt the deep south.
    - Gleba cliffs are vanilla-faithful again: the merged surface has to use the nauvis cliff ladder (interval 40, first band ~10), so the south arm of eon_cliff_elevation now rescales gleba elevation (2/3, offset -50/3) to emulate vanilla's ladder (interval 60, first band 40) - no more cliffs in wetland/lowland ground and the same contour spacing on dry land (measured: 2.9x vanilla cliff count down to ~1.0x with the single blend).
    - Transition flora leads the tile line: water-cane feathers across the handoff, red-pita/honeycomb/cups/coral start ahead of Gleba tiles; elevation and shoreline signals morph fast for crisp bands while moisture keeps the wide mix.
    - Nauvis-Gleba transition is a mixing band instead of a hard line: highland/midland reach north, dry Nauvis tiles die out early, forest and grass end at the shore fringe, water hands over water-to-water, fields morph across the full width.
    - Fewer chimneys and volcanic rocks spawn on volcano terrain.
    - Gleba natives react to pollution (yoinked from EverythingOnNauvis-Patches, always on since spores are dead without other planets): pentapod units/spawners join attacks on pollution instead of spores, harvest and agricultural towers emit pollution.
    - Atomic bomb ground effects for deleted planets are deleted outright (nuke-effects-aquilo/vulcanus plus their atomic-rocket triggers) instead of being gated behind explosion surface conditions, so the bomb always leaves nuclear ground.
    - Tungsten ore now grows on volcano flanks, guarded by demolishers (vanilla Vulcanus behavior): smaller, more numerous patches favored by mineable volcano ground. No fallback: volcanism cannot be disabled, so every map has volcanoes and therefore tungsten.
    - Lava and crater cliffs are masked to volcano terrain like every other volcano feature: vanilla's lava formula keys off a biome value that is meaningless on Nauvis and used to strand lava-hot lakes on dirt and Aquilo ice with no volcano around them.
    - Volcano decoratives feather past the terrain edge in two bands (outer debris wider than mid details), mirroring the staggered Gleba transition; chimneys, big rocks and lava fire stay tight.
    - Calcite stains now pair with calcite ore wherever it grows, inside or outside volcanoes, instead of only staining volcano terrain.
    - Volcanoes vary in size (small/dense and big/sparse spot systems) and grow bigger further from spawn.
    - Volcano spawn protection moved from field subtraction into candidate density: volcanoes near spawn are fewer, never cropped (no more missing lava or clipped demolisher territory).
    - Demolisher sizes fit their volcanoes: slowed progression normalized by volcano packing density (yoinked from EverythingOnNauvis-Patches, dense maps progress earlier, sparse maps later), mixed sizes across a volcano's territories, small-only volcanoes capped to medium.
    - Volcano rims feather each side's own decoratives, band-gated with depth falloff: aquilo ice, bergs and drifts on the aquilo flank; Nauvis and Gleba flora (rock entities stay home) and trees on the others; Nauvis trees also cross onto the icy shore fringe; crater-cliffs stay off Aquilo.
    - Territory masks rule the boundaries: aquilo tiles, snow variants and fish stay off the whole volcano mask (coverage + folds + soft-edged rim) and off non-Nauvis liquids — no fish in lava, ammonia ocean, or Gleba wetlands/lakes (fish yoinked from EverythingOnNauvis-Patches).
    - Aquilo keeps only crude oil, lithium brine and fluorine vents: all other ores stay off aquilo land and ammonia ocean.
    - Tungsten is leaner (richness base halved-ish) with frequency-normalized distance gradients; flaming ashland trees stay deep inside volcanoes; lava fills big-volcano centers (vanilla upper bound).
  Bugfixes:
    - Nauvis/Gleba decorative fades were leaking everywhere: the probability snapshots are
      signed, so any fade that MULTIPLIED the expression by -inf turned negative snapshots
      into +inf (spawn at max density in the very region being excluded). Every -inf
      exclusion now REPLACES via if(); only 0..1 fades multiply. Grass tufts stay on nauvis
      (feathered ~10 tiles before the gleba line, zero on volcano ground, zero on aquilo);
      gleba transition flora mirror that; all other decoratives hard-masked upstream-style.
    - Demolisher territory is bound to the volcano CORE (folds + lava rings, outer
      folds-flat skirt excluded): the mask is the same signals that place the core tiles,
      built on the 16px-shifted spot field so the engine's top-left-corner chunk sampling
      stays centered (measured +15/+16px SE bias un-shifted, ~0 after), plus a thin inner
      edge of the flat skirt (spots > 0.6, tile-truth). The skirt becomes a buffer ring:
      rim/water fringe chunks no longer grab territory, and demolisher patrol anchors stay
      inside volcano ground (measured: every lava-bearing chunk is covered; the canyon of
      screening off-territory chunks is zero). The index expression is sampled at one fixed
      world-aligned corner per 32x32 chunk (claimed iff >= 0), and minimum_territory_size
      = 3 drops the last 1x1/2x1 voronoi cells that stranded a medium demolisher on a single
      patrol point (tail-chasing); territory voronoi cells (radius 512) are larger than the
      typical volcano, so interior chunks share one cell and one patrolable territory.
    - Tungsten hugs the lava heart of the volcano: the favor band is the flank ring at
      spots > 0.65 (outside the lava core, which blocks placement itself), candidate
      frequency boosted x3 to repay the inward clip, and the render gate is the territory
      core mask so virtually no ore renders outside demolisher territory (0.3% measured,
      all in northwest-rim chunks one sample off a chunk corner; nil at any reported gps).
      Roughly one in five small volcanoes has no ore (accepted: presence on the rest
      beats rim drift).
    - Nauvis ores (iron, copper, stone, coal, uranium, crude oil, holmium/scrap) no longer spawn inside volcano areas.
    - Dead grey trunks no longer spawn outside Nauvis territory (no more dead trees on volcanoes).
    - Volcanoes get elevation-driven cliff terraces up their flanks; rings generate as nauvis cliffs and control.lua re-skins volcano-terrain ones as cliff-vulcanus, keeping orientation. Only newly generated chunks convert.
    - Gleba lakes restored: wetland-blue-slime and gleba-deep-lake are registered on Nauvis again (unlisted tiles never place), with water handing over water-to-water at the border.
    - Gleba no longer takes priority over volcano terrain: the full volcano (including the outer folds-flat ring, i.e. demolisher territory) now beats Gleba everywhere, per aquilo > vulcanus > gleba > nauvis.
    - Gleba territory now grows cliff-gleba cliffs: cliff elevation/density blend toward Gleba fields in the south and control.lua re-skins new-chunk cliffs on Gleba tiles (same pattern as cliff-vulcanus).
    - Scrap (when eon-holmium-ore is off): restored the VANILLA FULGORA
      placement and shapes instead of the round nauvis-style blob patches -
      structure-cell blocks (frequency = % of cells covered, capped at 600%, so
      the slider behaves like vanilla), per-cell sub-noise, road carves, dense
      vault spots, no scrap in the starting area, vanilla richness. Transplanted
      onto the merged map with two substitutions: the fulgora elevation/coast
      land gate became a nauvis land gate (eon_scrap_land on the raw
      elevation_nauvis field, water level 0 + shore margin), and the tile mask
      is gated by eon_scrap_ore_exclusion (0 wherever iron/copper/coal/stone/
      uranium/crude-oil probability > 0) so scrap never shares a tile with
      another ore (sign-safe if() form; the resource-autoplace patch-set skip
      only de-overlaps spot grids, not ~22-tile cell blocks).
    - Live-server gotcha for continuing saves: a surface's baked
      autoplace_settings.entity.settings never re-syncs from the planet
      prototype - a save created while eon-holmium-ore was on has 'holmium-ore'
      registered but NO 'scrap', so scrap never autoplaces on it (verified live:
      entity_scrap=false, 0 scrap on the whole map while iron works). Scenario
      resets only rewrite mgs.seed, so this never self-heals. Fix the surface
      registry (and regenerate chunks) to heal such saves - see
      map-gen-settings-eon-defaults.json.
Version: 0.1.9
Date: 2025-05-XX
  Changes:
    - New startup setting "Replace scrap with holmium ore" (default on): when enabled, scrap is replaced with holmium ore on Nauvis.
    - New startup setting "Remove space platform surface restrictions" (default on): when enabled, all surface conditions are removed so space-platform machines (crushers, ...) can be built on the surface and planet machines (chests, burner furnaces, ...) work on space platforms.
    - New startup setting "Asteroid chunk stack size 50" (default on): asteroid chunks stack up to 50 instead of the vanilla stack size.
    - Gleba placement is now tuned per map via Nauvis map-gen settings property expression names "eon_gleba_south_offset" (default 1000, how far south Gleba terrain starts) and "eon_gleba_deep_south_cap" (default 1, caps how strongly distant southern terrain turns into Gleba; lower it for more biter-friendly Nauvis gaps deep south). No restart needed, applies to newly generated chunks.
    - Far-south terrain no longer becomes pure Gleba: the south bias is capped, so deep south stays mostly Gleba with regular Nauvis gaps where biter nests can spawn again.
  Bugfixes:
    - Atomic bombs no longer create ammoniacal-ocean and lava tiles on Nauvis. Surface conditions are now kept for explosion prototypes so only the vanilla nuclear-ground effect applies (matches vanilla Nauvis behaviour).
Version: 0.1.8
Date: 2025-05-05
  Changes:
    - Borders of gleba terrain are less smooth now
  Bugfixes:
    - Fixed compatibility for honeycomb fungus when playing with Spaghetorio mod
    - Fixed some locale typo
    - Fixed compatibility with factorio 2.0.47 with new gleba decoratives
Version: 0.1.7
Date: 2025-04-18
  Changes:
    - Gleba tiles are much more prevalent in the south
    - New algorithm for spawning yumako and jellynut
    - Vulcane have a slightly different lava spot size
  Bugfixes:
    - Yumako and jellynut plants now will spawn with water disabled
Version: 0.1.6
Date: 2025-03-21
  Changes:
    - Ores related to Nauvis will not spawn on ice
    - Lightning collectors are now hidden from player
Version: 0.1.5
Date: 2025-03-14
  Changes:
    - Gleba tiles absorb pollution
Version: 0.1.4
Date: 2025-02-19
  Modding:
    - Added space travel flag
Version: 0.1.3
Date: 2025-02-02
  Bugfixes:
    - Now the menu simulations are fixed for good
Version: 0.1.2
Date: 2025-01-30
  Bugfixes:
    - Removed some menu simulations which could crash the game
Version: 0.1.1
Date: 2025-01-19
  Bugfixes:
    - Calcite and Tungsten ore wont spawn on ammonia oceans
  Modding:
    - Resource changes to tungsten ore and calcite are now done in data instead of data-final-fixes
Version: 0.1.0
Date: 2025-01-19
  Features:
    - This version was played from finish through end
    - Added descriptions to resources
    - Tungsten ore and calcite now spawn like normal nauvis ores
  Bugfixes:
    - Removed startup settings which did not do anything.
    - Removed small lava patches around the map (or at least the ones that i carefully checked out :))
Version: 0.0.9
Date: 2025-01-18
  Bugfixes:
    - Heating tower unlocked after concrete
    - lithium processing is now unlockable
Version: 0.0.8
Date: 2025-01-15
  Bugfixes:
    - Updated holmium graphics with higher contrast.
Version: 0.0.7
Date: 2025-01-14
  Features:
    - Asteroid chunks now have stack size of 50
    - new technology for traveling to solar system edge
    - removed rail support foundations technology since fulgora does not exist any more
Version: 0.0.6
Date: 2025-01-10
  Bugfixes:
    - Vulcanic rocks also provide calcite. This is needed for big mining drill
Version: 0.0.5
Date: 2025-01-09
  Bugfixes:
    - Removed some research triggers that were needed to continue with fulgora items
    - Updated mod compatibility list
Version: 0.0.4
Date: 2025-01-09
  Features:
    - Agriculture technology, calcite processing and tungsten carbide technologies are unlocked earier
    - Heating tower is unlocked after nuclear power
Version: 0.0.3
Date: 2025-01-07
  Bugfixes:
    - Removed vulcanus_enemy_base autoplace control
Version: 0.0.2
Date: 2025-01-07
  Bugfixes:
    - Removed some gleba water tiles, since there is no smooth transition towards nauvis water
Version: 0.0.1
Date: 2025-01-06
  Features:
    - Initial release