Probability

Started by
5 comments, last by JohnBolton 18 years, 7 months ago
I haven't studied probability in school yet, so bear with me in case I use bad terminology or a wrong method of thinking. The scenario: I'm designing a simplistic RPG combat system. The player is able to deal a certain amount of damage in numerical form, depending on his level. As his level increases, I want the probability of hitting high values to increase, and the probability of missing (hitting 0) to decrease. My attempt at the solution: Use a graph. The X-axis runs from 0 to 100 and the Y-axis runs from 0 to 1. In the game, a random number will be generated between 0 and 100. This number will be the input to a function f(x). The output is a number between 0 and 1, which will be used as a percentage of the player's max hit -- i.e., and output of 1 means the player hit his maximum, .5 means the player hit half the max, etc. Now, this f(x) function will be different depending on the player's ability. I have 3 graphs here - first is the graph of f(x) if the player's level is low, second is if his level is medium, and the last on is what f(x) should look like if the player's level is high: Note: p1 and p2 are the same points in all graphs. Negative numbers will be treated as 0. The question: What should the equation look like? I haven't studied higher level math yet (this year I'm only in precalc), so I don't really know what to do. My thinking is that this equation would have more than 1 input, as in, instead of f(x), it would be f(x,z) where z is the players ability. Is this possible/acceptable in math? What is the correct way of doing this? I'll take whatever help you can offer!
.:<<-v0d[KA]->>:.
Advertisement
Heres something quick I made up. It shouldn't be too hard to figure out how it works.

y = (x/100)^(2-1.5z)

Hope it helps.
I guess a way you could do something like this is say the player can reach a max level of 100 or less, but greater than 0. For example, the player could have a level from 1 to 50, or 1 to 100. Then use this function:

probability = log(level)+c /(2+c), where c is a constant > 0.

Then you would generate a random number between 0.0 and 1.0 and if the generated number is less than or equal to the probability, then the player has hit his maximum.

An example.

Level = 1
c = 0.05

Log(1) + 0.05 / (2 + 0.05)
= 0 + 0.05 / 2.05
= 0.05 / 2.05
= 0.02439...

which means the player has about a 2.4 chance of dealing his maximum damage at level 1.

At level 50 it would be something like this:

Level = 50
c = 0.05

Log(50) + 0.05 / 2.05 = 0.8531...

And at level 100 the probability would be 100%

The value of c can be tweaked to change the curve a bit and allow you to control the probability at level 1.

How did I get this? Well there are, say 100 levels. Log(100) = 2. That is where we get the constant 2 from. If we had more than 100 levels, the constant 2 would have to be changed to the Log of the highest level. So if we were at level 100, the probability would be 2. That was too high. It is out of the range 0 to 1. So divide by 2. But the problem is that Log(1) = 0. So we add the constant in so we get a non-zero value. However, this meant that we would go out of range again, so we add the constant when we divide. This puts us right back into the range we wanted.

A more general version of this function would be:

Log(level) + c / ( Log(max_levels) + c )

Hope this solves your problem.
Wouldn't a single graph sufice? More or less like so:
/\|         ....|       ..|      .|      .|    ..|....+-------------->

An aproximation of a combination of all three graphs in one.

y = ( x-50/|x-50| - (1/(x-50)) ) + 0.5

I think this one up here might do the trick, i add 0.5 in the end, so that the function is centered in the Y axis, and use x-50 instead of x so that is is centered in the x axis, the function is also invalid for x=50, because a divide by zero happens, and x must be integer.

y = 1 - (1/x)
y = -1 - (1/x)

These were the original functions, in the first one i'de start with 1 and progressively take smaller and smaller parts of 1 as x increases to create a curve that rises very fast and then very slowly. In the second one the oposite, start with -1 and progressively increase smaller and smaller parts of 1 as x decreases. To put these two together i needed then to change the first one in both functions by x/|x|, so that i get 1 when x is positive and -1 when it is negative. The rest of the changes are the offsets, already described above.

If you want the funtion with more curvature just increase x(to 2x, 3x, x^2, whatever), if you want it with less, decrease x(to x/2, x/3, sqrt(x)).

[Edited by - xor on September 4, 2005 12:50:43 AM]
Well, your first graph is quadratic, the second linear, and the third logarithmic.

So:

f1 will be of the form f(x) = ax^2 + bx + c
f2 will be of the form f(x) = mx + b
f3 will be of the form f(x) = log x

The next step is to specialize these forms for your input and output sets.

Starting off with x/100 creates a number proportional to x, and within the interval [0,1]. So we can set f2 = (1/100)x.

For f1 and f3, we need to do something to x/100 to change the shape of the graph, but without altering the functions domain.

Differentiating f2 yields f2' = 1/100.

For f1, we need this derivative to be relatively small for small x, and relatively large for large x. Multiplying f2' by x gives us a slope which increases with x.

Therefore, f1 = integral of x/100 = x^2/200. This function has a domain of 50, so we divide by fifty to retain the old domain yielding:

f1 = x^2/10000

If that curve steepens too quickly, just multiply f2' by x^2 rather than x (this yields f1 = x^3/1000000).

For f3 we want f2' to be large for small x, and small for lage x. This just happens to be a characteristic of the logarithm.

Suppose we multiply f2' by log(x). Well, x can't ever be greater than 100, and log(100) is 2. This means we need to modify the slope to be:

log(x)/2

Integrating yields f3 = log(x^2)/4.

This is going to generally yield fairly high probabilities.

EDIT: Sorry, I misread your post. I thought you were in calculus, but you're in precalculus. You may not understand what I'm talking about in this post then. [smile]

HTH,
nilkn

[Edited by - nilkn on September 4, 2005 12:07:45 AM]
Quote:Original post by mike25025
Heres something quick I made up. It shouldn't be too hard to figure out how it works.

y = (x/100)^(2-1.5z)

Hope it helps.


I agree, this is probably very close to what the OP wants. What the OP has illustrated is a series of graphs with decreasing power. As was already mentioned, quadratic, linear, and logarithmic, although the last one could well be some power < 1.

Anyway, you're problem now is to take an equation like this an apply the boundary conditions. That is, making it line up with p1 and p2. Might I suggest starting with something like y = m * (x/100)^(2-1.5z) + b, doing a bit of algebraic substitutions involving p1 and p2, and seeing what m and b turn out to be. This should give you a pretty good result.
My stuff.Shameless promotion: FreePop: The GPL god-sim.
You didn't explictly state it, but it looks like you want to base the probability on the difference in the levels between the attacker and defender. I think this function works really well:
    P(x) = atan(a*x+b) / pi + 0.5    x = level_of_attacker - level_of_defender    a affects how quickly the values approach 0 and 1    b shifts the graph right and left 
When a = 0.1 and b = 0, the graph looks like this:

Image Hosted by ImageShack.us

The nice thing about this function is that it is simple, configurable, and continuous. Also, the probabilities are never 0% or 100%.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

This topic is closed to new replies.

Advertisement