# How i can replicate this chance system?

In summary : if i get 239/239 i enable some function, and if it’s not 239 but another random number, call other function

how can i achieve this and manage to do it in percentages?, what would 1/239 equal to in percentage?

3 Likes

You could just do

``````local r = math.random(1,239)

if r == 239 then
-- Got lucky
else
-- Didn't get lucky
end
``````

A 1/239 chance in decimal would literally just be 1 divided by 239, multiply that by 100 to get percent and you have about a 0.4184% chance

1 Like

Thanks for the info, I think this could do it, but since my game needs to rely on accurate random functions, i don’t think math.random would be the best, But thanks anyways, i’ll have that in mind

`math.random` generates usually perfectly fine random numbers unless you’re doing something that needs to be cryptographically secure.

Although you can use the new Random object which has slightly better results when making multiple random calls very close together.

Besides that, any number your computer generates is going to be puesdo-random in nature without using external sources.

1 Like

Yeah, But Usually weighted systems make use of tables, which kinda concerns me

1 Like

Weighted randomness still uses math.random though, they just make more numbers equal to each different type of thing.

Here’s a post that covers weighted randomness

You just reminded me, i got a weighted system a long time ago, but i forgot what it uses, or what to input

can you help me ?

``````local Chances = {
{Rarity = "Blood Hour",     Chance = 50};
{Rarity = "Vision Hour",    Chance = 30};
{Rarity = "Blackout",         Chance = 10};
{Rarity = "Rare+",         Chance = 7};
{Rarity = "Epic",          Chance = 3};
}

local function GetRandomRarity()
local Sum = 0

for , Table in ipairs(Chances) do
Sum += Table.Chance
end

local RNG = Random.new():NextInteger(1, Sum)

local Weight = 0

for , Table in ipairs(Chances) do
Weight += Table.Chance
if Weight >= RNG then
return Table.Rarity
end
end
end

local RandomRarity = GetRandomRarity()

print(GetRandomRarity())
``````

you see, the chances in the table are 50, 30, 10, 7 and 3, but how i know what porcentage they are?, or what is this system using?

for example, would i put “50” that is 50% or 0.5, that is also 50%?

For the future, this is not a “do it for me” category. You should at least understand the code given to you.

Anyways, weighted systems are essentially just a sum of all values. It doesn’t matter if your values are `50, 30, 10, 7, 3` or `5, 3, 1, 0.7, 0.3`, they both have the same odds for the items.

Getting the odds is also basic math: divide your weighted value by the sum all the weighted values (multiplied by 100 for the percentage).

1 Like

Alright, thank you, sorry if i “sounded” too harsh or bad at the beginning, As for that, i said i already got the code, but i was asking for reference or guide in what to change, you can see

I wrote my own `WeightedRandom` module a few months ago if you would like to use it:

WeightedRandom.lua
``````--!strict

local WeightedRandom = {}

export type WeightedRandom<I> = typeof(setmetatable({} :: WeightedRandomClass<I>, {} :: WeightedRandomMetatable))

export type WeightedRandomClass<I> = {
Random: Random,
GetItems: (self: WeightedRandom<I>) -> {[I]: Item},
AddItem: (self: WeightedRandom<I>, item: I, weight: number, luckFactor: number?) -> (),
RemoveItem: (self: WeightedRandom<I>, item: I) -> (),
GetWeight: (self: WeightedRandom<I>, item: I, luckFactor: number?) -> number?,
GetWeights: (self: WeightedRandom<I>, luckFactor: number?) -> {[I]: number},
GetTotalWeight: (self: WeightedRandom<I>, luckFactor: number?) -> number,
GetProbability: (self: WeightedRandom<I>, item: I, luckFactor: number?) -> number?,
GetProbabilities: (self: WeightedRandom<I>, luckFactor: number?) -> {[I]: number},
Next: (self: WeightedRandom<I>, luckFactor: number?) -> I
}

export type WeightedRandomMetatable = {
__index: (self: any, index: any) -> any,
__newindex: (self: any, index: any, value: any) -> (),
__iter: (self: any) -> (),
__tostring: (self: any) -> string
}

export type Item = {
Weight: number,
LuckInfluence: number
}

local function clone<T>(t: T, deep: boolean?): T
t = table.clone(t :: any) :: any

if deep == true then
for index: any, value: any in t :: any do
if typeof(value) == "table" then
(t :: any)[index] = clone(value, true)
end
end
end

return t
end

function WeightedRandom.new<I>(random: Random?): WeightedRandom<I>
local items: {[I]: Item} = {}

