So I want to randomly pick different values from a table but with some rarer than others, how do I do this?
local values = {"value1","value2","value3"} local selectedvalue = math.random(1,#values) --this works, but how do I do it if vaule 1 has twice as much change to be selected than value 2 and 3? This just gives them all the same chance...
One way of going about this is by duplicating the values in the table, like so:
local values = {"value1","value1","value2","value3"}
This way, however, can be long to type, so you could do something like this:
-- For each entry, the first value is the actual value, and the second is the 'weight' or chance. local values = { {"value1", 2}, {"value2", 1}, {"value3", 1} } local SelectFrom = {} local SelectedValue for i, v in ipairs(values) do for i2 = 1, v[2] do table.insert(SelectFrom, v[1]) end SelectedValue = math.random(1, #SelectFrom) end
This works like the first method, but compresses the values, then decompresses them when selecting.
There may be other (better) ways; this is just the first one I came up with. It is also untested.
The first method is a pretty good one, and I'd go with that because it's the first one I thought of too. The alternative is to have a weight table, wherein the selection is done in part of a single random number out of 1.
local items = { {item1, 2}, {item2, 3}, {item3, 1}, {item4, 1} }; local max = 0; for i=1,#items do max = max+items[i][2] end; local selection,cnt = math.random(),0; for i=1,#items do cnt = cnt+items[i][2]/max; if cnt > selection then selection = items[i][1] break end; end; if type(selection) == 'number' then selection = items[#items][1] end --Just in case
selection
would at that point become your item. This is good because it can be mixed with other loot tables and have inheritance implemented with ease.