Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How would YOU run different sections of code based on a random probability?

Asked by 7 years ago

I was messing around with math.random() in some practice places when I decided to code out a sort of draw system you find in a lot of mobile games. You know - open a super mystery box and have a 70% chance for a common item, 20% for uncommon, 10% for a rare, etc.

I took the obvious route with if statements like this

-- Note: ignore any typos I forgot I'm on a different computer :P

math.randomseed(tick())
randomNumber = math.random(0,100)


if randomNumber >= 0 and randomNumber < 70 then
-- 70% chance code

elseif randomNumber >= 70 and randomNumber < 90 then
-- 20% chance code

elseif randomNumber >= 90 then
-- 10% chance code

end

So I'm curious how you would improve this as if you wanted to chance the probability of one category you'd likely have to change most of the other ones as well. I really feel like I'm missing something incredibly obvious that I could be using.

Thanks a bunch!

0
This is called 'Fitness Proportionate Selection' in the computing world: https://en.wikipedia.org/wiki/Fitness_proportionate_selection duckwit 1404 — 7y

1 answer

Log in to vote
0
Answered by 7 years ago
Edited 7 years ago

Nothing incredibly obvious

--Set up the table of items in an array-style table to be able to sort it
local items = { --Chances add up to 100%
    {'Orange',50}, --{Item, Chance}
    {'Apple',20},
    {'Banana',30},
}
--edit: added normalizing function
local function normalize(t) 
    local total = 0
    for i=1, #t do 
        total = total + t[i][2] 
    end 
    for i=1, #t do 
        t[i][2] = t[i][2] * (100/total) 
    end 
end

normalize(items)

table.sort(items,function(value1,value2) --table.sort accepts a custom sort function
    return value1[2] < value2[2] --sort the table by least chance to most chance
end)
local function randomItem() --define a function that will choose a random item
    local n = math.random() * 100 --choose a random number from 0 to 100
    local currentValue = 0 --current chance
    local chosen --define a variable to be set with the item that is picked
    for i=1, #items do
        currentValue = currentValue + items[i][2] --add to the chance with the item[i]'s chance
        --check if the current chance is greater than the number picked
        if currentValue >= n then 
            chosen = items[i][1] -- set chosen to the item
            break --break the for loop
        end
    end
    return chosen --return the chosen
end

local picked = {}
for i=1, 100 do 
    local item = randomItem()
    picked[item] = (picked[item] or 0) + 1
end
print(picked.Apple)
print(picked.Banana)
print(picked.Orange)
--This should print roughly 20, 30 and 50
0
Why do you sort the table? Also, don't forget to normalise the probabilities or you'll still have to rewrite each one by hand when there is a change in the distribution. duckwit 1404 — 7y
0
The for loop needs to check for the lower chance before checking for the higher one, otherwise "n" could be < 20 and not choose "Apple" Disillusions 61 — 7y
0
Tbh the original method looks alot cleaner and easier :/. farrizbb 465 — 7y
0
Thank you! Had to study it for a bit, but I think I got what's going on! THE_BOZOMO 14 — 7y
Ad

Answer this question