Guest User

Untitled

a guest
Jul 13th, 2014
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.77 KB | None | 0 0
  1. -- BeeAlverizer 1 fork of BeeAnalyzer 4
  2. -- Original code by Direwolf20
  3. -- Hotfix 1 by Mandydax
  4. -- Hotfix 2 by Mikeyhun/MaaadMike
  5.  
  6. -- Major overhaul to make work without turtle by Damaged
  7.  
  8. -- attribute scoring for same species tie-breaking -----------------------------
  9.  
  10. local allBeeData = {}
  11. local princessSlot = 0
  12. alveary = peripheral.wrap("back")
  13. analyzer = peripheral.wrap("left")
  14. memoryChest = peripheral.wrap("top")
  15.  
  16. function getCountInMemoryChest(i)
  17.    stackData = memoryChest.getStackInSlot(i)
  18.    return stackData.qty
  19. end
  20.  
  21. scoresFertility = {
  22.    [1] = 0.1,
  23.    [2] = 0.2,
  24.    [3] = 0.3,
  25.    [4] = 0.4
  26. }
  27. scoresSpeed = {
  28.    ["0.3"] = 0.01, -- Slowest
  29.    ["0.6"] = 0.02, -- Slower
  30.    ["0.8"] = 0.03, -- Slow
  31.    ["1"]   = 0.04, -- Normal
  32.    ["1.2"] = 0.05, -- Fast
  33.    ["1.4"] = 0.06, -- Faster
  34.    ["1.7"] = 0.07  -- Fastest
  35. }
  36. scoresAttrib = {
  37.    diurnal       = 0.004,
  38.    nocturnal     = 0.003,
  39.    tolerantFlyer = 0.002,
  40.    caveDwelling  = 0.0001
  41. }
  42. scoresTolerance = {
  43.    ["NONE"]   = 0.00000,
  44.    ["UP 1"]   = 0.00001,
  45.    ["UP 2"]   = 0.00002,
  46.    ["UP 3"]   = 0.00003,
  47.    ["UP 4"]   = 0.00004,
  48.    ["UP 5"]   = 0.00005,
  49.    ["DOWN 1"] = 0.00001,
  50.    ["DOWN 2"] = 0.00002,
  51.    ["DOWN 3"] = 0.00003,
  52.    ["DOWN 4"] = 0.00004,
  53.    ["DOWN 5"] = 0.00005,
  54.    ["BOTH 1"] = 0.00002,
  55.    ["BOTH 2"] = 0.00004,
  56.    ["BOTH 3"] = 0.00006,
  57.    ["BOTH 4"] = 0.00008,
  58.    ["BOTH 5"] = 0.00010
  59. }
  60.  
  61. -- the bee graph ---------------------------------------------------------------
  62.  
  63. bees = {}
  64.  
  65. function addParent(parent, offspring)
  66.    if bees[parent] then
  67.       bees[parent].mutateTo[offspring] = true
  68.       else
  69.       bees[parent] = {
  70.          --name = parent,
  71.          score = nil,
  72.          mutateTo = {[offspring]=true},
  73.          mutateFrom = {}
  74.       }
  75.    end
  76. end
  77.  
  78. function addOffspring(offspring, parentss)
  79.    if bees[offspring] then
  80.       for i, parents in ipairs(parentss) do
  81.          table.insert(bees[offspring].mutateFrom, parents)
  82.       end
  83.       else
  84.       bees[offspring] = {
  85.          score = nil,
  86.          mutateTo = {},
  87.          mutateFrom = parentss
  88.       }
  89.    end
  90.    for i, parents in ipairs(parentss) do
  91.       for i, parent in ipairs(parents) do
  92.          addParent(parent, offspring)
  93.       end
  94.    end
  95. end
  96.  
  97. -- score bees that have no parent combinations as 1
  98. -- iteratively find the next bee up the line and increase the score
  99. function scoreBees()
  100.    -- find all bees with no mutateFrom data
  101.    local beeCount = 0
  102.    local beeScore = 1
  103.    for name, beeData in pairs(bees) do
  104.       if #beeData.mutateFrom == 0 then
  105.          beeData.score = beeScore
  106.          else
  107.          beeCount = beeCount + 1
  108.       end
  109.    end
  110.    while beeCount > 0 do
  111.       beeScore = beeScore * 2
  112.       -- find all bees where all parent combos are scored
  113.       for name, beeData in pairs(bees) do
  114.          if not beeData.score then
  115.             local scoreBee = true
  116.             for i, beeParents in ipairs(beeData.mutateFrom) do
  117.                local parent1 = bees[beeParents[1]]
  118.                local parent2 = bees[beeParents[2]]
  119.                
  120.                if not parent1.score
  121.                   or parent1.score == beeScore
  122.                   or not parent2.score
  123.                   or parent2.score == beeScore then
  124.                   scoreBee = false
  125.                   break
  126.                end
  127.             end
  128.             if scoreBee then
  129.                beeData.score = beeScore
  130.                beeCount = beeCount - 1
  131.             end
  132.          end
  133.       end
  134.    end
  135. end
  136.  
  137. -- produce combinations from 1 or 2 lists
  138. function choose(list, list2)
  139.    local newList = {}
  140.    if list2 then
  141.       for i = 1, #list2 do
  142.          for j = 1, #list do
  143.             if list[j] ~= list[i] then
  144.                table.insert(newList, {list[j], list2[i]})
  145.             end
  146.          end
  147.       end
  148.       else
  149.       for i = 1, #list do
  150.          for j = i, #list do
  151.             if list[i] ~= list[j] then
  152.                table.insert(newList, {list[i], list[j]})
  153.             end
  154.          end
  155.       end
  156.    end
  157.    return newList
  158. end
  159.  
  160. -- Fix for some versions returning bees.species.*
  161. function fixName(name)
  162.    return name:gsub("bees%.species%.",""):gsub("^.", string.upper)
  163. end
  164.  
  165. for key, value in pairs (alveary.getBeeBreedingData()) do
  166.    addOffspring( fixName(value.result), {{ fixName(value.allele1), fixName(value.allele2) }} )
  167. end
  168. scoreBees()
  169.  
  170. -- logging ---------------------------------------------------------------------
  171.  
  172. local logFile = fs.open("bee.log", "w")
  173. function log(msg)
  174.    msg = msg or ""
  175.    logFile.write(tostring(msg))
  176.    logFile.flush()
  177.    io.write(msg)
  178. end
  179. function logLine(msg)
  180.    msg = msg or ""
  181.    logFile.write(msg.."\n")
  182.    logFile.flush()
  183.    io.write(msg.."\n")
  184. end
  185.  
  186. function logTable(table)
  187.    for key, value in pairs (table) do
  188.       logLine(key .. " = " .. tostring(value))
  189.    end
  190. end
  191.  
  192.  
  193. -- analyzing functions ---------------------------------------------------------
  194.  
  195. function clearSystem()
  196.    -- clear out alveary
  197.    for i = 1,9 do
  198.       memoryChest.pullItem("north",i)
  199.    end
  200.    -- clear out analyzer
  201.    for i = 1, 12 do
  202.       analyzer.pushItem("up",i)
  203.    end
  204. end
  205.  
  206. function getBees()
  207.    -- get bees from apiary
  208.    log("waiting for bees.")
  209.    while not not alveary.getStackInSlot(1) do
  210.       sleep(10)
  211.       log(".")
  212.    end
  213.    log("*")
  214.    for i, 3,9 do
  215.       if memoryChest.pullItem("north",i) then
  216.          log("*")
  217.       end
  218.    end
  219.    logLine()
  220. end
  221.  
  222.  
  223.    
  224. function breedBees(droneSlot)
  225.    memoryChest.pushItemToSlot("north",princessSlot,1,1)
  226.    memoryChest.pushItemToSlot("north",droneSlot,1,2)
  227. end
  228.      
  229. function analyzeBees()
  230.    princessSlot = 0
  231.    logLine("analyzing bees...")
  232.    local highestScore
  233.    for i,data in pairs(memoryChest.getAllStacks()) do
  234.       if data.rawName == "item.beeprincess" then
  235.          princessSlot = i
  236.       end
  237.       if not ( data.rawName == "item.beeprincessge" or data.rawName == "item.beequeenge" or data.rawName == "item.beedronege" ) then
  238.          memoryChest.pushItem("east",i)
  239.          print("P")
  240.       else
  241.          print("B")
  242.          if not data.beeInfo.isAnalyzed then
  243.             analyzer.pullItem("up",i)
  244.             while not analyzer.pushItem("up",9,data.qty,i) do sleep(1) end
  245.             data = memoryChest.getStackInSlot(i)
  246.          end
  247.          -- Check if it's a drone or princess
  248.          if string.find(data.rawName, "princess") then
  249.             allBeeData[i]["type"] = "princess"
  250.          else
  251.             allBeeData[i]["type"] = "drone"
  252.          end              
  253.          -- Active values
  254.          for key, value in pairs (data.beeInfo.active) do
  255.             if key == "species" then
  256.                allBeeData[i]["speciesPrimary"] = value
  257.             else
  258.                allBeeData[i][key] = value
  259.             end
  260.          end
  261.          -- Inactive values
  262.          allBeeData[i]["speciesSecondary"] = data.beeInfo.inactive.species
  263.          
  264.          
  265.          allBeeData[i]["speciesPrimary"] = fixName(allBeeData[i]["speciesPrimary"])
  266.          allBeeData[i]["speciesSecondary"] = fixName(allBeeData[i]["speciesSecondary"])
  267.          if allBeeData[i]["type"] == "princess" then
  268.             if i ~= 1 then
  269.                memoryChest.swap(i,1)
  270.             end
  271.             princessSlot = 1
  272.          end
  273.       end
  274.       -- check for untargeted species
  275.       if allBeeData[i] and (not bees[allBeeData[i]["speciesPrimary"]].targeted or not bees[allBeeData[i]["speciesSecondary"]].targeted) then
  276.          memoryChest.pushItem("east",i)
  277.          allBeeData[i] = nil
  278.       end
  279.    end
  280.    
  281.    if princessSlot > 0 then
  282.       -- selection sort drones
  283.       logLine("sorting drones...")
  284.       for i = 2, memoryChest.getInventorySize() do
  285.          highestScore = i
  286.          if getCountInMemoryChest(i) > 0 and allBeeData[i] then
  287.             allBeeData[i].score = scoreBee(allBeeData[princessSlot], allBeeData[i])
  288.             for j = i + 1, memoryChest.getInventorySize() do
  289.                if getCountInMemoryChest(j) > 0 and allBeeData[j] then
  290.                   if not allBeeData[j].score then
  291.                      allBeeData[j].score = scoreBee(allBeeData[princessSlot], allBeeData[j])
  292.                   end
  293.                   if allBeeData[j].score > allBeeData[highestScore].score then
  294.                      highestScore = j
  295.                   end
  296.                end
  297.             end
  298.             -- swap bees
  299.             if highestScore ~= i then
  300.                memoryChest.swap(i, highestScore)
  301.                allBeeData[i], allBeeData[highestScore] = allBeeData[highestScore], allBeeData[i]
  302.             end
  303.          end
  304.       end
  305.       printHeader()
  306.       allBeeData[princessSlot].slot = 1
  307.       printBee(allBeeData[princessSlot])
  308.       for i = 2, memoryChest.getInventorySize() do
  309.          if allBeeData[i] then
  310.             allBeeData[i].slot = i
  311.             printBee(allBeeData[i])
  312.          end
  313.       end
  314.    end
  315.    logLine()
  316. end
  317.  
  318. function scoreBee(princessData, droneData)
  319.    local droneSpecies = {droneData["speciesPrimary"], droneData["speciesSecondary"]}
  320.    -- check for untargeted species
  321.    if not bees[droneSpecies[1]].targeted or not bees[droneSpecies[2]].targeted then
  322.       return 0
  323.    end
  324.    local princessSpecies = {princessData["speciesPrimary"], princessData["speciesSecondary"]}
  325.    local score
  326.    local maxScore = 0
  327.    for _, combo in ipairs({{princessSpecies[1], droneSpecies[1]}
  328.       ,{princessSpecies[1], droneSpecies[2]}
  329.       ,{princessSpecies[2], droneSpecies[1]}
  330.    ,{princessSpecies[2], droneSpecies[2]}}) do
  331.    -- find maximum score for each combo
  332.    score = (bees[combo[1]].score + bees[combo[2]].score) / 2
  333.    for name, beeData in pairs(bees) do
  334.       if beeData.targeted then
  335.          for i, parents in ipairs(beeData.mutateFrom) do
  336.             if combo[1] == parents[1] and combo[2] == parents[2]
  337.                or combo[2] == parents[1] and combo[1] == parents[2] then
  338.                score = (score + beeData.score) / 2
  339.             end
  340.          end
  341.       end
  342.    end
  343.    maxScore = maxScore + score
  344.    end
  345.    -- add one for each combination that results in the maximum score
  346.    score = maxScore
  347.    -- score attributes
  348.    score = score + math.max(scoresFertility[droneData["fertility"]], scoresFertility[princessData["fertility"]])
  349.    score = score + math.min(scoresSpeed[tostring(droneData["speed"])], scoresSpeed[tostring(princessData["speed"])])
  350.    if droneData["nocturnal"] or princessData["nocturnal"] then score = score + scoresAttrib["nocturnal"] end
  351.    if droneData["tolerantFlyer"] or princessData["tolerantFlyer"] then score = score + scoresAttrib["tolerantFlyer"] end
  352.    if droneData["caveDwelling"] or princessData["caveDwelling"] then score = score + scoresAttrib["caveDwelling"] end
  353.    score = score + math.max(scoresTolerance[string.upper(droneData["temperatureTolerance"])], scoresTolerance[string.upper(princessData["temperatureTolerance"])])
  354.    score = score + math.max(scoresTolerance[string.upper(droneData["humidityTolerance"])], scoresTolerance[string.upper(princessData["humidityTolerance"])])
  355.    return score
  356. end
  357.  
  358. function printHeader()
  359.    logLine()
  360.    logLine("sl t species f spd n f c tmp hmd score ")
  361.    logLine("--|-|-------|-|---|-|-|-|---|---|------")
  362. end
  363.  
  364. -- string constants for console output
  365. toleranceString = {
  366.    ["NONE"] = "  - ",
  367.    ["UP 1"] = " +1 ",
  368.    ["UP 2"] = " +2 ",
  369.    ["UP 3"] = " +3 ",
  370.    ["UP 4"] = " +4 ",
  371.    ["UP 5"] = " +5 ",
  372.    ["DOWN 1"] = " -1 ",
  373.    ["DOWN 2"] = " -2 ",
  374.    ["DOWN 3"] = " -3 ",
  375.    ["DOWN 4"] = " -4 ",
  376.    ["DOWN 5"] = " -5 ",
  377.    ["BOTH 1"] = "+-1 ",
  378.    ["BOTH 2"] = "+-2 ",
  379.    ["BOTH 3"] = "+-3 ",
  380.    ["BOTH 4"] = "+-4 ",
  381.    ["BOTH 5"] = "+-5 "
  382. }
  383.  
  384. speedString = {
  385.    ["0.3"] = "0.3", -- Slowest
  386.    ["0.6"] = "0.6", -- Slower
  387.    ["0.8"] = "0.8", -- Slow
  388.    ["1"]   = "1.0", -- Normal
  389.    ["1.2"] = "1.2", -- Fast
  390.    ["1.4"] = "1.4", -- Faster
  391.    ["1.7"] = "1.7"  -- Fastest
  392. }
  393.  
  394. function printBee(beeData)
  395.    log(beeData["slot"] < 10 and " "..beeData["slot"].." " or beeData["slot"].." ")
  396.    -- type
  397.    log(beeData["type"] == "princess" and "P " or "D ")
  398.    -- species
  399.    log(beeData["speciesPrimary"]:gsub("bees%.species%.",""):sub(1,3)..":"..beeData["speciesSecondary"]:gsub("bees%.species%.",""):sub(1,3).." ")
  400.    -- fertility
  401.    log(tostring(beeData["fertility"]).." ")
  402.    -- speed
  403.    log(speedString[tostring(beeData["speed"])].." ")
  404.    -- nocturnal
  405.    log(beeData["nocturnal"] and "X " or "- ")
  406.    -- flyer
  407.    log(beeData["tolerantFlyer"] and "X " or "- ")
  408.    -- cave dwelling
  409.    log(beeData["caveDwelling"] and "X " or "- ")
  410.    -- temperature tolerance
  411.    log(toleranceString[string.upper(beeData["temperatureTolerance"])])
  412.    -- humidity tolerance
  413.    log(toleranceString[string.upper(beeData["humidityTolerance"])])
  414.    -- score
  415.    log(beeData.score and string.format("%5.1d", beeData.score).." " or "      ")
  416.    logLine()
  417. end
  418.  
  419. function dropExcess()
  420.    logLine("dropping excess...")
  421.    for i = 3, memoryChest.getInventorySize() do
  422.       if getCountInMemoryChest(i) > 0 then
  423.          -- drop drones over ( max inv - 9 ) to clear space for newly bred bees and product
  424.          if i > ( memoryChest.getInventorySize() - 9 ) then
  425.             memoryChest.pushItem("east",i)
  426.             allBeeData[i] = nil
  427.          end
  428.       end
  429.    end
  430. end
  431.  
  432. function isPurebred(princessData, droneData)
  433.    -- check if princess and drone are exactly the same and no chance for mutation
  434.    if princessData["speciesPrimary"] ~= princessData["speciesSecondary"] then
  435.       return false
  436.    end
  437.    for key, value in pairs(princessData) do
  438.       if value ~= droneData[key] and key ~= "territory" and key ~= "type" and key ~= "slot" then
  439.          return false
  440.       end
  441.    end
  442.    return true
  443. end
  444.  
  445. function getUnknown(princessData, droneData)
  446.    -- lists species that are not in the bee graph
  447.    local unknownSpecies = {}
  448.    if not bees[princessData["speciesPrimary"]] then
  449.       table.insert(unknownSpecies, princessData["speciesPrimary"])
  450.    end
  451.    if not bees[princessData["speciesSecondary"]] then
  452.       table.insert(unknownSpecies, princessData["speciesSecondary"])
  453.    end
  454.    for _, beeData in pairs(droneData) do
  455.       if not bees[beeData["speciesPrimary"]] then
  456.          table.insert(unknownSpecies, beeData["speciesPrimary"])
  457.       end
  458.       if not bees[beeData["speciesSecondary"]] then
  459.          table.insert(unknownSpecies, beeData["speciesSecondary"])
  460.       end
  461.    end
  462.    return unknownSpecies
  463. end
  464.  
  465. -- targeting -------------------------------------------------------------------
  466.  
  467. -- set species and all parents to targeted
  468. function targetBee(name)
  469.    local bee = bees[name]
  470.    if bee and not bee.targeted then
  471.       bee.targeted = true
  472.       for i, parents in ipairs(bee.mutateFrom) do
  473.          for j, parent in ipairs(parents) do
  474.             targetBee(parent)
  475.          end
  476.       end
  477.    end
  478. end
  479.  
  480. -- set bee graph entry to targeted if species was specified on the command line
  481. -- otherwise set all entries to targeted
  482. tArgs = { ... }
  483. if #tArgs > 0 then
  484.    logLine("targeting bee species:")
  485.    for i, target in ipairs(tArgs) do
  486.       targetBee(target)
  487.       for name, data in pairs(bees) do
  488.          if data.targeted and data.score > 1 then
  489.             logLine(name .. string.rep(" ", 20-#name), data.score)
  490.          end
  491.       end
  492.    end
  493.    else
  494.    for _, beeData in pairs(bees) do
  495.       beeData.targeted = true
  496.    end
  497. end
  498.  
  499. -- breeding loop ---------------------------------------------------------------
  500.  
  501. logLine("Clearing system...")
  502. clearSystem()
  503. redstone.setOutput("bottom", true)
  504. while true do
  505.    analyzeBees()
  506.    if allBeeData[princessSlot] then
  507.       if isPurebred(princessData, allBeeData[2]) then
  508.          logLine("Bees are purebred")
  509.          redstone.setOutput("bottom", false)
  510.          break
  511.       end
  512.       breedBees(1, 2)
  513.       allBeeData[1] = nil
  514.       allBeeData[2] = nil
  515.       dropExcess()
  516.    end
  517.    getBees()
  518. end
  519. logFile.close()
Advertisement
Add Comment
Please, Sign In to add comment