forestry/forestry_bees/helper.lua
2024-10-11 19:39:04 +02:00

166 lines
6.1 KiB
Lua

--function forestry_bees.Bee(bee_type,active_type_gene,inactive_type_gene,active_fertility_gene,inactive_fertility_gene)
--local itemstack = ItemStack({name = forestry_bees.bee_name(bee_type,active_type_gene)})
--itemstack:get_meta():set_string("active_type_gene",active_type_gene)
--itemstack:get_meta():set_string("inactive_type_gene",inactive_type_gene)
--itemstack:get_meta():set_string("active_fertility_gene",active_fertility_gene)
--itemstack:get_meta():set_string("inactive_fertility_gene",inactive_fertility_gene)
--return itemstack
--end
function forestry_bees.Bee(bee_type,genes)
local itemstack = ItemStack({name = forestry_bees.bee_name(bee_type,genes["type_gene"][1])}) --the "1" is cuz the table genes["type_gene"] has 2 entries: active and inactive
itemstack:get_meta():set_string("genes", minetest.serialize(genes))
--for gene_type,gene in pairs(genes) do
-- itemstack:get_meta():set_string(gene_type,gene)
--end
return itemstack
end
function forestry_bees.calculate_drop(bee)
local genes = minetest.deserialize(bee:get_meta():get_string("genes"))
local possible_drops = forestry_bees.bee_drops[genes["type_gene"][1]] --this gets us a table
local out_table = {}
for drop,chance in pairs(possible_drops) do
if math.random() < chance * genes["production"][1] then --the prob of getting something is P = (base chance from bee_drops) * (item modifier (frames and stuff)) * (bee production gene)
table.insert(out_table,ItemStack(drop))
end
end
return out_table
end
function forestry_bees.bee_name(bee_type,active_type_gene)
return "forestry_bees:"..active_type_gene.."_"..bee_type
end
function forestry_bees.stacks_in_inv(inv,listname)
local stack_list = inv:get_list(listname)
local result = 0
for i = 1,#stack_list do
if not stack_list[i]:is_empty() then
result = result + 1
end
end
return result
end
function forestry_bees.format_bee(bee)
local name = bee:get_name()
local meta = bee:get_meta()
local genes = forestry_bees.return_all_genes_double(string.sub(string.match(string.match(name,":.*"),".*_"),2,-2))
return forestry_bees.Bee(string.sub(string.match(string.sub(string.match(name,"_.*"),2),"_.*"),2),genes)
end
function forestry_bees.breed_princess_drone(princess,drone)
--local princess_meta = princess:get_meta()
local princess_genes = minetest.deserialize(princess:get_meta():get_string("genes")) --princess_meta["genes"]
--local drone_meta = drone:get_meta()
local drone_genes = minetest.deserialize(drone:get_meta():get_string("genes"))
local queen = forestry_bees.Bee("queen",princess_genes)
local queen_meta = queen:get_meta()
queen_meta:set_string("drone_genes",minetest.serialize(drone_genes))
return queen
end
local function final_gene(gene1,gene2)
local output = {}
--randomly choose if the genes are 1,2 or 2,1
if math.random(2)==2 then
output[1] = gene1
output[2] = gene2
else
output[1] = gene2
output[2] = gene1
end
return output
end
local function mutation(type1,type2,pos)
local out_table1 = {}
local out_table2 = {}
local mutation = {false, false}
--check every possible mutation to see if we may obtain it
if ( (not (forestry_bees.bee_mutations[type1] == nil)) and (not (forestry_bees.bee_mutations[type1][type2] == nil)) ) then
for out_type, t in pairs(forestry_bees.bee_mutations[type1][type2]) do
local prob1 = math.random()
local prob2 = math.random()
local flag = t["check_fun"](pos)
if (t["chance"] > prob1) and flag then
table.insert(out_table1, out_type)
end
if (t["chance"] > prob2) and flag then
table.insert(out_table2, out_type)
end
end
end
local output = final_gene(type1,type2)
if next(out_table1) then --if a mutation accurred in gene 1
mutation[1] = true
output[1] = out_table1[math.random(#out_table1)]
end
if next(out_table2) then --if a mutation accurred in gene 2
mutation[2] = true
output[2] = out_table2[math.random(#out_table2)]
end
--out_table is always non-empty, now we uniformally
--sample from out_table to get the output gene
return output, mutation
end
local function choose_genes(genes)
--from the table "genes" we for each entry randomly choose 1,2 and keep that gene
--returning a table
local output = {}
for key,gene_pair in pairs(genes) do
output[key] = gene_pair[math.random(2)]
end
return output
end
local function output_genes(mother_genes,father_genes,pos)
local mother_chosen_genes = choose_genes(mother_genes)
local father_chosen_genes = choose_genes(father_genes)
local genes = {}
genes["type_gene"], is_mutated = mutation(mother_chosen_genes["type_gene"], father_chosen_genes["type_gene"],pos)
for key,_ in pairs(mother_chosen_genes) do
--if key == "type_gene" then
-- genes[key] = mutation(mother_chosen_genes[key], father_chosen_genes[key])
if not (key == "type_gene") then
genes[key] = final_gene(mother_chosen_genes[key], father_chosen_genes[key])
end
end
--if a mutation occurred we change the corresponding genes to the base_genes of the mutated bee
if is_mutated[1] then
for key,value in pairs(forestry_bees.return_genes(genes["type_gene"][1])) do
genes[key][1] = value
end
end
if is_mutated[2] then
for key,value in pairs(forestry_bees.return_genes(genes["type_gene"][2])) do
genes[key][2] = value
end
end
return genes
end
function forestry_bees.apiary_result(queen, pos)
--given a queen calculates the correct princess + drone output
local meta = queen:get_meta()
local mother_genes = minetest.deserialize(meta:get_string("genes"))
local father_genes = minetest.deserialize(meta:get_string("drone_genes"))
local genes = output_genes(mother_genes,father_genes,pos)
--local genes = final_gene(mother_chosen_gene, father_chosen_gene)
local princess = forestry_bees.Bee("princess", genes)
local dronelist = {}
local fertility = mother_genes["fertility"][1]
for i=1,fertility do
local genes = output_genes(mother_genes,father_genes,pos)
local drone = forestry_bees.Bee("drone", genes)
table.insert(dronelist, drone)
end
return princess, dronelist
end