AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Suggestions / Requests (https://forums.alliedmods.net/forumdisplay.php?f=12)
-   -   Solved Suggestions on randoming (https://forums.alliedmods.net/showthread.php?t=309089)

Airkish 07-13-2018 13:28

Suggestions on randoming
 
sup folks,

need suggestions for best random experience.
i.e. I have 5 items with chances of: 97 90 54 35 2

How do I pick one of those items based on chance?

edon1337 07-13-2018 13:49

Re: Suggestions on randoming
 
5 items with chances > pick one based on chance?

What chance?

Relaxing 07-13-2018 13:52

Re: Suggestions on randoming
 
Get a random number starting from a range of the minimum and the maximum number of an array, and then find the closest number(the random number result) on that array.

Code:
new min = 0, max = 100, result result = random_num(min, max) find_the_closest_number_on_array(data[], len, result)

Airkish 07-13-2018 14:08

Re: Suggestions on randoming
 
Quote:

Originally Posted by Relaxing (Post 2603358)
Get a random number starting from a range of the minimum and the maximum number of an array, and then find the closest number(the random number result) on that array.

Code:
new min = 0, max = 100, result result = random_num(min, max) find_the_closest_number_on_array(data[], len, result)

Is there such function and how do I actually use it?

Relaxing 07-13-2018 14:37

Re: Suggestions on randoming
 
Here's an algorithm I found on web: https://www.geeksforgeeks.org/find-c...-number-array/

maqi 07-13-2018 21:31

Re: Suggestions on randoming
 
If you are picking a single item randomly between a few, the sum of all chances must be 100%. Otherwise its just wrong, like in your example :D

fysiks 07-13-2018 22:52

Re: Suggestions on randoming
 
If you're looking for a chance between two options (yes and no) then you can use this:

Code:

#define chance(%1) ( %1 > random(100) )
chance(90) will return true 90% of the time (on average).

But, as maqi mentioned, if you are trying to give one of the 5 items, the probabilities need to add up to 100 and then you would use a different algorithm to determine which item they get.

EDIT:

Here is a function that will select from a list of items depending on their probability. The probabilities must add up to 100. It returns the index of the item that was chosen randomly.

Code:

stock random_item(itemChances[], count=sizeof itemChances)
{
        static rand, i, sum
        rand = random(100)
        i = sum = 0
        for( i = 0; i < count; i++ )
        {
                sum += itemChances[i]
                if( sum > rand )
                        break
        }
        return i
}

Examples:
Code:

new chanceItem = random_item([10, 70, 20], 3)
10% of the time, chanceItem will be 0
70% of the time, chanceItem will be 1
20% of the time, chanceItem will be 2

Airkish 07-14-2018 00:08

Re: Suggestions on randoming
 
Quote:

Originally Posted by fysiks (Post 2603426)
If you're looking for a chance between two options (yes and no) then you can use this:

Code:

#define chance(%1) ( %1 > random(100) )
chance(90) will return true 90% of the time (on average).

But, as maqi mentioned, if you are trying to give one of the 5 items, the probabilities need to add up to 100 and then you would use a different algorithm to determine which item they get.

EDIT:

Here is a function that will select from a list of items depending on their probability. The probabilities must add up to 100. It returns the index of the item that was chosen randomly.

Code:

stock random_item(itemChances[], count=sizeof itemChances)
{
        static rand, i, sum
        rand = random(100)
        i = sum = 0
        for( i = 0; i < count; i++ )
        {
                sum += itemChances[i]
                if( sum > rand )
                        break
        }
        return i
}

Examples:
Code:

new chanceItem = random_item([10, 70, 20], 3)
10% of the time, chanceItem will be 0
70% of the time, chanceItem will be 1
20% of the time, chanceItem will be 2

I can't make chances add up, it would be too complicated.

I'm thinking about this:
4 different rarities - 1 (1-10%), 2 (11-30%), 3 (31-60%), 4 (61-100%).

random(100) to get % and check rarity, then just pick random item who has that rarity?
Not sure how fair it would be

fysiks 07-14-2018 01:28

Re: Suggestions on randoming
 
Quote:

Originally Posted by Airkish (Post 2603431)
I can't make chances add up, it would be too complicated.

I'm thinking about this:
4 different rarities - 1 (1-10%), 2 (11-30%), 3 (31-60%), 4 (61-100%).

It's super easy:

Code:

item = random_item([10, 20, 30, 40], 4) + 1
Quote:

Originally Posted by Airkish (Post 2603431)
random(100) to get % and check rarity, then just pick random item who has that rarity?
Not sure how fair it would be

That doesn't make any sense. Use my function as shown above.

klippy 07-14-2018 05:08

Re: Suggestions on randoming
 
You could map your probabilities so they all add up to a total of 1, whatever their values are. I'll be expressing probabilities in the range [0, 1] but you can always multiply it by 100 to display the chance in percents.

Untested, but the same algorithm did work in JavaScript for me:
Code:

GetRandomItem(const Float:itemChances[], count = sizeof itemChances) {
        new Array:mappedChances = ArrayCreate(1, 0);
        new index = 0;
        new Float:sum = 0.0;
       
#if AMXX_VERSION_NUM > 182
        ArrayResize(mappedChances, count);
#endif

        // Put all elements into mappedChances and accumulate
        for(index = 0; index < count; index++) {
                ArrayPushCell(mappedChances, itemChances[index]);
                sum += itemChances[index];
        }
        // Map so the sum of all chances is 1
        for(index = 0; index < count; index++) {
                ArraySetCell(mappedChances, index, ArrayGetCell(mappedChances, index) / sum);
        }
        sum = 0.0;
        new const Float:rand = random_float(0.0, 1.0);
        for(index = 0; index < count; index++) {
                sum += ArrayGetCell(mappedChances, index);
                if(rand <= sum) {
                        break;
                }
        }
       
        ArrayDestroy(mappedChances);
        return index;
}

Code:

new const Float:itemChances[] = { 0.5, 0.1, 0.05, 0.15, 0.2, 0.4, 0.04, 0.06, 0.5 };
new const result = GetRandomItem(itemChances, sizeof itemChances);

As you can see, the chances in the array add up to 2.0 (or 200% percent), but in that case if you divide them by 2 they will add up to 1.0.
It's pretty much what Fysiks did but with the mapping step so input values don't have to add up to 100%.


All times are GMT -4. The time now is 09:10.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.