mirror of
https://github.com/sys4-fr/server-nalc.git
synced 2024-12-25 02:00:37 +01:00
[farming] Update from Skyblock
This commit is contained in:
parent
b25fd961f6
commit
bf269a6574
@ -9,7 +9,9 @@ minetest.register_craftitem("farming:beans", {
|
|||||||
inventory_image = "farming_beans.png",
|
inventory_image = "farming_beans.png",
|
||||||
on_use = minetest.item_eat(1),
|
on_use = minetest.item_eat(1),
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
if minetest.is_protected(pointed_thing.above, placer:get_player_name()) then return end
|
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
|
||||||
|
return
|
||||||
|
end
|
||||||
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
||||||
if nod and nod.name == "farming:beanpole" then
|
if nod and nod.name == "farming:beanpole" then
|
||||||
minetest.set_node(pointed_thing.under, {name="farming:beanpole_1"})
|
minetest.set_node(pointed_thing.under, {name="farming:beanpole_1"})
|
||||||
@ -58,13 +60,12 @@ minetest.register_node("farming:beanpole", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
selection_box = farming.select,
|
selection_box = farming.select,
|
||||||
groups = {
|
groups = {snappy = 3, flammable = 2, attached_node = 1},
|
||||||
snappy = 3, flammable = 2, attached_node = 1,
|
|
||||||
not_in_creative_inventory = 1
|
|
||||||
},
|
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
if minetest.is_protected(pointed_thing.above, placer:get_player_name()) then return end
|
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
|
||||||
|
return
|
||||||
|
end
|
||||||
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
||||||
if nod and minetest.get_item_group(nod.name, "soil") < 2 then
|
if nod and minetest.get_item_group(nod.name, "soil") < 2 then
|
||||||
return
|
return
|
||||||
|
@ -5,7 +5,9 @@ minetest.register_craftitem("farming:grapes", {
|
|||||||
inventory_image = "farming_grapes.png",
|
inventory_image = "farming_grapes.png",
|
||||||
on_use = minetest.item_eat(2),
|
on_use = minetest.item_eat(2),
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
if minetest.is_protected(pointed_thing.above, placer:get_player_name()) then return end
|
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
|
||||||
|
return
|
||||||
|
end
|
||||||
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
||||||
if nod and nod.name == "farming:trellis" then
|
if nod and nod.name == "farming:trellis" then
|
||||||
minetest.set_node(pointed_thing.under, {name="farming:grapes_1"})
|
minetest.set_node(pointed_thing.under, {name="farming:grapes_1"})
|
||||||
@ -54,12 +56,12 @@ minetest.register_node("farming:trellis", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
selection_box = farming.select,
|
selection_box = farming.select,
|
||||||
groups = {
|
groups = {snappy = 3, flammable = 2, attached_node = 1},
|
||||||
snappy = 3, flammable = 2, attached_node = 1,
|
|
||||||
},
|
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
if minetest.is_protected(pointed_thing.above, placer:get_player_name()) then return end
|
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
|
||||||
|
return
|
||||||
|
end
|
||||||
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
local nod = minetest.get_node_or_nil(pointed_thing.under)
|
||||||
if nod and minetest.get_item_group(nod.name, "soil") < 2 then
|
if nod and minetest.get_item_group(nod.name, "soil") < 2 then
|
||||||
return
|
return
|
||||||
|
@ -2,17 +2,21 @@
|
|||||||
-- Hoe registration function
|
-- Hoe registration function
|
||||||
|
|
||||||
farming.register_hoe = function(name, def)
|
farming.register_hoe = function(name, def)
|
||||||
|
|
||||||
-- Check for : prefix (register new hoes in your mod's namespace)
|
-- Check for : prefix (register new hoes in your mod's namespace)
|
||||||
if name:sub(1,1) ~= ":" then
|
if name:sub(1,1) ~= ":" then
|
||||||
name = ":" .. name
|
name = ":" .. name
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check def table
|
-- Check def table
|
||||||
if def.description == nil then
|
if def.description == nil then
|
||||||
def.description = "Hoe"
|
def.description = "Hoe"
|
||||||
end
|
end
|
||||||
|
|
||||||
if def.inventory_image == nil then
|
if def.inventory_image == nil then
|
||||||
def.inventory_image = "unknown_item.png"
|
def.inventory_image = "unknown_item.png"
|
||||||
end
|
end
|
||||||
|
|
||||||
if def.recipe == nil then
|
if def.recipe == nil then
|
||||||
def.recipe = {
|
def.recipe = {
|
||||||
{"air","air",""},
|
{"air","air",""},
|
||||||
@ -20,9 +24,11 @@ farming.register_hoe = function(name, def)
|
|||||||
{"","group:stick",""}
|
{"","group:stick",""}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
if def.max_uses == nil then
|
if def.max_uses == nil then
|
||||||
def.max_uses = 30
|
def.max_uses = 30
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Register the tool
|
-- Register the tool
|
||||||
minetest.register_tool(name, {
|
minetest.register_tool(name, {
|
||||||
description = def.description,
|
description = def.description,
|
||||||
@ -31,6 +37,7 @@ farming.register_hoe = function(name, def)
|
|||||||
return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses)
|
return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Register its recipe
|
-- Register its recipe
|
||||||
-- Registration using material made for MFF
|
-- Registration using material made for MFF
|
||||||
if def.material == nil then
|
if def.material == nil then
|
||||||
@ -62,7 +69,9 @@ end
|
|||||||
-- Turns dirt with group soil=1 into soil
|
-- Turns dirt with group soil=1 into soil
|
||||||
|
|
||||||
function farming.hoe_on_use(itemstack, user, pointed_thing, uses)
|
function farming.hoe_on_use(itemstack, user, pointed_thing, uses)
|
||||||
|
|
||||||
local pt = pointed_thing
|
local pt = pointed_thing
|
||||||
|
|
||||||
-- check if pointing at a node
|
-- check if pointing at a node
|
||||||
if not pt or pt.type ~= "node" then
|
if not pt or pt.type ~= "node" then
|
||||||
return
|
return
|
||||||
@ -97,6 +106,7 @@ function farming.hoe_on_use(itemstack, user, pointed_thing, uses)
|
|||||||
|
|
||||||
-- turn the node into soil, wear out item and play sound
|
-- turn the node into soil, wear out item and play sound
|
||||||
minetest.set_node(pt.under, {name = "farming:soil"})
|
minetest.set_node(pt.under, {name = "farming:soil"})
|
||||||
|
|
||||||
minetest.sound_play("default_dig_crumbly", {pos = pt.under, gain = 0.5})
|
minetest.sound_play("default_dig_crumbly", {pos = pt.under, gain = 0.5})
|
||||||
if not minetest.setting_getbool("creative_mode") then --MFF DEBUT crabman(26/07/2015) not wearout if creative mod and invtweak refill break tools
|
if not minetest.setting_getbool("creative_mode") then --MFF DEBUT crabman(26/07/2015) not wearout if creative mod and invtweak refill break tools
|
||||||
local tool_name = itemstack:get_name()
|
local tool_name = itemstack:get_name()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
--[[
|
--[[
|
||||||
Minetest Farming Redo Mod 1.22 (26th October 2015)
|
Minetest Farming Redo Mod 1.22 (8th December 2015)
|
||||||
by TenPlus1
|
by TenPlus1
|
||||||
NEW growing routine by prestidigitator
|
NEW growing routine by prestidigitator
|
||||||
auto-refill by crabman77
|
auto-refill by crabman77
|
||||||
@ -21,7 +21,9 @@ local DEBUG_abm_runs = 0
|
|||||||
local DEBUG_abm_time = 0
|
local DEBUG_abm_time = 0
|
||||||
local DEBUG_timer_runs = 0
|
local DEBUG_timer_runs = 0
|
||||||
local DEBUG_timer_time = 0
|
local DEBUG_timer_time = 0
|
||||||
|
|
||||||
if farming.DEBUG then
|
if farming.DEBUG then
|
||||||
|
|
||||||
function farming.DEBUG.reset_times()
|
function farming.DEBUG.reset_times()
|
||||||
DEBUG_abm_runs = 0
|
DEBUG_abm_runs = 0
|
||||||
DEBUG_abm_time = 0
|
DEBUG_abm_time = 0
|
||||||
@ -30,6 +32,7 @@ if farming.DEBUG then
|
|||||||
end
|
end
|
||||||
|
|
||||||
function farming.DEBUG.report_times()
|
function farming.DEBUG.report_times()
|
||||||
|
|
||||||
local abm_n = DEBUG_abm_runs
|
local abm_n = DEBUG_abm_runs
|
||||||
local abm_dt = DEBUG_abm_time
|
local abm_dt = DEBUG_abm_time
|
||||||
local abm_avg = (abm_n > 0 and abm_dt / abm_n) or 0
|
local abm_avg = (abm_n > 0 and abm_dt / abm_n) or 0
|
||||||
@ -37,15 +40,15 @@ if farming.DEBUG then
|
|||||||
local timer_dt = DEBUG_timer_time
|
local timer_dt = DEBUG_timer_time
|
||||||
local timer_avg = (timer_n > 0 and timer_dt / timer_n) or 0
|
local timer_avg = (timer_n > 0 and timer_dt / timer_n) or 0
|
||||||
local dt = abm_dt + timer_dt
|
local dt = abm_dt + timer_dt
|
||||||
print("ABM ran for "..abm_dt.."µs over "..abm_n.." runs: "..
|
|
||||||
abm_avg.."µs/run")
|
print("ABM ran for "..abm_dt.."µs over "..abm_n.." runs: "..abm_avg.."µs/run")
|
||||||
print("Timer ran for "..timer_dt.."µs over "..timer_n.." runs: "..
|
print("Timer ran for "..timer_dt.."µs over "..timer_n.." runs: "..timer_avg.."µs/run")
|
||||||
timer_avg.."µs/run")
|
|
||||||
print("Total farming time: "..dt.."µs")
|
print("Total farming time: "..dt.."µs")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local statistics = dofile(farming.path.."/statistics.lua")
|
local statistics = dofile(farming.path.."/statistics.lua")
|
||||||
|
|
||||||
dofile(farming.path.."/soil.lua")
|
dofile(farming.path.."/soil.lua")
|
||||||
dofile(farming.path.."/hoes.lua")
|
dofile(farming.path.."/hoes.lua")
|
||||||
dofile(farming.path.."/grass.lua")
|
dofile(farming.path.."/grass.lua")
|
||||||
@ -95,12 +98,14 @@ end
|
|||||||
-- If true, count elapsed day time. Otherwise, count elapsed night time.
|
-- If true, count elapsed day time. Otherwise, count elapsed night time.
|
||||||
-- @return
|
-- @return
|
||||||
-- The amount of day or night time that has elapsed.
|
-- The amount of day or night time that has elapsed.
|
||||||
--
|
|
||||||
local function day_or_night_time(t_game, t_day, dt, count_day)
|
|
||||||
local t1_day = t_day - dt / SECS_PER_CYCLE
|
|
||||||
|
|
||||||
|
local function day_or_night_time(t_game, t_day, dt, count_day)
|
||||||
|
|
||||||
|
local t1_day = t_day - dt / SECS_PER_CYCLE
|
||||||
local t1_c, t2_c -- t1_c < t2_c and t2_c always in [0, 1)
|
local t1_c, t2_c -- t1_c < t2_c and t2_c always in [0, 1)
|
||||||
|
|
||||||
if count_day then
|
if count_day then
|
||||||
|
|
||||||
if t_day < 0.25 then
|
if t_day < 0.25 then
|
||||||
t1_c = t1_day + 0.75 -- Relative to sunup, yesterday
|
t1_c = t1_day + 0.75 -- Relative to sunup, yesterday
|
||||||
t2_c = t_day + 0.75
|
t2_c = t_day + 0.75
|
||||||
@ -119,6 +124,7 @@ local function day_or_night_time(t_game, t_day, dt, count_day)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local dt_c = clamp(t2_c, 0, 0.5) - clamp(t1_c, 0, 0.5) -- this cycle
|
local dt_c = clamp(t2_c, 0, 0.5) - clamp(t1_c, 0, 0.5) -- this cycle
|
||||||
|
|
||||||
if t1_c < -0.5 then
|
if t1_c < -0.5 then
|
||||||
local nc = math.floor(-t1_c)
|
local nc = math.floor(-t1_c)
|
||||||
t1_c = t1_c + nc
|
t1_c = t1_c + nc
|
||||||
@ -166,10 +172,13 @@ local MAX_LIGHT = 1000
|
|||||||
-- Node or position table, or node name.
|
-- Node or position table, or node name.
|
||||||
-- @return
|
-- @return
|
||||||
-- List (plant_name, stage), or nothing (nil) if node isn't loaded
|
-- List (plant_name, stage), or nothing (nil) if node isn't loaded
|
||||||
--
|
|
||||||
local function plant_name_stage(node)
|
local function plant_name_stage(node)
|
||||||
|
|
||||||
local name
|
local name
|
||||||
|
|
||||||
if type(node) == 'table' then
|
if type(node) == 'table' then
|
||||||
|
|
||||||
if node.name then
|
if node.name then
|
||||||
name = node.name
|
name = node.name
|
||||||
elseif node.x and node.y and node.z then
|
elseif node.x and node.y and node.z then
|
||||||
@ -179,11 +188,15 @@ local function plant_name_stage(node)
|
|||||||
else
|
else
|
||||||
name = tostring(node)
|
name = tostring(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not name or name == "ignore" then return nil end
|
if not name or name == "ignore" then return nil end
|
||||||
|
|
||||||
local sep_pos = name:find("_[^_]+$")
|
local sep_pos = name:find("_[^_]+$")
|
||||||
|
|
||||||
if sep_pos and sep_pos > 1 then
|
if sep_pos and sep_pos > 1 then
|
||||||
|
|
||||||
local stage = tonumber(name:sub(sep_pos + 1))
|
local stage = tonumber(name:sub(sep_pos + 1))
|
||||||
|
|
||||||
if stage and stage >= 0 then
|
if stage and stage >= 0 then
|
||||||
return name:sub(1, sep_pos - 1), stage
|
return name:sub(1, sep_pos - 1), stage
|
||||||
end
|
end
|
||||||
@ -195,6 +208,7 @@ end
|
|||||||
--- Map from node name to
|
--- Map from node name to
|
||||||
-- { plant_name = ..., name = ..., stage = n, stages_left = { node_name, ... } }
|
-- { plant_name = ..., name = ..., stage = n, stages_left = { node_name, ... } }
|
||||||
local plant_stages = {}
|
local plant_stages = {}
|
||||||
|
|
||||||
farming.plant_stages = plant_stages
|
farming.plant_stages = plant_stages
|
||||||
|
|
||||||
--- Registers the stages of growth of a (possible plant) node.
|
--- Registers the stages of growth of a (possible plant) node.
|
||||||
@ -204,21 +218,26 @@ farming.plant_stages = plant_stages
|
|||||||
-- @return
|
-- @return
|
||||||
-- The (possibly zero) number of stages of growth the plant will go through
|
-- The (possibly zero) number of stages of growth the plant will go through
|
||||||
-- before being fully grown, or nil if not a plant.
|
-- before being fully grown, or nil if not a plant.
|
||||||
--
|
|
||||||
local register_plant_node
|
local register_plant_node
|
||||||
|
|
||||||
-- Recursive helper
|
-- Recursive helper
|
||||||
local function reg_plant_stages(plant_name, stage, force_last)
|
local function reg_plant_stages(plant_name, stage, force_last)
|
||||||
|
|
||||||
local node_name = plant_name and plant_name .. "_" .. stage
|
local node_name = plant_name and plant_name .. "_" .. stage
|
||||||
local node_def = node_name and minetest.registered_nodes[node_name]
|
local node_def = node_name and minetest.registered_nodes[node_name]
|
||||||
|
|
||||||
if not node_def then return nil end
|
if not node_def then return nil end
|
||||||
|
|
||||||
local stages = plant_stages[node_name]
|
local stages = plant_stages[node_name]
|
||||||
|
|
||||||
if stages then return stages end
|
if stages then return stages end
|
||||||
|
|
||||||
if minetest.get_item_group(node_name, "growing") > 0 then
|
if minetest.get_item_group(node_name, "growing") > 0 then
|
||||||
local ns = reg_plant_stages(plant_name, stage + 1, true)
|
|
||||||
|
|
||||||
|
local ns = reg_plant_stages(plant_name, stage + 1, true)
|
||||||
local stages_left = (ns and { ns.name, unpack(ns.stages_left) }) or {}
|
local stages_left = (ns and { ns.name, unpack(ns.stages_left) }) or {}
|
||||||
|
|
||||||
stages = {
|
stages = {
|
||||||
plant_name = plant_name,
|
plant_name = plant_name,
|
||||||
name = node_name,
|
name = node_name,
|
||||||
@ -227,8 +246,10 @@ local function reg_plant_stages(plant_name, stage, force_last)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if #stages_left > 0 then
|
if #stages_left > 0 then
|
||||||
|
|
||||||
local old_constr = node_def.on_construct
|
local old_constr = node_def.on_construct
|
||||||
local old_destr = node_def.on_destruct
|
local old_destr = node_def.on_destruct
|
||||||
|
|
||||||
minetest.override_item(node_name,
|
minetest.override_item(node_name,
|
||||||
{
|
{
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
@ -246,7 +267,9 @@ local function reg_plant_stages(plant_name, stage, force_last)
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif force_last then
|
elseif force_last then
|
||||||
|
|
||||||
stages = {
|
stages = {
|
||||||
plant_name = plant_name,
|
plant_name = plant_name,
|
||||||
name = node_name,
|
name = node_name,
|
||||||
@ -258,11 +281,14 @@ local function reg_plant_stages(plant_name, stage, force_last)
|
|||||||
end
|
end
|
||||||
|
|
||||||
plant_stages[node_name] = stages
|
plant_stages[node_name] = stages
|
||||||
|
|
||||||
return stages
|
return stages
|
||||||
end
|
end
|
||||||
|
|
||||||
register_plant_node = function(node)
|
register_plant_node = function(node)
|
||||||
|
|
||||||
local plant_name, stage = plant_name_stage(node)
|
local plant_name, stage = plant_name_stage(node)
|
||||||
|
|
||||||
if plant_name then
|
if plant_name then
|
||||||
local stages = reg_plant_stages(plant_name, stage, false)
|
local stages = reg_plant_stages(plant_name, stage, false)
|
||||||
return stages and #stages.stages_left
|
return stages and #stages.stages_left
|
||||||
@ -272,15 +298,22 @@ register_plant_node = function(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function set_growing(pos, stages_left)
|
local function set_growing(pos, stages_left)
|
||||||
|
|
||||||
if not stages_left then return end
|
if not stages_left then return end
|
||||||
|
|
||||||
local timer = minetest.get_node_timer(pos)
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
|
||||||
if stages_left > 0 then
|
if stages_left > 0 then
|
||||||
|
|
||||||
if not timer:is_started() then
|
if not timer:is_started() then
|
||||||
|
|
||||||
local stage_length = statistics.normal(STAGE_LENGTH_AVG, STAGE_LENGTH_DEV)
|
local stage_length = statistics.normal(STAGE_LENGTH_AVG, STAGE_LENGTH_DEV)
|
||||||
|
|
||||||
stage_length = clamp(stage_length, 0.5 * STAGE_LENGTH_AVG, 3.0 * STAGE_LENGTH_AVG)
|
stage_length = clamp(stage_length, 0.5 * STAGE_LENGTH_AVG, 3.0 * STAGE_LENGTH_AVG)
|
||||||
|
|
||||||
timer:set(stage_length, -0.5 * math.random() * STAGE_LENGTH_AVG)
|
timer:set(stage_length, -0.5 * math.random() * STAGE_LENGTH_AVG)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif timer:is_started() then
|
elseif timer:is_started() then
|
||||||
timer:stop()
|
timer:stop()
|
||||||
end
|
end
|
||||||
@ -292,10 +325,13 @@ end
|
|||||||
-- The node's position.
|
-- The node's position.
|
||||||
-- @param node
|
-- @param node
|
||||||
-- The cached node table if available, or nil.
|
-- The cached node table if available, or nil.
|
||||||
--
|
|
||||||
function farming.handle_growth(pos, node)
|
function farming.handle_growth(pos, node)
|
||||||
|
|
||||||
if not pos then return end
|
if not pos then return end
|
||||||
|
|
||||||
local stages_left = register_plant_node(node or pos)
|
local stages_left = register_plant_node(node or pos)
|
||||||
|
|
||||||
if stages_left then set_growing(pos, stages_left) end
|
if stages_left then set_growing(pos, stages_left) end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -307,14 +343,19 @@ minetest.after(0,
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
local abm_func = farming.handle_growth
|
local abm_func = farming.handle_growth
|
||||||
|
|
||||||
if farming.DEBUG then
|
if farming.DEBUG then
|
||||||
|
|
||||||
local normal_abm_func = abm_func
|
local normal_abm_func = abm_func
|
||||||
|
|
||||||
abm_func = function(...)
|
abm_func = function(...)
|
||||||
local t0 = minetest.get_us_time()
|
local t0 = minetest.get_us_time()
|
||||||
local r = { normal_abm_func(...) }
|
local r = { normal_abm_func(...) }
|
||||||
local t1 = minetest.get_us_time()
|
local t1 = minetest.get_us_time()
|
||||||
|
|
||||||
DEBUG_abm_runs = DEBUG_abm_runs + 1
|
DEBUG_abm_runs = DEBUG_abm_runs + 1
|
||||||
DEBUG_abm_time = DEBUG_abm_time + (t1 - t0)
|
DEBUG_abm_time = DEBUG_abm_time + (t1 - t0)
|
||||||
|
|
||||||
return unpack(r)
|
return unpack(r)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -322,39 +363,51 @@ end
|
|||||||
-- Just in case a growing type or added node is missed (also catches existing
|
-- Just in case a growing type or added node is missed (also catches existing
|
||||||
-- nodes added to map before timers were incorporated).
|
-- nodes added to map before timers were incorporated).
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
|
|
||||||
nodenames = { "group:growing" },
|
nodenames = { "group:growing" },
|
||||||
interval = 300,
|
interval = 300,
|
||||||
chance = 1,
|
chance = 1,
|
||||||
action = abm_func})
|
action = abm_func
|
||||||
|
})
|
||||||
|
|
||||||
--- Plant timer function.
|
--- Plant timer function.
|
||||||
--
|
--
|
||||||
-- Grows plants under the right conditions.
|
-- Grows plants under the right conditions.
|
||||||
--
|
|
||||||
function farming.plant_growth_timer(pos, elapsed, node_name)
|
function farming.plant_growth_timer(pos, elapsed, node_name)
|
||||||
|
|
||||||
local stages = plant_stages[node_name]
|
local stages = plant_stages[node_name]
|
||||||
|
|
||||||
if not stages then return false end
|
if not stages then return false end
|
||||||
|
|
||||||
local max_growth = #stages.stages_left
|
local max_growth = #stages.stages_left
|
||||||
|
|
||||||
if max_growth <= 0 then return false end
|
if max_growth <= 0 then return false end
|
||||||
|
|
||||||
if stages.plant_name == "farming:cocoa" then
|
if stages.plant_name == "farming:cocoa" then
|
||||||
|
|
||||||
if not minetest.find_node_near(pos, 1, { "default:jungletree", "moretrees:jungletree_leaves_green" }) then
|
if not minetest.find_node_near(pos, 1, { "default:jungletree", "moretrees:jungletree_leaves_green" }) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local under = minetest.get_node_or_nil({ x = pos.x, y = pos.y - 1, z = pos.z })
|
local under = minetest.get_node_or_nil({ x = pos.x, y = pos.y - 1, z = pos.z })
|
||||||
|
|
||||||
if not under or under.name ~= "farming:soil_wet" then return true end
|
if not under or under.name ~= "farming:soil_wet" then return true end
|
||||||
end
|
end
|
||||||
|
|
||||||
local growth
|
local growth
|
||||||
|
|
||||||
local light_pos = { x = pos.x, y = pos.y, z = pos.z }
|
local light_pos = { x = pos.x, y = pos.y, z = pos.z }
|
||||||
local lambda = elapsed / STAGE_LENGTH_AVG
|
local lambda = elapsed / STAGE_LENGTH_AVG
|
||||||
|
|
||||||
if lambda < 0.1 then return true end
|
if lambda < 0.1 then return true end
|
||||||
|
|
||||||
if max_growth == 1 or lambda < 2.0 then
|
if max_growth == 1 or lambda < 2.0 then
|
||||||
|
|
||||||
local light = (minetest.get_node_light(light_pos) or 0) -- CHANGED
|
local light = (minetest.get_node_light(light_pos) or 0) -- CHANGED
|
||||||
|
--print ("light level:", light)
|
||||||
|
|
||||||
if not in_range(light, MIN_LIGHT, MAX_LIGHT) then return true end
|
if not in_range(light, MIN_LIGHT, MAX_LIGHT) then return true end
|
||||||
|
|
||||||
growth = 1
|
growth = 1
|
||||||
else
|
else
|
||||||
local night_light = (minetest.get_node_light(light_pos, 0) or 0) -- CHANGED
|
local night_light = (minetest.get_node_light(light_pos, 0) or 0) -- CHANGED
|
||||||
@ -370,51 +423,68 @@ function farming.plant_growth_timer(pos, elapsed, node_name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
growth = statistics.poisson(lambda, max_growth)
|
growth = statistics.poisson(lambda, max_growth)
|
||||||
|
|
||||||
if growth < 1 then return true end
|
if growth < 1 then return true end
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.swap_node(pos, { name = stages.stages_left[growth] })
|
if minetest.registered_nodes[stages.stages_left[growth]] then
|
||||||
|
minetest.swap_node(pos, { name = stages.stages_left[growth] })
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
return growth ~= max_growth
|
return growth ~= max_growth
|
||||||
end
|
end
|
||||||
|
|
||||||
if farming.DEBUG then
|
if farming.DEBUG then
|
||||||
|
|
||||||
local timer_func = farming.plant_growth_timer;
|
local timer_func = farming.plant_growth_timer;
|
||||||
|
|
||||||
farming.plant_growth_timer = function(pos, elapsed, node_name)
|
farming.plant_growth_timer = function(pos, elapsed, node_name)
|
||||||
|
|
||||||
local t0 = minetest.get_us_time()
|
local t0 = minetest.get_us_time()
|
||||||
|
|
||||||
local r = { timer_func(pos, elapsed, node_name) }
|
local r = { timer_func(pos, elapsed, node_name) }
|
||||||
|
|
||||||
local t1 = minetest.get_us_time()
|
local t1 = minetest.get_us_time()
|
||||||
|
|
||||||
DEBUG_timer_runs = DEBUG_timer_runs + 1
|
DEBUG_timer_runs = DEBUG_timer_runs + 1
|
||||||
DEBUG_timer_time = DEBUG_timer_time + (t1 - t0)
|
DEBUG_timer_time = DEBUG_timer_time + (t1 - t0)
|
||||||
|
|
||||||
return unpack(r)
|
return unpack(r)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- refill placed plant by crabman (26/08/2015)
|
-- refill placed plant by crabman (26/08/2015)
|
||||||
local can_refill_plant = {
|
local can_refill_plant = {
|
||||||
["farming:blueberry_1"] = "farming:blueberries",
|
["farming:blueberry_1"] = "farming:blueberries",
|
||||||
["farming:carrot_1"] = "farming:carrot",
|
["farming:carrot_1"] = "farming:carrot",
|
||||||
["farming:coffee_1"] = "farming:coffee_beans",
|
["farming:coffee_1"] = "farming:coffee_beans",
|
||||||
["farming:corn_1"] = "farming:corn",
|
["farming:corn_1"] = "farming:corn",
|
||||||
["farming:cotton_1"] = "farming:seed_cotton",
|
["farming:cotton_1"] = "farming:seed_cotton",
|
||||||
["farming:cucumber_1"] = "farming:cucumber",
|
["farming:cucumber_1"] = "farming:cucumber",
|
||||||
["farming:melon_1"] = "farming:melon_slice",
|
["farming:melon_1"] = "farming:melon_slice",
|
||||||
["farming:potato_1"] = "farming:potato",
|
["farming:potato_1"] = "farming:potato",
|
||||||
["farming:pumpkin_1"] = "farming:pumpkin_slice",
|
["farming:pumpkin_1"] = "farming:pumpkin_slice",
|
||||||
["farming:raspberry_1"] = "farming:raspberries",
|
["farming:raspberry_1"] = "farming:raspberries",
|
||||||
["farming:rhubarb_1"] = "farming:rhubarb",
|
["farming:rhubarb_1"] = "farming:rhubarb",
|
||||||
["farming:tomato_1"] = "farming:tomato",
|
["farming:tomato_1"] = "farming:tomato",
|
||||||
["farming:wheat_1"] = "farming:seed_wheat"
|
["farming:wheat_1"] = "farming:seed_wheat",
|
||||||
|
["farming:grapes_1"] = "farming:grapes",
|
||||||
|
["farming:beans_1"] = "farming:beans",
|
||||||
|
["farming:rhubarb_1"] = "farming:rhubarb",
|
||||||
|
["farming:cocoa_1"] = "farming:cocoa_beans",
|
||||||
}
|
}
|
||||||
|
|
||||||
function farming.refill_plant(player, plantname, index)
|
function farming.refill_plant(player, plantname, index)
|
||||||
|
|
||||||
local inv = player:get_inventory()
|
local inv = player:get_inventory()
|
||||||
local old_stack = inv:get_stack("main", index)
|
local old_stack = inv:get_stack("main", index)
|
||||||
|
|
||||||
if old_stack:get_name() ~= "" then return end
|
if old_stack:get_name() ~= "" then return end
|
||||||
for i,stack in ipairs(inv:get_list("main")) do
|
|
||||||
|
for i, stack in pairs(inv:get_list("main")) do
|
||||||
|
|
||||||
if stack:get_name() == plantname and i ~= index then
|
if stack:get_name() == plantname and i ~= index then
|
||||||
|
|
||||||
inv:set_stack("main", index, stack)
|
inv:set_stack("main", index, stack)
|
||||||
stack:clear()
|
stack:clear()
|
||||||
inv:set_stack("main", i, stack)
|
inv:set_stack("main", i, stack)
|
||||||
@ -427,6 +497,7 @@ end -- END refill
|
|||||||
-- Place Seeds on Soil
|
-- Place Seeds on Soil
|
||||||
|
|
||||||
function farming.place_seed(itemstack, placer, pointed_thing, plantname)
|
function farming.place_seed(itemstack, placer, pointed_thing, plantname)
|
||||||
|
|
||||||
local pt = pointed_thing
|
local pt = pointed_thing
|
||||||
|
|
||||||
-- check if pointing at a node
|
-- check if pointing at a node
|
||||||
@ -463,19 +534,24 @@ function farming.place_seed(itemstack, placer, pointed_thing, plantname)
|
|||||||
|
|
||||||
-- if not protected then add node and remove 1 item from the itemstack
|
-- if not protected then add node and remove 1 item from the itemstack
|
||||||
if not minetest.is_protected(pt.above, placer:get_player_name()) then
|
if not minetest.is_protected(pt.above, placer:get_player_name()) then
|
||||||
|
|
||||||
minetest.set_node(pt.above, {name = plantname, param2 = 1})
|
minetest.set_node(pt.above, {name = plantname, param2 = 1})
|
||||||
|
|
||||||
if not minetest.setting_getbool("creative_mode") then
|
if not minetest.setting_getbool("creative_mode") then
|
||||||
|
|
||||||
itemstack:take_item()
|
itemstack:take_item()
|
||||||
|
|
||||||
-- check for refill
|
-- check for refill
|
||||||
if itemstack:get_count() == 0
|
if itemstack:get_count() == 0
|
||||||
and can_refill_plant[plantname] then
|
and can_refill_plant[plantname] then
|
||||||
|
|
||||||
minetest.after(0.10,
|
minetest.after(0.10,
|
||||||
farming.refill_plant,
|
farming.refill_plant,
|
||||||
placer,
|
placer,
|
||||||
can_refill_plant[plantname],
|
can_refill_plant[plantname],
|
||||||
placer:get_wield_index()
|
placer:get_wield_index()
|
||||||
)
|
)
|
||||||
end -- END refill
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return itemstack
|
return itemstack
|
||||||
@ -485,6 +561,7 @@ end
|
|||||||
-- Function to register plants (for compatibility)
|
-- Function to register plants (for compatibility)
|
||||||
|
|
||||||
farming.register_plant = function(name, def)
|
farming.register_plant = function(name, def)
|
||||||
|
|
||||||
local mname = name:split(":")[1]
|
local mname = name:split(":")[1]
|
||||||
local pname = name:split(":")[2]
|
local pname = name:split(":")[2]
|
||||||
|
|
||||||
@ -492,15 +569,18 @@ farming.register_plant = function(name, def)
|
|||||||
if not def.description then
|
if not def.description then
|
||||||
def.description = "Seed"
|
def.description = "Seed"
|
||||||
end
|
end
|
||||||
|
|
||||||
if not def.inventory_image then
|
if not def.inventory_image then
|
||||||
def.inventory_image = "unknown_item.png"
|
def.inventory_image = "unknown_item.png"
|
||||||
end
|
end
|
||||||
|
|
||||||
if not def.steps then
|
if not def.steps then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Register seed
|
-- Register seed
|
||||||
minetest.register_node(":" .. mname .. ":seed_" .. pname, {
|
minetest.register_node(":" .. mname .. ":seed_" .. pname, {
|
||||||
|
|
||||||
description = def.description,
|
description = def.description,
|
||||||
tiles = {def.inventory_image},
|
tiles = {def.inventory_image},
|
||||||
inventory_image = def.inventory_image,
|
inventory_image = def.inventory_image,
|
||||||
@ -512,6 +592,7 @@ farming.register_plant = function(name, def)
|
|||||||
walkable = false,
|
walkable = false,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
selection_box = farming.select,
|
selection_box = farming.select,
|
||||||
|
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":"..pname.."_1")
|
return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":"..pname.."_1")
|
||||||
end
|
end
|
||||||
@ -525,6 +606,7 @@ farming.register_plant = function(name, def)
|
|||||||
|
|
||||||
-- Register growing steps
|
-- Register growing steps
|
||||||
for i = 1, def.steps do
|
for i = 1, def.steps do
|
||||||
|
|
||||||
local drop = {
|
local drop = {
|
||||||
items = {
|
items = {
|
||||||
{items = {mname .. ":" .. pname}, rarity = 9 - i},
|
{items = {mname .. ":" .. pname}, rarity = 9 - i},
|
||||||
@ -535,12 +617,14 @@ farming.register_plant = function(name, def)
|
|||||||
}
|
}
|
||||||
|
|
||||||
local g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, growing = 1}
|
local g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1, growing = 1}
|
||||||
|
|
||||||
-- Last step doesn't need growing=1 so Abm never has to check these
|
-- Last step doesn't need growing=1 so Abm never has to check these
|
||||||
if i == def.steps then
|
if i == def.steps then
|
||||||
g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1}
|
g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1}
|
||||||
end
|
end
|
||||||
|
|
||||||
local node_name = mname .. ":" .. pname .. "_" .. i
|
local node_name = mname .. ":" .. pname .. "_" .. i
|
||||||
|
|
||||||
minetest.register_node(node_name, {
|
minetest.register_node(node_name, {
|
||||||
drawtype = "plantlike",
|
drawtype = "plantlike",
|
||||||
waving = 1,
|
waving = 1,
|
||||||
@ -553,6 +637,7 @@ farming.register_plant = function(name, def)
|
|||||||
groups = g,
|
groups = g,
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
})
|
})
|
||||||
|
|
||||||
register_plant_node(node_name)
|
register_plant_node(node_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -31,13 +31,13 @@ function farming.register_mgv6_decorations()
|
|||||||
register_plant("melon_8", 1, 20, "group:water", 1)
|
register_plant("melon_8", 1, 20, "group:water", 1)
|
||||||
register_plant("pumpkin_8", 1, 20, "group:water", 1)
|
register_plant("pumpkin_8", 1, 20, "group:water", 1)
|
||||||
register_plant("raspberry_4", 3, 10, "", -1)
|
register_plant("raspberry_4", 3, 10, "", -1)
|
||||||
register_plant("rhubarb_3", 3, 15, "group:tree", 1)
|
register_plant("rhubarb_3", 3, 15, "", -1)
|
||||||
register_plant("blueberry_4", 3, 10, "", -1)
|
register_plant("blueberry_4", 3, 10, "", -1)
|
||||||
register_plant("beanbush", 18, 35, "", -1)
|
register_plant("beanbush", 18, 35, "", -1)
|
||||||
register_plant("grapebush", 25, 45, "", -1)
|
register_plant("grapebush", 25, 45, "", -1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- v7 maps have a beach so plants growing near water is limited to 6- high
|
-- v7 maps have a beach so plants growing near water is limited to 6 high
|
||||||
function farming.register_mgv7_decorations()
|
function farming.register_mgv7_decorations()
|
||||||
register_plant("potato_3", 15, 40, "", -1)
|
register_plant("potato_3", 15, 40, "", -1)
|
||||||
register_plant("tomato_7", 5, 20, "", -1)
|
register_plant("tomato_7", 5, 20, "", -1)
|
||||||
@ -49,7 +49,7 @@ function farming.register_mgv7_decorations()
|
|||||||
register_plant("melon_8", 1, 6, "", -1)
|
register_plant("melon_8", 1, 6, "", -1)
|
||||||
register_plant("pumpkin_8", 1, 6, "", -1)
|
register_plant("pumpkin_8", 1, 6, "", -1)
|
||||||
register_plant("raspberry_4", 3, 10, "", -1)
|
register_plant("raspberry_4", 3, 10, "", -1)
|
||||||
register_plant("rhubarb_3", 3, 15, "group:tree", 1)
|
register_plant("rhubarb_3", 3, 15, "", -1)
|
||||||
register_plant("blueberry_4", 3, 10, "", -1)
|
register_plant("blueberry_4", 3, 10, "", -1)
|
||||||
register_plant("beanbush", 18, 35, "", -1)
|
register_plant("beanbush", 18, 35, "", -1)
|
||||||
register_plant("grapebush", 25, 45, "", -1)
|
register_plant("grapebush", 25, 45, "", -1)
|
||||||
|
@ -61,7 +61,7 @@ minetest.register_node("farming:jackolantern", {
|
|||||||
sounds = default.node_sound_wood_defaults(),
|
sounds = default.node_sound_wood_defaults(),
|
||||||
on_punch = function(pos, node, puncher)
|
on_punch = function(pos, node, puncher)
|
||||||
node.name = "farming:jackolantern_on"
|
node.name = "farming:jackolantern_on"
|
||||||
minetest.set_node(pos, node)
|
minetest.swap_node(pos, node)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ minetest.register_node("farming:jackolantern_on", {
|
|||||||
drop = "farming:jackolantern",
|
drop = "farming:jackolantern",
|
||||||
on_punch = function(pos, node, puncher)
|
on_punch = function(pos, node, puncher)
|
||||||
node.name = "farming:jackolantern"
|
node.name = "farming:jackolantern"
|
||||||
minetest.set_node(pos, node)
|
minetest.swap_node(pos, node)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ minetest.register_abm({
|
|||||||
nodenames = {"farming:soil", "farming:soil_wet"},
|
nodenames = {"farming:soil", "farming:soil_wet"},
|
||||||
interval = 15,
|
interval = 15,
|
||||||
chance = 4,
|
chance = 4,
|
||||||
|
catch_up = false,
|
||||||
|
|
||||||
action = function(pos, node)
|
action = function(pos, node)
|
||||||
|
|
||||||
pos.y = pos.y + 1
|
pos.y = pos.y + 1
|
||||||
@ -51,8 +53,10 @@ minetest.register_abm({
|
|||||||
if node.name == "farming:soil" then
|
if node.name == "farming:soil" then
|
||||||
minetest.set_node(pos, {name = "farming:soil_wet"})
|
minetest.set_node(pos, {name = "farming:soil_wet"})
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif node.name == "farming:soil_wet" then
|
elseif node.name == "farming:soil_wet" then
|
||||||
minetest.set_node(pos, {name = "farming:soil"})
|
minetest.set_node(pos, {name = "farming:soil"})
|
||||||
|
|
||||||
elseif node.name == "farming:soil" then
|
elseif node.name == "farming:soil" then
|
||||||
minetest.set_node(pos, {name = "default:dirt"})
|
minetest.set_node(pos, {name = "default:dirt"})
|
||||||
end
|
end
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
local statistics = {}
|
local statistics = {}
|
||||||
|
|
||||||
local ROOT_2 = math.sqrt(2.0)
|
local ROOT_2 = math.sqrt(2.0)
|
||||||
|
|
||||||
-- Approximations for erf(x) and erfInv(x) from
|
-- Approximations for erf(x) and erfInv(x) from
|
||||||
-- https://en.wikipedia.org/wiki/Error_function
|
-- https://en.wikipedia.org/wiki/Error_function
|
||||||
|
|
||||||
local erf
|
local erf
|
||||||
local erf_inv
|
local erf_inv
|
||||||
|
|
||||||
@ -13,19 +13,26 @@ local C = 2.0/(math.pi * A)
|
|||||||
local D = 1.0 / A
|
local D = 1.0 / A
|
||||||
|
|
||||||
erf = function(x)
|
erf = function(x)
|
||||||
|
|
||||||
if x == 0 then return 0; end
|
if x == 0 then return 0; end
|
||||||
|
|
||||||
local xSq = x * x
|
local xSq = x * x
|
||||||
local aXSq = A * xSq
|
local aXSq = A * xSq
|
||||||
local v = math.sqrt(1.0 - math.exp(-xSq * (B + aXSq) / (1.0 + aXSq)))
|
local v = math.sqrt(1.0 - math.exp(-xSq * (B + aXSq) / (1.0 + aXSq)))
|
||||||
|
|
||||||
return (x > 0 and v) or -v
|
return (x > 0 and v) or -v
|
||||||
end
|
end
|
||||||
|
|
||||||
erf_inv = function(x)
|
erf_inv = function(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 = math.log(1 - x * x)
|
||||||
local u = C + 0.5 * y
|
local u = C + 0.5 * y
|
||||||
local v = math.sqrt(math.sqrt(u * u - D * y) - u)
|
local v = math.sqrt(math.sqrt(u * u - D * y) - u)
|
||||||
|
|
||||||
return (x > 0 and v) or -v
|
return (x > 0 and v) or -v
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -37,6 +44,7 @@ local poisson
|
|||||||
local cdf_table = {}
|
local cdf_table = {}
|
||||||
|
|
||||||
local function generate_cdf(lambda_index, lambda)
|
local function generate_cdf(lambda_index, lambda)
|
||||||
|
|
||||||
local max = math.ceil(4 * lambda)
|
local max = math.ceil(4 * lambda)
|
||||||
local pdf = math.exp(-lambda)
|
local pdf = math.exp(-lambda)
|
||||||
local cdf = pdf
|
local cdf = pdf
|
||||||
@ -56,6 +64,7 @@ for li = 1, 100 do
|
|||||||
end
|
end
|
||||||
|
|
||||||
poisson = function(lambda, max)
|
poisson = function(lambda, max)
|
||||||
|
|
||||||
if max < 2 then
|
if max < 2 then
|
||||||
return (math.random() < math.exp(-lambda) and 0) or 1
|
return (math.random() < math.exp(-lambda) and 0) or 1
|
||||||
elseif lambda >= 2 * max then
|
elseif lambda >= 2 * max then
|
||||||
@ -67,6 +76,7 @@ poisson = function(lambda, max)
|
|||||||
local cdfs = cdf_table[lambda_index]
|
local cdfs = cdf_table[lambda_index]
|
||||||
|
|
||||||
if cdfs then
|
if cdfs then
|
||||||
|
|
||||||
lambda = 0.25 * lambda_index
|
lambda = 0.25 * lambda_index
|
||||||
|
|
||||||
if u < cdfs[0] then return 0; end
|
if u < cdfs[0] then return 0; end
|
||||||
@ -74,9 +84,13 @@ poisson = function(lambda, max)
|
|||||||
if u >= cdfs[max - 1] then return max; end
|
if u >= cdfs[max - 1] then return max; end
|
||||||
|
|
||||||
if max > 4 then -- Binary search
|
if max > 4 then -- Binary search
|
||||||
|
|
||||||
local s = 0
|
local s = 0
|
||||||
|
|
||||||
while s + 1 < max do
|
while s + 1 < max do
|
||||||
|
|
||||||
local m = math.floor(0.5 * (s + max))
|
local m = math.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
|
end
|
||||||
else
|
else
|
||||||
@ -88,6 +102,7 @@ poisson = function(lambda, max)
|
|||||||
return max
|
return max
|
||||||
else
|
else
|
||||||
local x = lambda + math.sqrt(lambda) * std_normal(u)
|
local x = lambda + math.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 math.floor(x + 0.5)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -102,14 +117,17 @@ statistics.erf_inv = erf_inv
|
|||||||
--
|
--
|
||||||
-- @return
|
-- @return
|
||||||
-- Any real number (actually between -3.0 and 3.0).
|
-- Any real number (actually between -3.0 and 3.0).
|
||||||
--
|
|
||||||
statistics.std_normal = function()
|
statistics.std_normal = function()
|
||||||
|
|
||||||
local u = math.random()
|
local u = math.random()
|
||||||
|
|
||||||
if u < 0.001 then
|
if u < 0.001 then
|
||||||
return -3.0
|
return -3.0
|
||||||
elseif u > 0.999 then
|
elseif u > 0.999 then
|
||||||
return 3.0
|
return 3.0
|
||||||
end
|
end
|
||||||
|
|
||||||
return std_normal(u)
|
return std_normal(u)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -121,14 +139,17 @@ end
|
|||||||
-- The distribution standard deviation.
|
-- The distribution standard deviation.
|
||||||
-- @return
|
-- @return
|
||||||
-- Any real number (actually between -3*sigma and 3*sigma).
|
-- Any real number (actually between -3*sigma and 3*sigma).
|
||||||
--
|
|
||||||
statistics.normal = function(mu, sigma)
|
statistics.normal = function(mu, sigma)
|
||||||
|
|
||||||
local u = math.random()
|
local u = math.random()
|
||||||
|
|
||||||
if u < 0.001 then
|
if u < 0.001 then
|
||||||
return mu - 3.0 * sigma
|
return mu - 3.0 * sigma
|
||||||
elseif u > 0.999 then
|
elseif u > 0.999 then
|
||||||
return mu + 3.0 * sigma
|
return mu + 3.0 * sigma
|
||||||
end
|
end
|
||||||
|
|
||||||
return mu + sigma * std_normal(u)
|
return mu + sigma * std_normal(u)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -140,10 +161,13 @@ end
|
|||||||
-- The distribution maximum.
|
-- The distribution maximum.
|
||||||
-- @return
|
-- @return
|
||||||
-- An integer between 0 and max (both inclusive).
|
-- An integer between 0 and max (both inclusive).
|
||||||
--
|
|
||||||
statistics.poisson = function(lambda, max)
|
statistics.poisson = function(lambda, max)
|
||||||
|
|
||||||
lambda, max = tonumber(lambda), tonumber(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)
|
return poisson(lambda, max)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user