I wrote this small weighted random function for a project I’m working on. It turned out to be general enough I figured others could use it for their own projects. The random function itself is quoted here, and there is a DefoldCodePad link to an example program where you can adjust the drop chances in the example table. It should be simple to adopt this code to your projects.
- Returns a random item from item_table parameter based on the “weight” field
- Weights are relative to each other so they do not have to sum to a certain number
- Excluding the weight field, setting it to 0, or nil will exclude it from being picked
- Setting all weights to 0 returns the first value from the pairs iterator
- If no weight fields are found in the item_table values, this function will return nil
- Use any random function with interval of [0,1) (or [0,1] should also work with the code below)
local function rand_weighted(item_table)
local weight_sum = 0
for _, item in pairs(item_table) do
if item.weight then
weight_sum = weight_sum + item.weight
end
end
local r = math.random() * weight_sum
for _, item in pairs(item_table) do
if item.weight then
r = r - item.weight
if r <= 0 then
return item
end
end
end
end
The rest of the code in the Codepad example is to demonstrate the use of this. It’s very verbose in the comments and code for clariy. This is the first time I’ve contributed code to a public audience and I have no professional development experience, so please give any constructive feedback on how to better share stuff like this or future improvements.
This did not seem worth creating a git repo and an asset portal submission since it is a simple well-known algorithm, so I’ve put it together in the Defold Codepad. I also wanted a reason to use the Defold Codepad.
The weights in the example initially give the red tiles/items the biggest chance of dropping. Those can be adjusted per the instructions in the comments (there is a table at the top of the file with a big comment block). I found the Codepad limited in being able to demonstrate what I wanted to demo once I started writing it, but it is still useful to play around with.
Edit: typos, add description from example code comments, fix comment indention in Codepad link at factory.create(), clearer Codepad link