mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-02-09 13:37:02 +02:00
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
94 lines
3.4 KiB
Lua
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
|