How to use different chances in math.random

Hey there, I’m trying to randomly pick a name out of a table using its chance, for example Apple could have a 80% chance of being picked and a Pear has a 20% chance. How would I go about this.

example table:

local table = {
["Apple"] = {80, 1};
["Pear"] = {20, 2};
}
local ChosenFruit = table. --Some code in here
print(ChosenFruit)

Sorry if I didnt explain this very well but any help is very apricated :slight_smile:

The solution of this is how I learned to make chance system. I know it works because I still to this day use it all the time.

3 Likes

The way that I do it is create a table of your chances…it works like this:

-- Define Data
local dataTable = {
	{
		item = "Apple";
		weight = 80;
	};
	{
		item = "Pear";
		weight = 20;
	};
}

-- Build Roll Table
local rollTable = {}
for _, data in ipairs(dataTable) do
	for i = 1, data.weight, 1 do
		table.insert(rollTable, data)
	end
end

-- Pick Item
local roll = math.random(1, #rollTable)
print("Chosen Fruit:", rollTable[roll].item)

EXPLAINATION
It’s all about data formatting. You have an array of tables which contains the item and it’s associated weight. Using that information, you build a roll table. The number of times an item appears in the table directly corresponds to it’s associated weight. Once that’s done, you generate a random number. That’s the roll (like rolling the dice), then you access that particular index in the roll table which points to an item in the data table, and then the item is printed.

This is actually memory efficient, better than other methods that I have tried because if you have a large amount of items that are very large, each entry is only 8 bytes (more with metadata) because you are not copying the table, you are just getting a reference to it. This includes sub-tables as well. Another added benefit of this system is that it can be a variable count. Got 3 items with weights totaling up to 75? No problem. Got 27 items with weights totaling 932? No problem. It does use more memory than the answer provided by @domboss37, but this is also very CPU efficient if you are using the table multiple times because once the table is constructed, it’s just a simple array index operation to get the data. For server side code, any gains in CPU efficiency is a bonus to reduced lag.

Games like World of Warcraft do something similar with fixed size tables (which takes more effort to setup). The biggest one is their hit table that is fixed at 1,000 entries. When a combat encounter starts, two such tables are constructed. As attacks are made, the roll numbers determine if it’s a miss, hit, critical hit, etc…

Hope this helps.

4 Likes