Game Design 101: Balancing Economy

Theory

Andrey Panfilov
Strike the Pixels!
12 min readDec 12, 2019

--

What’s game balance, anyway?

Balance is just numbers.

In my line of work, balance is traditionally divided into to categories:

1. Battle balance

Blizzard’s World of Warcraft

2. Economy balance

CCP Games’ Eve Online

Those numbers are connected.

If they are not connected, “imbalance” happens.

Today we’re going to speak about economy balance.

The first thing to understand is that everything is built on cycles, or loops. Our hearts beat in a loop. The seasons change in a loop. The sun rises and then sets to rise again.

You could argue that life itself is built on a pretty simple loop: any living thing spends energy to gain more energy to spend it… etc.

Or if we look at the modern human’s life, it would probably look something like this: you go to work (so you spend energy and gain money) to buy food (so you spend money and gain energy). The difference from a random animal’s life is that unlike energy, money can be hoarded, so the human has an outer loop: they save up some amount of money to spend it all at once and buy something cool — like a console, or a car, or a dinner at an expensive restaurant — to gain joy.

Practice

Okay, now let’s finally dive into the nitty-gritty stuff. Let’s build a simple game cycle of our own.

The game:

  • the player can kill mobs
  • the mobs drop gold and give XP
  • the player spends gold to buy better swords and healing potions
  • when the player gains a certain amount of XP, she levels up

Conditions:

  • level cap is 10
  • there are 5 swords (excluding the starting one)
  • we want the player to spend 20 days in our game

I will link to a google spreadsheet at the end of the article.

1. Distribute content between days

Let’s start with some assumptions. There are 20 days for the player to play, but only 10 levels, and only 5 swords. So we’ll have to make the player grind a bit to level up and to grind more to buy a sword.

How do we choose the distribution, though? We could try to come up with some formula, but our game is pretty simple, so we can just use our common sense:

  • the content should be handed out generously at the beginning
  • it should thin out towards the end

Yeah, something like that should do. Note that we assume that the sword should be bought at the end of the level.

2. Income and expenses

Now let’s calculate the player’s income and expenses. First, let’s translate the “player gets level X on day Y” to “player spends X days on level Y”:

Now let’s calculate how much gold should the player earn on each level. We could make it very straightforward, but let’s use a proxy metric: how much gold would the player earn on level per day if he spent the whole day on that level.

For that, we would need to build a progression. We could just insert some ascending numbers we like, but it is usually better to use a formula. It can be anything really: a linear function, an exponent, a logarithm. Let’s use the linear function since it’s the simplest one. Let’s say that income per day on level X equals X multiplied by some coefficient k:

f(X) = X * k

And let’s say k is equal to 100, because why not?

After we get our numbers for daily income, calculating income on level is pretty easy — we just multiply our daily income by the number of days the player spends on that level.

Cool, now we need to calculate the expenses. We’re going to use some assumptions again because initial drafts of balance are always about assumptions:

  • the player acts exactly like we assume her to
  • she buys and immediately uses the health potion the moment she is injured
  • she buys the sword the very moment she has enough money
  • she should have 0 gold left at the end of each level

So let’s talk about the days and levels where the player doesn’t buy a sword. Obviously, that means that she spends 100% of what she earns on healing potions:

What about the rest of the levels? Well, we can just pick some numbers we like. So let’s say that the player needs to spend 30% of her income on level one to buy the sword, and the proportion shifts towards more expensive swords with every level.

Now it’s easy to calculate how much gold is spent on healing potions on levels where the player buys a sword because it is just the rest of his gold on that level. Let’s also make sure that the math checks out and the player has no gold left at the end of the level.

3. The mobs

So now we need to know how many mobs the player kills on each level. Let’s use a proxy metric again: we probably don’t really want to have the player kill more and more mobs per day, so let’s make it some constant number. Then we can calculate how many mobs the player kills on each level. We also round everything up, because the player is born to suffer.

Now we know the total gold income on each level and also the number of mobs on each level, so if we divide the former by the latter, we will get the amount of gold the player has to earn for killing a mob.

