Often when designing games, we need to design a pull algorithm, or a way to give the player a random game object from a pool of random objects. It’s hard to visualize how these random distributions look in practice and so difficult to design them well. Over the course of this article, I’m going to present a bunch of small simulations to help understand various algorithms.
Table of Contents
<li>[Basic Player Engagement](#chap1) - [Stimulation](#chap1a) - [On The Simplifications of the Article](#chap1b)
</li> - [Basic Systems](#chap2)
<li>[Pull Systems](#chap3) - [Simple Simulation](#chap3a) - [Pokemon Go](#chap3b)
</li> - [Introducing New Content](#chap5)
<li>[Various Pull Algorithms](#chap6) - [Deterministic](chap6a) - [Placing a Ceiling on Bad Pulls](#chap6b) - [Pokemon Red and Blue](#chap6c)
</li> - [Conclusion](#conclusion)
Basic Player Engagement
Stimulation
This is our first simulation and it’s pretty simple. Just click the interact! button to give the player a game piece. Different players require different amounts of engagement. If a player receives too little stimulation, they will leave.
This is a really abstract representation of how getting stuff in games works. Nevertheless, you can imagine that if this were Pokemon Go, every time you pressed the interact button, the player got a new Pokemon.
</tr></table>
## On The Simplifications of the Article
This is an obvious and gross simplification of the player's experience. However, if we look at it as purely the experience on the single axis of the pull system, and a heavy simplification of that as well, we can still derive value from these simulations. It is also worth remembering that a new feature could do well in this simulation, but still be bad for your game due to something that this article doesn’t cover, such as negatively impacting the decision making in the game or increasing complexity to the point of impenetrability. Video games are complex and need to be looked at with multiple lenses.
## Basic Systems
A common game development pattern is to use a system to drive the player’s engagement instead of hand-crafting it in the manner of the above simulations. It’s often time consuming and expensive to hand-craft a full drop pattern. So, with this simulation, we’re going to go over a basic system to do that for us.
There are three sliders to play with in this simulation:
- Pull Rate: How often the player gets a new game piece.
- Novelty Requirement: The player's need to get new stuff.
Pull Rate
0
Novelty Requirement
1
Observations:
- You can see that in this simulation, you get to an almost steady state very quickly, where the players that want more engagement than the system provides leave and the rest persist indefinitely.
## Pull Systems
## Simple Simulation
We're now going to add some detail to the previous simulation to make it skew closer to a real pull system.
The impetus for this piece came from watching *Pokemon Go* release the second generation of Pokemon into the wild, so we’re going to use that game as the primary example for the rest of the piece. In particular, we’re going to look at the way players randomly encounter new Pokemon to catch, and consider that a pull system.
We’re going to start with the most abstract representation, where we’ll just assume that all of the pieces are of equal value and we’ll assume 100 of them.
Pull Rate
0
Novelty Requirement
1
Number of Pieces
100
Value of New Piece
2
Value of Duplicate Piece
0
Average Number of Pulls:
Average Number of Unique Pieces:
Average Time for Player:
Observations:
- Setting the pull rate to a value equal to that in the previous graph and leaving the value of duplicate pieces at 0 results in the graph tending to 0 as all the players get more and more pieces and so are less likely to experience that boost of getting a new piece.
- If we set the value of a new item to be equal to the value of a duplicate, we can recreate the previous graph trivially.
- Increasing the pull rate beyond a point when the value of duplicate pieces is still 0 results in a *decrease* in average time beyond a certain point as players quickly collect all of the pieces and then quickly leave.
- Increasing the value of the duplicate pieces has a large impact on the size of the tail of the graph.
- For 100 pieces and optimizing for highest average time, the players average about 77 unique pieces.
Possible Improvements:
- Calculating the potential value of a pull - When players have things that they are excited to get, then they are naturally more excited about the chance to get those things. However, that is a layer of complexity too far for these simulations, so the calculation of those effects are left as an exercise for the reader. However, this excitement is a major part of the player experience and you should keep it in mind when designing your own systems.
- Uneven pull rates - In the real world, the pull rate can be as complex as you want it to be. Here, I left it as a steady stream just to keep the simulations simple.
## Pokemon Go
Let’s get a little deeper into what a real pull system looks like. Taking *Pokemon Go* itself, different Pokemon are differently valuable due to the following axes:
- Intrinsic Value - Pokemon have value to players beyond that of simple gameplay. People who like puppies are probably going to like Growlithes no matter what the stats are.
- Not having caught it before - This is a collection game and you want to Catch ‘Em All, so getting a Pokemon that you have not caught before is naturally going to be a major reward moment for most players.
- Evolution - This is similar to the previous one, if of lower intensity. Being able to convert a piece into one that you have yet to get is valuable to players.
- Combat value - Getting a Pokemon that is stronger than the ones you already have or that is able to power up a major member of your team is valuable to players.
We're not going to simulate all of that, just something a little closer to it than the simulation above. Note, that at this level of abstraction, this data can represent a lot of games, not just *Pokemon Go*. To do this, I:
- Gave all of the cards a rarity tier and gave them a new and old value based off that with some random noise.
- Set the number of pieces to 150.
Pull Rate
0
Novelty Requirement
1
Average Number of Pulls:
Average Number of Unique Pieces:
Average Time For Player:
Observations:
- Naturally, these graphs look very similar to the previous ones when the duplicate value is non-zero but less than the new value.
## Introducing New Content
*Pokemon Go*, when introducing the second generation, just added more pieces to their existing pulls. Releasing like that when your players have already performed a large number of pulls results in a graph that looks something like the below one.
Pull Rate
0
Novelty Requirement
1
Number of Old Pieces
100
Number of New Pieces
100
Starting Number of Pulls
0
Value of New Piece
2
Value of Duplicate Piece
0
Average Number of Pulls:
Average Number of Unique Pieces:
Average Time For Player:
Observations:
- For comparison, you can set one of the above graphs to the same parameters to see what your engagement curve would look like if you just only let people pull from the new items. Of course, this is not practical as your players want the ability to catch them all, but it is notable how much worse the graphs for this pull algorithm look.
- Making sure that your duplicate pieces hold value makes a huge difference here.
## Various Pull Algorithms
We've only worked with simple, highly random pull algorithms thus far. In this section, we'll take a look at some other kinds.
## Deterministic
What does this graph look like in the trivial case of just going through every element one by one?
Pull Rate
0
Novelty Requirement
1
Number of Pieces
100
Value of New Piece
2
Value of Duplicate Piece
0
Average Number of Pulls:
Average Number of Unique Pieces:
Average Time For Player:
Note that it *feels* very different for players to get random pulls and to get deterministic pulls. One reason for this is that being able to calculate the effort required for something changes the way players value that thing. These simulations have no way to model that though. They can only show you what players get.
Observations:
- The optimal pull rate is much lower here than for the simple simulation. It also results in a lower average time.
- It's very easy to get all of the pieces to all of the players.
## Placing a Ceiling on Bad Pulls
A common approach to smooth out the variance of a pull system is to place a ceiling on the number of low-value pulls. That results in graphs that look like this:
Pull Rate
0
Novelty Requirement
1
Number of Pieces
100
Value of New Piece
2
Value of Duplicate Piece
0
Bad Pull Cap
0
Average Number of Pulls:
Average Number of Unique Pieces:
Average Time For Player:
Observations:
- The graph drops off much more sharply here.
- It's very easy to param such that all players get all of the items.
- The optimal average time is very close to that of the simple simulation, but the variance is much smaller. All of the players have a very similar experience, which leads to them getting all of the pieces and then leaving.
- So, while all of the players come very close to the average mark, there are no players that spend much more time than the average.
- The optimal pull rate here is lower than that of the simple simulation.
On a personal note, I dislike it when games do this without communicating the skew to the player because I feel it reinforces the gambler’s fallacy. I also feel that making the cap more explicit is a better experience for the player as the player doesn’t feel like bad pulls help them get to good pulls when it is implicit.
## Pokemon Red and Blue
Another option is to divide your pool of pulls across a lot of smaller pools and then let the player move between them. This is essentially what *Pokemon Red* did and also what a game like *Heroes Charge* does as well. This changes the flow to be much wavier, and so the graph looks more like this:
Pull Rate
0
Novelty Requirement
1
Number of Old Pieces
100
Number of New Pieces
100
Starting Number of Pulls
0
Value of New Piece
2
Value of Duplicate Piece
0
Average Number of Pulls:
Average Number of Unique Pieces:
Average Time For Player:
Of course, there are a lot of ways to implement a division like this and the amount of effort required is dependent on the kind of separation that you want to make.
Observations:
- The optimal average time here is much higher than in any of the other simulations.
- The optimal pull rate is lower than in any of the others, but only slightly below the cap.
- Once again, the player ends up with all of the pieces here in the optimal scenario.
## Conclusion
This is, of course, a very incomplete taxonomy. Hopefully though, it lets you think about how players interact with the pull systems that you have made and the potential problems and benefits of these solutions.
You can look through the source code here - [https://github.com/nikwin/pullArticle](https://github.com/nikwin/pullArticle)
If you have any feedback on this or if you want to see more things like this, you can reach me on Twitter at [@murthynikhil](https://twitter.com/murthynikhil). If you make any new simulations like this, please do tell me. I’d love to see more explanations like this.