Damaged

Bee Breeding New test 2

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