Something went wrong. Try again.
[Archived] evolutionary genetic algorithm project and mob plugin for Minetest as part of a bachelor degree final thesis
Something went wrong. Try again.
adaptive-mob population.lua
6.8 kB · 254 lines
Lua
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
local chat_log = adaptive_ai.chat_loglocal breeding = adaptive_ai.breedinglocal random = math.randomlocal floor = math.floorlocal pop = adaptive_ai.helper.poplocal load_file = adaptive_ai.helper.load_file
local default_size = 10local default_range = 20local timer = 0local 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 creatureend
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 = falseend
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] = populend
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 populend
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 nilend
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 = trueend
minetest.register_globalstep(function(dtime) timer = timer + dtime; if timer >= 30 and dirty then save_to_file() endend)
minetest.register_on_shutdown(function() adaptive_ai.population.save_to_file()end)
population.tribes = tribespopulation.load_tribes = load_tribespopulation.create_tribe = create_tribepopulation.get_from_census = get_from_censuspopulation.add_to_tribe = add_to_tribepopulation.empty = emptypopulation.get_couple = get_couplepopulation.default_size = default_sizepopulation.default_range = default_rangepopulation.save_to_file = save_to_filepopulation.get_tribe = get_tribepopulation.get_popul_size = get_popul_size
adaptive_ai.population = population