But wait, is it exciting when you get the same amount of gold for each mob? No-no-no, we’re better than this.

What does the game designer do when he encounters a problem of something being too predictable? He uses random. Now he has two problems.

So let’s say that we want to do it like this:

  • the mob can drop either the “normal” amount of gold or the “high” amount of gold
  • there is a higher probability to drop the “normal” amount than “high” amount

We would probably never use a system like this in the real scenario, but it serves well to illustrate some points about random.

Now let’s just choose the probabilities. 70% seems high enough, and 30% seems low enough to me:

But what do we do now?

A quick digression about the probability theory

In probability theory, our “gold for one mob” would be called the expected value of a random variable. Random variable can be only gold(min) and gold(max) in this case and is never equal to gold for one mob, but on average, after enough killed mobs, the player will get “gold for one mob” per each mob killed.

Photo by Brett Jordan on Unsplash

Think about it like this: let’s take dice — or, rather, a single die. Let’s play a simple game with it:

  • roll the die
  • add the result to our score
  • roll again
  • etc

So how many points we would get for an average roll? If we roll the die a 1000 times (I mean, it’s not like we have anything better to do) and average the score by the number of rolls, we will get a number close to 3.5.

That may not be very intuitive, because there is no face with 3.5 dots on it, but it is true.

But can we somehow get the same result without rolling the die a lot of times? It does get a bit old after 900 rolls, I guess.

Luckily for us, the average result of the D6 roll is an expected value of the D6. Expected value can be calculated like so:

  • take the number of dots on the die face
  • multiply it by the probability to get this face after a roll
  • repeat until you’ve run out of the die faces
  • sum it all up

Since we assume that the die is honest, the probability to get any result is the same — 1/6 (because D6 has 6 faces).

So the expected value of D6 is:

E = 1 * 1/6 + 2 * 1/6 + 3 * 1/6 + 4 * 1/6 + 5 * 1/6 + 6 * 1/6 = 3.5

The math checks out. I’m so glad I don’t have to roll the die anymore.

Back to the mobs

So as we said, in our case gold for one mob is the expected value of killing a mob:

E(gold) = gold(min) * p(min) + gold(max) * p(max)

We already know E(gold) and we chose p(min) and p(max), but we still have one equation and two unknowns, which means that we need to either get more equations or fewer unknowns.

So let’s just say that the “low” amount of gold is half of our “average gold per mob”, so

gold(min) = E(gold) / 2

Now it’s easy to find gold(max):

gold(max) = ( E(gold) — gold(min) * p(min) ) / p(max)

4. Healing potions

The only thing left to calculate now is the amount of healing potions the player buys on each level. Let’s just assume that there is only one type of healing potion, and it always costs the same:

5. Recap

So in the end, we’ve built a crude model of a simple game economy. We:

  • distributed the content between days and levels
  • calculated the player’s incomes and expenses on each level
  • calculated the amount of mobs on each level and reward for killing them
  • calculated the amount of healing potions the player has to buy on each level

This model is intentionally not very good, and now I’m going to demonstrate that.

6. Let’s check ourselves

I’m going to use Python to write a simple script to check if the balance I’ve made is any good:

import randommonsters_count = 3
gold_min = 9
p_min = 0.7
gold_max = 36
p_max = 0.3
golds = []for j in range(100):
gold = 0
for i in range(monsters_count):
roll = random.random()
if roll < p_min:
gold += gold_min
else:
gold += gold_max
golds.append(gold)
print(“Average player has: “ + str(sum(golds)/len(golds)) + “ gold”)

If you don’t know Python, don’t be intimidated. What this code does is:

  • set values for the variables of the monsters amount, gold rewards, etc for level 1 that we calculated earlier
  • creates an empty array
  • runs a hundred times, as if a hundred players were playing:
  • “flips a coin” with the probabilities we calculated
  • decides if the player gets “low” gold reward or “high” gold reward
  • repeats as many times as there are monsters on the level
  • sums up the gold the “player” got on the level
  • adds it into an array created in the beginning
  • takes the arithmetic mean of that array and prints it in a human-friendly format

