From bf269a6574f2bfcfbbffec06b7fd2ef4d04053fa Mon Sep 17 00:00:00 2001 From: LeMagnesium Date: Sat, 5 Mar 2016 19:14:24 +0100 Subject: [PATCH] [farming] Update from Skyblock --- minetestforfun_game/mods/farming/beanpole.lua | 15 +- minetestforfun_game/mods/farming/cocoa.lua | 2 +- minetestforfun_game/mods/farming/grapes.lua | 12 +- minetestforfun_game/mods/farming/hoes.lua | 10 ++ minetestforfun_game/mods/farming/init.lua | 153 ++++++++++++++---- minetestforfun_game/mods/farming/mapgen.lua | 6 +- minetestforfun_game/mods/farming/pumpkin.lua | 4 +- minetestforfun_game/mods/farming/soil.lua | 4 + .../mods/farming/statistics.lua | 36 ++++- minetestforfun_game/mods/farming/wheat.lua | 2 +- 10 files changed, 185 insertions(+), 59 deletions(-) diff --git a/minetestforfun_game/mods/farming/beanpole.lua b/minetestforfun_game/mods/farming/beanpole.lua index 9d975e57..634f6bf3 100755 --- a/minetestforfun_game/mods/farming/beanpole.lua +++ b/minetestforfun_game/mods/farming/beanpole.lua @@ -9,7 +9,9 @@ minetest.register_craftitem("farming:beans", { inventory_image = "farming_beans.png", on_use = minetest.item_eat(1), 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) if nod and nod.name == "farming:beanpole" then minetest.set_node(pointed_thing.under, {name="farming:beanpole_1"}) @@ -58,13 +60,12 @@ minetest.register_node("farming:beanpole", { } }, selection_box = farming.select, - groups = { - snappy = 3, flammable = 2, attached_node = 1, - not_in_creative_inventory = 1 - }, + groups = {snappy = 3, flammable = 2, attached_node = 1}, sounds = default.node_sound_leaves_defaults(), 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) if nod and minetest.get_item_group(nod.name, "soil") < 2 then return @@ -235,4 +236,4 @@ minetest.register_node("farming:beanbush", { not_in_creative_inventory=1 }, sounds = default.node_sound_leaves_defaults(), -}) +}) \ No newline at end of file diff --git a/minetestforfun_game/mods/farming/cocoa.lua b/minetestforfun_game/mods/farming/cocoa.lua index b8ee3a00..35845c88 100755 --- a/minetestforfun_game/mods/farming/cocoa.lua +++ b/minetestforfun_game/mods/farming/cocoa.lua @@ -182,4 +182,4 @@ minetest.register_abm({ }) end end, -}) +}) \ No newline at end of file diff --git a/minetestforfun_game/mods/farming/grapes.lua b/minetestforfun_game/mods/farming/grapes.lua index aeb29ff4..93cf1d11 100755 --- a/minetestforfun_game/mods/farming/grapes.lua +++ b/minetestforfun_game/mods/farming/grapes.lua @@ -5,7 +5,9 @@ minetest.register_craftitem("farming:grapes", { inventory_image = "farming_grapes.png", on_use = minetest.item_eat(2), 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) if nod and nod.name == "farming:trellis" then minetest.set_node(pointed_thing.under, {name="farming:grapes_1"}) @@ -54,12 +56,12 @@ minetest.register_node("farming:trellis", { } }, selection_box = farming.select, - groups = { - snappy = 3, flammable = 2, attached_node = 1, - }, + groups = {snappy = 3, flammable = 2, attached_node = 1}, sounds = default.node_sound_leaves_defaults(), 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) if nod and minetest.get_item_group(nod.name, "soil") < 2 then return diff --git a/minetestforfun_game/mods/farming/hoes.lua b/minetestforfun_game/mods/farming/hoes.lua index 6eb55f6d..98144f2c 100755 --- a/minetestforfun_game/mods/farming/hoes.lua +++ b/minetestforfun_game/mods/farming/hoes.lua @@ -2,17 +2,21 @@ -- Hoe registration function farming.register_hoe = function(name, def) + -- Check for : prefix (register new hoes in your mod's namespace) if name:sub(1,1) ~= ":" then name = ":" .. name end + -- Check def table if def.description == nil then def.description = "Hoe" end + if def.inventory_image == nil then def.inventory_image = "unknown_item.png" end + if def.recipe == nil then def.recipe = { {"air","air",""}, @@ -20,9 +24,11 @@ farming.register_hoe = function(name, def) {"","group:stick",""} } end + if def.max_uses == nil then def.max_uses = 30 end + -- Register the tool minetest.register_tool(name, { 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) end }) + -- Register its recipe -- Registration using material made for MFF if def.material == nil then @@ -62,7 +69,9 @@ end -- Turns dirt with group soil=1 into soil function farming.hoe_on_use(itemstack, user, pointed_thing, uses) + local pt = pointed_thing + -- check if pointing at a node if not pt or pt.type ~= "node" then 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 minetest.set_node(pt.under, {name = "farming:soil"}) + 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 local tool_name = itemstack:get_name() diff --git a/minetestforfun_game/mods/farming/init.lua b/minetestforfun_game/mods/farming/init.lua index ed6eae91..069ab7ae 100755 --- a/minetestforfun_game/mods/farming/init.lua +++ b/minetestforfun_game/mods/farming/init.lua @@ -1,5 +1,5 @@ --[[ - Minetest Farming Redo Mod 1.22 (26th October 2015) + Minetest Farming Redo Mod 1.22 (8th December 2015) by TenPlus1 NEW growing routine by prestidigitator auto-refill by crabman77 @@ -21,7 +21,9 @@ local DEBUG_abm_runs = 0 local DEBUG_abm_time = 0 local DEBUG_timer_runs = 0 local DEBUG_timer_time = 0 + if farming.DEBUG then + function farming.DEBUG.reset_times() DEBUG_abm_runs = 0 DEBUG_abm_time = 0 @@ -30,6 +32,7 @@ if farming.DEBUG then end function farming.DEBUG.report_times() + local abm_n = DEBUG_abm_runs local abm_dt = DEBUG_abm_time 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_avg = (timer_n > 0 and timer_dt / timer_n) or 0 local dt = abm_dt + timer_dt - 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: ".. - timer_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: "..timer_avg.."µs/run") print("Total farming time: "..dt.."µs") end end local statistics = dofile(farming.path.."/statistics.lua") + dofile(farming.path.."/soil.lua") dofile(farming.path.."/hoes.lua") dofile(farming.path.."/grass.lua") @@ -95,12 +98,14 @@ end -- If true, count elapsed day time. Otherwise, count elapsed night time. -- @return -- 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) + if count_day then + if t_day < 0.25 then t1_c = t1_day + 0.75 -- Relative to sunup, yesterday t2_c = t_day + 0.75 @@ -119,6 +124,7 @@ local function day_or_night_time(t_game, t_day, dt, count_day) end local dt_c = clamp(t2_c, 0, 0.5) - clamp(t1_c, 0, 0.5) -- this cycle + if t1_c < -0.5 then local nc = math.floor(-t1_c) t1_c = t1_c + nc @@ -166,10 +172,13 @@ local MAX_LIGHT = 1000 -- Node or position table, or node name. -- @return -- List (plant_name, stage), or nothing (nil) if node isn't loaded - -- + local function plant_name_stage(node) + local name + if type(node) == 'table' then + if node.name then name = node.name elseif node.x and node.y and node.z then @@ -179,11 +188,15 @@ local function plant_name_stage(node) else name = tostring(node) end + if not name or name == "ignore" then return nil end local sep_pos = name:find("_[^_]+$") + if sep_pos and sep_pos > 1 then + local stage = tonumber(name:sub(sep_pos + 1)) + if stage and stage >= 0 then return name:sub(1, sep_pos - 1), stage end @@ -195,6 +208,7 @@ end --- Map from node name to -- { plant_name = ..., name = ..., stage = n, stages_left = { node_name, ... } } local plant_stages = {} + farming.plant_stages = plant_stages --- Registers the stages of growth of a (possible plant) node. @@ -204,21 +218,26 @@ farming.plant_stages = plant_stages -- @return -- The (possibly zero) number of stages of growth the plant will go through -- before being fully grown, or nil if not a plant. - -- + local register_plant_node + -- Recursive helper local function reg_plant_stages(plant_name, stage, force_last) + local node_name = plant_name and plant_name .. "_" .. stage local node_def = node_name and minetest.registered_nodes[node_name] + if not node_def then return nil end local stages = plant_stages[node_name] + if stages then return stages end 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 {} + stages = { plant_name = plant_name, name = node_name, @@ -227,8 +246,10 @@ local function reg_plant_stages(plant_name, stage, force_last) } if #stages_left > 0 then + local old_constr = node_def.on_construct local old_destr = node_def.on_destruct + minetest.override_item(node_name, { on_construct = function(pos) @@ -246,7 +267,9 @@ local function reg_plant_stages(plant_name, stage, force_last) end, }) end + elseif force_last then + stages = { plant_name = plant_name, name = node_name, @@ -258,11 +281,14 @@ local function reg_plant_stages(plant_name, stage, force_last) end plant_stages[node_name] = stages + return stages end register_plant_node = function(node) + local plant_name, stage = plant_name_stage(node) + if plant_name then local stages = reg_plant_stages(plant_name, stage, false) return stages and #stages.stages_left @@ -272,15 +298,22 @@ register_plant_node = function(node) end local function set_growing(pos, stages_left) + if not stages_left then return end local timer = minetest.get_node_timer(pos) + if stages_left > 0 then + if not timer:is_started() then + 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) + timer:set(stage_length, -0.5 * math.random() * STAGE_LENGTH_AVG) end + elseif timer:is_started() then timer:stop() end @@ -292,10 +325,13 @@ end -- The node's position. -- @param node -- The cached node table if available, or nil. - -- + function farming.handle_growth(pos, node) + if not pos then return end + local stages_left = register_plant_node(node or pos) + if stages_left then set_growing(pos, stages_left) end end @@ -307,14 +343,19 @@ minetest.after(0, end) local abm_func = farming.handle_growth + if farming.DEBUG then + local normal_abm_func = abm_func + abm_func = function(...) local t0 = minetest.get_us_time() local r = { normal_abm_func(...) } local t1 = minetest.get_us_time() + DEBUG_abm_runs = DEBUG_abm_runs + 1 DEBUG_abm_time = DEBUG_abm_time + (t1 - t0) + return unpack(r) end end @@ -322,39 +363,51 @@ end -- Just in case a growing type or added node is missed (also catches existing -- nodes added to map before timers were incorporated). minetest.register_abm({ + nodenames = { "group:growing" }, - interval = 300, - chance = 1, - action = abm_func}) + interval = 300, + chance = 1, + action = abm_func +}) --- Plant timer function. -- -- Grows plants under the right conditions. - -- + function farming.plant_growth_timer(pos, elapsed, node_name) + local stages = plant_stages[node_name] + if not stages then return false end local max_growth = #stages.stages_left + if max_growth <= 0 then return false end if stages.plant_name == "farming:cocoa" then + if not minetest.find_node_near(pos, 1, { "default:jungletree", "moretrees:jungletree_leaves_green" }) then return true end else 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 end local growth - local light_pos = { x = pos.x, y = pos.y, z = pos.z } local lambda = elapsed / STAGE_LENGTH_AVG + if lambda < 0.1 then return true end + if max_growth == 1 or lambda < 2.0 then + 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 + growth = 1 else 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 growth = statistics.poisson(lambda, max_growth) + if growth < 1 then return true 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 end if farming.DEBUG then + local timer_func = farming.plant_growth_timer; + farming.plant_growth_timer = function(pos, elapsed, node_name) + local t0 = minetest.get_us_time() - local r = { timer_func(pos, elapsed, node_name) } - local t1 = minetest.get_us_time() + DEBUG_timer_runs = DEBUG_timer_runs + 1 DEBUG_timer_time = DEBUG_timer_time + (t1 - t0) + return unpack(r) end end -- refill placed plant by crabman (26/08/2015) local can_refill_plant = { - ["farming:blueberry_1"] = "farming:blueberries", - ["farming:carrot_1"] = "farming:carrot", - ["farming:coffee_1"] = "farming:coffee_beans", + ["farming:blueberry_1"] = "farming:blueberries", + ["farming:carrot_1"] = "farming:carrot", + ["farming:coffee_1"] = "farming:coffee_beans", ["farming:corn_1"] = "farming:corn", - ["farming:cotton_1"] = "farming:seed_cotton", - ["farming:cucumber_1"] = "farming:cucumber", - ["farming:melon_1"] = "farming:melon_slice", - ["farming:potato_1"] = "farming:potato", - ["farming:pumpkin_1"] = "farming:pumpkin_slice", - ["farming:raspberry_1"] = "farming:raspberries", - ["farming:rhubarb_1"] = "farming:rhubarb", - ["farming:tomato_1"] = "farming:tomato", - ["farming:wheat_1"] = "farming:seed_wheat" + ["farming:cotton_1"] = "farming:seed_cotton", + ["farming:cucumber_1"] = "farming:cucumber", + ["farming:melon_1"] = "farming:melon_slice", + ["farming:potato_1"] = "farming:potato", + ["farming:pumpkin_1"] = "farming:pumpkin_slice", + ["farming:raspberry_1"] = "farming:raspberries", + ["farming:rhubarb_1"] = "farming:rhubarb", + ["farming:tomato_1"] = "farming:tomato", + ["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) + local inv = player:get_inventory() local old_stack = inv:get_stack("main", index) + 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 + inv:set_stack("main", index, stack) stack:clear() inv:set_stack("main", i, stack) @@ -427,6 +497,7 @@ end -- END refill -- Place Seeds on Soil function farming.place_seed(itemstack, placer, pointed_thing, plantname) + local pt = pointed_thing -- 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 minetest.is_protected(pt.above, placer:get_player_name()) then + minetest.set_node(pt.above, {name = plantname, param2 = 1}) + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + -- check for refill if itemstack:get_count() == 0 and can_refill_plant[plantname] then + minetest.after(0.10, farming.refill_plant, placer, can_refill_plant[plantname], placer:get_wield_index() ) - end -- END refill + end end return itemstack @@ -485,6 +561,7 @@ end -- Function to register plants (for compatibility) farming.register_plant = function(name, def) + local mname = name:split(":")[1] local pname = name:split(":")[2] @@ -492,15 +569,18 @@ farming.register_plant = function(name, def) if not def.description then def.description = "Seed" end + if not def.inventory_image then def.inventory_image = "unknown_item.png" end + if not def.steps then return nil end -- Register seed minetest.register_node(":" .. mname .. ":seed_" .. pname, { + description = def.description, tiles = {def.inventory_image}, inventory_image = def.inventory_image, @@ -512,6 +592,7 @@ farming.register_plant = function(name, def) walkable = false, sunlight_propagates = true, selection_box = farming.select, + on_place = function(itemstack, placer, pointed_thing) return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":"..pname.."_1") end @@ -525,6 +606,7 @@ farming.register_plant = function(name, def) -- Register growing steps for i = 1, def.steps do + local drop = { items = { {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} + -- Last step doesn't need growing=1 so Abm never has to check these if i == def.steps then g = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1} end local node_name = mname .. ":" .. pname .. "_" .. i + minetest.register_node(node_name, { drawtype = "plantlike", waving = 1, @@ -553,6 +637,7 @@ farming.register_plant = function(name, def) groups = g, sounds = default.node_sound_leaves_defaults(), }) + register_plant_node(node_name) end diff --git a/minetestforfun_game/mods/farming/mapgen.lua b/minetestforfun_game/mods/farming/mapgen.lua index 00d4fd12..dcd51a33 100755 --- a/minetestforfun_game/mods/farming/mapgen.lua +++ b/minetestforfun_game/mods/farming/mapgen.lua @@ -31,13 +31,13 @@ function farming.register_mgv6_decorations() register_plant("melon_8", 1, 20, "group:water", 1) register_plant("pumpkin_8", 1, 20, "group:water", 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("beanbush", 18, 35, "", -1) register_plant("grapebush", 25, 45, "", -1) 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() register_plant("potato_3", 15, 40, "", -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("pumpkin_8", 1, 6, "", -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("beanbush", 18, 35, "", -1) register_plant("grapebush", 25, 45, "", -1) diff --git a/minetestforfun_game/mods/farming/pumpkin.lua b/minetestforfun_game/mods/farming/pumpkin.lua index 60f01755..708d7eab 100755 --- a/minetestforfun_game/mods/farming/pumpkin.lua +++ b/minetestforfun_game/mods/farming/pumpkin.lua @@ -61,7 +61,7 @@ minetest.register_node("farming:jackolantern", { sounds = default.node_sound_wood_defaults(), on_punch = function(pos, node, puncher) node.name = "farming:jackolantern_on" - minetest.set_node(pos, node) + minetest.swap_node(pos, node) end, }) @@ -82,7 +82,7 @@ minetest.register_node("farming:jackolantern_on", { drop = "farming:jackolantern", on_punch = function(pos, node, puncher) node.name = "farming:jackolantern" - minetest.set_node(pos, node) + minetest.swap_node(pos, node) end, }) diff --git a/minetestforfun_game/mods/farming/soil.lua b/minetestforfun_game/mods/farming/soil.lua index ba96a57e..e748d5c0 100755 --- a/minetestforfun_game/mods/farming/soil.lua +++ b/minetestforfun_game/mods/farming/soil.lua @@ -25,6 +25,8 @@ minetest.register_abm({ nodenames = {"farming:soil", "farming:soil_wet"}, interval = 15, chance = 4, + catch_up = false, + action = function(pos, node) pos.y = pos.y + 1 @@ -51,8 +53,10 @@ minetest.register_abm({ if node.name == "farming:soil" then minetest.set_node(pos, {name = "farming:soil_wet"}) end + elseif node.name == "farming:soil_wet" then minetest.set_node(pos, {name = "farming:soil"}) + elseif node.name == "farming:soil" then minetest.set_node(pos, {name = "default:dirt"}) end diff --git a/minetestforfun_game/mods/farming/statistics.lua b/minetestforfun_game/mods/farming/statistics.lua index 265ccb3a..c8defa2f 100755 --- a/minetestforfun_game/mods/farming/statistics.lua +++ b/minetestforfun_game/mods/farming/statistics.lua @@ -1,9 +1,9 @@ local statistics = {} - local ROOT_2 = math.sqrt(2.0) -- 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_inv @@ -13,19 +13,26 @@ local C = 2.0/(math.pi * A) local D = 1.0 / A erf = function(x) + 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))) + return (x > 0 and v) or -v end erf_inv = function(x) + if x == 0 then return 0; end + if x <= -1 or x >= 1 then return nil; end + local y = math.log(1 - x * x) local u = C + 0.5 * y local v = math.sqrt(math.sqrt(u * u - D * y) - u) + return (x > 0 and v) or -v end @@ -37,6 +44,7 @@ local poisson local cdf_table = {} local function generate_cdf(lambda_index, lambda) + local max = math.ceil(4 * lambda) local pdf = math.exp(-lambda) local cdf = pdf @@ -56,6 +64,7 @@ for li = 1, 100 do end poisson = function(lambda, max) + if max < 2 then return (math.random() < math.exp(-lambda) and 0) or 1 elseif lambda >= 2 * max then @@ -67,6 +76,7 @@ poisson = function(lambda, max) local cdfs = cdf_table[lambda_index] if cdfs then + lambda = 0.25 * lambda_index 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 max > 4 then -- Binary search + local s = 0 + while s + 1 < max do + local m = math.floor(0.5 * (s + max)) + if u < cdfs[m] then max = m; else s = m; end end else @@ -88,6 +102,7 @@ poisson = function(lambda, max) return max else 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) end end @@ -102,14 +117,17 @@ statistics.erf_inv = erf_inv -- -- @return -- Any real number (actually between -3.0 and 3.0). - -- + statistics.std_normal = function() + local u = math.random() + if u < 0.001 then return -3.0 elseif u > 0.999 then return 3.0 end + return std_normal(u) end @@ -121,14 +139,17 @@ end -- The distribution standard deviation. -- @return -- Any real number (actually between -3*sigma and 3*sigma). - -- + statistics.normal = function(mu, sigma) + local u = math.random() + if u < 0.001 then return mu - 3.0 * sigma elseif u > 0.999 then return mu + 3.0 * sigma end + return mu + sigma * std_normal(u) end @@ -140,11 +161,14 @@ end -- The distribution maximum. -- @return -- An integer between 0 and max (both inclusive). - -- + 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 + return poisson(lambda, max) end -return statistics \ No newline at end of file +return statistics diff --git a/minetestforfun_game/mods/farming/wheat.lua b/minetestforfun_game/mods/farming/wheat.lua index 1fed3af0..30728eb6 100755 --- a/minetestforfun_game/mods/farming/wheat.lua +++ b/minetestforfun_game/mods/farming/wheat.lua @@ -248,4 +248,4 @@ minetest.register_node("farming:wheat_8", { not_in_creative_inventory = 1 }, sounds = default.node_sound_leaves_defaults(), -}) +}) \ No newline at end of file