An Open Discussion About Nerfs

Every online gamer has been there. Your favorite character, class, item, skill, or strategy is now less useful. The game developers just posted the change log for the latest patch, and something you liked was just nerfed. You might be confused or frustrated (“Why would they do that?”). You might even be upset (“Now my <blank> is worthless!”). Why do players react so strongly to these sorts of changes, and why do developers continue to make them? To begin answering this, we must start, as usual, with the basics.

What is a “nerf?” Aside from being a fairly goofy word, the answer depends on who you ask. A designer will likely give a strict definition: “a change to something that makes it less powerful or useful than before.” A player will give a simpler response: “Anything that isn’t a buff.”

Alright then, what is a “buff?” A buff is a change that makes something clearly better than it was before. In the realm of games, this generally means numbers going up. Damage, range, rate of fire, movement speed, etc. To the typical player, if numbers went up, it was a buff. If numbers didn’t go up, it was a nerf. This sounds reasonable, but is slightly flawed. For example, a designer may intend to make a lateral change, a change not intended to strictly increase or decrease the power of, say, a weapon in the game. Many times this involves numbers being shifted around but as we’ve now established, if numbers didn’t go up, many players will view the change as a nerf.

But why is this a problem? Well, nerfs just feel bad. They’re not very fun. A big part of many games is power fantasy; players like the feeling of being stronger than everything around them, and nerfs get in the way of this enjoyment. Thus, a clear understanding of why nerfs are a necessary tool can ease the sting of something you like becoming less powerful. Clear communication on the reasons and intent behind individual changes can do wonders, but this may not explain why nerfs in general are necessary.

I believe there are 4 main reasons a developer might (and indeed, must) nerf aspects of a game over time:

  1. Power creep
  2. Skill creep
  3. Overpowered elements have a greater effect than underpowered ones
  4. Constantly buffing is not sustainable

Time for some subheadings to explain these in more detail!

Power Creep

Power creep is the general increase in power of game content over time. Typically, new game content is stronger to compel players to seek it out or use it, and over time this can cause imbalances within the game.

Power creep is almost certainly the core reason for most nerfs. Unfortunately, power creep is almost inevitable in any game that undergoes regular content updates. In order to remain a compelling experience, the game must sate the needs of the players and to allow them to feel some form of progression. Often this will alter the original balance structure of the game. If stats were designed around a maximum of 100, and the new maximum is 150, suddenly that much Strength on a character becomes too much. Now Strength, or items that increase Strength, or skills that scale with Strength, may need to be nerfed.

Developers may try to avoid power creep by only providing new options that individually are equal in power to current content, but they must take care not to provide options that, when mixed in creative ways, become overpowered. The style of the game may make this more difficult. For example, it is easier to make tradeoffs between guns in a shooter, but is more difficult in a progression-oriented MMORPG where players expect new items to be better. Another way to combat the problem may be to very carefully add content that scales smoothly on as many fronts as possible. If damage roughly doubles, health may need to do the same. This is exceptionally difficult to pull off in practice, however, so often the only way to stop runaway increases in power are to bring things back down with some good ol’ nerfs.

Skill Creep

So let’s say the game manages power creep perfectly. Fantastic. Maybe the game doesn’t even need content updates because it’s just THAT compelling (Good luck finding a game like this, by the way. They’re exceedingly rare nowadays). The game will still suffer from skill creep.

Skill creep is the natural occurrence of players getting better at a game over time. Players will learn map layouts perfectly, settle into better strategies, collect the strongest gear in the game, explore every option, and get better than the developers at the game. Obviously this is completely unavoidable, and is often overlooked as a reason to nerf by both players and developers. If the game is popular enough and the players are dedicated enough (note: they are ALWAYS dedicated enough), they will play the game far more than the developers and through sheer numbers discover things never found in testing. This can lead to the game being played at a skill level the designers may not have anticipated.

Even if the designers were prepared, in a player vs player setting players will find good strategies, then counter-strategies, then counter-counter-strategies, and so on. At a certain point this cycle may present a tactic that cannot [easily] be countered. In this case, the best solution is often to nerf said tactic. In a single-player or cooperative setting, players may reach a level of mastery that eschews the desired difficulty of the game, but this is often easier to deal with by buffing the opposition instead of nerfing the player since buffs, even when contrary to the player, simply feel better.

Developers must take care, though, as there will always be an extremely large discrepancy between the best players of their game and the average player (unless the game is a very challenging or so-called “hardcore” experience). Making changes that will only affect the top-tier players can have unexpected (sometimes devastating) implications for the average or below-average player.

Overpowered vs Underpowered

Now that the primary ways a game’s balance can change are out-of-the-way, it’s thought experiment time!

