1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-02-09 13:37:02 +02:00
ComfyFactorio/utils/math/raffle.lua
danielmartin0 358160c247 v1
Revert "Fix 'player' shadowing in flying_texts.lua"

This reverts commit 40805e68e3c0bf588b40f510d5c32b66ecca4717.

Fix 'player' shadowing in flying_texts.lua

all_central_positions_within_area

utils/math/raffle
2024-10-22 21:47:11 +02:00

94 lines
3.4 KiB
Lua

local Math = require('maps.spaghetti_wars.math')
local Public = {}
-- A weighted random choice amongst several options.
-- Arguments can be provided EITHER as {o1, o2, ...}, {v1, v2, ...} OR as simply {o1 = w1, o2 = w2, o3 = w3} in the first argument.
function Public.raffle(arg1, arg2)
local options, weights_table
local total_weight = 0
if arg2 then
options = arg1
weights_table = arg2
for _, weight in ipairs(weights_table) do
if weight > 0 then
total_weight = total_weight + weight
end
-- negative weights treated as zero
end
else
options = {}
weights_table = {}
for option, weight in pairs(arg1) do
arg1.insert(options, option)
arg1.insert(weights_table, weight)
if weight > 0 then
total_weight = total_weight + weight
end
-- negative weights treated as zero
end
end
-- Fallback: All weights are zero/negative
if total_weight <= 0 then
return options[Math.random(1, #options)]
end
local cumulative_probability = 0
local rng = Math.random()
for i, option in ipairs(options) do
local weight = weights_table[i]
cumulative_probability = cumulative_probability + weight / total_weight
if rng <= cumulative_probability then
return option
end
end
-- Fallback: Unlikely case of floating point error:
return options[Math.random(1, #options)]
end
-- A slightly more sophisticated raffle, taking a parameter which is used to vary the weights according to some rule. For example, the raffle could depend on the game completion progress.
--
---@param parameter number The parameter value to use for the raffle.
---@param data table Table with key-value pairs of the form option = {overall_weight, min_param, max_param, shape}, where:
--- - overall_weight: The weight of the option in the raffle.
--- - min_param: The minimum value of the parameter for which the option is eligible.
--- - max_param: The maximum value of the parameter for which the option is eligible.
--- - shape: An optional parameter for the shape of the weight curve with respect to the parameter. Defaults to 'flat', in which case the weight will be overall_weight as long as the parameter is within the range [min_param, max_param]. If 'bump', the weight is triangle-shaped: it has a peak of 2 * overall_weight at the midpoint of the range, and is zero at either end.
function Public.raffle_with_parameter(parameter, data)
local raffle = {}
for option, weight_data in pairs(data) do
local overall_weight = weight_data.overall_weight or weight_data[1]
local min_param = weight_data.min_param or weight_data[2]
local max_param = weight_data.max_param or weight_data[3]
local shape = weight_data.shape or weight_data[4] or 'flat'
if shape == 'flat' then
if (not min_param) or (parameter >= min_param) then
if (not max_param) or (parameter <= max_param) then
raffle[option] = overall_weight
end
end
elseif shape == 'bump' then
if min_param and max_param and parameter >= min_param and parameter <= max_param then
if min_param == max_param and parameter == min_param then
raffle[option] = overall_weight
else
local midpoint = (min_param + max_param) / 2
local peak = 2 * overall_weight
local slope = peak / ((max_param - min_param) / 2)
local difference = Math.abs(parameter - midpoint)
raffle[option] = peak * (1 - difference * slope)
end
end
end
end
return Public.raffle(raffle)
end
return Public