random-stuff/computercraft/autonomous-bee-processor.lua

164 lines
5.1 KiB
Lua

local input_chest = "actuallyadditions:giantchestlarge_0"
--local princess_chest = "actuallyadditions:giantchestlarge_2"
local bee_products_chest = "actuallyadditions:giantchestlarge_1"
local bee_overflow_chest = "actuallyadditions:giantchestlarge_7"
local apiaries = {peripheral.find "forestry:apiary"}
local index = {}
local bee_list = {}
local storage = {peripheral.find("actuallyadditions:giantchestlarge", function(n) return n ~= input_chest and n ~= bee_products_chest and n ~= bee_overflow_chest end)}
print("Got", #storage, "storage chests")
local function find_free_space()
for _, inv in pairs(storage) do
if not inv.cached_size then inv.cached_size = inv.size() end
local name = peripheral.getName(inv)
if not index[name] then
return name, 1
end
for slot = 1, inv.cached_size do
if not index[name][slot] then return name, slot end
end
end
end
local function run_cleanup()
for i = 1, peripheral.call(bee_overflow_chest, "size") do
local bee = bee_list[1]
local moved = peripheral.call(bee_overflow_chest, "pullItems", bee[1], bee[2])
index[bee[1]][bee[2]].count = index[bee[1]][bee[2]].count - moved
if index[bee[1]][bee[2]].count == 0 then
index[bee[1]][bee[2]] = nil
table.remove(bee_list, 1)
end
print("Eliminated", moved, "bees")
end
end
local tol_table = {
none = 0,
both_1 = 3,
both_2 = 4,
both_3 = 6,
up_1 = 1.5,
down_1 = 1.5,
up_2 = 2,
down_2 = 2,
up_3 = 3,
down_3 = 3
}
local function score_genome_slot(g)
local score = g.speed * 8 + (20 / g.lifespan) + g.fertility
if g.never_sleeps then score = score + 5 end
if g.tolerates_rain then score = score + 2 end
if g.cave_dwelling then score = score + 5 end
score = score + tol_table[g.humidity_tolerance]
score = score + tol_table[g.temperature_tolerance]
return score
end
local function score_bee(individual)
return score_genome_slot(individual.genome.active) + 0.5 * score_genome_slot(individual.genome.inactive)
end
local function insert_into_list(bee, inv, slot)
local score = score_bee(bee.bee_data)
local lo, hi = 1, #bee_list + 1
while lo < hi do
local mid = math.floor((lo + hi) / 2)
local compr_score = bee_list[mid][3]
if score < compr_score then
hi = mid
else
lo = mid + 1
end
end
table.insert(bee_list, lo, { inv, slot, score })
end
local indexed_count = 0
print "Bee indexing initiating"
for _, chest in pairs(storage) do
local name = peripheral.getName(chest)
if not index[name] then index[name] = {} end
for slot, item in pairs(chest.list()) do
local meta = chest.getItemMeta(slot)
index[name][slot] = { count = item.count, name = meta.displayName, bee_data = meta.individual }
indexed_count = indexed_count + 1
if indexed_count % 100 == 0 then sleep() print(indexed_count, "bees indexed") end
end
end
print(indexed_count, "bees indexed")
print "Bee list preload initiating"
for inv, contents in pairs(index) do
for slot, bee in pairs(contents) do
insert_into_list(bee, inv, slot)
end
end
while true do
local modified_count = 0
for slot, info in pairs(peripheral.call(input_chest, "list")) do
if string.find(info.name, "drone") then
local meta = peripheral.call(input_chest, "getItemMeta", slot)
local invname, targslot = find_free_space()
if not invname then
printError "Bee store at capacity - initiating cleanup."
run_cleanup()
sleep(1)
else
local moved = peripheral.call(input_chest, "pushItems", invname, slot, 64, targslot)
if not moved then
printError "Bees nonmotile"
sleep(1)
else
data = { count = moved, name = meta.displayName, bee_data = meta.individual }
index[invname] = index[invname] or {}
index[invname][targslot] = data
modified_count = modified_count + 1
insert_into_list(data, invname, targslot)
end
end
elseif not string.find(info.name, "princess") then
peripheral.call(input_chest, "pushItems", bee_products_chest, slot)
end
end
print("Loaded", modified_count, "unique bees into stores")
modified_count = 0
for _, apiary in pairs(apiaries) do
local content = apiary.list()
if not content[1] then -- need princess
print "Loading princess"
local success = false
for slot, ccontent in pairs(peripheral.call(input_chest, "list")) do
if ccontent and string.find(ccontent.name, "princess") then
peripheral.call(input_chest, "pushItems", peripheral.getName(apiary), slot)
success = true
break
end
end
if not success then
printError "Insufficient princesses"
sleep(1)
end
end
if not content[2] then
print "Loading drone"
local bee = table.remove(bee_list)
if not bee then
printError "Drone not found"
sleep(1)
else
local moved = peripheral.call(bee[1], "pushItems", peripheral.getName(apiary), bee[2])
index[bee[1]][bee[2]].count = index[bee[1]][bee[2]].count - moved
if index[bee[1]][bee[2]].count == 0 then
index[bee[1]][bee[2]] = nil
end
modified_count = modified_count + 1
end
end
sleep(0.05)
end
print("Moved", modified_count, "drones")
end