local chat_log = adaptive_ai.chat_log local breeding = adaptive_ai.breeding local random = math.random local floor = math.floor local pop = adaptive_ai.helper.pop local load_file = adaptive_ai.helper.load_file local default_size = 10 local default_range = 20 local timer = 0 local dirty = false population = {} tribes = {} populs = {} census = {} --local lfs = require "lfs" --local mkdir = minetest.mkdir or lfs.mkdir local mkdir = minetest.mkdir or function(path) os.execute("mkdir \"" .. path .. "\"") end local path = adaptive_ai.path.."population_" local file_tag = {"tribe_list", "census"} local function save_census(save) local file, to_file, count, gene_copy count = 0 for _,c in pairs(census) do count = count + 1 gene_copy = c.genes c.genes = nil to_file = (minetest.serialize(c)) file = io.open(path..file_tag[2].."\\"..c.name..".txt", "w") if not file then mkdir(path..file_tag[2]) file = io.open(path..file_tag[2].."\\"..c.name..".txt", "w") end file:write(save == false and "" or to_file) file:close() c.genes = gene_copy to_file = (minetest.serialize(gene_copy)) file = io.open(path..file_tag[2].."\\"..c.name.." genes.txt", "w") file:write(save == false and "" or to_file) file:close() end chat_log("Census: "..count) end local function get_from_census(entity) if not entity.nametag then return nil end local name = entity.nametag--:gsub("%s", "_") local from_file = load_file(path..file_tag[2].."\\"..name..".txt") local genes_file = load_file(path..file_tag[2].."\\"..name.." genes.txt") local creature = from_file or nil if creature then creature.genes = genes_file table.insert(census, creature) local t_id = creature.tribe_id if not tribes[t_id] then local tribe = {} tribe.pos = creature.pos tribe.name = entity.name tribe.range = default_range tribe.size = default_size tribe.id = t_id tribes[t_id] = tribe chat_log("Created tribe #"..t_id) end if not populs[t_id] then populs[t_id] = {creature} chat_log("Created popul #"..t_id) else table.insert(populs[t_id], creature) chat_log("Increased popul #"..t_id) end end return creature end local function save_to_file(save) local file = io.open(path..file_tag[1]..".txt", "w") local to_file = (minetest.serialize(tribes)) file:write(to_file) file:close() save_census(save) timer = 0 dirty = false end local function load_tribes() local from_file = load_file(path..file_tag[1]..".txt")--, true) tribes = from_file or {} --error(#tribes > 0 and "Tribes loaded succesfully" or "Tribes not loaded") --error(#census > 0 and "Census loaded succesfully" or "Census not loaded") end local function add_to_census(creature) local c_name, c_tag, disambiguate = creature.name, creature.tag, 1 while census[creature.name] ~= nil do creature.name = c_name.." "..disambiguate disambiguate = disambiguate + 1 end census[creature.name] = creature chat_log("New censused creature: "..creature.name) end local function fill_tribe(tribe, popul) local breed, asexual = breeding[tribe.name].breed, breeding[tribe.name].asexual local pos, t_id, range = tribe.pos, tribe.id, tribe.range --math.randomseed(os.time()) local creature, p, i, j while #popul < tribe.size do p = {x=floor(pos.x+0.5), y=floor(pos.y+1), z=floor(pos.z+0.5)} p.x = p.x + random(0,range) - floor(range/2 + 0.5) p.z = p.z + random(0,range) - floor(range/2 + 0.5) i = random(#popul) if asexual then creature = {} creature = breed(creature, popul[i]) else repeat j = random(#popul) until i ~= j creature = {} creature = breed(creature, popul[i], popul[j]) end creature.pos = p creature.tribe_id = t_id --chat_log("Created "..creature.name) table.insert(popul, creature) add_to_census(creature) end populs[t_id] = popul end local function create_tribe(pos, name, founders, range, clone, size) if not founders or #founders == 0 then error("Not enough creatures in starting population.") end local tribe = {} tribe.pos = pos tribe.name = name tribe.range = range tribe.size = size or default_size tribe.id = #tribes + 1 local popul = {} local p, f for _,father in ipairs(founders) do f = {} f = clone(father, f) --chat_log("Cloned "..f.name) f.tribe_id = tribe.id p = {x=floor(pos.x+0.5), y=floor(pos.y+0.5), z=floor(pos.z+0.5)} p.x = p.x + random(0,range) - floor(range/2 + 0.5) p.z = p.z + random(0,range) - floor(range/2 + 0.5) f.pos = p table.insert(popul, f) add_to_census(f) end fill_tribe(tribe, popul) table.insert(tribes, tribe) save_to_file() return popul end local function get_tribe(t_id) --chat_log(tribes[t_id] and "Getting tribe" or "Not getting tribe") return tribes[t_id] end local function get_popul_size(t_id) return populs[t_id] and #populs[t_id] or nil end local function get_couple(creature) local p = populs[creature.tribe_id] local i repeat i = random(#p) until p[i].name ~= creature.name return p[i] end local function empty() for i,t in ipairs(tribes) do t = {} end for i,c in ipairs(populs) do c.delete = true end tribes = {} census = {} save_census(false) save_to_file() end local function add_to_tribe(t_id, creature) creature.tribe_id = t_id table.insert(populs[t_id], creature) census[creature.name] = creature dirty = true end minetest.register_globalstep(function(dtime) timer = timer + dtime; if timer >= 30 and dirty then save_to_file() end end) minetest.register_on_shutdown(function() adaptive_ai.population.save_to_file() end) population.tribes = tribes population.load_tribes = load_tribes population.create_tribe = create_tribe population.get_from_census = get_from_census population.add_to_tribe = add_to_tribe population.empty = empty population.get_couple = get_couple population.default_size = default_size population.default_range = default_range population.save_to_file = save_to_file population.get_tribe = get_tribe population.get_popul_size = get_popul_size adaptive_ai.population = population