Okay, first of all, what is this concept of “diminishing returns”? Put simply, “diminishing returns” is the concept of getting less out of some system the more times you put in a constant amount. In the real world, diminishing returns are all over the place. Take, for instance, your body’s tolerance to alcohol….
Let’s say I’ve just turned 21 and never had a drink in my life (because we know I’m all about law-abiding and whatnot). Now let’s say that since I’m 21, I decided I’m going to get drunk every single day for the rest of my life. Worthwhile goal, of course, but it gets expensive fast. On the first day I do this, 2 shots of rum may be more than enough. But the next day, 2 shots might not give me quite the same effect. Within a week I’d probably need three or four shots to keep it up, and within a month five or more per night. The same input (shots of rum) gives me less output (intoxication) each occurrance. In this case, I’m having to increase the input in order to keep the output constant.
Other real-world examples include: weight loss, where light jogging once a week will do wonders when you’re obese, but does nothing once you’re only slightly out of shape; any drug your body can come to tolerate, be it alcohol, heroin, or over-the-counter pain killers; or uptime on a heavily-trafficed website (such as Amazon), where cost rises exponentially the closer you get to that impossible “100% guaranteed uptime”.
Rule #1: The formula is just producing a “texture” for your system. You can’t just say “Oh, I’ll go with
sqrt(x)” and be done with it. The formula you use gives your diminishing returns system a certain feel, but you will almost certainly need to tweak it to fit a given game! Tweak the input before you send it. Tweak the output before it’s returned. You can grab the exact arc you need for a given game without all that much work, and doing so is almost always a good idea.
The systems I have found while trying to figure out good ways to design my own games (FYI, the research I’ve done has yet to make it into a game, so don’t ask):
- Logarithms: no upper limit, insanely fast degradation of value. Changing the base and translating input and output can help tremendously, but this is really a system to build for very specific situations, not general-use.
- Roots: no upper limit, very translatable (square root? cube?
x^(0.9927), even), much more smooth degradation than logarithm, and a lot more generally usable.
- Decay: In particular, exponential decay (
e^(-Cx)) can be translated for general-use formulae in situations where you have a set cap, but want to reward every little extra bit of input, even if the reward is so small as to be meaningless.
- Convergent Series: In this case, I’m talking about something like the reciprocal powers of 2 (1 + 1/2 + 1/4 + 1/8 + …), where each step gets closer to 2, but it is never reached. Similar in concept to exponential decay – you have a set cap, but always reward input, even if only by a little.
- Hard-coded: This may seem like a poor choice to a die-hard software engineer, but sometimes it’s by far the best. I think that most games that have a very small set of inputs should seriously consider hard-coded tables. Think of games like D&D, where stats (strength, dexterity, etc.) have a very small range — it’s easier to map inputs to outputs by hand than come up with a fancy formula.
I’ll go into a lot more detail on each of these systems in future articles. For now, the above list should at least help people out who just don’t know what options exist (say, me back when I first design Bloodsport Colosseum).
Diminishing returns articles on Nerdbucket: