Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

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

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!

1 comment

0

This is called 'Fitness Proportionate Selection' in the computing world: https://en.wikipedia.org/wiki/Fitness_proportionate_selection

1 answer

✓ Accepted answer

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

4 comments

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.

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"

0

Tbh the original method looks alot cleaner and easier :/.

0

Thank you! Had to study it for a bit, but I think I got what's going on!

This discussion is preserved as it was. New answers, comments, and votes are closed.