Let’s say we have a PvP game with 6 classes. Now let’s say there are 4 perfectly balanced classes (It’s a hypothetical, we can make up ridiculous scenarios if we want!), one overpowered class, and one underpowered class. We’ll assume the game reached this state organically, without any balance changes to the game since launch. Here, balanced indicates that the strength of the class is exactly where the designers intended, and when compared to each other they are roughly equal.

Players of the underpowered class will be unhappy and demand buffs, but the underpowered class will only negatively affect those that play that class. Now, other players may feel slightly bad if the class is so underpowered that it is no longer any challenge, but in general they won’t care all that much. Left alone long enough, the players of the class will probably switch classes (or stop playing altogether), but the game in general will move on, albeit in a lessened state.

On the other hand, the overpowered class degrades the experience for everyone except for those playing it. It causes the players of the class to feel superficially powerful but, depending on how large the balance discrepancy, it causes everyone else in the game to feel helpless. If it’s *really* bad, it can cause many players to consider quitting the game, which is a terrible state for everyone.

Thus, when faced with a mix of underpowered, balanced, and overpowered aspects of a game, it is nearly always a better use of time to focus on nerfing the overpowered aspect first, then shifting efforts towards anything underpowered. In cases where there isn’t enough development time to do both at once, it is possible that when we nerf the overpowered class, another previously balanced classes takes its place. If this happens cyclically, the underpowered class may remain underpowered for a significant amount of time while developers deal with the other classes. I believe these scenarios lead to player assumptions that a game “always nerfs” when it is just a part of the organic power struggle within games.

Constant Buffing

So we’ve established that nerfs are not very fun. But players like fun! And designers like providing fun! So instead of nerfing our overpowered class, let’s buff the balanced classes a bit, and the underpowered class a bit more. Great! Everyone’s stronger than they were originally intended, but people are enjoying the feeling of power.

But over time, one class will eventually fall behind the others. Not because of any changes to the class, but because of new content and skill creep. We can buff again, but eventually we will always find that a class starts to fall behind (or gets ahead) over time. If we buff all the classes to meet the strongest class, we eventually reach a state where every class is simply too strong to provide any kind of challenge. In PvP, everyone dies in seconds (or instantly). In regular gameplay, nothing is a challenge anymore. Now we have a major problem.

Feeling a little overpowered is fun. Killing everything instantly is fun for about an hour. It is always better for the game’s longevity to meter out power increases and keep them under relatively tight control. These power increases will happen, one way or another, through new content or skill creep. As balance starts to settle,  under and overpowered aspects of the game will rear their heads, and then the wonderful nerfs begin! As long as designers habitually explain their changes and avoid over-nerfing (a game can’t constantly nerf for the same reasons it cannot constantly buff), it will help players to feel better about the changes.

Shifting the Experience Curve on a Live Title

Introduction to the Problem

Some time ago I was given the task of rounding out the leveling curve of a live game that has had its level cap increased several times. The level cap increases resulted in a curve with a very difficult last 5-10 levels, while being a little too quick and easy to level early on.

The task involved:

  1. Determining a new curve that ended at the same amount of total experience required (92,500)
  2. Easing the ramp-up in experience required at the high levels
  3. Not increasing the curve too steeply for the early levels
  4. Rolling out the change to several million characters during a game update.

The method for actually creating the new curve itself was a great learning experience, but I will be focusing on the steps taken to shift everyone’s current experience to the new curve without any noticeable disruption in leveling. For reference, however, here is a comparison of the two curves:

There were two main obstacles in rolling out the changes. First, regardless of level, if a player was X% away from their next level, they must be X% away after the change so that a player’s level and exp bar would not change. A fairly simple equation solves this problem. The second obstacle was the time in which the update had to occur. The target downtime during an update is under 10-15 minutes, and the procedure, done in SQL 2005, had to execute during this window.

The following describes the iterative approach that led me to the solution. (To some the solution may seem obvious, but shhh…no spoilers!)

Initial Solution

My first attempt at the problem involved a fairly straight-forward, programmatically-minded solution. The equation mentioned earlier for mapping a character’s old experience to the new experience is:

//currentExp : experience character currently has
//oldReqX : experience to reach current level (old curve)
//oldReqY : experience to reach next level (old curve)
//newReqX : experience to reach current level (new curve)
//newReqY : experience to reach next level (new curve)

percent = (currentExp - oldReqX) / (oldReqY - oldReqX)
newExp = newReqY + (percent * (newReqY - newReqX))

I used a CURSOR to iterate through every character, determined the character’s level (we only store experience values, not level directly) to get the oldReq and newReq values, and ran an UPDATE on every row to change their experience based on the above formula.