If you wish, you can run it for yourself. For that, you would need to go to the Python website, click “Downloads” and follow the instructions for your OS. There are two types of Python: Python 2 and Python 3. I use Python 3.

Python comes with a very simple IDE called IDLE. You’ll have to read about it on the Python website too, but I promise it’s really easy.

So, the results are in:

Average player has: 53.19 gold

Looking good! I mean our calculations showed that the player has to get 50 gold on level 1, but it’s not that far. In our calculations, we did a lot of rounding, and random is not 100% reliable (I mean it’s called “random”), so it’s okay.

This is a pitfall that a lot of young game designers fall into. The average player’s life seems okay here, but does the average player truly exist?

Let’s improve our script and add some code to visualize results. If you want to follow through, you’ll need to go to cmd (on Windows) or Terminal (on Mac) and type “pip install seaborn”, and then “pip install matplotlib” to get the data visualization libraries I’m going to use.

import random
import seaborn as sns
import matplotlib.pyplot as plt
monsters_count = 3
gold_min = 9
p_min = 0.7
gold_max = 36
p_max = 0.3
golds = []for j in range(100):
gold = 0
for i in range(monsters_count):
roll = random.random()
if roll < p_min:
gold += gold_min
else:
gold += gold_max
golds.append(gold)
print(“Average player has: “ + str(sum(golds)/len(golds)) + “ gold”)sns.set()
fig = sns.distplot(golds, kde=False)
fig.set(xlabel=’Amount of gold after level 1',
ylabel=’Number of players with that amount of gold’)
plt.show()

So now the code does the same but also plots a graph of the distribution of players by the amount of gold they have at the end of the level.

Yikes. So 40 players really got around 55-ish gold, but:

  • 40 other players got about 35, which is less than needed. They will probably have problems with playing since they will lack gold for new swords or healing potions.
  • 17 players got around 80 gold and 3 got around 100, which means they will have no challenge at all

So why did it happen?

The problem, of course, is in the way the monsters drop gold.

It’s kind of like in this picture:

On average, the shooter hit the bullseye, but in reality, no single shot actually did.

How do we fix it?

Add more mobs

Well, for one, we have to understand that random works better on high numbers.

So if we talk about level 10, we need to kill 15 mobs with a “low” reward of 100 gold and a “high” reward of 434 gold to earn 3 000 gold. If we run these numbers through the script, we will get the following result:

So it’s still no a great picture, but what if level 10 had a hundred mobs? In that case, each mob would drop a “low” reward of 15 or a “high” reward of 65 gold, with the expected value of 30 gold per mob.

As you can see, the amount of gold is distributed much closer to the expected value: 2800–3200 gold instead of 2000–3500.

You could go further and make the player kill 200 mobs instead of 100, and the further you’d go, the less dispersed would be the result.

Narrow the reward range

Let’s imagine gold(min) is only E(gold) / 1.5 instead of E(gold) / 2:

Left: before, right: after

You can see that the results now gravitate closer towards 50. They will move closer and closer there until we hit the point where gold(min) = gold(max) = E(gold).

In the next chapter:

Balancing battle! We will calculate the player’s HP scaling with level, mobs HP, player’s damage, mobs damage, etc.

Also, here is the link to my spreadsheet:

https://docs.google.com/spreadsheets/d/1uav8h8N4g9EQ8shrKdChP8HX4wGDIfAcQp5LWMpMdWQ/edit?usp=sharing

Questions while you wait for the next chapter:

1. Currently, the balance is built in such a way that spending on potions on some levels is less than on the previous ones. That’s not necessarily a bad thing, but how could we change that if we wanted?

2. What would change in the mobs’ section if each level had mobs + boss instead of just mobs? How about mobs + mini-bosses + boss?

3. What do we do with mob rewards if we want to make the player’s experience even less dependent on random?

4. How do we calculate the player’s XP income and expenses if we want the player to have a level?

--

--

Andrey Panfilov
Strike the Pixels!

Game Producer and ex-Game Designer who’s been to dev hell and back, and then back to dev hell and back again.