I want to create a function that will return an item from a table where the item has a certain chance of being returned.
I already found some stuff about weighted random functions and tutorials on the DevForum, but none have been very clear on how exactly I can achieve this.
math.random gives all items in a table the same chance of being picked, instead, I want something like this:
local OrderedTable = {
["This is very common"] = 80, -- 80 percent chance this value is returned
["This is less common"] = 30, -- 30 percent chance this value is returned
["This is very uncommon"] = 10 -- 10 percent chance this value is returned
}
What you can do is something like this. Use math.random to get a random number from 1-100. Then have three if statements, one checking if the number is <= 80, another if its > 80 and <= 95, and another if its > 95.
You can adjust the numbers to whatever chance you want but you get the idea. The numbers in your example don’t add up to 100% so I made up some numbers as an example.
It doesn’t have to add up to 100, basically, all common stuff gets a high number, and the less common stuff will get a lower number.
I’m looking for a more efficient way of doing this, I’ll be using this on a table that could get 100+ items, it’s not feasible to spaghetti code 100 if’s and add more code every time I create a new item.
Just got it working, some DevForum posts about this were a bit unclear, but in my code, there was another factor that made it look like it wasn’t actually working.
I changed this code a bit to get the following function:
function WeightedRandom:RandomFromWeightedTable(OrderedTable)
local TotalWeight = 0
for Piece, Weight in pairs(OrderedTable) do
TotalWeight = TotalWeight + Weight
end
local Chance = math.random(1, TotalWeight)
local Counter = 0
for Piece, Weight in pairs(OrderedTable) do
Counter = Counter + Weight
if Chance <= Counter then
return Piece
end
end
end