STACKED — THE PUZZLE GAME
Difficulty Curve Setup
I built a game using Unity. It is now available on iOS & Android. You can download it here.
The purpose of this game (for product managers and other observers) is to demonstrate some of the problems faced in a production application, and take you along the journey of fixing and running experiments. I hope this serves well for younger PMs.
Note: the app updates and plans here will take time as this is being developed by me. And I’m not good at this. I learned Unity a couple of months ago. But I do play a lot of games.
Designing Levels
If you look at the levels closely enough, you’ll realize it’s a matrix of numbers. This, in fact, was the starting point for the entire game. I wrote a simple python script that would generate these random matrices with a complexity ceiling (limit on number of 4s, 3s & 2s).
Once the level is defined, it is solved by a brute force logic engine (which I again wrote in Python). For every level ID, the code collects the solution and the number of steps it took to reach completion.
So, ultimately, I have a library of matrices and their solutions and pivot of the number of solutions for each number of steps:
Ultimately, there are 20k unique levels that have been generated & solved, out of a max possible solution set (for a 5x6 matrix with 4 as the max value of any element) of (5³⁰ - whatever combinations are not good, e.g. all 1s or all 2s))
Probability of Solving A Level
Let’s deviate for a moment and get into everyone's favorite topic: probability.
I’m no expert at probability, but I think if I were presented with a 2x2 matrix, and I was told that there is a single hit solution (a hit being a tap to clear the screen due to the cascading effect of the plates breaking), I’d fathom that I have 1 out of 4 possible places to get it right the first time.
Similarly, if I was given a 3x5 matrix, and the same conditions above, I would have 1 out of 15 chances to get it right.
Now, if I was told that it can be solved after 2 hits, things are slightly different. After the first hit (where the probability of getting it right is 1/15), I would have 15 more possible places to hit.
This means, the probability of me getting both the steps right is 1/15 * 1/15 or 1/225.
To be honest, I don’t really buy it. I’m sure there is conditional probability involved — the first hit determines how many more possible solutions remain. This then goes into a complex probability tree which makes my brain hurt.
But, the simpler method of multiplying all possible positions appeals to my monkey brain — and I’m happy with that as a way forward.
Ultimately, I’m going to assume that for 1 step solutions, the probability is (1/ n * m), for 2-step solutions (1/ n*m)² and for 3-step solutions (1/ n*m)³.
The Scoring Function
After a lot of trial and error, I arrived at this level difficulty scoring function
It’s essentially gets the real probability of solving the matrix by dividing the total number of solutions which are done in n steps by the total possible solutions (which is (a*b)^n ).
As additional step, I’ve normalized the scores to a max of 10,000 and then subtracted it from 10,000, so that the higher scores indicate more difficulty.
Final distribution:
As you can see, there are a lot of solutions in the near 10k area. Which is good, but increases difficulty setting for us.
Difficulty Curves
So far, we’ve established scores for each level. Now, we need to design sections in a way that encourages slower players to continue playing, but at the same time, keep the game interesting enough to the faster player.
There are so many options on the curve, but I wanted to experiment a little.
Taking inspiration from story writing curves:
So, if we modify this a bit, we can get to the below for every section:
A simple python code now can be written to prepare these levels and load them up into the app.
In the next release, I’ll shift to a more dynamic grading system along with player scoring → the idea being that each person plays the game differently and hence the perceived difficulty has to respond to that.
Stay tuned!