Team Cereustooling wiki

Generate a Limveld seed

Partly checkedagainst the code on 2026-11-12 11:45

seedgen makes new Limveld patterns. Vanilla mode follows the rules FromSoft's own generator used. Eclipse mode keeps that skeleton and adds the Eclipse rules from eclipse.json.

Status partial: every command and flag below was read from the code. The commands were not run for this page, and no generated pattern has ever been run in game. A generated pattern is a JSON file. Getting it into the game is not built yet: see Put a seed in the mod.

Before you start

  • Work in S:/fromsoftware-rs/.tmp/seedgen-vanilla/seedgen/. The scripts import each other and open eclipse.json by a relative path, so run them from that folder.
  • model.py reads two things at import. Both must exist:
    • the regulation as XML: S:\souls-script-kt\param-nightreign\regulation-bin (override with env NR_REGULATION_XML);
    • the viewer's seed file: S:\_modding\tools\seed-viewer\seedviewer\seeds.json (override with env NR_SEED_VIEWER).
  • render.py needs Pillow (PIL).
  • The folder is under .tmp/, which is not tracked by git. Do not write outputs into the tool folder unless you mean to keep them. Pass --out with a path in your own work folder.

Steps

  1. Pick the Nightlord, the era and the Shifting Earth.

    • --lord: 0 Gladius, 1 Adel, 2 Gnoster, 3 Maris, 4 Libra, 5 Fulghor, 6 Caligo, 7 Heolstor, 8 Harmonia, 9 Straghess.
    • --era: launch, dlc or hollow. hollow is Great Hollow and goes with --earth 4.
    • --earth: 0 none, 1 Mountaintop, 2 Crater, 3 Rotted Woods, 4 Great Hollow, 5 Noklateo.
    • The combination must be one vanilla has a pattern set for. If not, the script stops with vanilla has no pattern set for Nightlord ..., era ..., earth ....
  2. Generate in vanilla mode:

    python generate.py --lord 6 --earth 0 --era launch --count 5 --seed 1 --out <work folder>/caligo-vanilla.json
    
  3. Or generate with the Eclipse layer:

    python generate.py --mode eclipse --lord 6 --count 20 --first-id 95000 --out <work folder>/caligo.json
    

    Add --new-content 0.25 to override the new_content slider for this batch. Add --config <file> to use another settings file than eclipse.json.

  4. Read what it prints. There is one line per pattern: the id, the event, the POI count, then OK or the list of rule findings. generate.py runs validate.check() on every pattern it makes. In Eclipse mode that includes the Eclipse checks (dedupe, ailment spacing, mimic chest, invasion).

  5. Render a pattern to look at it:

    python render.py <work folder>/caligo.json --index 0 --out <work folder>/caligo0.png
    

    For a vanilla pattern, pass its id instead of a file: python render.py 240 --out 240.png. --bg <image> draws on top of a background picture, for example thefifthmatt's pattern/<id>.jpg. The picture is 1536 px for 1536 m, centred on Limveld. Without --out the file is render-<id>.png in the current folder.

  6. Export, if you need the rows or want the patterns in a copy of the viewer:

    python export.py <work folder>/caligo.json --params <work folder>/caligo.params.json --viewer <work folder>/seeds.json
    
    • --params writes LotResultMapPatternFlag, LotResultSmallBaseAndSpot and LotResultPlayAreaParam rows as JSON, in the regulation's field names.
    • --viewer writes a copy of the viewer's seeds.json with the generated seeds added. Do not point it at the live viewer file.

The flags

generate.py:

Flag Default Meaning
--lord 6 Nightlord number
--earth 0 Shifting Earth number
--era launch launch, dlc or hollow
--count 1 how many patterns
--seed 1 the random seed of the run (same seed, same output)
--mode vanilla vanilla or eclipse
--config eclipse.json Eclipse settings file, read only in Eclipse mode
--first-id 90000 id of the first pattern; the rest count up
--new-content none Eclipse only: overrides new_content (0 = vanilla only, 1 = new only)
--out none JSON file to write. Without it nothing is saved, only the check lines are printed

render.py <id or file.json>: --index (default 0, which pattern of a file), --bg, --out.

