# [Help] probability with weighting

Hi guys,

maybe you can help me with this function, I am not able to think anymore…

I want to find a function, that gaves me a random index of space, but (!) with weighting.
I thought, it would be a good idea to half the probability every time I’m going through the loop.
This works fine, but I don’t like it really…

The main idea is, to create a function, that returns a value (for example a weapon), that have a possibility to spawn.
For example:
RPG have a possibility to spawn of 10%
PISTOL - 75%
RIFLE - 40%
[…]

Now I have this:

``````local space = {
{"A", "VALUE"}
{"A", "VALUE"}
{"A", "VALUE"}
{"A", "VALUE"}
}

function dwRand(space)
local rn = math.random(1, 100)
local p = 100
local sum = 0

for i, j in ipairs(space) do
p = p / 2
sum = sum + p

if ( math.floor(sum,3) >= math.floor(rn,3) ) then
return i
end

end

return 1

end
``````

Do you think it is a good idea to give every index a weighting?
like this:

``````local space = {
{"sabregt", 0.05},
{"fbi", 0.10},
{"cheetah", 0.25},
{"emperor", 0.33},
{"banshee", 0.50},
{"taxi", 0.70},
{"bfinjection", 0.75},
{"blista", 0.75},
{"sentinel", 0.80},
}
``````

I tried this, and the result was not what I was expecting…
because:

1. rand = 0.55 > weight = 0.05
2. rand = 0.55 > weight = 0.10
3. rand = 0.55 > weight = 0.33
4. rand = 0.55 > weight = 0.50 - spawn banshee
okay so far…
but if I am getting 0.75 or greater, for the random number, the blista is never spawning. But I still want to keep the possibility…

tl;tr: I am trying to find a function, that allows me to get a random array index, in combination of a weightbased possibility.

I hope this thread is not going too long; had a looooong night

Try tinkering with this, I havent tested it, just adapted this code which “should” give you want you need. Read the link above for more of an explanation of how this works. And let me know if it does alright for you (again you may want to look over it some before testing, I’m extremely tired and didn’t test it )

``````local space = {
{"sabregt", 5},
{"fbi", 10},
{"cheetah", 25},
{"emperor", 33},
{"banshee", 50},
{"taxi", 70},
{"bfinjection", 75},
{"blista", 75},
{"sentinel", 80},
}

function chooseWithChance(args)
local argCount = #args
local sumOfChances = 0

for i = 1, argCount do
sumOfChances = sumOfChances + args[i]
end

local randomDouble = math.random(sumOfChances)

while (sumOfChances > randomDouble) do
sumOfChances = sumOfChances - args[argCount]
argCount = argCount - 1
end

return (argCount)
end

function drawRand()
local probabilities = {}

for key,value in pairs(space) do
end

return space[chooseWithChance(probabilites)]
end

``````

Can’t really think now either, but I guess something along these lines might work.

``````spawnables = {
{"A", 1},
{"B", 3},
{"C", 0.5}
}

-- And then later on --

fullChance = 0
for _, item in pairs(spawnables) do
fullChance = fullChance + item[2]
end

chance = math.random(fullChance)

for _, item in pairs(spawnables) do
-- Aaaand you got your winner!
end
end
``````

I don’t believe this approach would work considering when checking `chance <= item[2]` this is true for multiple items and youd need to specifically order your list so that this would start with lowest weight first. This would also evaluate to true for multiple items that could have the same weight (chance), which would then mean youd have to check for any other item with this same weight, then after that pick randomly between one of those

Fixed the chance thingy. Don’t know how to do the sort thingy (and can’t look it up currently), so I guess you’ll have to do that too @schneehaze.

Thank you both.

``````-- [2] is probability
local weapons = {
{"WEAPON_HEAVYSNIPER",      15, "PICKUP_WEAPON_HEAVYSNIPER"},
{"WEAPON_BULLPUPSHOTGUN",   30, "PICKUP_WEAPON_PUMPSHOTGUN"},
{"WEAPON_STICKYBOMB",       30, "PICKUP_WEAPON_STICKYBOMB"},
{"WEAPON_KNIFE",            35, "PICKUP_WEAPON_KNIFE"},
{"WEAPON_CARBINERIFLE",     40, "PICKUP_WEAPON_CARBINERIFLE"},
{"WEAPON_COMBATPISTOL",     50, "PICKUP_WEAPON_COMBATPISTOL"},
{"WEAPON_PISTOL",           50, "PICKUP_WEAPON_PISTOL"}
}

function chooseWithChance(args)
local argCount = #args
local sumOfChances = 0

for i = 1, argCount do
sumOfChances = sumOfChances + args[i][2]
end

local randomDouble = math.random(sumOfChances)

while sumOfChances > randomDouble do
sumOfChances = sumOfChances - args[argCount][2]
argCount = argCount - 1
end

--f**king 0
if( argCount == 0 ) then
argCount = #args --get the last element
end

local gotP = args[argCount][2]
--check if another object has the same probability
local sameP = {}
local j = 1
for i = 1, argCount do
if(gotP == args[i][2]) then
sameP[j] = i
j = j + 1
end
end
if( #sameP > 1 ) then
--Chat("Weapon: "..args[argCount][1])
argCount = sameP[math.random(#sameP)]
--Chat("RandomWeapon: "..args[argCount][1])
end

return argCount
end
``````

Yessssss

Image is showing the randomness between weapons, that has the same probability.

1 Like