Question on complex probabilities

I haven’t had any math classes that went heavily into probabilities. Bear with me because I feel I couldn’t ask my question sensibly without explaining the situation. I recently decided to fire up Final Fantasy VII and play it some. I’m trying to raise my stats by morphing certain creatures into sources (which raise my stats). Well I found it’s a lot easier to link a bunch of morph materia with sneak attack materia causing the character to morph enemies without me even having to do anything but get into fights. The problem is when the sneak attack materia is leveled up completely, it still only has an 80% of working. I have 5 of them, all of which have an 80% chance of causing a morph in each battle. I’m currently only fighting one enemy per battle, but each takes two morphs to work. I’m wondering what the odds are for a particular battle that less than two morphs will work forcing me to do it myself. Also, what about when I get a 6th materia combination and it only has a 20%, 40%, etc., chance of working? And is there a quick way of solving these problems on a scientific calculator? Thanks.

The odds of a particular materia failing to cause a morph effect are 20%, or 0.2. Hence the odds of all five failing are (0.2)^5, or 0.00032. The odds of exactly four failing and one succeeding are (0.2)^4 * 0.8 * 5, or 0.0064. Hence the odds of less than two successes are 0.00032+0.0064=0.00674, or less than one percent.

In general if you have n independent events (like the chance of each individual materia working) and the probability of a success with each individual event is p, then the probability of exactly k successes is

p^k * (1-p)^(n-k) * C(n,k)

where C(n,k) = “n choose k” = n!/(k! * (n-k)!) is the number of different choices for which k events will succeed. Your calculator probably has a function to calculate C(n,k) automatically, most scientific calculators do.

To get the probability of “k or fewer successes” you have to add up the individual probabilities for k successes, k-1 successes, and so on.

By the same token, if you only had four sneak attacks, you would have a 0.0016 chance of none working, and a 0.0256 chance of exactly one working, for an overall 97.28% chance of two or more working. With three, your chance of success would be 89.6%, and even with only two, you’d have a 64% chance of success. With this in mind, it might be worthwhile to replace one or more of your sneak attack materia with something else which would make the fight easier (though I don’t know enough about the game to make any suggestions on this score).

As Chronos alluded to, adding more sneak attack/morph materia pairs will quickly increase your chance of success at first, but you’ll pretty quickly run into a point of diminishing returns.

Unfortunately, there’s no simple expression for the probability you’re after, so the scientific calculator may be a no-go.

Awesome. That’ll help me out a lot. So regarding having a sixth materia with a 20% chance of success, could I just add the following three results together?

p0 = most common materia chance of success (80%); p1 = lone materia chance (20%)
n = total number of materia (6); n0 = number of repeating materia (5)
k = number of successes (1)

(1 - p0) ^ n0 * (1 - p1) = 0.000256 ; chance of none working
p0 ^ k * (1 - p0) ^ (n0 - k) * C(n0, k) * (1 - p1) = 0.00512 ; chance of one 80% working
(1 - p0) ^ n0 * p1 = 0.000064 ; chance of 20% working

Thus I come up with 0.00544 as the odds of 5 80% materia and 1 20% materia having less than two successes. It seems about right being just a little under the chance of less than 2 out of 5 working. Do you guys concur? It would be fairly easy to make a program that calculates it if the above is correct.

The probability of at least two successes with your combination is .998656–very high, but not much higher than what you get with just the 5 maxed out materia.

Again, there’s no simple formula for something like that.

I forgot about this part. If your calculator is programmable, then there is in fact a simple method for solving any probability problem, requiring very little time to program. It’s called the Monte Carlo method, after the famous casino. All you do is model your problem with a random number generator, run it many times, and see how many successes you actually get. This has advantages and disadvantages over direct computation: It’s usually easier to figure out how to do it, and you’re less likely to make a mistake, but it’s never quite exact (how close it is depends on the number of trials you run it for), and depending on the problem, it can be slow to run (usually not a big deal, with modern computer speeds).

I must be getting old, because I have no idea what the OP was saying. Materia? Morph? Sources? Levelled up? It’s like trying to read Jabberwocky or something.

Alright, I created a program on my computer in C just as Chronos mentioned. I ran it with 5 items at 80% with a minimum success of 2 items at 10 million iterations and it came up with a 99.323610 percent chance of success, which is about 14/10,000 of a percentage off of what was calculated. Consequently, I’d say it’s fairly accurate. Also, I ran it with 100 million iterations with an extra item at 20% (like my second question above) and it came up with a 99.455891% chance of success. This is about 1/10,000 of a percentage off from what I predicted in my second post. I therefore have to respectfully disagree with ultrafilter. I will post again in a few minutes providing the source code to my program and an example of using it.

