Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- *-* <- Absolutely needed, do not delete.
- -- BeeAlverizer 1.1 fork of BeeAnalyzer 4
- -- Original code by Direwolf20
- -- Hotfixes by Mandydax, Mikeyhun and MaaadMike
- -- Major overhaul and rewrite to make work without turtle by Damaged
- -- JSON lib located at http://pastebin.com/jy3QenZn save as JSON.lua
- -- Be careful of case
- local JSON = (loadfile "JSON.lua")()
- JSON.strictTypes = true
- -- Build: http://users.on.net/~damageinc/Alveary%20placement.jpg
- -- Make sure you name this program "bee" (careful of case)
- -- Direction definitions.
- -- When looking at computer, what direction is it?
- -- Or simply put the direction in the label EG: bee1.west
- local alvearyDirection = "west"
- for i,case in pairs({ ".west", ".east", ".north", ".south" }) do
- if string.find(os.getComputerLabel(),case) then
- alvearyDirection = string.sub(case, 2)
- break
- end
- end
- print("I appear to be facing: "..alvearyDirection)
- local analyzerDirection
- local junkDirection
- if alvearyDirection == "west" then
- analyzerDirection = "south"
- junkDirection = "north"
- end
- if alvearyDirection == "north" then
- analyzerDirection = "west"
- junkDirection = "east"
- end
- if alvearyDirection == "east" then
- analyzerDirection = "north"
- junkDirection = "south"
- end
- if alvearyDirection == "south" then
- analyzerDirection = "east"
- junkDirection = "west"
- end
- -- attribute scoring for same species tie-breaking -----------------------------
- local droneTarget
- local princessSlot = 0
- alveary = peripheral.wrap("back")
- memoryChest = peripheral.wrap("top")
- local maxMem = memoryChest.getInventorySize()
- -- Fix for some versions returning bees.species.*
- function fixName(name)
- return name:gsub("bees%.species%.",""):gsub("^.", string.upper)
- end
- function getBeeData(i)
- return memoryChest.getStackInSlot(i)["beeInfo"]
- end
- function getPrimarySpecies(i)
- local thisBee = getBeeData(i)
- if thisBee["speciesPrimary"] ~= nil then
- return fixName(thisBee["speciesPrimary"])
- else
- return fixName(thisBee["active"]["species"])
- end
- end
- function getSecondarySpecies(i)
- if getBeeData(i)["speciesSecondary"] ~= nil then
- return fixName(getBeeData(i)["speciesSecondary"])
- else
- return fixName(getBeeData(i)["inactive"]["species"])
- end
- end
- scoresFertility = {
- [1] = 0.1,
- [2] = 0.2,
- [3] = 0.3,
- [4] = 0.4
- }
- scoresSpeed = {
- ["0.3"] = 0.01, -- Slowest
- ["0.6"] = 0.02, -- Slower
- ["0.8"] = 0.03, -- Slow
- ["1"] = 0.04, -- Normal
- ["1.2"] = 0.05, -- Fast
- ["1.4"] = 0.06, -- Faster
- ["1.7"] = 0.07 -- Fastest
- }
- scoresAttrib = {
- diurnal = 0.004,
- nocturnal = 0.003,
- tolerantFlyer = 0.002,
- caveDwelling = 0.0001
- }
- scoresTolerance = {
- ["NONE"] = 0.00000,
- ["UP 1"] = 0.00001,
- ["UP 2"] = 0.00002,
- ["UP 3"] = 0.00003,
- ["UP 4"] = 0.00004,
- ["UP 5"] = 0.00005,
- ["DOWN 1"] = 0.00001,
- ["DOWN 2"] = 0.00002,
- ["DOWN 3"] = 0.00003,
- ["DOWN 4"] = 0.00004,
- ["DOWN 5"] = 0.00005,
- ["BOTH 1"] = 0.00002,
- ["BOTH 2"] = 0.00004,
- ["BOTH 3"] = 0.00006,
- ["BOTH 4"] = 0.00008,
- ["BOTH 5"] = 0.00010
- }
- -- the bee graph ---------------------------------------------------------------
- bees = {}
- function addParent(parent, offspring)
- if bees[parent] then
- bees[parent].mutateTo[offspring] = true
- else
- bees[parent] = {
- --name = parent,
- score = nil,
- mutateTo = {[offspring]=true},
- mutateFrom = {}
- }
- end
- end
- function addOffspring(offspring, parentss)
- if bees[offspring] then
- for i, parents in ipairs(parentss) do
- table.insert(bees[offspring].mutateFrom, parents)
- end
- else
- bees[offspring] = {
- score = nil,
- mutateTo = {},
- mutateFrom = parentss
- }
- end
- for i, parents in ipairs(parentss) do
- for i, parent in ipairs(parents) do
- addParent(parent, offspring)
- end
- end
- end
- -- score bees that have no parent combinations as 1
- -- iteratively find the next bee up the line and increase the score
- function scoreBees()
- -- find all bees with no mutateFrom data
- local beeCount = 0
- local beeScore = 1
- for name, beeData in pairs(bees) do
- if #beeData.mutateFrom == 0 then
- beeData.score = beeScore
- else
- beeCount = beeCount + 1
- end
- end
- while beeCount > 0 do
- beeScore = beeScore * 2
- -- find all bees where all parent combos are scored
- for name, beeData in pairs(bees) do
- if not beeData.score then
- local scoreBee = true
- for i, beeParents in ipairs(beeData.mutateFrom) do
- local parent1 = bees[beeParents[1]]
- local parent2 = bees[beeParents[2]]
- if not parent1.score
- or parent1.score == beeScore
- or not parent2.score
- or parent2.score == beeScore then
- scoreBee = false
- break
- end
- end
- if scoreBee then
- beeData.score = beeScore
- beeCount = beeCount - 1
- end
- end
- end
- end
- end
- -- produce combinations from 1 or 2 lists
- function choose(list, list2)
- local newList = {}
- if list2 then
- for i = 1, #list2 do
- for j = 1, #list do
- if list[j] ~= list[i] then
- table.insert(newList, {list[j], list2[i]})
- end
- end
- end
- else
- for i = 1, #list do
- for j = i, #list do
- if list[i] ~= list[j] then
- table.insert(newList, {list[i], list[j]})
- end
- end
- end
- end
- return newList
- end
- for key, value in pairs (alveary.getBeeBreedingData()) do
- addOffspring( fixName(value.result), {{ fixName(value.allele1), fixName(value.allele2) }} )
- end
- scoreBees()
- -- logging ---------------------------------------------------------------------
- local logFile = fs.open("bee.log", "w")
- function log(msg)
- msg = msg or ""
- logFile.write(tostring(msg))
- logFile.flush()
- io.write(msg)
- end
- function logLine(msg)
- msg = msg or ""
- logFile.write(msg.."\n")
- logFile.flush()
- io.write(msg.."\n")
- end
- function logTable(table)
- for key, value in pairs (table) do
- logLine(key .. " = " .. tostring(value))
- end
- end
- -- analyzing functions ---------------------------------------------------------
- function clearSystem()
- -- clear out alveary
- for i = 2,9 do
- memoryChest.pullItem(alvearyDirection,i)
- end
- -- clear out analyzer
- for i = 1, 12 do
- memoryChest.pullItem(analyzerDirection,i)
- end
- end
- function getBees()
- -- get bees from apiary
- log("waiting for bees.")
- while true do
- local gotStuff = false
- for i = 3,9 do
- if memoryChest.pullItem(alvearyDirection,i) ~= 0 then
- gotStuff = true
- end
- end
- if gotStuff == true then
- break
- end
- sleep(10)
- log(".")
- end
- log("*")
- logLine()
- end
- local droneData
- function analyzeBees()
- princessSlot = 0
- logLine("analyzing bees...")
- memoryChest.condenseItems()
- local highestScore
- local highestScoreDrone
- droneData = { }
- for i,data in pairs(memoryChest.getAllStacks()) do
- data = memoryChest.getStackInSlot(i)
- if not ( string.find(data["rawName"], "item.beedrone") or string.find(data["rawName"], "item.beeprincess") ) then
- memoryChest.pushItem(junkDirection,i)
- print("P")
- else
- print("B")
- --print(JSON:encode(data["beeInfo"]))
- --print(data["beeInfo"]["isAnalyzed"])
- if data["beeInfo"]["isAnalyzed"] == false then
- memoryChest.pushItemIntoSlot(analyzerDirection,i,64,3)
- while memoryChest.pullItemIntoSlot(analyzerDirection,9,61,i) == 0 do sleep(1) end
- end
- -- check for untargeted species
- if memoryChest.getStackInSlot(i) ~= nil and (not bees[getPrimarySpecies(i)].targeted or not bees[getSecondarySpecies(i)].targeted) then
- memoryChest.pushItem(junkDirection,i)
- else
- if string.find(data["rawName"], "princess") then
- princessSlot = i
- end
- end
- end
- end
- if princessSlot ~= 0 then
- for i,data in pairs(memoryChest.getAllStacks()) do
- if i ~= princessSlot then
- droneData[i] = scoreBee(i)
- if droneData[i] == 0 then
- memoryChest.pushItem(junkDirection,i)
- droneData[i] = nil
- end
- end
- end
- -- find the best drone
- logLine("sorting drones...")
- highestScore = 0
- for i,beeScore in pairs(droneData) do
- if beeScore > highestScore then
- highestScore = beeScore
- highestScoreDrone = i
- end
- end
- printHeader()
- for i = 1, maxMem do
- if memoryChest.getStackInSlot(i) ~= nil then
- printBee(i)
- end
- end
- end
- logLine()
- return highestScoreDrone
- end
- function scoreBee(droneID)
- local beeDataDrone = getBeeData(droneID)
- local beeDataPrincess = getBeeData(princessSlot)
- local droneSpecies = {getPrimarySpecies(droneID), getSecondarySpecies(droneID)}
- -- check for untargeted species
- if not bees[droneSpecies[1]].targeted or not bees[droneSpecies[2]].targeted then
- return 0
- end
- local princessSpecies = {getPrimarySpecies(princessSlot), getSecondarySpecies(princessSlot)}
- local score
- local maxScore = 0
- for _, combo in ipairs({{princessSpecies[1], droneSpecies[1]}
- ,{princessSpecies[1], droneSpecies[2]}
- ,{princessSpecies[2], droneSpecies[1]}
- ,{princessSpecies[2], droneSpecies[2]}}) do
- -- find maximum score for each combo
- score = (bees[combo[1]].score + bees[combo[2]].score) / 2
- for name, beeData in pairs(bees) do
- if beeData.targeted then
- for i, parents in ipairs(beeData.mutateFrom) do
- if combo[1] == parents[1] and combo[2] == parents[2]
- or combo[2] == parents[1] and combo[1] == parents[2] then
- score = (score + beeData.score) / 2
- end
- end
- end
- end
- maxScore = maxScore + score
- end
- -- add one for each combination that results in the maximum score
- score = maxScore
- -- score attributes
- score = score + math.max(scoresFertility[beeDataDrone["active"]["fertility"]], scoresFertility[beeDataPrincess["active"]["fertility"]])
- score = score + math.min(scoresSpeed[tostring(beeDataDrone["active"]["speed"])], scoresSpeed[tostring(beeDataPrincess["active"]["speed"])])
- if beeDataDrone["active"]["nocturnal"] or beeDataPrincess["active"]["nocturnal"] then score = score + scoresAttrib["nocturnal"] end
- if beeDataDrone["active"]["tolerantFlyer"] or beeDataPrincess["active"]["tolerantFlyer"] then score = score + scoresAttrib["tolerantFlyer"] end
- if beeDataDrone["active"]["caveDwelling"] or beeDataPrincess["active"]["caveDwelling"] then score = score + scoresAttrib["caveDwelling"] end
- score = score + math.max(scoresTolerance[string.upper(beeDataDrone["active"]["temperatureTolerance"])], scoresTolerance[string.upper(beeDataPrincess["active"]["temperatureTolerance"])])
- score = score + math.max(scoresTolerance[string.upper(beeDataDrone["active"]["humidityTolerance"])], scoresTolerance[string.upper(beeDataPrincess["active"]["humidityTolerance"])])
- return score
- end
- function printHeader()
- logLine()
- logLine("sl t species f spd n f c tmp hmd score ")
- logLine("--|-|-------|-|---|-|-|-|---|---|------")
- end
- -- string constants for console output
- toleranceString = {
- ["NONE"] = " - ",
- ["UP 1"] = " +1 ",
- ["UP 2"] = " +2 ",
- ["UP 3"] = " +3 ",
- ["UP 4"] = " +4 ",
- ["UP 5"] = " +5 ",
- ["DOWN 1"] = " -1 ",
- ["DOWN 2"] = " -2 ",
- ["DOWN 3"] = " -3 ",
- ["DOWN 4"] = " -4 ",
- ["DOWN 5"] = " -5 ",
- ["BOTH 1"] = "+-1 ",
- ["BOTH 2"] = "+-2 ",
- ["BOTH 3"] = "+-3 ",
- ["BOTH 4"] = "+-4 ",
- ["BOTH 5"] = "+-5 "
- }
- speedString = {
- ["0.3"] = "0.3", -- Slowest
- ["0.6"] = "0.6", -- Slower
- ["0.8"] = "0.8", -- Slow
- ["1"] = "1.0", -- Normal
- ["1.2"] = "1.2", -- Fast
- ["1.4"] = "1.4", -- Faster
- ["1.7"] = "1.7" -- Fastest
- }
- function printBee(i)
- local beeData = getBeeData(i)
- log(i < 10 and " "..i.." " or i.." ")
- -- type
- log(string.find(memoryChest.getStackInSlot(i)["rawName"], "princess") and "P " or "D ")
- -- species
- log(getPrimarySpecies(i):gsub("bees%.species%.",""):sub(1,3)..":"..getSecondarySpecies(i):gsub("bees%.species%.",""):sub(1,3).." ")
- -- fertility
- log(tostring(beeData["active"]["fertility"]).." ")
- -- speed
- log(speedString[tostring(beeData["active"]["speed"])].." ")
- -- nocturnal
- log(beeData["active"]["nocturnal"] and "X " or "- ")
- -- flyer
- log(beeData["active"]["tolerantFlyer"] and "X " or "- ")
- -- cave dwelling
- log(beeData["active"]["caveDwelling"] and "X " or "- ")
- -- temperature tolerance
- log(toleranceString[string.upper(beeData["active"]["temperatureTolerance"])])
- -- humidity tolerance
- log(toleranceString[string.upper(beeData["active"]["humidityTolerance"])])
- -- score
- log(droneData[i] and string.format("%5.1d", droneData[i]).." " or " ")
- logLine()
- end
- function dropExcess()
- logLine("dropping excess...")
- for i = ( maxMem - 9 ), maxMem do
- -- drop drones over ( max inv - 9 ) to clear space for newly bred bees and product
- memoryChest.pushItem(junkDirection,i)
- end
- end
- function isPurebred(droneID)
- -- check if princess and drone are exactly the same and no chance for mutation
- local princessPrimary = getPrimarySpecies(princessSlot)
- if princessPrimary ~= getSecondarySpecies(princessSlot) then
- return false
- end
- if getPrimarySpecies(droneID) ~= princessPrimary then
- return false
- end
- if getSecondarySpecies(droneID) ~= princessPrimary then
- return false
- end
- local droneBeeData = getBeeData(droneID)
- local princessBeeData = getBeeData(princessSlot)
- for i,key in pairs({ "fertility", "speed", "nocturnal", "tolerantFlyer", "caveDwelling", "temperatureTolerance", "humidityTolerance" }) do
- if
- droneBeeData["active"][key] ~= princessBeeData["active"][key] or
- droneBeeData["inactive"][key] ~= princessBeeData["inactive"][key]
- then
- return false
- end
- end
- return true
- end
- -- targeting -------------------------------------------------------------------
- -- set species and all parents to targeted
- function targetBee(name)
- local bee = bees[name]
- if bee and not bee.targeted then
- bee.targeted = true
- for i, parents in ipairs(bee.mutateFrom) do
- for j, parent in ipairs(parents) do
- targetBee(parent)
- end
- end
- end
- end
- tArgs = { ... }
- if fs.exists("bee.data") and #tArgs == 0 then
- local recoveredData = fs.open("bee.data", "r")
- local historyData = recoveredData.readLine()
- if historyData then
- historyData = JSON:decode(historyData)
- tArgs[1] = historyData["target"]
- logLine("Recovered old data.")
- end
- recoveredData.close()
- end
- function findMe()
- local myProgramName
- for i,fileName in pairs( fs.list("") ) do
- if type(fileName) == "string" then
- if fileName ~= "" then
- local tempFile = fs.open(fileName,"r")
- if string.sub(tempFile.readLine(),4,6) == "*-*" then
- myProgramName = fileName
- break
- end
- end
- end
- end
- return myProgramName
- end
- -- set bee graph entry to targeted if species was specified on the command line
- -- otherwise set all entries to targeted
- if #tArgs > 0 then
- logLine("targeting bee species:")
- fs.delete("bee.data")
- recoveredData = fs.open("bee.data", "w")
- local tempArray = {}
- tempArray["target"] = tArgs[1]
- recoveredData.write( JSON:encode( tempArray ) )
- recoveredData.close()
- for i, target in ipairs(tArgs) do
- targetBee(target)
- for name, data in pairs(bees) do
- if data.targeted and data.score > 1 then
- logLine(name .. string.rep(" ", 20-#name), data.score)
- end
- end
- end
- local myProgramName = findMe()
- logLine("Found program:"..myProgramName)
- if myProgramName ~= nil then
- fs.delete("startup")
- local startupFile = fs.open("startup","w")
- startupFile.write("shell.run(\""..myProgramName.."\")")
- startupFile.close()
- else
- logLine("Cannot find program name, you edited the first line of the program didn't you!")
- end
- else
- for _, beeData in pairs(bees) do
- beeData.targeted = true
- end
- end
- -- breeding loop ---------------------------------------------------------------
- logLine("Clearing system...")
- clearSystem()
- if not memoryChest.getAllStacks() then
- print("No bees to work on, add bees and restart")
- else
- redstone.setOutput("bottom", true)
- while true do
- droneTarget = analyzeBees()
- if princessSlot ~= 0 then
- if isPurebred(droneTarget) then
- logLine("Bees are purebred.")
- logLine("Princess: "..princessSlot)
- logLine("Drone: "..droneTarget)
- redstone.setOutput("bottom", false)
- fs.delete("bee.data")
- fs.delete("startup")
- break
- end
- memoryChest.pushItemIntoSlot(alvearyDirection,princessSlot,1,1)
- memoryChest.pushItemIntoSlot(alvearyDirection,droneTarget,1,2)
- dropExcess()
- end
- getBees()
- end
- end
- logFile.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement