Damaged

Bee Breeding revision 2

Mar 30th, 2014
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 31.43 KB | None | 0 0
  1. -- BeeAnalyzer 4.4.1
  2. -- Original code by Direwolf20
  3. -- Hotfix 1 by Mandydax
  4. -- Hotfix 2 by Mikeyhun/MaaadMike
  5. -- 4.0 Major overhaul by MacLeopold
  6. --     Breeds bees with best attributes in this order:
  7. --     fertility, speed, nocturnal, flyer, cave, temperature tolerance, humidity tolerance
  8. --     other attributes are ignored (lifespawn, flowers, effect and territory)
  9. --     Can specify multiple target species to help with keeping to the correct line
  10. -- 4.1 Minor fix for FTB Unleashed, no more inventory module or suckSneaky needed
  11. -- 4.2 Major overhaul 2
  12. --     Added magic bees, removed old bees
  13. --     Added species graph
  14. --     Changed targeting to target parent species
  15. --     Changed breeding to keep stock of good bees to prevent losing attributes
  16. --     Added logging
  17. --     Changed scoring to look for best combination of princess and drone
  18. -- 4.3 Updated targeting
  19. -- 4.4 Switched to OpenPeripherals by Eiktyrner
  20. -- 4.4.1  Modified to work with:
  21. --          OpenPeripheral Core 0.3.0-s39
  22. --          OpenPeripheral Addons 0.1.0-s41
  23.  
  24. -- attribute scoring for same species tie-breaking -----------------------------
  25.  
  26. scoresFertility = {
  27.   [1] = 0.1,
  28.   [2] = 0.2,
  29.   [3] = 0.3,
  30.   [4] = 0.4
  31. }
  32. scoresSpeed = {
  33.   ["0.3"] = 0.01, -- Slowest
  34.   ["0.6"] = 0.02, -- Slower
  35.   ["0.8"] = 0.03, -- Slow
  36.   ["1"]   = 0.04, -- Normal
  37.   ["1.2"] = 0.05, -- Fast
  38.   ["1.4"] = 0.06, -- Faster
  39.   ["1.7"] = 0.07  -- Fastest
  40. }
  41. scoresAttrib = {
  42.   diurnal       = 0.004,
  43.   nocturnal     = 0.003,
  44.   tolerantFlyer = 0.002,
  45.   caveDwelling  = 0.0001
  46. }
  47. scoresTolerance = {
  48.   ["NONE"]   = 0.00000,
  49.   ["UP 1"]   = 0.00001,
  50.   ["UP 2"]   = 0.00002,
  51.   ["UP 3"]   = 0.00003,
  52.   ["UP 4"]   = 0.00004,
  53.   ["UP 5"]   = 0.00005,
  54.   ["DOWN 1"] = 0.00001,
  55.   ["DOWN 2"] = 0.00002,
  56.   ["DOWN 3"] = 0.00003,
  57.   ["DOWN 4"] = 0.00004,
  58.   ["DOWN 5"] = 0.00005,
  59.   ["BOTH 1"] = 0.00002,
  60.   ["BOTH 2"] = 0.00004,
  61.   ["BOTH 3"] = 0.00006,
  62.   ["BOTH 4"] = 0.00008,
  63.   ["BOTH 5"] = 0.00010
  64. }
  65.  
  66. -- the bee graph ---------------------------------------------------------------
  67.  
  68. bees = {}
  69.  
  70. function addParent(parent, offspring)
  71.   if bees[parent] then
  72.     bees[parent].mutateTo[offspring] = true
  73.   else
  74.     bees[parent] = {
  75.       --name = parent,
  76.       score = nil,
  77.       mutateTo = {[offspring]=true},
  78.       mutateFrom = {}
  79.     }
  80.   end
  81. end
  82.  
  83. function addOffspring(offspring, parentss)
  84.   if bees[offspring] then
  85.     for i, parents in ipairs(parentss) do
  86.       table.insert(bees[offspring].mutateFrom, parents)
  87.     end
  88.   else
  89.     bees[offspring] = {
  90.       score = nil,
  91.       mutateTo = {},
  92.       mutateFrom = parentss
  93.     }
  94.   end
  95.   for i, parents in ipairs(parentss) do
  96.     for i, parent in ipairs(parents) do
  97.       addParent(parent, offspring)
  98.     end
  99.   end
  100. end
  101.  
  102. -- score bees that have no parent combinations as 1
  103. -- iteratively find the next bee up the line and increase the score
  104. function scoreBees()
  105.   -- find all bees with no mutateFrom data
  106.   local beeCount = 0
  107.   local beeScore = 1
  108.   for name, beeData in pairs(bees) do
  109.     if #beeData.mutateFrom == 0 then
  110.       beeData.score = beeScore
  111.     else
  112.       beeCount = beeCount + 1
  113.     end
  114.   end
  115.   while beeCount > 0 do
  116.     beeScore = beeScore * 2
  117.     -- find all bees where all parent combos are scored
  118.     for name, beeData in pairs(bees) do
  119.       if not beeData.score then
  120.         local scoreBee = true
  121.         for i, beeParents in ipairs(beeData.mutateFrom) do
  122.           local parent1 = bees[beeParents[1]]
  123.           local parent2 = bees[beeParents[2]]
  124.  
  125.           if not parent1.score
  126.               or parent1.score == beeScore
  127.               or not parent2.score
  128.               or parent2.score == beeScore then
  129.             scoreBee = false
  130.             break
  131.           end
  132.         end
  133.         if scoreBee then
  134.           beeData.score = beeScore
  135.           beeCount = beeCount - 1
  136.         end
  137.       end
  138.     end
  139.   end
  140. end
  141.  
  142. -- produce combinations from 1 or 2 lists
  143. function choose(list, list2)
  144.   local newList = {}
  145.   if list2 then
  146.     for i = 1, #list2 do
  147.       for j = 1, #list do
  148.         if list[j] ~= list[i] then
  149.           table.insert(newList, {list[j], list2[i]})
  150.         end
  151.       end
  152.     end
  153.   else
  154.     for i = 1, #list do
  155.       for j = i, #list do
  156.         if list[i] ~= list[j] then
  157.           table.insert(newList, {list[i], list[j]})
  158.         end
  159.       end
  160.     end
  161.   end
  162.   return newList
  163. end
  164.  
  165. -- Fix for some versions returning bees.species.*
  166. function fixName(name)
  167.   return name:gsub("bees%.species%.",""):gsub("^.", string.upper)
  168. end
  169.  
  170. m = peripheral.wrap("front")
  171. for key, value in pairs (m.getBeeBreedingData()) do
  172.   addOffspring( fixName(value.result), {{ fixName(value.allele1), fixName(value.allele2) }} )
  173. end
  174.  
  175. -- Forestry Bees ---------------------------------------------------------------
  176. --[[
  177. -- Agrarian Branch
  178. addOffspring("Rural", {{"Diligent", "Meadows"}})
  179. addOffspring("Farmed", {{"Rural", "Cultivated"}})
  180. -- Apis Branch
  181. addOffspring("Common", choose({"Forest", "Meadows", "Modest", "Marbled", "Tropical", "Wintry", "Marshy", "Water", "Rocky", "Embittered", "Unusual", "Mystical", "Sorcerous", "Attuned"}))
  182. addOffspring("Cultivated", choose({"Common"}, {"Forest", "Meadows", "Modest", "Marbled", "Tropical", "Wintry", "Marshy", "Water", "Rocky", "Embittered", "Unusual", "Mystical", "Sorcerous", "Attuned"}))
  183. -- Austere Branch
  184. addOffspring("Frugal", {{"Sinister", "Modest"}, {"Fiendish", "Modest"}})
  185. addOffspring("Austere", {{"Frugal", "Modest"}})
  186. -- Beastly Branch
  187. addOffspring("Jaded", {{"Ender", "Relic"}})
  188. -- End Branch
  189. addOffspring("Spectral", {{"Hermitic", "Ender"}})
  190. addOffspring("Phantasmal", {{"Spectral", "Ender"}})
  191. -- Festive Branch
  192. addOffspring("Celebratory", {{"Austere", "Excited"}})
  193. addOffspring("Hazardous", {{"Austere", "Desolate"}})
  194. addOffspring("Leporine", {{"Meadows", "Forest"}})
  195. addOffspring("Merry", {{"Wintry", "Forest"}})
  196. addOffspring("Tipsy", {{"Wintry", "Meadows"}})
  197. -- Frozen Branch
  198. addOffspring("Icy", {{"Industrious", "Wintry"}})
  199. addOffspring("Glacial", {{"Icy", "Wintry"}})
  200. addOffspring("Frigid", {{"Diligent", "Wintry"}})
  201. addOffspring("Absolute", {{"Frigid", "Ocean"}})
  202. -- Heroic Branch
  203. addOffspring("Heroic", {{"Steadfast", "Valiant"}})
  204. -- Industrious Branch
  205. addOffspring("Diligent", {{"Cultivated", "Common"}})
  206. addOffspring("Unweary", {{"Diligent", "Cultivated"}})
  207. addOffspring("Industrious", {{"Unweary", "Diligent"}})
  208. -- Infernal Branch
  209. addOffspring("Sinister", {{"Cultivated", "Modest"}, {"Cultivated", "Tropical"}})
  210. addOffspring("Fiendish", {{"Sinister", "Cultivated"}, {"Sinister", "Modest"}, {"Sinister", "Tropical"}})
  211. addOffspring("Demonic", {{"Fiendish", "Sinister"}})
  212. -- Monastic Branch
  213. addOffspring("Secluded", {{"Monastic", "Austere"}})
  214. addOffspring("Hermitic", {{"Secluded", "Monastic"}})
  215. -- Noble Branch
  216. addOffspring("Noble", {{"Cultivated", "Common"}})
  217. addOffspring("Majestic", {{"Noble", "Cultivated"}})
  218. addOffspring("Imperial", {{"Majestic", "Noble"}})
  219. -- Tropical Branch
  220. addOffspring("Exotic", {{"Austere", "Tropical"}})
  221. addOffspring("Edenic", {{"Exotic", "Tropical"}})
  222. -- Vengeful Branch
  223. addOffspring("Vindictive", {{"Monastic", "Demonic"}})
  224. addOffspring("Vengeful", {{"Vindictive", "Demonic"}, {"Vindictive", "Monastic"}})
  225. addOffspring("Avenging", {{"Vengeful", "Vindictive"}})
  226.  
  227. -- Extra Bees ------------------------------------------------------------------
  228.  
  229. -- Agricultural Branch
  230. addOffspring("Bovine", {{"Rural", "Water"}})
  231. addOffspring("Caffeinated", {{"Rural", "Tropical"}})
  232. addOffspring("Citrus", {{"Farmed", "Modest"}})
  233. addOffspring("Fermented", {{"Rural", "Fruity"}})
  234. addOffspring("Minty", {{"Farmed", "Tropical"}})
  235. -- Alloyed Branch
  236. addOffspring("Impregnable", {{"Resilient", "Noble"}})
  237. -- Aquatic Branch
  238. addOffspring("River", {{"Common", "Water"}})
  239. addOffspring("Ocean", {{"Diligent", "Water"}})
  240. addOffspring("Stained", {{"Ocean", "Ebony"}})
  241. -- Barren Branch
  242. addOffspring("Arid", {{"Meadows", "Modest"}})
  243. addOffspring("Barren", {{"Arid", "Common"}})
  244. addOffspring("Desolate", {{"Barren", "Arid"}})
  245. -- Boggy Branch
  246. addOffspring("Damp", {{"Common", "Marshy"}})
  247. addOffspring("Boggy", {{"Damp", "Marshy"}})
  248. addOffspring("Fungal", {{"Boggy", "Damp"}})
  249. -- Caustic Branch
  250. addOffspring("Corrosive", {{"Virulent", "Sticky"}})
  251. addOffspring("Caustic", {{"Corrosive", "Fiendish"}})
  252. addOffspring("Acidic", {{"Caustic", "Corrosive"}})
  253. -- Energetic Branch
  254. addOffspring("Excited", {{"Cultivated", "Valiant"}})
  255. addOffspring("Energetic", {{"Excited", "Valiant"}})
  256. addOffspring("Ecstatic", {{"Energetic", "Excited"}})
  257. -- Fossilized
  258. addOffspring("Fossiled", {{"Primeval", "Growing"}})
  259. addOffspring("Oily", {{"Primeval", "Ocean"}})
  260. addOffspring("Preserved", {{"Primeval", "Boggy"}})
  261. addOffspring("Resinous", {{"Primeval", "Fungal"}})
  262. -- Gemstone Branch
  263. addOffspring("Diamond", {{"Lapis", "Imperial"}})
  264. addOffspring("Emerald", {{"Lapis", "Noble"}})
  265. addOffspring("Ruby", {{"Emerald", "Austere"}})
  266. addOffspring("Sapphire", {{"Emerald", "Ocean"}})
  267. -- Historic Branch
  268. addOffspring("Ancient", {{"Noble", "Diligent"}})
  269. addOffspring("Primeval", {{"Ancient", "Noble"}})
  270. addOffspring("Prehistoric", {{"Primeval", "Majestic"}})
  271. addOffspring("Relic", {{"Prehistoric", "Imperial"}})
  272. -- Hostile Branch
  273. addOffspring("Skeletal", {{"Desolate", "Frugal"}})
  274. addOffspring("Decaying", {{"Desolate", "Modest"}})
  275. addOffspring("Creepy", {{"Desolate", "Austere"}})
  276. -- Metallic Branch
  277. addOffspring("Galvanized", {{"Tarnished", "Cultivated"}})
  278. addOffspring("Invincible", {{"Resilient", "Ender"}})
  279. addOffspring("Lustered", {{"Resilient", "Unweary"}})
  280. -- Nuclear Branch
  281. addOffspring("Unstable", {{"Austere", "Rocky"}})
  282. addOffspring("Nuclear", {{"Unstable", "Rusty"}})
  283. addOffspring("Radioactive", {{"Nuclear", "Glittering"}})
  284. -- Precious Branch
  285. addOffspring("Lapis", {{"Resilient", "Water"}})
  286. addOffspring("Glittering", {{"Corroded", "Imperial"}})
  287. addOffspring("Shining", {{"Rusty", "Imperial"}})
  288. addOffspring("Valuable", {{"Glittering", "Shining"}})
  289. -- Refined Branch
  290. addOffspring("Distilled", {{"Oily", "Industrious"}})
  291. addOffspring("Refined", {{"Distilled", "Oily"}})
  292. addOffspring("Elastic", {{"Refined", "Resinous"}})
  293. addOffspring("Tarry", {{"Refined", "Fossiled"}})
  294. -- Rocky Branch
  295. addOffspring("Tolerant", {{"Diligent", "Rocky"}})
  296. addOffspring("Robust", {{"Tolerant", "Rocky"}})
  297. addOffspring("Resilient", {{"Robust", "Imperial"}})
  298. -- Rusty Branch
  299. addOffspring("Corroded", {{"Resilient", "Forest"}})
  300. addOffspring("Leaden", {{"Resilient", "Unweary"}})
  301. addOffspring("Rusty", {{"Resilient", "Meadows"}})
  302. addOffspring("Tarnished", {{"Resilient", "Marshy"}})
  303. -- Saccharine Branch
  304. addOffspring("Sweetened", {{"Diligent", "Valiant"}})
  305. addOffspring("Sugary", {{"Sweetened", "Diligent"}})
  306. addOffspring("Fruity", {{"Ripening", "Rural"}})
  307. -- Shadow Branch
  308. addOffspring("Shadowed", {{"Tolerant", "Sinister"}})
  309. addOffspring("Darkened", {{"Shadowed", "Embittered"}})
  310. addOffspring("Abyssmal", {{"Darkened", "Shadowed"}})
  311. -- Virulent Branch
  312. addOffspring("Malicious", {{"Sinister", "Tropical"}})
  313. addOffspring("Infectious", {{"Malicious", "Tropical"}})
  314. addOffspring("Virulent", {{"Infectious", "Malicious"}})
  315. -- Viscous Branch
  316. addOffspring("Viscous", {{"Exotic", "Water"}})
  317. addOffspring("Glutinous", {{"Viscous", "Exotic"}})
  318. addOffspring("Sticky", {{"Glutinous", "Viscous"}})
  319. -- Volcanic Branch
  320. addOffspring("Furious", {{"Sinister", "Embittered"}})
  321. addOffspring("Volcanic", {{"Furious", "Embittered"}})
  322. addOffspring("Glowering", {{"Excited", "Furious"}})
  323.  
  324. -- Primary Branch
  325. addOffspring("Bleached", {{"Wintry", "Valiant"}})
  326. addOffspring("Ebony", {{"Rocky", "Valiant"}})
  327. addOffspring("Maroon", {{"Forest", "Valiant"}})
  328. addOffspring("Natural", {{"Tropical", "Valiant"}})
  329. addOffspring("Prussian", {{"Water", "Valiant"}})
  330. addOffspring("Saffron", {{"Meadows", "Valiant"}})
  331. addOffspring("Sepia", {{"Marshy", "Valiant"}})
  332. -- Secondary Branch
  333. addOffspring("Amber", {{"Maroon", "Saffron"}})
  334. addOffspring("Azure", {{"Prussian", "Bleached"}})
  335. addOffspring("Indigo", {{"Maroon", "Prussian"}})
  336. addOffspring("Lavender", {{"Maroon", "Bleached"}})
  337. addOffspring("Lime", {{"Natural", "Bleached"}})
  338. addOffspring("Slate", {{"Ebony", "Bleached"}})
  339. addOffspring("Turquoise", {{"Natural", "Prussian"}})
  340. -- Tertiary Branch
  341. addOffspring("Ashen", {{"Slate", "Bleached"}})
  342. addOffspring("Fuchsia", {{"Indigo", "Lavender"}})
  343.  
  344. -- no branch
  345. addOffspring("Gnawing", {{"Barren", "Forest"}})
  346. addOffspring("Decoposing", {{"Arid", "Common"}, {"Gnawing", "Common"}})
  347. addOffspring("Growing", {{"Diligent", "Forest"}})
  348. addOffspring("Thriving", {{"Growing", "Rural"}})
  349. addOffspring("Blooming", {{"Growing", "Thriving"}})
  350. addOffspring("Ripening", {{"Sugary", "Forest"}})
  351.  
  352. -- Magic Bees ------------------------------------------------------------------
  353.  
  354. -- Abominable Branch
  355. addOffspring("Hateful", {{"Eldritch", "Infernal"}})
  356. addOffspring("Spiteful", {{"Hateful", "Infernal"}})
  357. addOffspring("Withering", {{"Demonic", "Spiteful"}})
  358. -- Alchemical Branch
  359. addOffspring("Minium", {{"Eldritch", "Frugal"}})
  360. -- Arcane Branch
  361. addOffspring("Esoteric", {{"Eldritch", "Cultivated"}})
  362. addOffspring("Mysterious", {{"Eldritch", "Esoteric"}})
  363. addOffspring("Arcane", {{"Mysterious", "Esoteric"}})
  364. -- Aware Branch
  365. addOffspring("Ethereal", {{"Arcane", "Supernatural"}})
  366. addOffspring("Aware", {{"Ethereal", "Attuned"}})
  367. addOffspring("Watery", {{"Ethereal", "Supernatural"}})
  368. addOffspring("Windy", {{"Ethereal", "Supernatural"}})
  369. addOffspring("Firey", {{"Ethereal", "Supernatural"}})
  370. addOffspring("Earthen", {{"Ethereal", "Supernatural"}})
  371. -- Essential Branch
  372. addOffspring("Essence", {{"Arcane", "Ethereal"}})
  373. addOffspring("Arkanen", {{"Essence", "Ethereal"}})
  374. addOffspring("Quintessential", {{"Essence", "Arcane"}})
  375. addOffspring("Vortex", {{"Essence", "Skulking"}})
  376. addOffspring("Wight", {{"Ghastly", "Skulking"}})
  377. addOffspring("Luft", {{"Essence", "Windy"}})
  378. addOffspring("Blitz", {{"Luft", "Windy"}})
  379. addOffspring("Wasser", {{"Essence", "Watery"}})
  380. addOffspring("Eis", {{"Wasser", "Watery"}})
  381. addOffspring("Erde", {{"Essence", "Earthen"}})
  382. addOffspring("Staude", {{"Erde", "Earthen"}})
  383. addOffspring("Feuer", {{"Essence", "Firey"}})
  384. addOffspring("Magma", {{"Feuer", "Firey"}})
  385. -- Extrinsic
  386. addOffspring("Nameless", {{"Oblivion", "Ethereal"}})
  387. addOffspring("Abandoned", {{"Nameless", "Oblivion"}})
  388. addOffspring("Forlorn", {{"Abandoned", "Nameless"}})
  389. addOffspring("Draconic", {{"Abandoned", "Imperial"}})
  390. -- Fleshly Branch
  391. addOffspring("Poultry", {{"Skulking", "Common"}})
  392. addOffspring("Beefy", {{"Skulking", "Common"}})
  393. addOffspring("Porcine", {{"Skulking", "Common"}})
  394. -- Gem Branch
  395. addOffspring("Apatine", {{"Rural", "Cuprum"}})
  396. addOffspring("Diamandi", {{"Austere", "Auric"}})
  397. addOffspring("Esmeraldi", {{"Austere", "Argentum"}})
  398. -- Metallic2 Branch
  399. addOffspring("Cuprum", {{"Industrious", "Meadows"}})
  400. addOffspring("Stannum", {{"Industrious", "Forest"}})
  401. addOffspring("Aluminum", {{"Industrious", "Cultivated"}})
  402. addOffspring("Ardite", {{"Industrious", "Infernal"}})
  403. addOffspring("Argentum", {{"Imperial", "Modest"}})
  404. addOffspring("Cobalt", {{"Imperial", "Infernal"}})
  405. addOffspring("Ferrous", {{"Common", "Industrious"}})
  406. addOffspring("Plumbum", {{"Stannum", "Common"}})
  407. addOffspring("Auric", {{"Minium", "Plumbum"}})
  408. addOffspring("Manyullyn", {{"Ardite", "Cobalt"}})
  409. -- Scholarly Branch
  410. addOffspring("Pupil", {{"Arcane", "Monastic"}})
  411. addOffspring("Scholarly", {{"Arcane", "Pupil"}})
  412. addOffspring("Savant", {{"Scholarly", "Pupil"}})
  413. -- Skulking Branch
  414. addOffspring("Skulking", {{"Eldritch", "Modest"}})
  415. addOffspring("Ghastly", {{"Skulking", "Ethereal"}})
  416. addOffspring("Smouldering", {{"Skulking", "Hateful"}})
  417. addOffspring("Spidery", {{"Skulking", "Tropical"}})
  418. -- Soulful Branch
  419. addOffspring("Spirit", {{"Ethereal", "Aware"}, {"Attuned", "Aware"}})
  420. addOffspring("Soul", {{"Spirit", "Aware"}})
  421. -- Supernatural Branch
  422. addOffspring("Charmed", {{"Eldritch", "Cultivated"}})
  423. addOffspring("Enchanted", {{"Eldritch", "Charmed"}})
  424. addOffspring("Supernatural", {{"Enchanted", "Charmed"}})
  425. -- Thaumic Branch
  426. addOffspring("Aqua", {{"Watery", "Watery"}})
  427. addOffspring("Aura", {{"Windy", "Windy"}})
  428. addOffspring("Ignis", {{"Firey", "Firey"}})
  429. addOffspring("Praecantatio", {{"Ethereal", "Ethereal"}})
  430. addOffspring("Solum", {{"Earthen", "Earthen"}})
  431. addOffspring("Stark", choose({"Earthen", "Firey", "Watery", "Windy"}))
  432. addOffspring("Vis", {{"Eldritch", "Ethereal"}})
  433. addOffspring("Flux", {{"Vis", "Demonic"}})
  434. addOffspring("Attractive", {{"Vis", "Flux"}})
  435. addOffspring("Rejuvenating", {{"Vis", "Imperial"}})
  436. addOffspring("Pure", {{"Vis", "Rejuvenating"}})
  437. addOffspring("Batty", {{"Skulking", "Windy"}})
  438. addOffspring("Brainy", {{"Skulking", "Pupil"}})
  439. addOffspring("Wispy", {{"Ethereal", "Ghastly"}})
  440. -- Time Branch
  441. addOffspring("Timely", {{"Ethereal", "Imperial"}})
  442. addOffspring("Lordly", {{"Timely", "Imperial"}})
  443. addOffspring("Doctoral", {{"Lordly", "Timely"}})
  444. -- Veiled Branch
  445. addOffspring("Eldritch", {{"Mystical", "Cultivated"}, {"Sorcerous", "Cultivated"}, {"Unusual", "Cultivated"}, {"Attuned", "Cultivated"}})
  446. ]]--
  447. scoreBees()
  448.  
  449. -- logging ---------------------------------------------------------------------
  450.  
  451. local logFile = fs.open("bee.log", "w")
  452. function log(msg)
  453.   msg = msg or ""
  454.   logFile.write(tostring(msg))
  455.   logFile.flush()
  456.   io.write(msg)
  457. end
  458. function logLine(msg)
  459.   msg = msg or ""
  460.   logFile.write(msg.."\n")
  461.   logFile.flush()
  462.   io.write(msg.."\n")
  463. end
  464.  
  465. function logTable(table)
  466.   for key, value in pairs (table) do
  467.     logLine(key .. " = " .. tostring(value))
  468.   end
  469. end
  470.  
  471. -- analyzing functions ---------------------------------------------------------
  472.  
  473.  
  474.  
  475. -- Expects the turtle facing apiary
  476. function clearSystem()
  477.   -- clear out apiary
  478.   while turtle.suck() do end
  479.  
  480.   -- clear out analyzer
  481.   turtle.turnLeft()
  482.   while turtle.suck() do end
  483.   turtle.turnRight()
  484. end
  485.  
  486. function getBees()
  487.   -- get bees from apiary
  488.   log("waiting for bees.")
  489.   turtle.select(1)
  490.   while not turtle.suck() do
  491.     sleep(10)
  492.     log(".")
  493.   end
  494.   log("*")
  495.   while turtle.suck() do
  496.     log("*")
  497.   end
  498.   logLine()
  499. end
  500.  
  501. function countBees()
  502.   -- spread dups and fill gaps
  503.   local count = 0
  504.   for i = 1, 16 do
  505.     local slotCount = turtle.getItemCount(i)
  506.     if slotCount == 1 then
  507.       for j = 1, i-1 do
  508.         if turtle.getItemCount(j) == 0 then
  509.           turtle.select(i)
  510.           turtle.transferTo(j)
  511.           break
  512.         end
  513.       end
  514.       count = count + 1
  515.     elseif slotCount > 1 then
  516.       for j = 2, slotCount do
  517.         turtle.select(i)
  518.         for k = 1, 16 do
  519.           if turtle.getItemCount(k) == 0 then
  520.             turtle.transferTo(k, 1)
  521.           end
  522.         end
  523.       end
  524.       if turtle.getItemCount(i) > 1 then
  525.         turtle.dropDown(turtle.getItemCount(i)-1)
  526.       end
  527.     end
  528.   end
  529.   return count
  530. end
  531.  
  532. function breedBees(princessSlot, droneSlot)
  533.    turtle.select(princessSlot)
  534.    turtle.drop()
  535.    turtle.select(droneSlot)
  536.    turtle.drop()
  537. end
  538.  
  539. function swapBee(slot1, slot2, freeSlot)
  540.   for i = 1, 16 do
  541.     if turtle.getItemCount(i) == 0 then
  542.       freeSlot = i
  543.     end
  544.   end
  545.   turtle.select(slot1)
  546.   turtle.transferTo(freeSlot)
  547.   turtle.select(slot2)
  548.   turtle.transferTo(slot1)
  549.   turtle.select(freeSlot)
  550.   turtle.transferTo(slot2)
  551. end  
  552.  
  553. function findEmptySlot()
  554.   local thisResult = 0
  555.   for i = 1, 16 do
  556.     if turtle.getItemCount(i) == 0 then
  557.       thisResult = i
  558.     end
  559.   end
  560.   return thisResult
  561. end
  562.  
  563. function analyzeBees(droneData)
  564.   logLine("analyzing bees...")
  565.   turtle.turnLeft()
  566.   local freeSlot
  567.   local princessSlot
  568.   local highestScore
  569.   local princessData
  570.   if not droneData then
  571.     droneData = {}
  572.   end
  573.   local beealyzer = peripheral.wrap("front")
  574.  
  575.   for i = 1, 16 do
  576.     if turtle.getItemCount(i) > 0 then
  577.       turtle.select(i)
  578.       if not droneData[i] then
  579.         if not turtle.drop() then
  580.           -- Item is not a bee, get rid of it and continue
  581.           turtle.dropDown()
  582.           print("P")
  583.         else
  584.           print("B")
  585.           -- Initialize tableData and then keep trying to get the bee information until it is a valid table
  586.           local tableData
  587.           while not tableData do
  588.             sleep(1)
  589.             tableData = beealyzer.getStackInSlot(9)
  590.           end
  591.           local beeData = {}
  592.          
  593.           -- Get bees back into turtle after grabbing values
  594.           while not turtle.suck() do
  595.             sleep(1)
  596.           end
  597.          
  598.           -- Check if it's a drone or princess
  599.           for key, value in pairs (tableData) do
  600.             if key == "rawName" then
  601.               if string.find(value, "princess") then
  602.                 beeData["type"] = "princess"
  603.               else
  604.                 beeData["type"] = "drone"
  605.               end
  606.             end
  607.           end
  608.          
  609.           -- Active values
  610.           for key, value in pairs (tableData.beeInfo.active) do
  611.             if key == "species" then
  612.               beeData["speciesPrimary"] = value
  613.             else
  614.               beeData[key] = value
  615.             end
  616.           end
  617.          
  618.           -- Inactive values
  619.           for key, value in pairs (tableData.beeInfo.inactive) do
  620.             if key == "species" then
  621.               beeData["speciesSecondary"] = value
  622.             end
  623.           end
  624.          
  625.           if not beeData["speciesPrimary"] then
  626.             logLine("Bee "..i.." not correctly analyzed")
  627.           else
  628.             beeData["speciesPrimary"] = fixName(beeData["speciesPrimary"])
  629.             beeData["speciesSecondary"] = fixName(beeData["speciesSecondary"])
  630.             if beeData["type"] == "princess" then
  631.               princessData = beeData
  632.               if i ~= 1 then
  633.                 swapBee(i,1,freeSlot)
  634.               end
  635.               princessSlot = 1
  636.             else
  637.               droneData[i] = beeData
  638.             end
  639.           end
  640.         end
  641.       else
  642.         beeData = droneData[i]
  643.       end
  644.      
  645.       if beeData then
  646.         -- check for untargeted species
  647.         if droneData[i] and (not bees[droneData[i]["speciesPrimary"]].targeted
  648.             or not bees[droneData[i]["speciesSecondary"]].targeted) then
  649.           turtle.dropDown()
  650.           droneData[i] = nil
  651.           freeSlot = i
  652.         else
  653.           -- Check if there are more than 1 bee in this slot, if so, try and spread them out in empty slots
  654.           local slotCount = turtle.getItemCount(i)
  655.           if slotCount == 1 then
  656.             for j = 1, i-1 do
  657.               -- Move bees to earlier slots to remove gaps caused by produce
  658.               if turtle.getItemCount(j) == 0 then
  659.                 turtle.select(i)
  660.                 turtle.transferTo(j)
  661.                 droneData[j] = droneData[i]
  662.                 droneData[i] = nil
  663.                 freeSlot = i
  664.                 break
  665.               end
  666.             end
  667.           -- Spread bees out if they are in a stack
  668.           elseif slotCount > 1 then
  669.             while turtle.getItemCount(i) > 1 do
  670.               turtle.select(i)
  671.               local k = findEmptySlot()
  672.               if not k then break end
  673.               turtle.transferTo(k, 1)
  674.               droneData[k] = droneData[i]
  675.             end
  676.             if turtle.getItemCount(i) > 1 then
  677.               turtle.dropDown(turtle.getItemCount(i)-1)
  678.             end
  679.             if turtle.getItemCount(i) == 0 then
  680.               droneData[i] = nil
  681.               freeSlot = i
  682.             end
  683.           end
  684.         end
  685.       end
  686.     else
  687.       freeSlot = i
  688.     end
  689.   end
  690.  
  691.   if princessData then
  692.     -- selection sort drones
  693.     logLine("sorting drones...")
  694.     for i = 2, 16 do
  695.       highestScore = i
  696.       if turtle.getItemCount(i) > 0 and droneData[i] then
  697.         droneData[i].score = scoreBee(princessData, droneData[i])
  698.         for j = i + 1, 16 do
  699.           if turtle.getItemCount(j) > 0 and droneData[j] then
  700.             if not droneData[j].score then
  701.               droneData[j].score = scoreBee(princessData, droneData[j])
  702.             end
  703.             if droneData[j].score > droneData[highestScore].score then
  704.               highestScore = j
  705.             end
  706.           end
  707.         end
  708.         -- swap bees
  709.         if highestScore ~= i then
  710.           swapBee(i, highestScore, freeSlot)
  711.           droneData[i], droneData[highestScore] = droneData[highestScore], droneData[i]
  712.         end
  713.       end
  714.     end
  715.     printHeader()
  716.     princessData.slot = 1
  717.     printBee(princessData)
  718.     for i = 2, 16 do
  719.       if droneData[i] then
  720.         droneData[i].slot = i
  721.         printBee(droneData[i])
  722.       end
  723.     end
  724.   end
  725.   logLine()
  726.   turtle.turnRight()
  727.   return princessData, droneData
  728. end
  729.  
  730. function scoreBee(princessData, droneData)
  731.   local droneSpecies = {droneData["speciesPrimary"], droneData["speciesSecondary"]}
  732.   -- check for untargeted species
  733.   if not bees[droneSpecies[1]].targeted or not bees[droneSpecies[2]].targeted then
  734.     return 0
  735.   end
  736.   local princessSpecies = {princessData["speciesPrimary"], princessData["speciesSecondary"]}
  737.   local score
  738.   local maxScore = 0
  739.   for _, combo in ipairs({{princessSpecies[1], droneSpecies[1]}
  740.                          ,{princessSpecies[1], droneSpecies[2]}
  741.                          ,{princessSpecies[2], droneSpecies[1]}
  742.                          ,{princessSpecies[2], droneSpecies[2]}}) do
  743.     -- find maximum score for each combo
  744.     score = (bees[combo[1]].score + bees[combo[2]].score) / 2
  745.     for name, beeData in pairs(bees) do
  746.       if beeData.targeted then
  747.         for i, parents in ipairs(beeData.mutateFrom) do
  748.           if combo[1] == parents[1] and combo[2] == parents[2]
  749.               or combo[2] == parents[1] and combo[1] == parents[2] then
  750.             score = (score + beeData.score) / 2
  751.           end
  752.         end
  753.       end
  754.     end
  755.     maxScore = maxScore + score
  756.   end
  757.   -- add one for each combination that results in the maximum score
  758.   score = maxScore
  759.   -- score attributes
  760.   score = score + math.max(scoresFertility[droneData["fertility"]], scoresFertility[princessData["fertility"]])
  761.   score = score + math.min(scoresSpeed[tostring(droneData["speed"])], scoresSpeed[tostring(princessData["speed"])])
  762.   if droneData["nocturnal"] or princessData["nocturnal"] then score = score + scoresAttrib["nocturnal"] end
  763.   if droneData["tolerantFlyer"] or princessData["tolerantFlyer"] then score = score + scoresAttrib["tolerantFlyer"] end
  764.   if droneData["caveDwelling"] or princessData["caveDwelling"] then score = score + scoresAttrib["caveDwelling"] end
  765.   score = score + math.max(scoresTolerance[string.upper(droneData["temperatureTolerance"])], scoresTolerance[string.upper(princessData["temperatureTolerance"])])
  766.   score = score + math.max(scoresTolerance[string.upper(droneData["humidityTolerance"])], scoresTolerance[string.upper(princessData["humidityTolerance"])])
  767.   return score
  768. end
  769.  
  770. function printHeader()
  771.   logLine()
  772.   logLine("sl t species f spd n f c tmp hmd score ")
  773.   logLine("--|-|-------|-|---|-|-|-|---|---|------")
  774. end
  775.  
  776. -- string constants for console output
  777. toleranceString = {
  778.   ["NONE"] = "  - ",
  779.   ["UP 1"] = " +1 ",
  780.   ["UP 2"] = " +2 ",
  781.   ["UP 3"] = " +3 ",
  782.   ["UP 4"] = " +4 ",
  783.   ["UP 5"] = " +5 ",
  784.   ["DOWN 1"] = " -1 ",
  785.   ["DOWN 2"] = " -2 ",
  786.   ["DOWN 3"] = " -3 ",
  787.   ["DOWN 4"] = " -4 ",
  788.   ["DOWN 5"] = " -5 ",
  789.   ["BOTH 1"] = "+-1 ",
  790.   ["BOTH 2"] = "+-2 ",
  791.   ["BOTH 3"] = "+-3 ",
  792.   ["BOTH 4"] = "+-4 ",
  793.   ["BOTH 5"] = "+-5 "
  794. }
  795.  
  796. speedString = {
  797.   ["0.3"] = "0.3", -- Slowest
  798.   ["0.6"] = "0.6", -- Slower
  799.   ["0.8"] = "0.8", -- Slow
  800.   ["1"]   = "1.0", -- Normal
  801.   ["1.2"] = "1.2", -- Fast
  802.   ["1.4"] = "1.4", -- Faster
  803.   ["1.7"] = "1.7"  -- Fastest
  804. }
  805.  
  806. function printBee(beeData)
  807.   log(beeData["slot"] < 10 and " "..beeData["slot"].." " or beeData["slot"].." ")
  808.   -- type
  809.   log(beeData["type"] == "princess" and "P " or "D ")
  810.   -- species
  811.   log(beeData["speciesPrimary"]:gsub("bees%.species%.",""):sub(1,3)..":"..beeData["speciesSecondary"]:gsub("bees%.species%.",""):sub(1,3).." ")
  812.   -- fertility
  813.   log(tostring(beeData["fertility"]).." ")
  814.   -- speed
  815.   log(speedString[tostring(beeData["speed"])].." ")
  816.   -- nocturnal
  817.   log(beeData["nocturnal"] and "X " or "- ")
  818.   -- flyer
  819.   log(beeData["tolerantFlyer"] and "X " or "- ")
  820.   -- cave dwelling
  821.   log(beeData["caveDwelling"] and "X " or "- ")
  822.   -- temperature tolerance
  823.   log(toleranceString[string.upper(beeData["temperatureTolerance"])])
  824.   -- humidity tolerance
  825.   log(toleranceString[string.upper(beeData["humidityTolerance"])])
  826.   -- score
  827.   log(beeData.score and string.format("%5.1d", beeData.score).." " or "      ")
  828.   logLine()
  829. end
  830.  
  831. function dropExcess(droneData)
  832.   logLine("dropping excess...")
  833.   local count = 0
  834.   for i = 3, 16 do
  835.     if turtle.getItemCount(i) > 0 then
  836.       -- drop drones over 9 to clear space for newly bred bees and product
  837.       if i > 11 then
  838.         turtle.select(i)
  839.         turtle.dropDown()
  840.         droneData[i] = nil
  841.         count = count - 1
  842.       end
  843.     end
  844.   end
  845.   return droneData
  846. end
  847.  
  848. function isPurebred(princessData, droneData)
  849.   -- check if princess and drone are exactly the same and no chance for mutation
  850.   if princessData["speciesPrimary"] ~= princessData["speciesSecondary"] then
  851.     return false
  852.   end
  853.   for key, value in pairs(princessData) do
  854.     if value ~= droneData[key] and key ~= "territory" and key ~= "type" and key ~= "slot" then
  855.       return false
  856.     end
  857.   end
  858.   return true
  859. end
  860.  
  861. function getUnknown(princessData, droneData)
  862.   -- lists species that are not in the bee graph
  863.   local unknownSpecies = {}
  864.   if not bees[princessData["speciesPrimary"]] then
  865.     table.insert(unknownSpecies, princessData["speciesPrimary"])
  866.   end
  867.   if not bees[princessData["speciesSecondary"]] then
  868.     table.insert(unknownSpecies, princessData["speciesSecondary"])
  869.   end
  870.   for _, beeData in pairs(droneData) do
  871.     if not bees[beeData["speciesPrimary"]] then
  872.       table.insert(unknownSpecies, beeData["speciesPrimary"])
  873.     end
  874.     if not bees[beeData["speciesSecondary"]] then
  875.       table.insert(unknownSpecies, beeData["speciesSecondary"])
  876.     end
  877.   end
  878.   return unknownSpecies
  879. end
  880.  
  881. -- targeting -------------------------------------------------------------------
  882.  
  883. -- set species and all parents to targeted
  884. function targetBee(name)
  885.   local bee = bees[name]
  886.   if bee and not bee.targeted then
  887.     bee.targeted = true
  888.     for i, parents in ipairs(bee.mutateFrom) do
  889.       for j, parent in ipairs(parents) do
  890.         targetBee(parent)
  891.       end
  892.     end
  893.   end
  894. end
  895.  
  896. -- set bee graph entry to targeted if species was specified on the command line
  897. -- otherwise set all entries to targeted
  898. tArgs = { ... }
  899. if #tArgs > 0 then
  900.   logLine("targeting bee species:")
  901.   for i, target in ipairs(tArgs) do
  902.     targetBee(target)
  903.     for name, data in pairs(bees) do
  904.       if data.targeted and data.score > 1 then
  905.         logLine(name .. string.rep(" ", 20-#name), data.score)
  906.       end
  907.     end
  908.   end
  909. else
  910.   for _, beeData in pairs(bees) do
  911.     beeData.targeted = true
  912.   end
  913. end
  914.  
  915. -- breeding loop ---------------------------------------------------------------
  916.  
  917. logLine("Clearing system...")
  918. clearSystem()
  919. local droneData = nil
  920. while true do
  921.   princessData, droneData = analyzeBees(droneData)
  922.   if princessData then
  923.     if isPurebred(princessData, droneData[2]) then
  924.       logLine("Bees are purebred")
  925.       turtle.turnRight()
  926.       break
  927.     end
  928.     local unknownSpecies = getUnknown(princessData, droneData)
  929.     if #unknownSpecies > 0 then
  930.       logLine("Please add new species to bee graph:")
  931.       for _, species in ipairs(unknownSpecies) do
  932.         logLine("  "..species)
  933.       end
  934.       turtle.turnRight()
  935.       break
  936.     end
  937.     breedBees(1, 2)
  938.     droneData[1] = nil
  939.     droneData[2] = nil
  940.     droneData = dropExcess(droneData)
  941.   end
  942.   getBees()
  943. end
  944. logFile.close()
Add Comment
Please, Sign In to add comment