I don’t think you need to know these things to answer the question, but I’ll give a short explanation anyway. Materia are basically magical rocks that give you a certain magical ability each. I’m pretty sure they’re unique to Final Fantasy VII. In the example, I talk about sneak attack materia and morph materia. Sneak attack materia give you a percentage chance of performing the action of whatever materia is linked with it, in this case morph. The percentage chance of one working in a particular battle is equal to 20 times the level it’s on, except for level 5 which is still 80%, but another level 1 materia spawns at that point. Of course morph materia allow you to perform the morph action. Morphing certain enemies transform them into items. The morph has to kill them though, and since I’m fighting enemies that have slightly more health points than I take off in one hit, I have to hit them with two morphs (or one regular attack and one morph but there’s no regular attack materia to link with sneak attack). Finally, sources give you one extra point on one of your stats. For instance, power sources raise your strength stat by one point, making you attack for more points. It’s the only way to strengthen yourself after hitting level 99, which I have. (Levelling up increases all your stats by a small amount and happens after you gain a certain amount of experience from fighting.) That wasn’t as short an explanation as I wanted, but I guess it’s a somewhat complicated topic.

Here is the source code to the program. I whipped it up in less than an hour so it isn’t very optimized, but it gets the job done. Bear in mind that there isn’t much error checking for the input so if you put in erroneous numbers, it may puke. (It shouldn’t do anything worse than segfault, but who knows with computers, especially Windows. I take no responsibility for whatever may happen if you compile and run it.) The number of items, minimum successful items, and probability should be greater than 0 (probability can equal 0) and less than 256. Iterations can be anything from 1 to 4,294,967,295. Furthermore, this was designed in FreeBSD with gcc. It’ll probably compile in any unix-like operating system with gcc, but may need minor revisions to compile in other environments. Anyway, here is the source:



int main(int argc, char **argv[])
{
	unsigned char num_probs;
	unsigned char prob[256];
	unsigned char successes;
	unsigned char min_success;
	unsigned long int num_iterations;
	unsigned long int rep;
	unsigned long int occurances;
	unsigned long int iteration;

	printf("Number of items: ");
	if (!scanf("%hhu", &num_probs) || num_probs == 0)
	{
		printf("Error with input
");
		exit(1);
	}
	printf("Minimum successful items: ");
	if (!scanf("%hhu", &min_success) || min_success > num_probs)
	{
		printf("Minimum successes must be a number less than the number of probabilities
");
		exit(1);
	}
	printf("Number of iterations: ");
	if (!scanf("%lu", &num_iterations) || num_iterations == 0)
	{
		printf("Iterations must be a positive integer
");
		exit(1);
	}
	printf("Probability 1: ");
	scanf("%hhu", &prob[0]);
	rep = 1;
	while (rep < num_probs)
	{
		printf("Probability %u: ", rep + 1, prob[rep - 1]);
		if (!scanf("%hhu", &prob[rep]))
			prob[rep] = prob[rep - 1];
		rep++;
	}
	srandomdev();
	occurances = 0;
	for (iteration = 0; iteration < num_iterations; iteration++)
	{
		successes = 0;
		for (rep = 0; rep < num_probs; rep++)
		{
			if ((int)random() % 100 < prob[rep])
				successes++;
		}
		if (successes >= min_success)
			occurances++;
		if (iteration % 1000000 == 0 && iteration != 0)
			printf("%lu iterations
", iteration);
	}
	printf("Done
");
	printf("Percentage of success: %f\%
", (float)occurances / (float)num_iterations * 100.0);
}


Here is an example of me using the program:



[kenshi@kenshi ~/programming]% ./probability                     
Number of items: 5
Minimum successful items: 2 
Number of iterations: 10000000
Probability 1: 80
Probability 2: 80
Probability 3: 80
Probability 4: 80
Probability 5: 80
1000000 iterations
2000000 iterations
3000000 iterations
4000000 iterations
5000000 iterations
6000000 iterations
7000000 iterations
8000000 iterations
9000000 iterations
Done
Percentage of success: 99.323610
zsh: exit 33    ./probability


I did make a mistake earlier. Here’s the derivation:

X is the number of success from maxed-out materia, and is binomial (5, .8). Y is the number of successes from the level 1 materia, and is binomial (1, .2). I think it’s reasonable to assume that X and Y are independent.

We want P(X + Y > 2), which is equal to 1 - P(X + Y < 2). P(X + Y < 2) = P(X + Y = 1) + P(X + Y = 0).

P(X + Y = 0) = P(X = 0, Y = 0) = P(X = 0)P(Y = 0) = (1 - .8)[sup]5[/sup](1 - .2)[sup]1[/sup] = .000256.

P(X + Y = 1) = P(X = 1, Y = 0) + P(X = 0, Y = 1) = P(X = 1)P(Y = 0) + P(X = 0)P(Y = 1) = 5 * .8 * (1 - .8)[sup]4[/sup] * (1 - .2)[sup]1[/sup] + (1 - .8)[sup]5[/sup]* .2 = .00512 + .000064 = .005184.

So P(X + Y > 2) = 1 - (.000256 + .005184) = .99456, which is closer to the simulated answer. I forgot the factor of 5 the last time.

Oh I just saw that I left out something. There needs to be a return line before the last closing brace, like this:

printf("Percentage of success: %f%
", (float)occurances / (float)num_iterations * 100.0);
return 0;
}

It still works (at least in my environment) but will return a non-zero value most of the time, causing the program running it to think it is returning an error when it’s not. It’s not a major problem in unices and probably not Windows but it’s a really easy fix.