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
9 years ago

So I want to randomly pick different values from a table but with some rarer than others, how do I do this?

1local values = {"value1","value2","value3"}
2 
3local selectedvalue = math.random(1,#values)
4--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 — 9y

2 answers

Log in to vote
3
Answered by 9 years ago

One way of going about this is by duplicating the values in the table, like so:

1local values = {"value1","value1","value2","value3"}

This way, however, can be long to type, so you could do something like this:

01-- For each entry, the first value is the actual value, and the second is the 'weight' or chance.
02local values = {
03    {"value1", 2},
04    {"value2", 1},
05    {"value3", 1}
06}
07 
08local SelectFrom = {}
09local SelectedValue
10for i, v in ipairs(values) do
11    for i2 = 1, v[2] do
12        table.insert(SelectFrom, v[1])
13    end
14    SelectedValue = math.random(1, #SelectFrom)
15end

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 9 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.

01local items = {
02    {item1, 2},
03    {item2, 3},
04    {item3, 1},
05    {item4, 1}
06};
07local max = 0;
08for i=1,#items do max = max+items[i][2] end;
09local selection,cnt = math.random(),0;
10for i=1,#items do
11    cnt = cnt+items[i][2]/max;
12    if cnt > selection then selection = items[i][1] break end;
13end;
14if 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