frontpage.
newsnewestaskshowjobs

Open Source @Github

fp.

Open in hackernews

Correlated randomness in Slay the Spire 2

https://tck.mn/blog/correlated-randomness-sts2/
56•rdmuser•3h ago

Comments

xdertz•1h ago
> the game used several distinct pseudorandom number generators, to prevent e.g. randomness within a combat from influencing future card rewards.

Why is this important? Feels like fixing what seems to be a non-issue lead to a bunch of real issues.

With a good RNG it should not be possible to predict future numbers based on past numbers so players cannot manipulate card rewards in their favour based on combat actions, right?

yccs27•1h ago
I guess it's mainly a limit to savescumming.
iNic•1h ago
For things like daily runs / seeded runs part of the fun is getting the same card rewards.
bzax•1h ago
You could observe future random numbers by taking combat actions, and then reset to the start of the fight and play a line which consumes fewer random numbers in order to manipulate your card rewards. Maybe you could generate the card reward at the start of the fight, but what if they play a card which impacts the card reward, e.g. by creating an extra card reward.
torgoguys•1h ago
Because they appear to have a curious way of doing their saves. From the article:

>The way Slay the Spire allows you to save and resume runs is by storing the total number of times each RNG has been called, and then calling each RNG that many times (throwing away the result) whenever a save file is loaded.

Depending on what the game is like (I know nothing about it), that could make sense, even if it is inelegant.

eig•1h ago
The game stores and allows you to see the RNG seed that controls the run's events and layout. The developers want players to be able to share seeds that produce interesting runs.

That requirement is what made this problem difficult for the devs to solve.

margalabargala•28m ago
This shouldn't actually be difficult to solve though.

The issue is that knowing the offset of seeds helps predict outputs.

Instead of calling RNG(seed+hash(string)) 10x, make one RNG(seed) and call that 10 times to get random seeds for your 10 rngs. Now you have perfect determinism and no correlation.

Arcorann•14m ago
My first solution was RNG(hash(seed.toString() + string)), which would get rid of the correlation while still being deterministic based on the seed.

It's also more robust than calling RNG 10 times since if you use the same algorithm to seed as for the RNG proper then you will get the same sequences in each instance, just offset.

vintermann•58m ago
I don't think it's deliberate RNG manipulation they worry about. It's a single player (or coop) game after all.

However, one of their design goals is that people playing on the same seed should have roughly the same game, it should feel "fair". Some things you probably want to be fairly random, for instance your card choices can depend on what cards you chose before. But it's also important that people choosing the exact same cards (and taking the same path, maybe?) should be offered the same options.

In STS1, the order of relics was fixed from the start as I recall. So if you skipped a shop, you'd get exactly the same relics in the next shop as you would have in the one you skipped. Good for seed fairness, but a little odd.

bulbar•31m ago
For a singular seed, they wanted the resulting run to be stable in the sense that small deviations in decision making does not result in a vastly different result (as far as random events are concerned)

Imagine the game of two players having the same state X. While combat, one player would trigger a random action, the other doesn't. After the combat, both should still get the same randomized reward options. This wouldn't work with just a singular RNG.

OskarS•59m ago
I've always thought that random number generators are one of the best examples of Hyrum's law ("all observable behaviours are part of your API"): once you release a random number generators that either uses a default seed or allows you to seed it, you can't ever change it, it's a huge breach of backwards compatibility. Imagine if you did a Minecraft style game that relied on the behaviour of some PRNG, and then you changed the implementation? The entire game will break. That's why GNU libc still uses a terrible LCG for rand() despite the fact that much better generators exist: they can't ever fix it, because srand() exists and people rely on it.

On the other hand, it's STUPENDOUSLY useful to have "default" random functionality in your core library, for the "just give me a random number" or "shuffle this array, I don't care how" users, who don't really care about the details. But if you do that: always seed it with some external entropy (current time or /dev/random or whatever), don't even allow users to seed it. That means you can improve it in the future, because users already can't ever rely on the sequence. If the users do want to rely on the sequence, they should have to specify the exact engine they want.

TL;DR: System.Random in C# should not ever have been seedable, big mistake.

haeseong•54m ago
That split is exactly what .NET 6 did. The parameterless Random switched to xoshiro256*, but new Random(seed) stays pinned to the old Numerical Recipes subtractive generator so historical seeds still reproduce, and that legacy generator is the affine one whose first output is linear in abs(seed), which is the whole root cause of this bug.
FromTheFirstIn•34m ago
If you’ve played the game it makes sense to have the seed be settable and shareable. In Slay the Spire it can be exciting to have an outrageously unlikely starting state or early option, and in order for players to share this with each other the seed has to be user controlled. It’s a big part of what gives the game its community!
cbondurant•54m ago
The trash heap event gave me the same relic the first 3 times in a row that I got it before it gave me anything else. I wonder that's another example of this correlation?

I hope the StS team is made aware of this and is able to make the earlier outcomes a bit more evenly spread, so that the distribution matches more closely with what people would intuit them to be.

