Damaged

Bee Breeding New test

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