254 lines
6.6 KiB
Lua
254 lines
6.6 KiB
Lua
|
|
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
|