Live data from Hacker News

Correlated randomness in Slay the Spire 2

tck.mn

51–60 of 92 posts

Re: Correlated randomness in Slay the Spire 2

#51
The post suggests replacing the linear congruential generator (LCG) with a permuted congruential generator (PCG). The latter has more random-looking output.

Another solution is to switch to a cryptographic hash function. For example, using sha256(seed || event type || counter) only requires storing seeds and counters in the save game.

This has several benefits:

  - You can find efficient implementations on all platforms without having to roll your own.
  - Gives the same output on all platforms by design.
  - Output is practically indistinguishable from randomness by design.
The main downside is that sha256 is significantly slower than any non-cryptographic PRNG, but considering how few random numbers you need during a typical game, this doesn't really matter.

Re: Correlated randomness in Slay the Spire 2

#52
post #30

> 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 impl…

> It is also worth mentioning that the standard library implementation might change over time, which would break all past seeds. If the stdLib changes and you need to use the same, then you're unfortunately going to be suck with porting the previous version into your own library. It's pretty forward thinking from the devs here, I would love to see my boss' face if I told him we need time to port some of the stdLib in…

For what it’s worth, Claude did this without even being asked when I had it implement /dev/urandom in my deterministic dotnet runtime. (Fun fact: if the runtime only ever receives zero bytes from /dev/urandom then it will hang on attempting to initialise System.Random! That was the first way I asked for it to be implemented.)

Re: Correlated randomness in Slay the Spire 2

#53
post #2

> 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,…

> 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?

I think you're overlooking the distinction between seeded and unseeded runs. An unseeded run is a run in which the player enters the game not knowing what the seed of the RNG is and not being able to pick it (this is the default mode). A seeded run is where the player provides the RNG seed. Generally, things like unlocks and steam achievements can only be earned on unseeded runs, but players want to be able to play seeded runs anyway. Of course all runs have an RNG seed: an unseeded run is when the seed is itself chosen at random, a seeded run is when the player specifies the seed.

Imagine a game with a standard deck of cards played over several rounds, where your opponent performs actions in response to your actions. The deck of cards is shuffled pseudo-randomly between every round. Every time you make a move, your opponent has N valid moves, and picks between them pseudo-randomly.

Players play a seeded run because they want to retry the same set of challenges, because they are asking themselves "if I had done this, would I have won" or "if I had done this, what would have happened".

So in this example, given a known seed: in round 1, my cards are shuffled this way, and in round 2, my cards a shuffled this other way, regardless of which moves I make in round 1.

If the opponent picks its response using the same RNG that shuffles the deck, the players actions in round 1 would change the shuffling of the deck in round 2. This would change the design parameters of what a seeded run means: it's no longer giving the guarantee "the deck is shuffled in the same way in round 2 regardless of what you do in round 1", which is the experience the designer wants to create and what the players want to play. Players might, e.g., say "who can get the highest score on this seed", they might search for the easiest or most difficult seeds, or they might search for seeds where particularly unlikely sequences of events are guaranteed to occur, because perhaps this sequence of events is so unlikely that a human would have to play a hundred million games to witness that sequence organically, and people want to see that sequence of events because it's interesting in some way. It's designed this way so that if you play the same seed, certain random events play out the same way, i.e., non-randomly.

Re: Correlated randomness in Slay the Spire 2

#54
Combining this article and discovery of an unwinnable seed in the original Slay the Spire [0] — I've always pondered the existence of some kind of "RNG hell", where a game uses the time as its random seed and, due to some quirk of the hashing function and the game mechanics, the game is rendered completely unwinnable for (say) four days straight. (Sometimes it feels like I'm in it!)

[0] https://oohbleh.github.io/losing-seed/

Re: Correlated randomness in Slay the Spire 2

#56
post #38

Earlier quoted context omitted.

More than just that, procgen as a whole requires an entirely different level of vigilance to avoid nondeterminism creeping in if the game requires it to be reproducible. None of the inputs to the procgen algorithm can be allowed to even so much as brush up against code you aren't actively exerting complete control over, and care is required to avoid inadvertently encountering any platform specific hardware quirks.

What's burned me before is iterating over hash maps. B-tree maps (or hash maps that are guaranteed to iterate in insertion order, or any fixed order) are your friend.

I've been burned by this outside games as well. Computation heavy process, in production it writes the inputs into the output as well for reproducibility, but some of them used unordered maps so it would slightly differ when you loaded it back up. Long term solution was to stop using unordered maps in general, but short term we had to make sure the inputs got sorted before being inserted so they would have the same insertion order every time...

Re: Correlated randomness in Slay the Spire 2

#57
post #8

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 c…

I had a similar realization recently; I was writing a compiler so I implemented a "random" function as part of the runtime. To avoid regression I have some simple code examples I compile and execute, and I compare their output to "known good" versions. I reached a point where I wanted to write a "sort array" routine and my immediate thought was to generate an array of 50 random numbers, sort them, and print them. But…

That's a bad example to use because it has very few repetitions (only the spaces I think?) and the key doesn't have different equivalent values so you can't test that you're order-preserving (or not).

But ideally sort is something you want to test with something like quickcheck/hypothesis, not gold tests (and I say that as probably the world's number 1 proponent of gold tests).

Re: Correlated randomness in Slay the Spire 2

#58
I haven't had time to read the whole article, but I really appreciate the cross section of the world that reads HackerNews and plays STS2. STS1 and STS2 are my favorite games and to see this pop up here brought a big smile on my face. Thanks for sharing.

Re: Correlated randomness in Slay the Spire 2

#60
post #49

>> However, I am confident that Mega Crit will address this issue. They did not address it in StS1, exactly the same bugs were reported there. I would not be very hopeful. They did not even change their RNG to something better, like MT.

This time it has a major impact on the possible RNG outcomes even for a player who doesn't know about the bug, and it was caught much earlier in development before the permanent stability of existing seeds was guaranteed.
Post reply on HN