Weighted Chance System

Got something working, here’s something that works for me if anyone needs it.

I’m using 0.01 - 0.001 chances and they don’t seem to work (Nevermind, I fixed it by increasing the multipler (10) to 10000

Hey! Great tutorial! Can the chances be grater than 1?

Yes, sorry for the late response!

1 Like

Just incase someone wants this:

function six(seven,eight,nine,ten)
	return (
		
		not seven
				
			and (
				tonumber(ten) and (ten > nine) and eight or ten
			)
			
			or (
				not ten and eight and math.random(eight)
				
				or (	
					six(
						nil, 
						nine, 
						eight, 
						six(
							seven, 
							eight 
							and (eight + ten)
							or 0, 
							next(seven, nine)
						) 
					)
				)
			)
		
	)
end

print(six{Common=100,Rare=10,Legendary=1})

i tried

6 Likes

I know this is so late, but how do you actually convert the numbers from “Rarities” table to actual percentage.

Decide on the rarities first. No matter what, the most common item should have a rarity of 0.

Think of it this way: math.random() produces any number between 0 and 1. This means higher rarities should be larger values, since it’s harder for the random value to be at or above it.

Work backwards. Mythic is 1% chance, so that means 99% is left. Legendary is 9% chance, so that means 90% if left. Rare is 30%, so 60% is left; that 60% is the chance of the common item.

Hope that helps!

5 Likes

May I ask what the difference between the math.random and Random.new(). Im not familiar with Random.new(), I have seen it plenty just personally never used it myself!

May I bug you for a question about how some games have their numbers like 0.0000045% rarity.

this is the improved code, and you didn’t even format it properly

local PrizeTable = {
	Prize_1 = 0.1,
	Prize_2 = 0.6,
	Prize_3 = 0.4,
	Prize_4 = 0.2,
	Prize_5 = 0.6,
	Prize_6 = 0.8,
	Prize_7 = 0.9,
	Prize_8 = 0.3,
	Prize_9 = 0.2,
	Prize_0 = 0.1,
}

local Weight = 0

for _, Chance in ipairs(PrizeTable) do
	Weight += (Chance * 10)
end

local ranNumber = math.random(1, Weight)

Weight = 0
for Prize, Chance in ipairs(PrizeTable) do
	Weight += (Chance * 10)

	if Weight >= ranNumber then
		print(`Congrats you won {Prize}`)
		break
	end
end
1 Like

In what way is this improved? All you did is replace pairs with ipairs and use the new string interpolation.

2 Likes

ipairs stops yielding if it reaches a nil value, and the new string interpolation cleans the code up

1 Like

Fair, but I wouldn’t really call it an improvement, more just an “alternate” if you for some reason were changing weight values to nil.

1 Like

bro really just obfuscated a code sample :skull:

3 Likes

i tried this but it chooses the rarity with the highest number instead of the lowest because i have it like 1/5 not in decimals
how can i fix this?

use :NextInteger for non decimal, :NextNumber that include decimals

How do we make it get three items in the table that are made sure arent the same value?

Isn’t ipairs unable to read dictionnaries?

1 Like

iirc they can operate on dictionaries; ipairs generator just returns the index and the value whilst pairs returns the key and the value

idk tried with ipairs it just wasn’t really looping at all