# Random Generation - Rare Powerups

This topic is 2462 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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?

##### Share on other sites
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?)

##### Share on other sites
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

##### Share on other sites

I ended up tackling it a bit different. Used this tutorial on weighted numbers.
http://www.javascriptkit.com/javatutors/weighrandom2.shtml

##### Share on other sites
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).

##### Share on other sites
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.