Hatching a random pet function occasionally returns nil

I am attempting to make a simple weighted chance system and it works fine 95% of the time but occasionally the function will return nil. I cant seem to find out why as it works most of the time. here is the function.

local function hatchRandomPet(eggName)
    local sum = 100

    local rand = math.random(0, sum)

    for _,eggInfo in ipairs(PetInfo.EggChances[eggName]) do
        rand = rand - eggInfo[1]
        if rand < 0 then
            return eggInfo[2]
        end
    end
end

here is the eggChances table its pulling from.

PetInfo.EggChances = {
    ["Egg1"] = {
        {40, "Bear"},
        {30, "Rabbit"},
        {20, "Cat"},
        {10, "Mouse"}
    },
    ["Egg2"] = {
        {40, "Koala"},
        {30, "Cow"},
        {20, "Deer"},
        {10, "Dragon"}
    },
    ["Egg3"] = {
        {40, "Shark"},
        {30, "Angler Fish"},
        {20, "Aqua Dragon"},
        {10, "Forgotten Kraken"}
    },
    ["Egg4"] = {
        {40, "Ice Golem"},
        {30, "Jellyfish"},
        {20, "Octopus Lord"},
        {10, "Aqua Lord"}
    },
    ["Egg5"] = {
        {40, "Desert Spider"},
        {30, "Spikey Balloon"},
        {25, "Electric Spider"},
        {5, "Builder"}
    },
    ["Egg6"] = {
        {40, "Golden Cat"},
        {30, "OctoHex"},
        {25, "Boom"},
        {5, "Oasis Lord"}
    },
    ["Egg7"] = {
        {40, "Fireball"},
        {30, "Hellish Golem"},
        {25, "Lil' Demon"},
        {5, "Demon"}
    },
    ["Egg8"] = {
        {40, "Lava Beast"},
        {30, "Demonic Dominus"},
        {25, "Demonic Destroyer"},
        {5, "Ultimus"}
    },
    ["Egg9"] = {
        {42, "Saphire Golem"},
        {32, "Emerald Dragon"},
        {25, "Quartz Golem"},
        {1, "Amethyst Geode"}
    },
    ["Egg10"] = {
        {42, "Diamond Geode"},
        {32, "Mining Robot"},
        {25, "Diamond Bat"},
        {1, "Electrified Geode"}
    },
    ["Egg11"] = {
        {40, "Angel"},
        {34.9, "Nice Cloud"},
        {25, "Pegasus"},
        {0.1, "Kraken"}
    },
    ["Egg12"] = {
        {40, "Cerberus"},
        {34.9, "Hades"},
        {25, "Zeus"},
        {0.1, "Hydra"}
    },
}
1 Like

the new rand is not guaranteed to be less than 0. This will make the function not return anything(nil).

1 Like

Yup, math.random(m, n) returns a random number between m and n inclusively (which is unlike any other language, not sure of the reasoning behind it). It’s especially odd because math.random() with no parameters is between 0 and a non-inclusive 1. So when you generate 100 exactly, you’ll get to 0, but never go lower than 0. You can change your logic to be <= or if it passes the entire loop, return the last possibility.

1 Like

If I’m not mistaken, what you’re trying to accomplish is a system that takes dictionary eggName and selects a random item from it, with the likelihood of each item getting chosen being affected by a weight value.

In that case, I think it might be good to use a system that doesn’t necessarily need to add up to 100. You could try creating a temporary WeightedEggs table and adding to it weight number of times (e.g. if eggName is Egg1 then “Bear” would be added to the table 40 times, “Rabbit” 30 times, etc. Then all you need to do is select a random item math.random(1,#WeightedEggs).

For example:

local function hatchRandomPet(eggName)
	local WeightedEggs = {}
	for _,eggInfo in ipairs(EggChances[eggName]) do
		for i = eggInfo[1], 1, -1 do
			table.insert(WeightedEggs,#WeightedEggs,eggInfo[2]);
		end
	end
    -- To confirm that it works as intended:
    for i,v in pairs(WeightedEggs) do
    	print(v);
    end
	return WeightedEggs[math.random(1,#WeightedEggs)]
end

print(hatchRandomPet("Egg1"));

I hope that works for you!

1 Like