local weightedRandomClass: WeightedRandomClass<I> = {
Random = random or Random.new(),
GetItems = function(weightedRandom: WeightedRandom<I>): {[I]: Item}
return clone(items, true)
end,
AddItem = function(weightedRandom: WeightedRandom<I>, item: I, weight: number, luckInfluence: number?): ()
items[item] = {
Weight = weight,
LuckInfluence = if luckInfluence ~= nil then luckInfluence else 0
}
end,
RemoveItem = function(weightedRandom: WeightedRandom<I>, item: I): ()
items[item] = nil
end,
GetWeight = function(weightedRandom: WeightedRandom<I>, item: I, luckFactor: number?): number?
if items[item] ~= nil then
return items[item].Weight + (items[item].Weight * (items[item].LuckInfluence * (if luckFactor ~= nil then luckFactor else 1)))
else
return nil
end
end,
GetWeights = function(weightedRandom: WeightedRandom<I>, luckFactor: number?): {[I]: number}
local weights: {[I]: number} = {}

for item: I in items do
weights[item] = weightedRandom:GetWeight(item, luckFactor) :: number
end

return weights
end,
GetTotalWeight = function(weightedRandom: WeightedRandom<I>, luckFactor: number?): number
local totalWeight: number = 0

for _: I, weight: number in weightedRandom:GetWeights(luckFactor) do
totalWeight += weight
end

end,
GetProbability = function(weightedRandom: WeightedRandom<I>, item: I, luckFactor: number?): number?
if items[item] ~= nil then
return (weightedRandom:GetWeight(item, luckFactor) :: number) / weightedRandom:GetTotalWeight(luckFactor)
else
return nil
end
end,
GetProbabilities = function(weightedRandom: WeightedRandom<I>, luckFactor: number?): {[I]: number}
local probabilities: {[I]: number} = {}

for item: I in weightedRandom:GetWeights(luckFactor) do
probabilities[item] = weightedRandom:GetProbability(item, luckFactor) :: number
end

return probabilities
end,
Next = function(weightedRandom: WeightedRandom<I>, luckFactor: number?): I
local weightedItems: {[I]: number} = weightedRandom:GetWeights(luckFactor)
local totalWeight: number = weightedRandom:GetTotalWeight(luckFactor)
local randomWeight: number = weightedRandom.Random:NextNumber() * totalWeight
local lastItem: I = nil

for item: I, weight: number in weightedItems do
randomWeight -= weight
lastItem = item

if randomWeight <= 0 then
return item
end
end

return lastItem
end,
}

local weightedRandomMetatable: WeightedRandomMetatable = table.freeze({
__index = function(self: any, index: any): any
return weightedRandomClass[index]
end,
__newindex = function(self: any, index: any, value: any): ()
if index == "Random" then
if typeof(value) ~= "Random" then
error(`invalid value for index '{index}' (Random expected, got {typeof(value)})`, 2)
end
else
error(`{index} cannot be assigned to`, 2)
end

weightedRandomClass[index] = value
end,
__iter = function(self: any): ()
error(`attempted to iterate over a WeightedRandom`, 2)
end,
__tostring = function(self: any): string
return `WeightedRandom`
end
})

return table.freeze(setmetatable({}, weightedRandomMetatable)) :: any
end

return WeightedRandom
``````

You can use it like so:

``````-- path to WeightedRandom
local WeightedRandom = require()
-- if you would like to strictly assign types
type WeightedRandom<I> = WeightedRandom.WeightedRandom<I>

-- creates a new WeightedRandom with strictly string items,
-- (or it automatically infers when using WeightedRandom:AddItem())
local myWeightedRandom: WeightedRandom<string> = WeightedRandom.new()

-- setup WeightedRandom
local someTableOdds = {
["Common"] = 50,
["Uncommon"] = 30,
["Rare"] = 10,
["Epic"] = 5,
["Legendary"] = 3,
["Mythical"] = 2
}

for rarity: string, weight: number in pairs(someTableOdds) do
-- optional 3rd parameter for luckInfluence
-- that defaults to 0
end

-- you can then use the following functions that includes an optional
-- luckFactor argument that defaults to 1
-- (multiplies the odds along with luckInfluence)

-- Get a random item with a luckFactor of 1 (default)
local chosenRarity: string = myWeightedRandom:Next()
print(`Chosen rarity: {chosenRarity}`)

-- Get probabilities with a luckFactor of 5
for rarity: string, probability: number in myWeightedRandom:GetProbabilities(5) do
print(`{rarity}: {probability * 100}`)
end
``````
1 Like

thank you so much, both of you

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.