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

How do I randomly pick something from a table with raritys?

Asked by
lucas4114 607 Moderation Voter
8 years ago

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...
1
Rarities* ChemicalHex 979 — 8y

2 answers

Log in to vote
3
Answered by 8 years ago

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.

Ad
Log in to vote
1
Answered by 8 years ago

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.

Answer this question