DrFair

Bee auto mutator

May 12th, 2016
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.92 KB | None | 0 0
  1. -- Computercraft program that auto mutates bees from forestrycraft
  2. -- Configs:
  3. species1 = "meadows"
  4. species2 = "forest"
  5. targetSpecies = "common"
  6. alwaysPreferTarget = false -- If true, will always use a bee if it has the target species in active or inactive
  7.  
  8. -- How to use:
  9. -- Place turtle down with a big chest, an analyzer and an apiary touching it.
  10. -- Edit the configs above to match the species it is working with, and the target species.
  11. -- You can also run program with params: <species1> <species2> <targetSpecies>
  12. -- Edit the configs below to match your setup from where stuff is relative to the turtle.
  13. -- The apiary must be untouched during the program.
  14. -- Turtle slot 1 must be empty.
  15. -- Start the program, wait for the turtle to do it's job.
  16.  
  17. -- All caps
  18. turtleFacing = "EAST"
  19. storageDirection = "SOUTH"
  20. analyzerDirection = "NORTH"
  21. apiaryDirection = "EAST"
  22.  
  23. -- DO NOT EDIT BELOW
  24. dirs = {[1] = "NORTH", ["NORTH"] = 1,
  25. [2] = "EAST", ["EAST"] = 2,
  26. [3] = "SOUTH", ["SOUTH"] = 3,
  27. [4] = "WEST", ["WEST"] = 4}
  28.  
  29. local Args = {...}
  30. if Args[1] == "update" then
  31. local running = shell.getRunningProgram()
  32. print("Updating " .. running .. ".")
  33. fs.delete(running)
  34. shell.run("pastebin", "get", "F6LPTxQ6", running)
  35. print("Finished updating.")
  36. return
  37. end
  38.  
  39. function analyzeAll()
  40. print("Analyzing all bees in storage..")
  41. for slot, e in pairs(storage.p.getAllStacks()) do
  42. if not isBeeAnalyzed(storage.p.getStackInSlot(slot)) then
  43. while not moveStack(storage, analyzer, slot) do
  44. if not moveAllAnalyzedToStorage() then
  45. sleep(1)
  46. end
  47. end
  48. end
  49. end
  50. sleep(1)
  51. if analyzer.p.hasWork() then print("Waiting for analyzing done..") end
  52. while analyzer.p.hasWork() do
  53. moveAllAnalyzedToStorage()
  54. sleep(1)
  55. end
  56. moveAllAnalyzedToStorage()
  57. print("Analyzing done..")
  58. end
  59.  
  60. function moveAllAnalyzedToStorage()
  61. for i = 9, 12 do
  62. moveStack(analyzer, storage, i)
  63. end
  64. end
  65.  
  66. function moveAllApiaryToStorage()
  67. print("Moving apiary products to storage..")
  68. for i = 1, 9 do
  69. if apiary.p.getStackInSlot(i) ~= nil and not moveStack(apiary, storage, i) then
  70. print("Could not move apiary products to storage?")
  71. return
  72. end
  73. end
  74. end
  75.  
  76. function analyzerHasHoney()
  77. local c = analyzer.getTankInfo()[1].contents
  78. return compareString(c.name, "honey") and c.amount >= 100
  79. end
  80.  
  81. function isBee(item)
  82. return item.individual ~= nil
  83. end
  84.  
  85. function isBeeAnalyzed(item)
  86. if item.individual == nil then return true end -- Not a bee
  87. return item.individual.isAnalyzed;
  88. end
  89.  
  90. function getBeeData(item)
  91. if item.individual == nil then return nil end -- Not a bee
  92. local data = {}
  93. data.isAnalyzed = item.individual.isAnalyzed
  94. data.type = getBeeType(item)
  95. if data.isAnalyzed then
  96. data.active = item.individual.active.species.name
  97. data.inactive = item.individual.inactive.species.name
  98. end
  99. return data
  100. end
  101.  
  102. function getBeeString(item)
  103. if item.individual == nil then return "nil" end -- Not a bee
  104. local data = getBeeData(item)
  105. return data.active .. ":" .. data.inactive
  106. end
  107.  
  108. function getBeeType(item)
  109. local name = item.name
  110. if compareString(name, "drone") then return "d" end
  111. if compareString(name, "princess") then return "p" end
  112. if compareString(name, "queen") then return "q" end
  113. return "nil"
  114. end
  115.  
  116. function getItem(inventory, slot)
  117. return inventory.p.getStackInSlot(slot)
  118. end
  119.  
  120. function getFirstQueen()
  121. for slot, i in pairs(storage.p.getAllStacks()) do
  122. local item = getItem(storage, slot)
  123. if getBeeType(item) == "q" then
  124. return slot
  125. end
  126. end
  127. return 0
  128. end
  129.  
  130. function getBestPrincessSlot()
  131. local bestValue = 0
  132. local bestSlot = 0
  133. for slot, i in pairs(storage.p.getAllStacks()) do
  134. if isBee(getItem(storage, slot)) and isBeeAnalyzed(getItem(storage, slot)) then
  135. if getBeeType(getItem(storage, slot)) == "p" then
  136. local nextValue = getBeeValue(getItem(storage, slot))
  137. if nextValue > bestValue then
  138. bestValue = nextValue
  139. bestSlot = slot
  140. end
  141. end
  142. end
  143. end
  144. -- if bestSlot == 0 then
  145. -- print("Could not find a propper queen to use.")
  146. -- else
  147. -- print("Found best princess in slot " .. bestSlot .. ": " .. getBeeString(getItem(storage, bestSlot)))
  148. -- end
  149. return bestSlot
  150. end
  151.  
  152. function getBestDroneSlot(queen)
  153. local bestValue = 0
  154. local bestSlot = 0
  155. for slot, i in pairs(storage.p.getAllStacks()) do
  156. if isBee(getItem(storage, slot)) and isBeeAnalyzed(getItem(storage, slot)) then
  157. if getBeeType(getItem(storage, slot)) == "d" then
  158. local nextValue = getMatchValue(getItem(storage, slot), queen)
  159. if nextValue > bestValue then
  160. bestValue = nextValue
  161. bestSlot = slot
  162. end
  163. end
  164. end
  165. end
  166. -- if bestSlot == 0 then
  167. -- print("Could not find a propper drone to use.")
  168. -- else
  169. -- print("Found drone in slot " .. bestSlot .. ": " .. getBeeString(getItem(storage, bestSlot)))
  170. -- end
  171. return bestSlot
  172. end
  173.  
  174. function getBeeValue(bee)
  175. local beeData = getBeeData(bee)
  176. local value = 0
  177. if compareString(beeData.active, species1) or compareString(beeData.active, species2) then
  178. value = value + 1
  179. end
  180. if compareString(beeData.inactive, species1) or compareString(beeData.inactive, species2) then
  181. value = value + 1
  182. end
  183. if compareString(beeData.inactive, targetSpecies) then -- Needs to run 2 times, if both inactive and active is, it is good
  184. if alwaysPreferTarget then value = value + 100
  185. else value = value + 2 end
  186. end
  187. if compareString(beeData.active, targetSpecies) then
  188. if alwaysPreferTarget then value = value + 100
  189. else value = value + 2 end
  190. end
  191. return value
  192. end
  193.  
  194. function getMatchValue(drone, queen)
  195. local queenData = getBeeData(queen)
  196. local lookfor = nil
  197. if compareString(queenData.active, species1) and compareString(queenData.inactive, species1) then
  198. lookfor = species2
  199. elseif compareString(queenData.active, species2) and compareString(queenData.inactive, species2) then
  200. lookfor = species1
  201. end
  202. if lookfor == nil then
  203. return getBeeValue(drone)
  204. end
  205. local beeData = getBeeData(drone)
  206. local value = 0
  207. if compareString(beeData.active, lookfor) then
  208. value = value + 1
  209. end
  210. if compareString(beeData.inactive, lookfor) then
  211. value = value + 1
  212. end
  213. if compareString(beeData.active, targetSpecies) then -- Needs to run 2 times, if both inactive and active is, it is good
  214. if alwaysPreferTarget then value = value + 100
  215. else value = value + 2 end
  216. end
  217. if compareString(beeData.inactive, targetSpecies) then
  218. if alwaysPreferTarget then value = value + 100
  219. else value = value + 2 end
  220. end
  221. return value
  222. end
  223.  
  224. function isDone()
  225. local droneDone = false
  226. local princessDone = false
  227. for slot, i in pairs(storage.p.getAllStacks()) do
  228. local item = getItem(storage, slot)
  229. if isBee(item) and isBeeAnalyzed(item) then
  230. local beeData = getBeeData(item)
  231. if compareString(beeData.active, targetSpecies) and compareString(beeData.inactive, targetSpecies) then
  232. if getBeeType(item) == "d" then
  233. droneDone = true
  234. elseif getBeeType(item) == "p" then
  235. princessDone = true
  236. end
  237. if droneDone and princessDone then return true end
  238. end
  239. end
  240. end
  241. return false
  242. end
  243.  
  244. function moveItems(invFrom, invTo, slotFrom, slotTo, totalItems)
  245. local found = invFrom.p.pushItem(getOppositeDir(invFrom.d), slotFrom, totalItems, 1)
  246. if found == 0 then return false end
  247. local total = invTo.p.pullItem(getOppositeDir(invTo.d), 1, totalItems, slotTo)
  248. if total == 0 then
  249. invFrom.p.pullItem(getOppositeDir(invFrom.d), 1, totalItems, slotFrom)
  250. return false
  251. end
  252. return true
  253. end
  254.  
  255. function moveStack(invFrom, invTo, slotFrom, slotTo)
  256. return moveItems(invFrom, invTo, slotFrom, slotTo, 1000)
  257. end
  258.  
  259. function moveStack(invFrom, invTo, slotFrom)
  260. local found = invFrom.p.pushItem(getOppositeDir(invFrom.d), slotFrom, 100, 1)
  261. if found == 0 then return false end
  262. local total = invTo.p.pullItem(getOppositeDir(invTo.d), 1)
  263. if total == 0 then
  264. invFrom.p.pullItem(getOppositeDir(invFrom.d), 1, 100, slotFrom)
  265. return false
  266. end
  267. return true
  268. end
  269.  
  270. function compareString(master, match)
  271. return string.match(master:lower(), match:lower()) ~= nil
  272. end
  273.  
  274. function getIntDir(dir)
  275. if type(dir) == "string" then
  276. return dirs[dir]
  277. end
  278. return dir
  279. end
  280.  
  281. function getOppositeDir(dir)
  282. local finalDir = getIntDir(dir)
  283. return dirs[((finalDir - 1 + 2) % 4) + 1] -- Stupid lua index offset ;)
  284. end
  285.  
  286. function convertDir(dir)
  287. local periDir = getIntDir(dir)
  288. local facingDir = dirs[turtleFacing]
  289. local cDir = facingDir - periDir
  290. if cDir == 0 then return "front" end
  291. if cDir == 1 then return "left" end
  292. if cDir == -1 then return "right" end
  293. if cDir == 2 then return "back" end
  294. if cDir == -2 then return "back" end
  295. end
  296.  
  297. function log(msg)
  298. local path = shell.getRunningProgram() .. "log"
  299. local file = fs.open(path, "a")
  300. file.writeLine(msg)
  301. file.close()
  302. end
  303.  
  304. function clearLog()
  305. local path = shell.getRunningProgram() .. "log"
  306. fs.delete(path)
  307. end
  308.  
  309. apiary = {p = peripheral.wrap(convertDir(apiaryDirection)), d = apiaryDirection}
  310. storage = {p = peripheral.wrap(convertDir(storageDirection)), d = storageDirection}
  311. analyzer = {p = peripheral.wrap(convertDir(analyzerDirection)), d = analyzerDirection}
  312.  
  313. totalCycles = 0
  314. firstCouple = nil
  315.  
  316. function saveData()
  317. local path = shell.getRunningProgram() .. "save"
  318. fs.delete(path)
  319. local file = fs.open(path, "a")
  320. local data = {}
  321. data.species1 = species1
  322. data.species2 = species2
  323. data.targetSpecies = targetSpecies
  324. data.cycle = totalCycles
  325. data.firstCouple = firstCouple
  326. file.writeLine(textutils.serialize(data))
  327. file.close()
  328. end
  329.  
  330. function loadData()
  331. local path = shell.getRunningProgram() .. "save"
  332. if not fs.exists(path) then
  333. return false
  334. end
  335. local file = fs.open(path, "r")
  336. local readAll = file.readAll()
  337. file.close()
  338. local data = textutils.unserialize(readAll)
  339. if data.species1 ~= species1 or data.species2 ~= species2 or data.targetSpecies ~= targetSpecies then
  340. return false
  341. end
  342. totalCycles = data.cycle
  343. firstCouple = data.firstCouple
  344. return true
  345. end
  346.  
  347. if Args[1] == "test" then
  348. if not loadData() then
  349. print("Saved data did not match config, starting new mutaton..")
  350. clearLog()
  351. saveData()
  352. end
  353. print("Done testing")
  354. return
  355. end
  356.  
  357. if #Args >= 3 then
  358. species1 = Args[1]
  359. species2 = Args[2]
  360. targetSpecies = Args[3]
  361. print("Got input: " .. species1 .. ":" .. species2 .. " > " .. targetSpecies)
  362. end
  363.  
  364. if not loadData() then
  365. print("Saved data did not match config, starting new mutaton..")
  366. clearLog()
  367. saveData()
  368. totalCycles = 0
  369. firstCouple = nil
  370. end
  371.  
  372. while true do
  373. local printStatus = true
  374. local currentQueen = getItem(apiary, 1)
  375. if currentQueen ~= nil and getBeeType(currentQueen) == "q" then
  376. print("Waiting for apiary to finish..")
  377. while getItem(apiary, 1) ~= nil do
  378. sleep(5)
  379. end
  380. end
  381. moveAllApiaryToStorage()
  382. local foundQueen = getFirstQueen()
  383. if foundQueen ~= 0 then
  384. print("Found queen in storage, breeding her first.")
  385. moveItems(storage, apiary, foundQueen, 1, 1)
  386. sleep(1)
  387. else
  388. analyzeAll()
  389. if isDone() then
  390. log("Successfully purebred " .. targetSpecies .. "!")
  391. print("Successfully purebred " .. targetSpecies .. " in " .. totalCycles .. " cycles!")
  392. print("First couple used was: " .. tostring(firstCouple))
  393. return
  394. end
  395. local bestPrincess = getBestPrincessSlot()
  396. if bestPrincess == 0 then
  397. print("Could not find useable princess, sorry!")
  398. return
  399. end
  400. local bestMatch = getBestDroneSlot(getItem(storage, bestPrincess))
  401. if bestMatch == 0 then
  402. exit("Could not find useable drone, sorry!")
  403. return
  404. end
  405. print("Found usable couple:")
  406. local coupleString = getBeeString(getItem(storage, bestPrincess)) .. " and " .. getBeeString(getItem(storage, bestMatch))
  407. if firstCouple == nil then firstCouple = coupleString end
  408. log("#" .. totalCycles .. ": " .. coupleString)
  409. print(coupleString)
  410. moveItems(storage, apiary, bestPrincess, 1, 1)
  411. moveItems(storage, apiary, bestMatch, 2, 1)
  412. totalCycles = totalCycles + 1
  413. saveData()
  414. sleep(5)
  415. end
  416. end
Advertisement
Add Comment
Please, Sign In to add comment