Tutorials & Beginner-First May 22, 2026

Your First Construct 3 Roguelike RNG Seed Ledger in One Evening - 2026 Beginner Pipeline

2026 Construct 3 beginner tutorial—build an rng_seed_ledger.json, pin tick groups, audit random() calls, and verify replay in one evening before itch HTML5 and NW.js Steam ship.

By GamineAI Team

Your First Construct 3 Roguelike RNG Seed Ledger in One Evening - 2026 Beginner Pipeline

Pixel-art hero for Construct 3 roguelike RNG seed ledger beginner pipeline 2026

You shipped a browser roguelite to itch. A player refreshed mid-run, reopened the tab, and posted “my build changed—refund” in your comments. You did not change balance that night. You also never wrote down which random() calls ran in which tick order after the refresh restored layout state but not RNG state.

H2 2026 Steam roguelite density means players compare your browser demo to Godot and Phaser titles that already document floor epochs and seed discipline. Construct 3 teams are not exempt because the engine uses event sheets instead of scripts. Nondeterminism after browser refresh is the smallest honest failure mode to fix before you wrap the same project in NW.js for a Steam demo.

This Tutorials & Beginner-First guide builds a seed ledger in one evening: a JSON file that records run identity, pinned tick groups, and a replay checklist you can attach to BUILD_RECEIPT culture before October fest traffic.

Non-repetition note: Blog-Planner refilled a 12-pitch backlog after seventy-one escape-hatch passes dominated by Steam metadata checklists. This is backlog High #1—Construct determinism, not another FAQ-line parity post. No existing URL owns construct 3 rng seed ledger intent.

Why this matters now (May 2026)

  1. Roguelite shelf pressure — Players expect same seed, same run after refresh; “lost run” reports spike on itch HTML5 demos during May–October fest cycles.
  2. Browser tab discard — Laptops discard background tabs; returning players re-enter with partial state unless you serialize RNG + sheet order explicitly.
  3. NW.js Steam path in Q3–Q4 2026 — Desktop export surfaces replay bugs that five-minute editor tests miss; seed ledger is cheaper than post-launch sheet archaeology.
  4. Cross-engine expectations — Teams reading Godot floor coordinators and Phaser chunk streaming will judge Construct demos by the same determinism vocabulary.
  5. Partner and playtest disciplinePlaytest feedback tools need a seed_id column; without a ledger you cannot reproduce “floor 4 loot wrong” rows.

Direct answer: Create rng_seed_ledger.json, pin one RunRNG group at the top of the event sheet, log every random() surface you use for gameplay, and pass a three-step replay test (fresh run, mid-run save, refresh resume) before promoting a demo build.

Who this is for and what you get

Audience You will be able to…
Beginner on first Construct roguelite Explain why refresh broke a run in plain language
Solo dev using event sheets Pin RNG without rewriting the game in JavaScript
Producer Attach seed_id to playtest forms and crash folders
Engineer shipping NW.js Export a receipt JSON partners can replay-verify

Time: ~3–4 hours first evening; 20 minutes per weekly demo promotion after.
Prerequisites: Construct 3 project with at least one procedural floor (loot table, enemy spawn table, or room pick from random()), willingness to use Local Storage or a simple JSON download for saves.

Outbound authority: Construct 3 manual — Saving games and System expressions — random for expression truth; verify against your installed build.

What you will have after one evening

  • release-evidence/rng/rng_seed_ledger.json with stable schema version
  • RNG_SEED_LEDGER.md explaining replay steps for humans
  • One pinned event group RunRNG documented at sheet top
  • Inventory of every gameplay random() with sheet + line notes
  • rng_replay_receipt_v1.json from tonight’s proof pass
  • Screenshot of ledger + Construct debugger RNG column after refresh test

Beginner path (first 90 minutes)

  1. Create folder release-evidence/rng/.
  2. Copy the ledger schema below into rng_seed_ledger.json.
  3. Add a On start of layout action: set global RunSeed from floor(random(0, 999999999)) once inside group RunRNG.
  4. Replace loot spawns that call bare random() with random(RunSeed + LootTableSalt + item_index).
  5. Run Test A (below)—if loot changes after F5 refresh, stop and fix before Test B.

