1
0
mirror of https://codeberg.org/tenplus1/farming.git synced 2024-11-10 20:30:31 +01:00

tweak poisson functions

This commit is contained in:
tenplus1 2024-09-12 11:21:32 +01:00
parent 87d6973420
commit a415cf5364
3 changed files with 37 additions and 55 deletions

View File

@ -251,7 +251,6 @@ local function hoe_area(pos, player)
end
-- replace dirt with tilled soil
res = nil
res = minetest.find_nodes_in_area_under_air(
{x = pos.x - r, y = pos.y - 1, z = pos.z - r},
{x = pos.x + r, y = pos.y + 2, z = pos.z + r},
@ -318,13 +317,10 @@ minetest.register_entity("farming:hoebomb_entity", {
local function throw_potion(itemstack, player)
local playerpos = player:get_pos()
local pos = player:get_pos()
local obj = minetest.add_entity({
x = playerpos.x,
y = playerpos.y + 1.5,
z = playerpos.z
}, "farming:hoebomb_entity")
x = pos.x, y = pos.y + 1.5, z = pos.z}, "farming:hoebomb_entity")
if not obj then return end
@ -440,10 +436,7 @@ minetest.register_tool("farming:scythe_mithril", {
if obj then
obj:set_velocity({
x = math.random(-10, 10) / 9,
y = 3,
z = math.random(-10, 10) / 9
})
x = math.random() - 0.5, y = 3, z = math.random() - 0.5})
end
end
end

View File

@ -17,8 +17,7 @@ farming = {
select = {type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}},
select_final = {type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, -2.5/16, 0.5}},
registered_plants = {},
min_light = 12,
max_light = 15,
min_light = 12, max_light = 15,
mapgen = minetest.get_mapgen_setting("mg_name"),
use_utensils = minetest.settings:get_bool("farming_use_utensils") ~= false,
mtg = minetest.get_modpath("default"),
@ -59,8 +58,7 @@ end
-- stats, locals, settings, function helper
local statistics = dofile(farming.path .. "/statistics.lua")
local random = math.random
local floor = math.floor
local random, floor = math.random, math.floor
local time_speed = tonumber(minetest.settings:get("time_speed")) or 72
local SECS_PER_CYCLE = (time_speed > 0 and (24 * 60 * 60) / time_speed) or 0
local function clamp(x, min, max) return (x < min and min) or (x > max and max) or x end

View File

@ -3,36 +3,36 @@
-- https://en.wikipedia.org/wiki/Error_function
local statistics = {}
local ROOT_2 = math.sqrt(2.0)
local erf
local erf_inv
local random, floor, ceil = math.random, math.floor, math.ceil
local exp, log, sqrt = math.exp, math.log, math.sqrt
local ROOT_2 = sqrt(2.0)
local A = 8 * (math.pi - 3.0) / (3.0 * math.pi * (4.0 - math.pi))
local B = 4.0 / math.pi
local C = 2.0 / (math.pi * A)
local D = 1.0 / A
erf = function(x)
local function erf(x)
if x == 0 then return 0; end
if x == 0 then return 0 end
local xSq = x * x
local aXSq = A * xSq
local v = math.sqrt(1.0 - math.exp(-xSq * (B + aXSq) / (1.0 + aXSq)))
local v = sqrt(1.0 - exp(-xSq * (B + aXSq) / (1.0 + aXSq)))
return (x > 0 and v) or -v
end
erf_inv = function(x)
local function erf_inv(x)
if x == 0 then return 0; end
if x == 0 then return 0 end
if x <= -1 or x >= 1 then return nil; end
if x <= -1 or x >= 1 then return nil end
local y = math.log(1 - x * x)
local y = log(1 - x * x)
local u = C + 0.5 * y
local v = math.sqrt(math.sqrt(u * u - D * y) - u)
local v = sqrt(sqrt(u * u - D * y) - u)
return (x > 0 and v) or -v
end
@ -43,14 +43,10 @@ local function std_normal(u)
end
local poisson
local cdf_table = {}
local function generate_cdf(lambda_index, lambda)
local max = math.ceil(4 * lambda)
local pdf = math.exp(-lambda)
local max = ceil(4 * lambda)
local pdf = exp(-lambda)
local cdf = pdf
local t = { [0] = pdf }
@ -64,30 +60,32 @@ local function generate_cdf(lambda_index, lambda)
end
local cdf_table = {}
for li = 1, 100 do
cdf_table[li] = generate_cdf(li, 0.25 * li)
end
poisson = function(lambda, max)
local function poisson(lambda, max)
if max < 2 then
return (math.random() < math.exp(-lambda) and 0) or 1
return (random() < exp(-lambda) and 0) or 1
elseif lambda >= 2 * max then
return max
end
local u = math.random()
local lambda_index = math.floor(4 * lambda + 0.5)
local u = random()
local lambda_index = floor(4 * lambda + 0.5)
local cdfs = cdf_table[lambda_index]
if cdfs then
lambda = 0.25 * lambda_index
if u < cdfs[0] then return 0; end
if max > #cdfs then max = #cdfs + 1 else max = math.floor(max); end
if u >= cdfs[max - 1] then return max; end
if u < cdfs[0] then return 0 end
if max > #cdfs then max = #cdfs + 1 else max = floor(max) end
if u >= cdfs[max - 1] then return max end
if max > 4 then -- Binary search
@ -95,30 +93,27 @@ poisson = function(lambda, max)
while s + 1 < max do
local m = math.floor(0.5 * (s + max))
local m = floor(0.5 * (s + max))
if u < cdfs[m] then max = m; else s = m; end
if u < cdfs[m] then max = m else s = m end
end
else
for i = 1, max - 1 do
if u < cdfs[i] then return i; end
if u < cdfs[i] then return i end
end
end
return max
else
local x = lambda + math.sqrt(lambda) * std_normal(u)
local x = lambda + sqrt(lambda) * std_normal(u)
return (x < 0.5 and 0) or (x >= max - 0.5 and max) or math.floor(x + 0.5)
return (x < 0.5 and 0) or (x >= max - 0.5 and max) or floor(x + 0.5)
end
end
-- Error function.
-- Error and Inverse error functions
statistics.erf = erf
-- Inverse error function.
statistics.erf_inv = erf_inv
--- Standard normal distribution function (mean 0, standard deviation 1).
@ -126,13 +121,9 @@ statistics.erf_inv = erf_inv
statistics.std_normal = function()
local u = math.random()
local u = random()
if u < 0.001 then
return -3.0
elseif u > 0.999 then
return 3.0
end
if u < 0.001 then return -3.0 elseif u > 0.999 then return 3.0 end
return std_normal(u)
end
@ -144,7 +135,7 @@ end
statistics.normal = function(mu, sigma)
local u = math.random()
local u = random()
if u < 0.001 then
return mu - 3.0 * sigma
@ -164,7 +155,7 @@ statistics.poisson = function(lambda, max)
lambda, max = tonumber(lambda), tonumber(max)
if not lambda or not max or lambda <= 0 or max < 1 then return 0; end
if not lambda or not max or lambda <= 0 or max < 1 then return 0 end
return poisson(lambda, max)
end