Gross. Due to many reasons (primarily the several million UPDATE queries and the poor use of a CURSOR), this was far too slow and would have taken upwards of several hours to run on the live database. Let’s try to cut this down a bit.

Solution #2

My first mistake in this attempt was not looking at the big picture and cutting out the major bottlenecks.

I made a few very minor adjustments to eek out some performance gains such as reordering the level checks (again, current experience is stored, not level) to look for low levels first since there are far more level 1 players than max level players. I also attempted to make a few “clever” math changes.

Unsurprisingly, performance hardly changed.

Solution #3

The next attempt involved simplifying the equation by pre-computing the calculations that remained constant, regardless of current experience.

// precompute 'multiplier' for each level, resulting in multiplier1, multiplier2, ... , multiplerMaxLevel

multiplier = (newReqY - newReqX) / (oldReqY - oldReqX)
newExp = newReqX + ((currentExp - oldReqX) * multiplier)

Essentially, we determine the ratio of how much experience is required in the new curve compared to the old curve and use this value in our calculations.

Great! We’ve cut down on our computations, and even better, removed all division. Running this would take an estimated 90 minutes on live. Much better, but still far too long for our small update window. We need another orders-of-magnitude improvement.

But wait a moment…we’ve just precomputed part of the equation. Can’t we just pre-compute everything? Of course we can! We can directly map every single point of experience from the old curve to the new curve. Simple and, when approached correctly, obvious.

Final Solution

Our solution to the problem uses a look-up table that contains every point of experience and its corresponding new value. There were two potential giveaways for this solution: 1) our equation involves constant values for everything aside from current experience, and we have a finite number of experience points, and 2) we have a graph with an equal number of Y values for every X.

So without further ado, our last query looks like so:

update characters
set ch.oldExp = l.newExp
from characters as ch
inner join tempExpLookup as l
on ch.oldExp = l.oldExp

Simple, straightforward, and extremely fast (compared to the other solutions). This ran on live (roughly 4 million rows) in under 30 seconds. We could probably find more optimizations, but this was more than fast enough for our purposes.

Lessons

I walked away from this problem with several lessons learned:

  1. Match the solution to the environment: While this type of solution would work perfectly well outside of a database environment, my natural tendency to do database work in a programmatic way can cause complications. When in SQL, think in SQL, not in C.
  2. Look for big-picture optimizations before making minor or “clever” tweaks. If your run time is orders of magnitude too slow because you’re calculating PI in every iteration, using bit shifts instead of multiplication isn’t going to help all that much. Which leads to:
  3. Pre-compute as much as possible: This applies to equations, object instantiations, etc. This is an obvious, easy method of getting performance gains for the low cost of re-evaluating your solution.

Thanks for reading!


This post is the first post produced as part of a month-long writing challenge I’ve committed to, so I hope to have many more posts done by the end of August.

Introduction – Who, Why, and What

Finally got around to creating one of these. I feel so productive!

As my first post, I feel compelled to explain a bit about who I am, why I am doing this, and what this will not be. That last part is mainly to serve as a reminder to myself so that I stay on track over time and don’t turn this into a cooking blog or something.

So without further ado:

Who Am I?

Sticking with who I am for the purposes of this site, I am exactly two things: a game developer, and a game player.

I’ve found that these two identities both help and oppose the other. Time spent in one area can help in both if done correctly, but often times simply gets in the way of doing the other. This project will hopefully help me balance and bridge the two a little more than I have in the past, especially in the direction of playing → developing.

Also, my name is Nick, main online handle is Hudelf.

Why Am I Doing This?

There are a number of reasons I want to do this. The main ones (and the ones that will shape the type of content that ends up here) are to:

  1. Think clearly and organize my thoughts on game design and development
  2. Improve my writing
  3. Improve my analysis of games
  4. Improve my abilities as a game designer/developer
  5. Help motivate myself in side-projects that I start by cataloging my progress

What This Blog Will Not Be

This is mainly a warning to my future self (Let’s call him Ian! Hi Ian!) to not fall into these traps that I anticipate if I’m not careful.

I do not want this space to turn into:

    1. A collection of game reviews. I intend to look at games and analyze their design successes/pitfalls, technical achievements, etc. but these should never serve strictly as a review.
    2. “What I did today” – There is nothing wrong with a space like that, but I want to make sure any accounts are combined with analysis and takeaways.
    3. Another dead project of mine. So Ian, promise me this won’t be neglected! I’m not so ambitious that I have a timeline, but I’d love to get out fairly regular posts (1 every week or two would be grand).

And that’s that. One post down!

Follow

Get every new post delivered to your Inbox.