Do not rewrite every enemy AI tonight. Do document every remaining bare random() as UNAUDITED in the ledger.

Developer path (fest prep stack)

  1. Join ledger run_id to BUILD_RECEIPT build_id in upload notes.
  2. Add seed_id column to playtest CSV exports from 18 playtest tools.
  3. Gate demo promotion on rng_replay_receipt_v1.jsonreplay_pass: true.
  4. Cross-check NW.js export uses same project version string as ledger project_version.
  5. File replay failures in 5-day crash log challenge folders by weekday.

Evening overview (five blocks)

Block Minutes Output
1 — Ledger schema 25 rng_seed_ledger.json + README
2 — Pin RunRNG group 45 Sheet screenshot + group list
3 — random() audit 60 random_surfaces[] populated
4 — Save + refresh tests 50 Three test results logged
5 — Receipt + proof 30 rng_replay_receipt_v1.json

Stop when Test C (browser refresh mid-run) shows identical loot on floor 1 after resume.

Block 1 — Seed ledger schema (copy exactly)

Create release-evidence/rng/rng_seed_ledger.json:

{
  "schema": "rng_seed_ledger_v1",
  "project_version": "0.4.2-demo",
  "engine": "construct-3",
  "runs": [
    {
      "run_id": "run-2026-05-22-001",
      "run_seed": 4815162342,
      "floor_index": 1,
      "tick_group_order": ["RunRNG", "WorldSim", "Combat", "UI"],
      "random_surfaces": [
        {
          "id": "loot_table_floor_1",
          "sheet": "Game",
          "event": "On enemy killed",
          "expression": "random(RunSeed + 101 + LootIndex)",
          "audited": true
        }
      ],
      "notes": "First evening pass — UI shake still UNAUDITED"
    }
  ]
}

Field dictionary

Field Meaning
schema Bump when you add required keys—partners parse semver
project_version Match NW.js export label and itch build tag
run_id Stable string you give playtesters
run_seed Integer set once per run in RunRNG
tick_group_order Top-to-bottom group names on main sheet
random_surfaces[] Every gameplay RNG touchpoint
audited true only after salt + seed formula reviewed

Honest limit: The ledger does not fix floating-point drift across browsers if you mix sin/cos physics with RNG—note physics_mode in notes when applicable.

Block 2 — Pin the RunRNG group (event sheet order)

Construct runs event sheets top to bottom each tick. If UI runs before RunRNG and calls random() for screen shake, you consume RNG sequence before combat rolls.

Pinning rules (document in RNG_SEED_LEDGER.md)

  1. Create group RunRNG at the top of the primary gameplay sheet.
  2. Inside: set RunSeed once on layout start; set RunNonce to 0.
  3. Disable “Active on start” on experimental groups until audited.
  4. Never call random() inside Every tick unless wrapped with documented salt.
  5. When adding floors, append groups below WorldSim, never above RunRNG.

Snippet-friendly pattern (event sheet logic)

Use a global number RunSeed and increment RunNonce when you need sub-streams:

On start of layout (RunRNG group)
  → System: Set RunSeed to floor(random(0, 999999999))
  → System: Set RunNonce to 0

On enemy killed (Combat group)
  → System: Add 1 to RunNonce
  → System: Set roll to random(RunSeed + 2000 + RunNonce)
  → Pick loot from table using roll

Why groups matter: A refresh that restores saved floor_index but not RunSeed recreates the classic “different loot” bug. Your save blob must include run_seed + run_nonce + floor_index.

Block 3 — random() audit pass (developer table)

