Random Not Fair Enough?

When you break blocks in MadStone, new blocks fall from the top of the screen, as if you are chipping away at an infinitely tall structure. During MadStone’s early days as a crude prototype (free download available soon), the game generated new blocks and MadStones by picking one randomly based on a set of ratios. For example, you might get a 1×1 block as your next block 20% of the time, a MadStone 10% of the time, etc.

This all worked pretty well, but as people were playing it (including me), they would sometimes complain that one side was getting too many MadStones. Of course, we knew that it was totally random, and the amount of MadStones that the two sides get would even out over time. The problem was that in any given 10 seconds, it didn’t always feelfair.

First idea: Sharing a “Random Seed”

We knew we had to fix it, but how? Our first idea was to give both of the players the same set of blocks. This is easily accomplished by having the two players share a “random seed.” This means that the game would still generate blocks randomly, but generated item #132 for player 1 would be the same as generated item #132 for player 2.

After fixing a few bugs, we implemented this solution and game looked like this: the players started with the same set of blocks, and they seemed to get about the same set of blocks/MadStones for about 20 seconds. But after that, it didn’t seem any more fair than before. What went wrong?

Two problems: the players play at different speeds, and they break different blocks. So even though they will get the same block for their 132nd block, they’ll arrive there at totally different times. Maybe one player will be 50 block generations ahead for a while, then they’ll both be even for a few seconds, and then the other will get way ahead. Unless the players are within about 5-15 block generations apart, it doesn’t look any more fair than completely random, and one often seems to be getting more MadStones than the other.

It seemed like this solution was close to being what we wanted, because it worked well when the game started. We just needed to figure out a way to keep that sense of fairness going all the time. Then it came to us: what if the game essentially started over every few seconds?

Solution: Reset the Seed

By changing the random seed for both players every few seconds, but sharing the one random seed between them, we were able to keep the sense that the players are generally getting the same blocks (and more importantly, the same number of MadStones). As long as the two players are both breaking blocks, and there isn’t an enormous gap in how fast they play, it will look like they are getting about the same number of MadStones. No matter how much faster one player plays, the other player always “catches up” with them every 3 seconds or so, because the random seed resets and they start getting the same blocks again.

This system of sharing a random seed between the two players and resetting it periodically felt much more fair than what we had before.

Now, I’m sure it still doesn’t always feel perfectly fair, but it was the best solution we could find without cheating the numbers and giving the players different MadStone ratios. For example, we could have used a system where the losing player has a higher chance of getting a MadStone than the winning player. However, we decided that although this might have felt more fair in some situations, it was very important to us that MadStone be actually fair, not favoring either player.
This system allowed us to preserve perfect fairness, and make it feel fair too.