FromTheFirstIn•33m ago
It always gives me Clash :(
stdc105•48m ago
Interestingly, StS2 got this problem because it was using C# System.Random in Godot, while the RNG class in GDScript (Godot Engine's own scripting language) is using PCG32 which should be free of this particular problem.
FromTheFirstIn•32m ago
This is such a great article- I’ve had so many runs where it’s felt like “why am I always getting this random card?” And now I’ll know! Thank you!
0xdecrypt•20m ago
Really interesting read. The fact that Rebound is literally impossible to get is hilarious and completely unexpected.
abstractcontrol•17m ago
Why don't they just pass the time into the RNG in order to randomize it instead of using fixed seeds?
wbobeirne•16m ago
Being able to share and replay seeds is a big part of the StS community.
ixwt•13m ago
People often want to share their seeds so that players can play the same game they did. If there was an interesting series of results for example, which gave you a good set of cards.

Minecraft does this too with world generation for example.

iliveinberlin•8m ago
This is also the cause of the thing in Minecraft where you find surface clay, move X blocks over, and dig straight down into diamonds.
d357r0y3r•6m ago
I feel vindicated. I knew this game was bullshit and it couldn't possibly have been a skill issue.
account42•4m ago
> Implementing a PRNG within the codebase instead of calling the C# standard library has an additional advantage: seeds are guaranteed to be the same on all platforms. In Spire 1, seeds on the desktop version of the game were different from seeds on the mobile version of the game, because the standard library implementation of PRNG differed between platforms. It is also worth mentioning that the standard library implementation might change over time, which would break all past seeds.

This is the correct conclusion - game developers should consider gameplay-relevant random generators part of their gameplay code rather than platform code.

Mechanical Watch (2022)

https://ciechanow.ski/mechanical-watch/
199•razin•2h ago•25 comments

Correlated randomness in Slay the Spire 2

https://tck.mn/blog/correlated-randomness-sts2/
60•rdmuser•3h ago•26 comments

John Carmack on Fabrice Bellard

https://twitter.com/ID_AA_Carmack/status/2064095424420487226
468•apitman•8h ago•240 comments

The time the x86 emulator team found code so bad they fixed it during emulation

https://devblogs.microsoft.com/oldnewthing/20260615-00/?p=112419
360•paulmooreparks•8h ago•108 comments

A backdoor in a LinkedIn job offer

https://roman.pt/posts/linkedin-backdoor/
1338•lwhsiao•17h ago•254 comments

Is Fable 5 Back?

https://isfable5back.com
11•AussieWog93•24m ago•4 comments

Show HN: Voice Age Verification

https://agewarden.ai/
5•wentw0rth•24m ago•3 comments

Getting Creative with Perlin Noise Fields

https://sighack.com/post/getting-creative-with-perlin-noise-fields
70•0x000xca0xfe•2d ago•14 comments

Trinket.io shutting down, so we saved it and hosted it a trinket.strivemath.org

https://trinket.strivemath.org/
60•apulkit6•3h ago•8 comments

Iroh 1.0

https://www.iroh.computer/blog/v1
1270•chadfowler•22h ago•389 comments

Banned Book Library in a Wi-Fi Smart Light Bulb

https://www.richardosgood.com/posts/banned-book-library/
465•sohkamyung•14h ago•256 comments

Ask HN: Has anyone replaced Claude/GPT with a local model for daily coding?

1123•cloudking•22h ago•482 comments

SpaceX Is Buying Cursor

https://www.bbc.com/news/articles/cvgd5g7d7gyo
115•jrm-veris•58m ago•120 comments

Feds freaked over Fable 5 after simple 'fix this code' prompt, not jailbreak

https://www.theregister.com/security/2026/06/15/feds-freaked-over-fable-5-after-simple-fix-this-c...
204•_tk_•4h ago•117 comments

TinyWind: A pixel pirate sailing game with real wind physics (380k+ kms sailed)

https://tinywind.io
906•tinywind•21h ago•162 comments

Understanding the rationale behind a rule when trying to circumvent it

https://devblogs.microsoft.com/oldnewthing/20260611-00/?p=112415
61•tosh•5h ago•18 comments

An interview with an Apple emoji designer

https://shadycharacters.co.uk/2026/06/ollie-wagner/
5•nate•2d ago•1 comments

Unicorn – The Ultimate CPU Emulator

https://www.unicorn-engine.org/
5•tosh•2h ago•0 comments

Russian artist and Putin critic shot dead in Poland

https://www.bbc.com/news/articles/clyrzd5g6k2o
31•2OEH8eoCRo0•58m ago•5 comments

Show HN: Garden of Flowers – an archive of pictorial typography before ASCII art

https://garden-of-flowers.heikkilotvonen.com/
100•california-og•9h ago•14 comments

I Love the Computer

https://michaelenger.com/blog/i-love-the-computer/
263•speckx•17h ago•149 comments

Color Photos of Stalin-Era Soviet Union Taken by a US Diplomat

https://rarehistoricalphotos.com/stalin-era-soviet-union-pictures-martin-manhoff/
59•Cider9986•2d ago•15 comments

I hacked into the worst e-bike and fixed it [video]

https://www.youtube.com/watch?v=hPrtVGimBYs
123•alexis-d•5d ago•59 comments

'Wow, it really worked ': 70s TV show causing worldwide panic today

https://www.theguardian.com/tv-and-radio/2026/jun/16/alternative-3-mockumentary-missing-scientist...
10•defrost•38m ago•2 comments

Hetzner Price Adjustment

https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/#cloud-servers
499•tuhtah•1d ago•682 comments

Peopleless economy? Not technically impossible

https://gmalandrakis.com/writings/ad-economicum.html
231•l0new0lf-G•16h ago•421 comments

My Homelab AI Dev Platform

https://rsgm.dev/post/ai-dev-platform/
334•rsgm•22h ago•54 comments

Why I email complete strangers

https://www.goodinternetmagazine.com/why-i-email-complete-strangers/
178•karakoram•15h ago•79 comments

Cohere's First Model for Developers

https://cohere.com/blog/north-mini-code
119•hmokiguess•5d ago•27 comments

Fox to buy Roku

https://www.wsj.com/business/deals/fox-roku-deal-f6e564f9
336•thm•1d ago•408 comments