How to convert a possibly ever-increasing number to a finite scale?

This is common in games, specially management games like Sim City, Civilization, etc: you have actions which provide additional integer bonuses to a metric, but the metric itself remains in a finite scale.

So, for example, suppose you have an `Environment` metric that's on a 0-10 scale. You can buy an item that adds +2 to the `Environment`, build a building that adds +20 etc. And yet the `Environment` metric will only display a value between 0 and 10 as a result. In the early stages of the game you might have amassed a total, "gross" amount of, say 200 environment points, and the `Environment` metric is 7. Later, the total environment points you gathered throughout the game might be in the tens of thousands, and still the `Environment` metric might read something like 7.5.

My question is, how can such a conversion be made? Can you provide some examples? I'm having a real hard time wrapping my head around this, thanks.

• Too broad question. Dive into some math textbook. There are many bounded functions in it. Commented Dec 17, 2015 at 5:42
• @BasileStarynkevitch: there are lots of different possible approaches, of course, but only a few simple, straight forward approaches. I do not think this kind of question is too broad. Commented Dec 17, 2015 at 15:32

Other way to do this is to have opposite "Required Environment" variable, that will increase with different buildings. Then, you can just divide those two, to get "ratio" how "Environment" variable is satisfied.

Ok, for example lets take "Sanitation" in some city building game, because "Environment" doesn't make so much sense. Every house or factory increases "Required Sanitation" value. This value represents how much Sanitation you need for perfectly cover the need for Sanitation. Each water treatment plant or garbage dump increases "Provided Sanitation" value. Now, you could display it as Provided/Required, but you can also display it as percentage value (lets call it Satisfaction) by simply dividing (Provided/Required * 100)%. You should also max it out at 100%, because it doesn't make sense to have more than 100% satisfaction. This value will always be between 0-100%.

So, the Sanitation Satisfaction drops as you build more houses and factories, and it raises as you build more garbage dumps. So even if you have thousand more "Provided Sanitation" numbers than at the beginning your game the "Satisfaction" rating can be same, because you require much more of it. This also simulates the "dimishing return" feel, because adding 10 sanitation to 70% at beginning of game is completely different to adding 10 sanitation to 70% at end of the game.

Of course, the "Required" value might be invisible to player.

• Your answer makes sense if it is a kind of game where something like a total "RequiredEnvironment" exists, due to the game mechanics, something like a "catch-22" which prevents your environment points ever reaching that value. Not sure if the OP has something like that in mind. Commented Dec 17, 2015 at 11:43
• I didn't know about the gamedev site, thanks! Could you go into a little more detail about how that kind of system would work, please? What "satisfying" the Environment variable might look like in practice, etc. (Sorry, I know it's a lot to ask.) Commented Dec 17, 2015 at 15:28
• Wow, this is exactly what I was looking for, thank you so much! Commented Dec 17, 2015 at 16:36

Simple: you start with `f(x)=1/x`, which goes down to zero when x goes to infinity. Now you want this approximate a constant `c` from below, utilize it this way:

`````` f(x)= c - 1/x
``````

From your example I guess you want to allow x=0, and f(0)=0, so try:

`````` f(x)= c*(1 - 1/(x+1))
``````

If the slope of that function does not suffer your needs, there are further ways to modify it like replacing `x` by `x^k`, where k might be a value between 0 and 1, or by replacing `x` by something like `x/b`, where b is a number like 1000, whatever your scoring range is, or both. I hope you get the idea.

• Wow, that worked great to contain the number within a limit, thanks! But all results I get are near the limit (e.g. it's always 9.x if the limit is 10, etc). Is there a way to increase the effective range or am I doing something wrong? Commented Dec 17, 2015 at 15:14
• @SanDiago: you probably have to scale x to your range of points , see my edit. Commented Dec 17, 2015 at 15:30
• Hey man, I gave the point to another user who had a more pertinent approach to my immediate problem. I wish I could give you more for being so helpful and solicitous, I'm sorry I couldn't be more clear in my question, I was really confused as to what I even had to do. But thanks a lot, really. You pointed me to a whole new direction I'm sure is going to be super useful in the future. Thanks again. Commented Dec 17, 2015 at 16:37

If my old memories in mathematics are still intact, I think what you need is some function with a small enough order of growth.

I would give a try to the following:

1) x -> x ^ p, where p < 1 (e.g. for 1/2, we have the classic square root)

2) x -> log[b] (x), where b is the base of the logarithm. E.g. log10(100) = 2, ,log(2)(1024) = 10

3) x -> arctan(x), this will surely limit the output even with your grow to infinity.

The first two functions diverge to infinity, as x grows to infinity, but it might be slow enough for you.

Of course, you should apply some factors to these functions (i.e. scaling) to obtain the best results.

• (Just wanted to let you know that I upvoted your comment and am trying out your approaches.) Commented Dec 17, 2015 at 15:29
• Ok, good luck! :) Commented Dec 17, 2015 at 17:16

The most common operation to limit a range of numbers to a finite scale is the MOD operation.

• There is an implied condition in the question that f(x + y) > f(x) for all positive x and y. The mod function fails to meet this requirement.
– user40980
Commented Dec 17, 2015 at 14:45