Random Generation - Rare Powerups

Started by
4 comments, last by Concentrate 12 years, 11 months ago
Hey all, hope this is the right form for this. Im currently making a random generator that spawns powerups every now and then. The problem is I'm trying to make some items more rare as you progress up in level and some items less rare the higher you get.

Here is what I have tried. Firstly I just tried to make items a set percentage


private int getPowerup()
{

int range = Random.Range(1, 101);

float atomic = 95;
float hammer = 60;

if(range >= atomic) {

return 9;

}else if(range >= hammer) {

return 10;

}

//else Gun
return 11;

}



Then I tried


private int getPowerup()
{

percentage = currentLevel / maxLevel;

int range = Random.Range(1, 101);

float atomic = 95 * (1 - percentage);
float hammer = 60 * percentage;

if(range >= atomic) {

return 9;

}else if(range >= hammer) {

return 10;

}

//else Gun
return 11;

}



But this doesn't seem to be exactly what I was after either. Would anyone have any recommendations as to what I should try?

Thanks in advance
Advertisement
It looks like you have Hammer as being very common at low level and less common at higher level, and Atomic as less common at low levels and more common at high levels?

Otherwise make sure percentage is properly evaluated as a float between 0 and 1 (you might have to cast the variables in the ratio?)
Hmm, I'm pretty sure I posted a reply yesterday? ok ill try again :)
[color=#1C2837][size=2]
PrestoChung: [color=#000000]

Thanks for the reply. Thats sort of the effect that I was going for. I want the 2 properties to increase and decrease as the level nears the last. Problem with the above code is the if statement. Eventually the hammer wont have any chance at all because the atomic will be such a high percentage it will just skip hammer in the if statement. I think I have a solution now though. Ill give it a shot and let you know how it goes. Thanks again



I ended up tackling it a bit different. Used this tutorial on weighted numbers.
http://www.javascriptkit.com/javatutors/weighrandom2.shtml
The method you've found should work, but may become unhandy. Assume that at the beginning 1% probability for item A and (therefore) 99% for item B is wanted. Then you need to generate a 100 element array where 1 element is set to A and 99 is set to B.

You may use a iterative solution instead, similar to your 1st code snippet in the OP. However, such a solution does a search and will hence be less runtime efficient than the above one.

Assume that the probabilities p[sub]i[/sub] for j items, 0 <= i < j, are given. Then generate a uniformly distributed random number n in [0,1] and compare it with partial sums of the probabilities and pick the belonging item as follows:

pick item i where p[sub]i-1[/sub] < n <= p[sub]i[/sub] with p[sub]-1[/sub] = -infty (any number less than 0 would work)

There is a little inconsistency because item #0 is in the closed range [0,p[sub]0[/sub]] while any other item is in a left-sided open range (p[sub]i-1[/sub],p[sub]i[/sub]], but that can be neglected for any practical purposes.

The above can be accomplished for example by

for( item=0; item<noofItems-1 && n>probabilities[item]; ++item) {
n -= probabilities[item];
}
// use 'item' here as needed

where the item<noofItems-1 is there just to avoid array accesses out of bounds due to numerical inaccuracies.

Another way would be to pre-compute an array with the partial sums


sum = 0;
for( item=0; item<noofItems-1; ++item) {
sum += probabilities[item];
summedProbabilities[item] = sum;
}
summedProbabilities[noofItems-1] = 1; // a value >1 can be used for absolute safety

where the last line again is for avoiding array accesses out of bounds later on. Then the assessment can be done like


for( item=0; n>probabilities[item]; ++item) {}
// use 'item' as needed here

This solution is a bit more runtime efficient than the former one, I think, but requires an additional array (of a length equal to the number of item types).
Just a thought, but instead of actually generating the series of items weighted number of times, you can act like you generated it by simply assuming it is in the range, so for example

[source]
int weapons[] = { ROCK, HAMMER, GUN };
int weight[] = { 7, 2,1} ; //70 % , 20% , 10% -- note should depend on the level

int pickedWeapon = rand() % 9 + 1 ; // 1-9
//[1,7] -> pick rock , P(X) = 70% since 7 different range
if( 1 <= pickedWeapon <= weight[0] ) { return weapon[0]; }
//[8,9] -> pick hammer , P(X) = 20% since 2 different range
else if(1 + weight[0]<= pickedWeapon <= weight[1] + weight[0]) { return weapon[1]; }
//[10,10] -> pick gun, P(X) = 10%, since 1 different range
else if(1 + weight[0] + weight[1] <= pickedWeapon <= weight[2] + weight[1] + weight[0]){ return weapon[2]; }
[/source]

The above was just an idea,nothing definite.
Edge cases will show your design flaws in your code!
Visit my site
Visit my FaceBook
Visit my github

This topic is closed to new replies.

Advertisement