HN Debrief

Correlated randomness in Slay the Spire 2

  • Gaming
  • Programming
  • Developer Tools
  • Open Source

The post digs into Slay the Spire 2’s random systems and shows that the game uses several separate pseudorandom number generators seeded in closely related ways. Because the underlying .NET seeded generator has a linear first-output relationship, those separate streams are correlated instead of independent. The result is not just a theoretical bug. Some card rewards and events become biased, some outcomes become impossible, and players can feel that certain rewards show up suspiciously often. People familiar with the game said this fits lived experience, from repeated relic outcomes to weirdly absent cards.

If your product depends on reproducible randomness, treat the generator, seeding scheme, and state serialization as core application logic. Audit every source of nondeterminism early, because platform library defaults and small implementation shortcuts can leak all the way into user-visible behavior.

Discussion mood

Mostly impressed and mildly amused. People liked the writeup, felt validated that the game’s randomness had seemed “off,” and used it as a concrete example of a broader engineering rule: reproducible randomness is product logic, not a library convenience.

Key insights

  1. 01

    Determinism fails in boring places

    Reproducible procedural generation is less about picking a fancy PRNG and more about eliminating every accidental source of drift. Platform RNG differences, unordered map iteration, and save systems that reconstruct state by replaying calls can all desync outcomes even when the core algorithm is fine. Owning the generator lets you serialize state directly and keep behavior stable across platforms and versions.

    When you promise seed reproducibility, add determinism checks to your engineering process, not just your game logic. Ban unstable iteration order in generation code and persist RNG state explicitly instead of reconstructing it indirectly.

      Attribution:
    • account42 #1
    • fc417fc802 #1
    • maxbond #1
    • connicpu #1
    • tveita #1
  2. 02

    Separate RNG streams are a feature

    Using multiple RNG streams is not overengineering here. It preserves the meaning of a shared seed by keeping map generation, rewards, shops, and combat variance from collapsing into one butterfly effect. Without that separation, tiny combat choices would rewrite later rewards, which breaks daily challenges, shared-seed competition, and the whole appeal of replaying an interesting seed.

    If users compare or share seeded runs, define which parts of the experience must stay stable under different player actions. Partition randomness around those invariants before you write content generation.

      Attribution:
    • cptroot #1
    • ufo #1 #2
    • kibwen #1
    • vintermann #1
    • bulbar #1
  3. 03

    The seeding bug is straightforward to avoid

    The bad behavior comes from deriving sub-generators with related seeds, not from the idea of sub-generators itself. Several comments pointed out that hashing the master seed together with a stream label, or otherwise deriving sub-seeds through a non-linear transform, would preserve determinism while killing the offset correlation that caused the visible bias.

    Review every place you derive one deterministic stream from another. If the derivation is arithmetic on the seed instead of a proper keyed hash or equivalent mixer, assume correlation until proven otherwise.

      Attribution:
    • margalabargala #1 #2
    • Arcorann #1
    • AlotOfReading #1
    • red_admiral #1
  4. 04

    Seedable RNG turns behavior into API

    Once callers can provide a seed, the output sequence stops being an implementation detail and becomes a compatibility promise. Comments used .NET 6 as the clean example. The unseeded default generator was upgraded, while the seeded constructor stayed pinned to the legacy algorithm so old sequences kept reproducing. That split explains how a mediocre old generator can survive for years in a modern runtime.

    Do not hide versioned deterministic behavior behind a generic `Random(seed)` style API. Expose specific engines for reproducible use cases and keep convenience randomness separate so you can improve it later.

      Attribution:
    • OskarS #1 #2
    • account42 #1
    • haeseong #1
  5. 05

    Early access makes seed stability temporary anyway

    A few players noted that Slay the Spire 2 is still patching heavily, so old seeds are already unstable when new cards, relics, or encounters get added. That weakens the short-term backward compatibility argument for preserving today’s bad behavior and makes now the obvious window to change the RNG design before seeded communities calcify around it.

    Fix deterministic content bugs before users start depending on exact seeds in production. Once a seeded ecosystem forms, every cleanup becomes a migration problem instead of a bug fix.

      Attribution:
    • kami23 #1
    • chriskw #1 #2

Against the grain

  1. 01

    Correlated RNG can create skill expression

    In some games, hidden RNG structure becomes a mastery layer rather than a flaw. Hades speedrunners use seemingly meaningless actions like breaking pots to push chamber generation toward faster patterns, which creates route planning and execution depth for experts. That does not make Slay the Spire 2’s bug good design, but it is a reminder that exploitable determinism is not always purely negative.

    If your game has competitive or speedrun communities, think about whether strict RNG cleanup removes a form of emergent play you might actually want. Decide deliberately which manipulation surfaces are bugs and which are part of the game’s ceiling.

      Attribution:
    • jcalx #1
  2. 02

    Crypto-grade randomness is unnecessary here

    Replacing a game PRNG with SHA-256 or another cryptographic primitive solves the correlation problem, but one comment argued this is needless overkill for a turn-based deckbuilder. The bar is not adversarial security. It is stable, well-distributed, fast-enough deterministic output. A simple modern generator like PCG32 already clears that bar without dragging in crypto machinery.

    Match the generator to the product requirement. For gameplay randomness, prioritize determinism, distribution quality, and portability before you reach for security-oriented tools.

      Attribution:
    • ASalazarMX #1

In plain english

.NET
Microsoft’s software runtime and standard library platform used by languages like C#.
PCG32
Permuted Congruential Generator 32-bit, a modern family of pseudorandom number generators designed to have good statistical properties and speed.
PRNG
Pseudorandom number generator, an algorithm that produces a deterministic sequence of numbers that looks random.
procgen
Procedural generation, creating game content like maps or rewards algorithmically instead of hand-authoring every result.

Reference links

Game-specific references

Runtime and RNG implementation references

Seeded-run and RNG manipulation examples

Related games and side references