2 issues with my race rerolling system in my game

The issue isn’t the chances adding up to 100 anymore. Its the fact that the races being split can still create large decimals.

local function divideChance(chance, parts)
    local dividedChances = {}
    local remainingChance = chance
    local partSize = math.floor((chance / parts) * 100 + 0.5) / 100

    for i = 1, parts do
        if i == parts then
            table.insert(dividedChances, remainingChance)
        else
            table.insert(dividedChances, partSize)
            remainingChance = remainingChance - partSize
        end
    end

    return dividedChances
end

local function rollRace(plr)
    local chances = deepCopy(RaceChances)

    if plr and chances[plr.data.Race.Value] then
        local currentRaceChance = chances[plr.data.Race.Value]
        chances[plr.data.Race.Value] = nil

        local totalRaces = 0

        for _, _ in pairs(chances) do
            totalRaces += 1
        end

        local dividedChances = divideChance(currentRaceChance, totalRaces)
        local totalWeight = 0

        for index, _ in pairs(chances) do
            local adjustedChance = chances[index] + dividedChances[index]
            chances[index] = adjustedChance
            totalWeight = totalWeight + chances[index]
        end

        local difference = 100 - totalWeight
        local remainingDifference = difference
        for index, _ in pairs(chances) do
            local proportion = chances[index] / totalWeight
            local adjustment = math.floor(difference * proportion * 100 + 0.5) / 100
            chances[index] = chances[index] + adjustment
            remainingDifference = remainingDifference - adjustment
        end

        -- Distribute any remaining difference to the first race
        for _, value in pairs(chances) do
            chances[_] = chances[_] + remainingDifference
            break
        end
    end

    local total = 0
    local random = math.random(1, 100)

    local result = nil

    for race, chance in pairs(chances) do
        total += chance
        if random <= total and result == nil then
            result = race
        end
    end

    if total ~= 100 then
        warn("RACE CHANCES DONT ADD UP TO 100, ADDS UP TO: " .. tostring(total))
        print(chances)
    end

    return result
end

The divideChance function divides the currentRaceChance into smaller parts with at most two decimal places. The main function then redistributes these divided chances to the other races. This should ensure that the chances don’t have more than two decimal places while still adding up to 100.

1 Like

returns this error
image
line 49 is the line right after the i,v loop starts
image

image
prob because its a table and not a dictionary. Lemme try and fix it myself.

Okay I got these SUPER promising results
image
but unfortunately SOMETIMES we get large decimals still.
image

image

This is what I did to fix the error btw,

local iterationNumber = 0
		
		for index, _ in pairs(chances) do
			iterationNumber += 1
			local adjustedChance = chances[index] + dividedChances[iterationNumber]
			chances[index] = adjustedChance
			totalWeight = totalWeight + chances[index]
		end

I will also add that the warning did not appear once saying that the total didnt add up to 100. PROGRESS!

Try this

local function round(num, decimalPlaces)
    local mult = 10^(decimalPlaces or 0)
    return math.floor(num * mult + 0.5) / mult
end

local function rollRace(plr)
    local chances = deepCopy(RaceChances)

    if plr and chances[plr.data.Race.Value] then
        local currentRaceChance = chances[plr.data.Race.Value]
        chances[plr.data.Race.Value] = nil

        local totalRaces = 0

        for _, _ in pairs(chances) do
            totalRaces += 1
        end

        local dividedChances = divideChance(currentRaceChance, totalRaces)
        local totalWeight = 0

        local iterationNumber = 0

        for index, _ in pairs(chances) do
            iterationNumber += 1
            local adjustedChance = chances[index] + dividedChances[iterationNumber]
            chances[index] = round(adjustedChance, 2)
            totalWeight = totalWeight + chances[index]
        end

        local difference = 100 - totalWeight
        local remainingDifference = difference
        for index, _ in pairs(chances) do
            local proportion = chances[index] / totalWeight
            local adjustment = math.floor(difference * proportion * 100 + 0.5) / 100
            chances[index] = round(chances[index] + adjustment, 2)
            remainingDifference = remainingDifference - adjustment
        end

        -- Distribute any remaining difference to the first race
        for _, value in pairs(chances) do
            chances[_] = round(chances[_] + remainingDifference, 2)
            break
        end
    end

    local total = 0
    local random = math.random(1, 100)

    local result = nil

    for race, chance in pairs(chances) do
        total += chance
        if random <= total and result == nil then
            result = race
        end
    end

    if total ~= 100 then
        warn("RACE CHANCES DONT ADD UP TO 100, ADDS UP TO: " .. tostring(total))
        print(chances)
    end

    return result
end
1 Like

Works perfectly! The only time it creates a large decimal now is when its a float, I can simply round that though since its a float. Thank you so much.

1 Like

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