export.py <patterns.json>: --params <file>, --viewer <file>.

The Eclipse settings (eclipse.json)

Key Value now Meaning
variety per category How many different enemy setups a POI type may use in one run. Keys are [group, category] from model.CAT.
dedupe_names true A boss family appears once per run across field, castle, evergaol, camp leader and night slots.
new_content 0.5 Share of a slot's draw that goes to new Eclipse content when the slot has both kinds. Has no effect yet: new content comes from catalog.tsv, and that file does not exist.
ailment.same_kind_radius 500 No two POIs of the same type with the same ailment within this many metres.
ailment.any_kind_radius 350 Radius for the cluster rule.
ailment.any_kind_max 1 At most this many other POIs with the same ailment inside any_kind_radius.
ailment.per_run_max 3 At most this many POIs of one ailment per run.
themes.count 2 Map quadrants (NE, NW, SE, SW) that get an ailment theme.
themes.boost 3.0 How much more likely matching setups are in a themed quadrant. themes.ailments (optional) limits the pool.
coverage 1.0 Down-weights content already used often in the same batch. 0 = off.
tile_caps true Keep vanilla's measured cap on how many POIs of one type share a 256 m tile. Vanilla mode always uses it.
spread 0 Above 0: slots far from POIs of the same type are more likely (distance to the power spread). 0 = off.
mimic.count 1 Mimic chests every seed gets.
mimic.extra_chance 0 Chance of one more.
mimic.max 1 Hard cap.
mimic.min_spacing 500 Metres between two mimics. Only matters if the cap is raised.
mimic.exclude_maps [] POI map ids never used.
invasion.chance 0.85 Share of seeds that get an invasion.
invasion.pool the Pursuer Weighted list of invaders: name, chr, map, weight.
invasion.attach 8 slots Attach points the invader's map may use; slots a POI already uses are dropped.
invasion.min_attach, max_attach 4, 8 A roll is dropped with fewer free attach points than min_attach.
invasion.live_chance 1.0 A note of the in-game value. eclipse.py does not read it.

Mimic chests are picked from treasure-assets.tsv: only real chests count (AEG599_903 with ObjAct 200 and AEG599_902 with ObjAct 210). The invasion lands on the day without the seed's own event. With no event it is a coin flip.

What a pattern file holds

A list of patterns. Each has id, lord, earth, era, mods, flags, pois (slot, map, variation), night (two entries: circle, boss, code, extra boss, extra code), set, event, mode and themes. Eclipse patterns also have mimics and invasion.

Check the generator itself

  • python validate.py [--verbose] checks every baked vanilla pattern against the decoded rules and prints how many pass. It takes no pattern file. To check generated patterns, read the OK lines from generate.py.
  • python compare.py [K] [--mode vanilla|eclipse] [--per-earth] compares generated statistics with the baked patterns. It writes compare-<mode>.json into the current folder, so it changes the tool folder. K defaults to 10.
  • report.py, calibrate.py and fit_spread.py also write files into the tool folder (report.json, sample-*.json, calibration.json).

What goes wrong

  • FileNotFoundError at import: the regulation XML folder or the viewer's seeds.json is missing. Set the two env variables above.
  • pattern <id>: no valid layout after N tries: the rules could not be met. Try another --seed.
  • could not place 1 mimic(s): the run has no real chest in any placed POI.
  • Nothing saved: --out was left off.
Source files this page documents (8)
  • fsrs:.tmp/seedgen-vanilla/seedgen/generate.py
  • fsrs:.tmp/seedgen-vanilla/seedgen/eclipse.py
  • fsrs:.tmp/seedgen-vanilla/seedgen/eclipse.json
  • fsrs:.tmp/seedgen-vanilla/seedgen/validate.py
  • fsrs:.tmp/seedgen-vanilla/seedgen/render.py
  • fsrs:.tmp/seedgen-vanilla/seedgen/export.py
  • fsrs:.tmp/seedgen-vanilla/seedgen/compare.py
  • fsrs:.tmp/seedgen-vanilla/seedgen/model.py

Changed one of these? Update this page: seeds/generate-a-seed.md (how).