Walk every sheet. For each random( usage, add a row to random_surfaces. Mark unaudited rows explicitly—hiding them guarantees fest-week surprises.

Sheet Event Risk Fix pattern
Game On start of layout High Move to RunRNG once
Game Every tick Blocker Remove or salt + document
UI On button hover Medium Use random(100000 + uid)
FX On explode Medium Derive from combat RunNonce
Menu On layout start High Separate menu seed MenuSeed

Menu vs run separation

Main menu backgrounds may use MenuSeed independent of RunSeed. Document both in the ledger so playtesters know which seed to report when the bug is “title screen particles wrong” vs “dungeon loot wrong”.

AJAX and async callbacks

If you fetch loot tables from JSON at runtime, do not call random() inside the callback without re-adding RunSeed salt. Async ordering is a common Construct nondeterminism source when callbacks complete in different order after refresh.

Block 4 — Save, resume, and browser refresh tests

Run these three tests on the same itch build or local preview. Record results in RNG_SEED_LEDGER.md.

Test A — Fresh run baseline

  1. Hard refresh browser (empty cache).
  2. Start run; note run_id and first loot drop.
  3. Note three enemy spawn positions.
  4. Export ledger row for this run.

Pass: Positions and loot match screenshot notes.

Test B — Mid-run local save

  1. Use Local Storage or downloaded save JSON including run_seed, run_nonce, floor_index.
  2. Quit tab.
  3. Reopen; load save.

Pass: Floor index and loot tables unchanged.

Test C — Browser refresh without quitting

  1. Mid-run on floor 1, press F5 (or mobile reload).
  2. If you lack auto-resume, load the autosave slot you implement tonight.

Pass: Same loot and enemy layout as pre-refresh.
Fail: Different loot → refresh restored layout globals but not RNG globals—fix save keys before NW.js export.

Autosave minimum JSON (browser)

{
  "run_id": "run-2026-05-22-001",
  "run_seed": 4815162342,
  "run_nonce": 14,
  "floor_index": 1,
  "project_version": "0.4.2-demo"
}

Store under key roguelite_autosave_v1 via Local Storage plugin. Version the key when schema changes.

Block 5 — Replay receipt (BUILD_RECEIPT cousin)

Create release-evidence/rng/rng_replay_receipt_v1.json after tests:

{
  "receipt_type": "rng_replay_receipt_v1",
  "project_version": "0.4.2-demo",
  "build_id": "optional-from-upload-log",
  "tests": {
    "fresh_run": "pass",
    "mid_run_save": "pass",
    "browser_refresh": "pass"
  },
  "replay_pass": true,
  "unaudited_random_surfaces": 2,
  "reviewer": "GamineAI Team",
  "observed_date_utc": "2026-05-22"
}

Promotion gate: Do not mark demo branch “fest-ready” while replay_pass is false or unaudited_random_surfaces > 0 for gameplay sheets.

NW.js Steam preflight (same evening, 30 minutes)

Browser proof is necessary; desktop proof is not optional for Q3–Q4 2026 NW.js ships.

  1. Export NW.js with same project_version string.
  2. Run Test C equivalent: close app mid-run, relaunch, resume save.
  3. Compare rng_seed_ledger.json run row to desktop log file if you write one.
  4. Note differences in receipt notes—platform tags belong in release evidence taxonomy.

Deck and Steam wrapper note: This tutorial does not cover Steam Input; pair with Unity Deck graphics only if you hybrid-export—not typical pure Construct paths.

Cross-engine comparison (why players mention Godot)

Concern Godot 4.5 pattern Construct 3 tonight
Floor transition Threaded loader + epoch Pin groups + save floor_index
Browser memory WASM ceiling playbook Chunk layouts; ledger does not fix OOM
Long-session maps Phaser chunk streaming Audit random() in procedural spawn
Evidence culture release-evidence/ folders release-evidence/rng/ tonight

Readers searching construct 3 vs godot roguelike 2026 should see complementary pipelines—not engine war.

Common mistakes (beginner-friendly)

  1. Calling random() in Every tick for cosmetic jitter—burns sequence; combat rolls shift.
  2. Duplicating On start of layout on multiple sheets—second layout resets seed silently.
  3. Saving only score and HP—refresh gives new loot on old floor.
  4. Testing only in editor—editor pause/resume does not equal browser F5.
  5. Mixing JavaScript SDK random with System random—pick one stream per feature.
  6. Ignoring preview layout vs game layout—different sheets, different start events.
  7. Promoting NW.js build without Test C on NW.js—desktop resume bugs differ.
  8. Skipping seed_id on playtest forms—you cannot reproduce reports.
  9. Using Date.now() as seed—breaks replay; use intentional RunSeed.
  10. Leaving template tutorial enemies with stock random()—audit includes template objects.

Weekly ritual (after evening pass)

Every Wednesday demo smoke (pairs upcoming backlog pitch #12):

  1. Open latest rng_replay_receipt_v1.json.
  2. If project_version changed, re-run Test C before branch promotion.
  3. Append new run_id rows to ledger—never delete old rows (history helps refund triage).
  4. Cross-link weekly note to BUILD_RECEIPT upload log.

Proof table (developer)

Claim Evidence artifact Pass criterion
Run seed set once Sheet screenshot RunRNG Single layout start setter
Loot uses salted roll random_surfaces[] row audited: true
Refresh stable Test C notes Matching loot screenshot
Save stable Test B save JSON Keys include seed + nonce
Promotion gated replay_pass true before fest branch

Construct addons and deeper learning

When you need plugins for save slots or debug overlays, start from 20 free Construct 3 addons and the Construct 3 guide hub. If you are new to event sheets entirely, read how to build a game without coding before scaling dungeon generation.

Playtest form one-liner

Add to your Google Form / playtest tool:

seed_id (from pause menu or run_id in ledger): ___

Players cannot help you reproduce bugs if the form only asks “what happened?”.

Salt table reference (copy to RNG_SEED_LEDGER.md)

Feature Suggested salt constant Added to
Loot drops 1000 + item index RunSeed
Room pick 2000 + floor_index RunSeed
Crit rolls 3000 + RunNonce RunSeed
Shop prices 4000 + shop_visit RunSeed
UI cosmetic 900000 + uid separate stream

Salts are not cryptographic security—they are namespace separation inside one PRNG sequence.

Worked example — floor 1 loot table (beginner walkthrough)

Imagine a three-item loot table: Health, Ammo, Curse. Without a ledger you might write:

On enemy killed → Set drop to choose(Health, Ammo, Curse) using random(100)

That works once. After F5 refresh, choose may fire with a different internal sequence because UI particles already consumed random rolls.

Tonight’s fix:

  1. Create global LootIndex starting at 0.
  2. On kill: add 1 to LootIndex.
  3. Set roll to random(RunSeed + 1000 + LootIndex).
  4. Map ranges: 0–49 Health, 50–79 Ammo, 80–99 Curse.
  5. Log the row in random_surfaces with audited: true.

Run Test C: kill three enemies, note drops, refresh, reload autosave, kill three enemies again. Drops should match the pre-refresh sequence if LootIndex restored correctly.

Debugger checklist (Construct 3)

Open the debugger while paused:

  • Confirm RunSeed is not zero after layout start.
  • Confirm LootIndex increments only on kill, not on tick.
  • Watch for duplicate On start of layout firing when returning from pause menu—add a RunInitialized boolean guard.

Screenshot the debugger with RunSeed, LootIndex, and floor_index visible; store in release-evidence/rng/screenshots/.

Evidence folder layout (solo team)

release-evidence/rng/
  rng_seed_ledger.json
  rng_replay_receipt_v1.json
  RNG_SEED_LEDGER.md
  screenshots/
    test-c-pass-2026-05-22.png
  weekly/
    2026-W21-notes.md

This mirrors release evidence taxonomy so partners recognize the folder in diligence ZIPs.

Pairing with the seven-day event-sheet freeze challenge

Backlog pitch #2 (seven-day freeze challenge) builds on tonight’s ledger. Order of operations:

  1. Tonight — ledger + Tests A–C.
  2. Next week — freeze sheet order for seven days before NW.js manifest preflight.
  3. Before Steam — combine receipt + BUILD_RECEIPT in upload notes.

Skipping the ledger and jumping straight to freeze week produces beautiful documentation of a still-nondeterministic game.

When to escalate to JavaScript scripting

Event sheets suffice for many roguelites. Escalate to scripting when:

  • You need deterministic replay files (input logs) for esports or speedrun communities
  • You port the same ruleset to a second engine
  • You implement networked co-op with server authoritative RNG

Until then, ledger + pinned groups beat a half-finished port.

Legal and store copy boundary

Determinism fixes gameplay truth; it does not replace store FAQ parity or wishlist truth audits. If refresh bugs stop but trailer promises co-op, refunds continue—tag those store-copy in refund dashboards.

Key takeaways

  • H2 2026 roguelite players punish refresh drift on itch and Steam demos.
  • Build rng_seed_ledger.json in one evening—not after NW.js mystery bugs.
  • Pin RunRNG at the top of the event sheet; document group order.
  • Audit every gameplay random(); mark unaudited rows honestly.
  • Pass Tests A–C before fest branch promotion.
  • Emit rng_replay_receipt_v1.json beside BUILD_RECEIPT culture.
  • Include run_seed + run_nonce in every save blob.
  • Add seed_id to playtest forms tonight.
  • Cross-link Godot and Phaser posts for engine comparison queries—not competition.
  • Backlog #1 restores Tutorial category after metadata escape-hatch streak.
  • 11 backlog pitches remain—Blog-Planner refill succeeded; keep consuming backlog.
  • Construct teams can ship determinism without leaving event sheets.

FAQ

Does Construct 3 guarantee deterministic runs across browsers?
No engine guarantees that for all features. You document RNG surfaces, pin order, and prove replay on your scopes.

Is random() seeded automatically on layout start?
No—unless you set it. Default behavior is why refresh tests fail.

Should I use the Advanced Random plugin?
If already integrated, treat it as another random_surfaces row with documented seed API. Do not mix silently with System random().

What about multiplayer?
This pipeline is single-player browser/desktop focused. Server authoritative RNG needs a different tutorial.

How does this relate to daily run leaderboards?
Use a daily salt in ledger notes (daily_seed_2026-05-22) shared by all players that day—separate from per-run RunSeed.

Can I skip NW.js if I stay on itch?
Yes, but run Test C on the same embed players use—GX.games and itch iframes differ.

How many random() rows before I ship?
Zero UNAUDITED rows on gameplay sheets for fest demos; cosmetic UI may wait one week if documented.

Where does AI loot generation fit?
If AI picks table indices, log the index in the ledger row, not model temperature—temperature is not replayable.

What file goes to partners?
rng_replay_receipt_v1.json + redacted ledger excerpt—no need to export entire project.

Does this replace save-format semver?
No—when you add modifiers mid-run, plan the backlog save-format migration pitch; ledger complements semver.

Conclusion

A roguelike without a seed ledger is asking players to trust vibes. One evening gives you run_id, pinned groups, salted rolls, and refresh proof you can attach to the same evidence folders you already use for builds and refunds.

Create release-evidence/rng/ tonight. Pin RunRNG. Run Test C until it passes. Export the receipt before you tell Discord the demo is fest-ready.

Next reads: Construct 3 guide, Godot floor coordinator beginner pipeline, and Phaser H2 roguelite streaming playbook.

Ninety-minute sprint (condensed evening)

Minute Task
0–15 Create rng/ folder + ledger JSON
15–35 Pin RunRNG group + layout seed
35–55 Audit top five random() calls
55–75 Test C refresh attempt
75–90 Write receipt + screenshot

Sprint version still beats shipping an unlogged demo.

Integration with refund and crash signals

When refund dashboards tag gameplay with language like “lost my run,” check whether replay_pass was false on that build_id. Correlation turns angry comments into ledger tasks—not moral debates.

SEO and discovery note

This tutorial targets construct 3 roguelike rng seed and construct 3 determinism browser refresh queries—distinct from Steam metadata parity so searchers find engine pipeline content for no-code roguelites.

Stretch goals (if you finish before four hours)

  • Add pause-menu display of run_id copied to clipboard for playtesters.
  • Wire replay_pass into a simple NW.js pre-export event that blocks export when false.
  • Draft one row in backlog #5 case study format from your own Test C notes—real timestamps, no invented revenue.
  • Read Godot WASM memory ceiling if your Construct layout also grows unbounded on long runs—RNG fixes do not replace memory discipline.

These stretch items are optional tonight; the ledger and Test C pass are not optional before you call the demo fest-ready.

Found this useful? Bookmark the Construct 3 guide and share the article with a teammate who ships event-sheet roguelites to itch this month—determinism bugs are faster to fix in pairs when one person runs Tests A–C while the other screenshots the debugger.