1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-06 00:23:49 +02:00
ComfyFactorio/maps/pirates/raffle.lua
Piratux b8c8d4e1b0 Fixed people dying in front of ship upon departure
Changes:
- People now don't die when ship departs and they are right in front of it.
2023-01-11 19:32:00 +02:00

180 lines
5.5 KiB
Lua

-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
local Math = require 'maps.pirates.math'
local Public = {}
-- Returns random value from values, with given probability weights. Both table parameters are expected to be arrays.
-- NOTE: This function:
-- - MAY return random equally distributed item from "values" when there is at least 1 weight <= 0 and
-- - WILL with all weights <= 0
function Public.raffle(values, weights) --arguments of the form {[a] = A, [b] = B, ...} and {[a] = a_weight, [b] = b_weight, ...} or just {a,b,c,...} and {1,2,3...}
local total_weight = 0
for k,w in pairs(weights) do
assert(values[k])
if w > 0 then
total_weight = total_weight + w
end
-- negative weights treated as zero
end
-- Fallback case
if (not (total_weight > 0)) then
local index = Math.random(1, table_size(values))
return values[index]
end
local cumulative_probability = 0
local rng = Math.random()
for k,v in pairs(values) do
assert(weights[k])
cumulative_probability = cumulative_probability + (weights[k] / total_weight)
if rng <= cumulative_probability then
return v
end
end
-- Fallback case
local index = Math.random(1, table_size(values))
return values[index]
end
-- Returns random key from table, with given probability values. Works with all types of keys.
-- NOTE: This function:
-- - MAY return random equally distributed item from "values" when there is at least 1 weight <= 0 and
-- - WILL with all weights <= 0
function Public.raffle2(table) --arguments of the form {v1 = w1, v2 = w2, ...}
local total_weight = 0
for _, w in pairs(table) do
if w > 0 then
total_weight = total_weight + w
end
-- negative weights treated as zero
end
-- Fallback case
if (not (total_weight > 0)) then
local index = Math.random(1, table_size(table))
for k, _ in pairs(table) do
if index == 1 then
return k
end
index = index - 1
end
end
local cumulative_probability = 0
local rng = Math.random()
for k, w in pairs(table) do
cumulative_probability = cumulative_probability + w/total_weight
if rng <= cumulative_probability then
return k
end
end
-- Fallback case
local index = Math.random(1, table_size(table))
for k, _ in pairs(table) do
if index == 1 then
return k
end
index = index - 1
end
end
--==thesixthroc's Lambda Raffles
-- This file provides a one-parameter family of raffles called 'Lambda raffles'. When you want to roll the raffle, you also provide a parameter 'lambda', and the raffle weights vary with lambda in a specified way. For example, the parameter could be the game completion progress, and the raffle could produce certain items only in the late game.
function Public.LambdaRaffle(data, lambda, extraConditionParameter)
-- example_argument = {
-- ['iron-stick'] = {
-- overallWeight = 1,
-- minLambda = 0,
-- maxLambda = 0.5,
-- shape = 'uniform', -- a uniform raffle weight of 1, if lambda is between 0 and 1
-- },
-- ['coal'] = {
-- overallWeight = 3,
-- minLambda = 0,
-- maxLambda = 0.5,
-- shape = 'density', -- a uniform raffle weight of 6, if lambda is between 0 and 1
-- },
-- ['copper-wire'] = {
-- overallWeight = 1,
-- minLambda = 0,
-- maxLambda = 1,
-- shape = 'bump', -- the raffle weight is a ⋀ shape, going from (0, 0) to (0.5, 2) to (1, 0)
-- condition = function(x) return x == 'copperIsland' end, --this optional key performs a check on extraConditionParameter to see whether this raffle value should be included at all
-- },
-- }
local raffle = {}
for k, v in pairs(data) do
if (not v.shape) or (v.shape == 'uniform' or v.shape == 'flat') then
if (not v.minLambda) or (lambda >= v.minLambda) then
if (not v.maxLambda) or (lambda <= v.maxLambda) then
if (not v.condition) or (extraConditionParameter and v.condition(extraConditionParameter)) then
raffle[k] = v.overallWeight
end
end
end
elseif (v.shape == 'density') then
if v.minLambda and v.maxLambda and v.maxLambda ~= v.minLambda and lambda >= v.minLambda and lambda <= v.maxLambda then
if (not v.condition) or (extraConditionParameter and v.condition(extraConditionParameter)) then
raffle[k] = v.overallWeight / (v.maxLambda - v.minLambda)
end
end
elseif (v.shape == 'bump') then
if v.minLambda and v.maxLambda and lambda >= v.minLambda and lambda <= v.maxLambda then
if (not v.condition) or (extraConditionParameter and v.condition(extraConditionParameter)) then
if v.minLambda == v.maxLambda and lambda == v.minLambda then
raffle[k] = v.overallWeight
else
local midpoint = (v.minLambda + v.maxLambda) / 2
local peak = 2 * v.overallWeight
local slope = peak / ((v.maxLambda - v.minLambda) / 2)
local difference = Math.abs(lambda - midpoint)
raffle[k] = peak * (1 - difference * slope)
end
end
end
end
end
return Public.raffle2(raffle)
end
-- a function that accepts more abbreviated raffle data:
function Public.LambdaRaffleFromAbbreviatedData(abbreviatedData, lambda, extraConditionParameter)
-- example_argument = {
-- ['iron-stick'] = {
-- 1, 0, 1, 'uniform'
-- },
-- ['copper-plate'] = {
-- 1, 0, 1, 'uniform', function(x) return x == 'copperIsland' end
-- },
-- }
local data = {}
for k, v in pairs(abbreviatedData) do
data[k] = {
overallWeight = v[1],
minLambda = v[2],
maxLambda = v[3],
shape = v[4],
condition = v[4],
}
end
return Public.LambdaRaffle(data, lambda, extraConditionParameter)
end
return Public