View difference between Paste ID: 2Fb1NJdV and X3ZT6F33
SHOW: | | - or go back to the newest paste.
1
	
2
3
    -- BeeAnalyzer x     
4-
	-- maybe i replace the output with simple breeding bee-bee... though it has score and is sorted now
4+
	-- dropping excess drones should retain a few of each needed type
5
	--
6
7
8
    invmod = peripheral.wrap("right")
9
	targetedSpecies = ""
10
	     
11
    -- the bee graph ---------------------------------------------------------------
12
     
13
    bees = {}
14
     
15
    function addParent(parent, offspring)
16
      if not bees[parent] then
17
        bees[parent] = {
18
          --name = parent,
19
          score = 0,
20
          mutateFrom = {}
21
        }
22
      end
23
    end
24
     
25
    function addOffspring(offspring, parentss)
26
      if bees[offspring] then
27
        for i, parents in ipairs(parentss) do
28
          table.insert(bees[offspring].mutateFrom, parents)
29
        end
30
      else
31
        bees[offspring] = {
32
          score = 0,
33
          mutateFrom = parentss
34
        }
35
      end
36
      for i, parents in ipairs(parentss) do
37
        for i, parent in ipairs(parents) do
38
          addParent(parent, offspring)
39
        end
40
      end
41
    end
42
     
43
	 
44
45
     
46
    -- produce combinations from 1 or 2 lists
47
    function choose(list, list2)
48
      local newList = {}
49
      if list2 then
50
        for i = 1, #list2 do
51
          for j = 1, #list do
52
            if list[j] ~= list[i] then
53
              table.insert(newList, {list[j], list2[i]})
54
            end
55
          end
56
        end
57
      else
58
        for i = 1, #list do
59
          for j = i, #list do
60
            if list[i] ~= list[j] then
61
              table.insert(newList, {list[i], list[j]})
62
            end
63
          end
64
        end
65
      end
66
      return newList
67
    end
68
     
69
    -- Forestry Bees ---------------------------------------------------------------
70
     
71
    -- Apis Branch
72
    addOffspring("Common", choose({"Forest", "Meadows", "Modest", "Marbled", "Tropical", "Wintry", "Marshy", "Water", "Rocky", "Embittered", "Unusual", "Mystical", "Sorcerous", "Attuned"}))
73
    addOffspring("Cultivated", choose({"Common"}, {"Forest", "Meadows", "Modest", "Marbled", "Tropical", "Wintry", "Marshy", "Water", "Rocky", "Embittered", "Unusual", "Mystical", "Sorcerous", "Attuned"}))
74
    -- Noble Branch
75
    addOffspring("Noble", {{"Cultivated", "Common"}})
76
    addOffspring("Majestic", {{"Noble", "Cultivated"}})
77
    addOffspring("Imperial", {{"Majestic", "Noble"}})
78
    -- Industrious Branch
79
    addOffspring("Diligent", {{"Cultivated", "Common"}})
80
    addOffspring("Unweary", {{"Diligent", "Cultivated"}})
81
    addOffspring("Industrious", {{"Unweary", "Diligent"}})
82
    -- Heroic Branch
83
    addOffspring("Heroic", {{"Steadfast", "Valiant"}})
84
    -- Infernal Branch
85
    addOffspring("Sinister", {{"Cultivated", "Modest"}, {"Cultivated", "Tropical"}})
86
    addOffspring("Fiendish", {{"Sinister", "Cultivated"}, {"Sinister", "Modest"}, {"Sinister", "Tropical"}})
87
    addOffspring("Demonic", {{"Fiendish", "Sinister"}})
88
    -- Austere Branch
89
    addOffspring("Frugal", {{"Sinister", "Modest"}, {"Fiendish", "Modest"}})
90
    addOffspring("Austere", {{"Frugal", "Modest"}})
91
	
92
    -- Tropical Branch
93
    addOffspring("Exotic", {{"Austere", "Tropical"}})
94
    addOffspring("Edenic", {{"Exotic", "Tropical"}})
95
	
96
    -- Frozen Branch
97
    addOffspring("Icy", {{"Industrious", "Wintry"}})
98
    addOffspring("Glacial", {{"Icy", "Wintry"}})
99
    addOffspring("Frigid", {{"Diligent", "Wintry"}})
100
    addOffspring("Absolute", {{"Frigid", "Ocean"}})
101
    -- Festive Branch
102
    addOffspring("Celebratory", {{"Austere", "Excited"}})
103
    addOffspring("Leporine", {{"Meadows", "Forest"}})
104
    addOffspring("Merry", {{"Wintry", "Forest"}})
105
    addOffspring("Tipsy", {{"Wintry", "Meadows"}})
106
107
    -- Agrarian Branch
108
    addOffspring("Rural", {{"Diligent", "Meadows"}})
109
    addOffspring("Farmed", {{"Rural", "Cultivated"}})
110
	
111
    -- Boggy Branch
112
    addOffspring("Swamp", {{"Common", "Marshy"}})
113
    addOffspring("Boggy", {{"Swamp", "Marshy"}})
114
    addOffspring("Fungal", {{"Boggy", "Swamp"}})
115
		
116
    -- Agricultural Branch
117
    addOffspring("Fermented", {{"Rural", "Fruity"}})
118
    addOffspring("Bovine", {{"Rural", "Water"}})
119
    addOffspring("Caffeine", {{"Rural", "Tropical"}})
120
    addOffspring("Citrus", {{"Farmed", "Modest"}})
121
    addOffspring("Minty", {{"Farmed", "Tropical"}})
122
	
123
    -- Barren Branch
124
    addOffspring("Arid", {{"Meadows", "Modest"}})
125
    addOffspring("Barren", {{"Arid", "Common"}})
126
    addOffspring("Desolate", {{"Barren", "Arid"}})
127
128
	
129
    -- Hostile Branch
130
    addOffspring("Skeletal", {{"Desolate", "Frugal"}})
131
    addOffspring("Decaying", {{"Desolate", "Modest"}})
132
    addOffspring("Creepy", {{"Desolate", "Austere"}})
133
    -- Rocky Branch
134
    addOffspring("Tolerant", {{"Diligent", "Rocky"}})
135
    addOffspring("Hardy", {{"Tolerant", "Rocky"}})
136
    addOffspring("Resilient", {{"Hardy", "Tolerant"}})
137
	
138
    -- Rusty Branch
139
    addOffspring("Rusty", {{"Resilient", "Diligent"}})
140
    addOffspring("Corroded", {{"Resilient", "Diligent"}})
141
    addOffspring("Tarnished", {{"Resilient", "Diligent"}})
142
    addOffspring("Leaden", {{"Resilient", "Unweary"}})
143
144
	
145
    -- Metallic Branch
146
    addOffspring("Lustered", {{"Resilient", "Unweary"}})
147
    addOffspring("Galvanized", {{"Tarnished", "Cultivated"}})
148
    addOffspring("Invincible", {{"Resilient", "Ender"}})
149
	
150
    -- Alloyed Branch
151
    addOffspring("Impregnable", {{"Resilient", "Noble"}})
152
    addOffspring("Resolute", {{"Corroded", "Tarnished"}})
153
    addOffspring("Brazen", {{"Corroded", "Galvanized"}})
154
    addOffspring("Fortified", {{"Rusty", "Fossiled"}})
155
    addOffspring("Lustrous", {{"Resilient", "Imperial"}})
156
157
    -- Precious Branch
158
    addOffspring("Shining", {{"Rusty", "Noble"}})
159
    addOffspring("Glittering", {{"Resolute", "Noble"}})
160
    addOffspring("Precious", {{"Glittering", "Shining"}})
161
    addOffspring("Valuable", {{"Glittering", "Ender"}})
162
163
	-- Mineral Branch
164
    addOffspring("Lapis", {{"Resilient", "Water"}})
165
    addOffspring("Sodalite", {{"Lapis", "Diligent"}})
166
    addOffspring("Pyrite", {{"Rusty", "Sinister"}})
167
    addOffspring("Bauxite", {{"Resilient", "Diligent"}})
168
    addOffspring("Cinnabar", {{"Resilient", "Sinister"}})
169
    addOffspring("Sphalerite", {{"Tarnished", "Sinister"}})
170
171
    -- Gemstone Branch
172
    addOffspring("Emerald", {{"Lapis", "Noble"}})
173
    addOffspring("Ruby", {{"Emerald", "Austere"}})
174
    addOffspring("Sapphire", {{"Emerald", "Ocean"}})
175
    addOffspring("Olivine", {{"Emerald", "Ender"}})
176
    addOffspring("Diamond", {{"Sapphire", "Imperial"}})
177
	
178
    -- Nuclear Branch
179
    addOffspring("Unstable", {{"Austere", "Rocky"}})
180
    addOffspring("Nuclear", {{"Unstable", "Rusty"}})
181
    addOffspring("Radioactive", {{"Nuclear", "Glittering"}})
182
    -- Historic Branch
183
    addOffspring("Ancient", {{"Noble", "Diligent"}})
184
    addOffspring("Primeval", {{"Ancient", "Noble"}})
185
    addOffspring("Prehistoric", {{"Primeval", "Majestic"}})
186
    addOffspring("Relic", {{"Prehistoric", "Imperial"}})
187
	
188
    -- Fossilized
189
    addOffspring("Fossiled", {{"Primeval", "Forest"}})
190
    addOffspring("Oily", {{"Primeval", "Modest"}})
191
    addOffspring("Preserved", {{"Primeval", "Boggy"}})
192
    addOffspring("Resinous", {{"Primeval", "Marshy"}})
193
194
    -- Refined Branch
195
    addOffspring("Distilled", {{"Oily", "Industrious"}})
196
    addOffspring("Refined", {{"Distilled", "Oily"}})
197
    addOffspring("Elastic", {{"Refined", "Resinous"}})
198
    addOffspring("Tarry", {{"Refined", "Fossiled"}})
199
200
	
201
    -- Aquatic Branch
202
    addOffspring("River", {{"Common", "Water"}})
203
    addOffspring("Ocean", {{"Common", "Water"}})
204
    addOffspring("Stained", {{"Ocean", "Water"}})
205
206
	
207
    -- Saccharine Branch
208
    addOffspring("Sweetened", {{"Diligent", "Tropical"}})
209
    addOffspring("Sugary", {{"Sweetened", "Diligent"}})
210
    addOffspring("Fruity", {{"Sugary", "Forest"}})
211
	
212
	
213
    -- Volcanic Branch
214
    addOffspring("Angry", {{"Sinister", "Embittered"}})
215
    addOffspring("Furious", {{"Angry", "Embittered"}})
216
    addOffspring("Volcanic", {{"Furious", "Angry"}})
217
    addOffspring("Glowering", {{"Excited", "Angry"}})
218
219
	
220
    -- Viscous Branch
221
    addOffspring("Viscous", {{"Exotic", "Water"}})
222
    addOffspring("Glutinous", {{"Viscous", "Exotic"}})
223
    addOffspring("Sticky", {{"Glutinous", "Viscous"}})
224
	
225
    -- Virulent Branch
226
    addOffspring("Malicious", {{"Sinister", "Tropical"}})
227
    addOffspring("Infectious", {{"Malicious", "Tropical"}})
228
    addOffspring("Virulent", {{"Infectious", "Malicious"}})
229
	
230
    -- Caustic Branch
231
    addOffspring("Corrosive", {{"Virulent", "Sticky"}})
232
    addOffspring("Caustic", {{"Corrosive", "Fiendish"}})
233
    addOffspring("Acidic", {{"Caustic", "Corrosive"}})
234
235
	
236
    -- Energetic Branch
237
    addOffspring("Excited", {{"Cultivated", "Valiant"}})
238
    addOffspring("Energetic", {{"Excited", "Valiant"}})
239
    addOffspring("Ecstatic", {{"Energetic", "Excited"}})
240
241
242
    -- Shadow Branch
243
    addOffspring("Shadowed", {{"Rocky", "Furious"}})
244
    addOffspring("Darkened", {{"Shadowed", "Embittered"}})
245
    addOffspring("Abyssmal", {{"Darkened", "Shadowed"}})
246
     
247
    -- Primary Branch
248
    addOffspring("Bleached", {{"Wintry", "Valiant"}})
249
    addOffspring("Ebony", {{"Rocky", "Valiant"}})
250
    addOffspring("Maroon", {{"Forest", "Valiant"}})
251
    addOffspring("Natural", {{"Tropical", "Valiant"}})
252
    addOffspring("Prussian", {{"Water", "Valiant"}})
253
    addOffspring("Saffron", {{"Meadows", "Valiant"}})
254
    addOffspring("Sepia", {{"Marshy", "Valiant"}})
255
    -- Secondary Branch
256
    addOffspring("Amber", {{"Maroon", "Saffron"}})
257
    addOffspring("Azure", {{"Prussian", "Bleached"}})
258
    addOffspring("Indigo", {{"Maroon", "Prussian"}})
259
    addOffspring("Lavender", {{"Maroon", "Bleached"}})
260
    addOffspring("Lime", {{"Natural", "Bleached"}})
261
    addOffspring("Slate", {{"Ebony", "Bleached"}})
262
    addOffspring("Turquoise", {{"Natural", "Prussian"}})
263
    -- Tertiary Branch
264
    addOffspring("Ashen", {{"Slate", "Bleached"}})
265
    addOffspring("Fuchsia", {{"Indigo", "Lavender"}})
266
     
267
268
	 -- hungry,confused,forestry,wooden branch
269
270
    addOffspring("Hungry", {{"Arid", "Rural"}})
271
    addOffspring("Starved", {{"Barren", "Hungry"}})
272
    addOffspring("Ravenous", {{"Hungry", "Starved"}})
273
    addOffspring("Dazed", {{"Arid", "Edenic"}})
274
    addOffspring("Irrational", {{"Barren", "Dazed"}})
275
    addOffspring("Delirious", {{"Dazed", "Irrational"}})
276
    addOffspring("Pulped", {{"Unweary", "Forest"}})
277
    addOffspring("Spoiled", {{"Pulped", "Decaying"}})
278
    addOffspring("Decomposed", {{"Pulped", "Decaying"}})
279
    addOffspring("Wooden", {{"Diligent", "Forest"}})
280
    addOffspring("Lumbered", {{"Diligent", "Wooden"}})
281
    addOffspring("Timbered", {{"Wooden", "Lumbered"}})
282
	
283
    -- Beastly Branch
284
    addOffspring("Jaded", {{"Ender", "Relic"}})
285
286
     
287
    -- Magic Bees ------------------------------------------------------------------
288
     
289
    -- Arcane Branch
290
    addOffspring("Esoteric", {{"Imperial", "Demonic"}, {"Heroic", "Demonic"}})	
291
    addOffspring("Mysterious", {{"Ender", "Esoteric"}})
292
    addOffspring("Arcane", {{"Mysterious", "Esoteric"}})
293
	
294
    -- Supernatural Branch
295
    addOffspring("Charmed", {{"Diligent", "Valiant"}})
296
    addOffspring("Enchanted", {{"Valiant", "Charmed"}})
297
    addOffspring("Supernatural", {{"Enchanted", "Charmed"}})
298
    -- Scholarly Branch
299
    addOffspring("Pupil", {{"Arcane", "Enchanted"}})
300
    addOffspring("Scholarly", {{"Arcane", "Pupil"}})
301
    addOffspring("Savant", {{"Scholarly", "Pupil"}})
302
303
	
304
    -- Thaumic Branch
305
    addOffspring("Stark", {{"Arcane", "Supernatural"}})
306
307
308
    -- Skulking Branch
309
    addOffspring("Skulking", {{"Mysterious", "Modest"}, {"Mysterious", "Desolate"}})	
310
    addOffspring("Brainy", {{"Skulking", "Sinister"}})		
311
    addOffspring("Gossamer", {{"Skulking", "Supernatural"}, {"Skulking", "Ancient"}})	
312
    addOffspring("Wispy", {{"Gossamer", "Cultivated"}})	
313
    addOffspring("Batty", {{"Skulking", "Frugal"}, {"Skulking", "Rocky"}})	
314
    addOffspring("Ghastly", {{"Skulking", "Austere"}, {"Skulking", "Creepy"}})	
315
316
		
317
    addOffspring("Aware", {{"Demonic", "Edenic"}})			
318
    addOffspring("Vis", {{"Aware", "Arcane"}, {"Aware", "Stark"}})		
319
    addOffspring("Pure", {{"Vis", "Edenic"}})			
320
    addOffspring("Flux", {{"Vis", "Edenic"}})			
321
    addOffspring("Node", {{"Pure", "Flux"}})			
322
    addOffspring("Rejuvenating", {{"Vis", "Energetic"}})			
323
    addOffspring("Timely", {{"Industrious", "Enchanted"}})			
324
    addOffspring("Lordly", {{"Timely", "Imperial"}})			
325
    addOffspring("Doctoral", {{"Timely", "Lordly"}})			
326
    addOffspring("Spirit", {{"Fiendish", "Enchanted"}, {"Fiendish", "Ender"}})		
327
    addOffspring("Soul", {{"Fiendish", "Spirit"}})			
328
    addOffspring("Minium", {{"Sinister", "Mysterious"}, {"Frugal", "Pupil"}})			
329
    addOffspring("Iron", {{"Industrious", "Diligent"}})			
330
    addOffspring("Gold", {{"Minium", "Lead"}})		
331
332
			
333
    addOffspring("Copper", {{"Industrious", "Meadows"}})				
334
    addOffspring("Tin", {{"Industrious", "Forest"}})				
335
    addOffspring("Silver", {{"Imperial", "Modest"}})				
336
    addOffspring("Lead", {{"Industrious", "Copper"}, {"Industrious", "Tin"}, {"Industrious", "Common"}})			
337
    addOffspring("Diamond", {{"Austere", "Gold"}})				
338
    addOffspring("Emerald", {{"Austere", "Silver"}})				
339
    addOffspring("Poultry", {{"Common", "Skulking"}})				
340
    addOffspring("Beefy", {{"Common", "Skulking"}})				
341
    addOffspring("Porcine", {{"Common", "Skulking"}})	
342
343
344
     
345
    -- logging ---------------------------------------------------------------------
346
     
347
    local logFile = fs.open("bee.log", "w")
348
    function log(msg)
349
      msg = msg or ""
350
      logFile.write(tostring(msg))
351
      logFile.flush()
352
      io.write(msg)
353
    end
354
    function logLine(msg)
355
      msg = msg or ""
356
      logFile.write(msg.."\n")
357
      logFile.flush()
358
      io.write(msg.."\n")
359
    end
360
     
361
    -- analyzing functions ---------------------------------------------------------
362
     
363
    -- Fix for some versions returning bees.species.*
364
    function fixName(name)
365
      return name:gsub("bees%.species%.",""):gsub("^.", string.upper)
366
    end
367
     
368
    function clearSystem()
369
      -- orient turtle
370
      while true do
371
        local p = peripheral.wrap("front")
372
        if p and p.isBee then
373
          break
374
        end
375
        turtle.turnRight()
376
      end
377
      -- clear out analyzer
378
      turtle.turnLeft()
379
      while turtle.suckUp() do end
380
      -- clear out beealyzer
381
      turtle.turnRight()
382
      turtle.suck()
383
      -- clear out apiary
384
      turtle.turnRight()
385
      while turtle.suck() do end
386
    end
387
     
388
    function getBees()
389
      -- get bees from apiary
390
      log("waiting for bees.")
391
      turtle.select(1)
392
      while not turtle.suck() do
393
        sleep(10)
394
        log(".")
395
      end
396
      log("*")
397
      while turtle.suck() do
398
        log("*")
399
      end
400
      logLine()
401
    end
402
     
403
    function countBees()
404
      -- spread dups and fill gaps
405
      local count = 0
406
      for i = 1, 16 do
407
        local slotCount = turtle.getItemCount(i)
408
        if slotCount == 1 then
409
          for j = 1, i-1 do
410
            if turtle.getItemCount(j) == 0 then
411
              turtle.select(i)
412
              turtle.transferTo(j)
413
              break
414
            end
415
          end
416
          count = count + 1
417
        elseif slotCount > 1 then
418
          for j = 2, slotCount do
419
            turtle.select(i)
420
            for k = 1, 16 do
421
              if turtle.getItemCount(k) == 0 then
422
                turtle.transferTo(k, 1)
423
              end
424
            end
425
          end
426
          if turtle.getItemCount(i) > 1 then
427
            turtle.dropDown(turtle.getItemCount(i)-1)
428
          end
429
        end
430
      end
431
      return count
432
    end
433
     
434
    function breedBees(princessSlot, droneSlot)
435
       turtle.select(princessSlot)
436
       invmod.dropSneaky(1)
437
       turtle.select(droneSlot)
438
       invmod.dropSneaky(0)
439
    end
440
     
441
    function ditchProduct()  
442
      print("ditching product...")
443
      turtle.turnLeft()
444
      m = peripheral.wrap("front")
445
      for i = 1, 16 do
446
        if turtle.getItemCount(i) > 0 then
447
          turtle.select(i)
448
          turtle.drop()
449
          if not m.isBee() then
450
            turtle.suck()
451
            turtle.dropDown()
452
          else
453
            turtle.suck()
454
          end
455
        end
456
      end
457
      turtle.turnRight()
458
    end
459
     
460
    function scanBees()
461
      log("scanning bees")
462
      turtle.turnLeft()
463
      turtle.turnLeft()
464
      for i = 1, 16 do
465
        if turtle.getItemCount(i) > 0 then
466
          log(".")
467
          turtle.select(i)
468
          invmod.dropSneakyUp(2)
469
          while not turtle.suckUp() do
470
            sleep(1)
471
          end
472
        end
473
      end
474
      logLine()
475
      turtle.turnRight()
476
      turtle.turnRight()
477
    end
478
     
479
    function swapBee(slot1, slot2, freeSlot)
480
      turtle.select(slot1)
481
      turtle.transferTo(freeSlot)
482
      turtle.select(slot2)
483
      turtle.transferTo(slot1)
484
      turtle.select(freeSlot)
485
      turtle.transferTo(slot2)
486
    end  
487
     
488
--if princess has no scored offspring (mutated) ... maybewe want to breed with the highest scored drone (droneScore)
489
--find the highest drone bee we have, find what we need to breed with it
490
--if we have that drone, breed princess with that drone
491
--else find the highest we have in that tree, and repeat
492
--if we dont have any then exit with needbee: bee (tree)
493
494
495
--returns which drone is highest parent for species, or species if available
496
function findAvailableParent(species, droneData)
497
	local droneIndex = 0
498
	local droneScore = 99999
499
500
	for i = 2, 16 do
501
		if droneData[i] then
502
			if droneData[i]["speciesPrimary"] == species or droneData[i]["speciesSecondary"] == species then
503
				droneIndex = i
504
				droneScore = bees[species].score
505
				return droneIndex, droneScore
506
			end
507
		end
508
	end
509
	
510
	for i, parents in ipairs(bees[species].mutateFrom) do
511
		index, score = findAvailableParent(parents[1], droneData)
512
		if score < droneScore then
513
			droneIndex = index
514
			droneScore = score
515
		end
516
		index, score = findAvailableParent(parents[2], droneData)
517
		if score < droneScore then
518
			droneIndex = index
519
			droneScore = score
520
		end
521
	end
522
	if droneScore == 99999 then
523
		logLine("Missing bee species: " .. species)
524
	end
525
	return droneIndex, droneScore
526
end
527
528
function analyzeBees()
529
530
	logLine("analyzing bees...")
531
	local freeSlot
532
	local princessSlot
533
	local princessData
534
	local droneData = {}
535
	turtle.turnLeft()
536
	local beealyzer = peripheral.wrap("front")
537
538
	for i = 1, 16 do
539
		if turtle.getItemCount(i) > 0 then
540
			turtle.select(i)
541
			turtle.drop()
542
			local beeData = beealyzer.analyze()        
543
			turtle.suck()
544
			if not beeData["speciesPrimary"] then
545
				print("Bee "..i.." not correctly analyzed")
546
			else
547
				beeData["speciesPrimary"] = fixName(beeData["speciesPrimary"])
548
				beeData["speciesSecondary"] = fixName(beeData["speciesSecondary"])
549
				if beeData["type"] == "princess" then
550
					princessData = beeData
551
					princessSlot = i
552
				else
553
					droneData[i] = beeData
554
				end
555
			end
556
		else
557
			freeSlot = i
558
		end
559
	end
560
561
	if princessData then
562
		if princessSlot ~= 1 then
563
			swapBee(1, princessSlot, freeSlot)
564
			droneData[princessSlot] = droneData[1]
565
			droneData[1] = nil
566
			princessSlot = 1
567
		end
568
569
		-- bubble sort drones
570
		print("sorting drones...")
571
		for i = 2, 16 do
572
			if turtle.getItemCount(i) > 0 and droneData[i] then
573
				droneData[i].score = scoreBee(princessData, droneData[i])
574
				for j = i - 1, 2, -1 do
575
					if droneData[j+1].score > droneData[j].score then
576
						swapBee(j+1, j, freeSlot)
577
						droneData[j+1], droneData[j] = droneData[j], droneData[j+1]
578
					end
579
				end
580
			end
581
		end
582
583
		if droneData[2] and droneData[2].score < 1 then
584
			--no breeding combos found for this princess
585
			i, j = findAvailableParent(targetedSpecies, droneData)
586
587
			if j == 99999 then
588
				droneData[2].score = 0
589
			else
590
				swapBee(2, i, freeSlot)
591
				droneData[2], droneData[i] = droneData[i], droneData[2]
592
			end
593
		end
594
595
		printHeader()
596
		princessData.slot = 1
597
		printBee(princessData)
598
		for i = 2, 16 do
599
			if droneData[i] then
600
				droneData[i].slot = i
601
				printBee(droneData[i])
602
			end
603
		end
604
	end
605
	logLine()
606
	turtle.turnRight()
607
	return princessData, droneData
608
end
609
     
610
611
612
--if drone score is 9999 return 9999 or 10k for pure
613
--find offspring for this combo, return highest scoring offspring ... for each bee, if its cerated from these get its score
614
615
616
function scoreBee(princessData, droneData)
617
618
	local droneSpecies = {droneData["speciesPrimary"], droneData["speciesSecondary"]}
619
	local princessSpecies = {princessData["speciesPrimary"], princessData["speciesSecondary"]}
620
	  
621
	if bees[droneSpecies[1]].score == 9999 and bees[droneSpecies[2]].score == 9999 then
622
		return 10000
623
	end
624
	if bees[droneSpecies[1]].score == 9999 or bees[droneSpecies[2]].score == 9999 then
625
		return 9999
626
	end
627
628
	local droneScore = 0
629
	
630
	for name, beeData in pairs(bees) do
631
		if beeData.score > droneScore then
632
			for i, parents in ipairs(beeData.mutateFrom) do
633
				if princessSpecies[1] == parents[1] or princessSpecies[2] == parents[1] then
634
					if droneSpecies[1] == parents[2] and droneSpecies[2] == parents[2] then
635-
						droneScore = beeData.score + 1
635+
						if princessSpecies[1] == princessSpecies[2] then
636
							droneScore = beeData.score + 2
637
						else
638
							droneScore = beeData.score + 1
639
						end
640
						break
641
					end
642
					if ((droneSpecies[1] == parents[1] and droneSpecies[2] == parents[2]) or (droneSpecies[2] == parents[1] and droneSpecies[1] == parents[2]))
643
						and	((princessSpecies[1] == parents[1] and princessSpecies[2] == parents[2]) or (princessSpecies[2] == parents[1] and princessSpecies[1] == parents[2])) then
644
						
645-
						droneScore = beeData.score + 1
645+
						droneScore = beeData.score + 2
646
						break
647
					end
648
					if droneSpecies[1] == parents[2] or droneSpecies[2] == parents[2] then
649
						droneScore = beeData.score
650
						break
651
					end
652
				end
653
				if princessSpecies[1] == parents[2] or princessSpecies[2] == parents[2] then
654
					if droneSpecies[1] == parents[1] and droneSpecies[2] == parents[1] then
655
						if princessSpecies[1] == princessSpecies[2] then
656
							droneScore = beeData.score + 2
657
						else
658
							droneScore = beeData.score + 1
659
						end
660
						break
661
					end
662
					if ((droneSpecies[1] == parents[1] and droneSpecies[2] == parents[2]) or (droneSpecies[2] == parents[1] and droneSpecies[1] == parents[2]))
663
						and	((princessSpecies[1] == parents[1] and princessSpecies[2] == parents[2]) or (princessSpecies[2] == parents[1] and princessSpecies[1] == parents[2])) then
664
						
665
						droneScore = beeData.score + 2
666
						break
667
					end
668
					if droneSpecies[1] == parents[1] or droneSpecies[2] == parents[1] then
669
						droneScore = beeData.score
670
						break
671
					end
672
				end
673
			end
674
		end
675
	end
676
677
	return droneScore
678
end
679
     
680
    function printHeader()
681
      logLine()
682
      logLine("typ species f spd d n f c tmp hmd score")
683
      logLine("-|-|-------|-|---|-|-|-|-|---|---|-----")
684
    end
685
     
686
    toleranceString = {
687
      ["NONE"] = "    ",
688
      ["UP_1"] = " +1 ",
689
      ["UP_2"] = " +2 ",
690
      ["UP_3"] = " +3 ",
691
      ["DOWN_1"] = " -1 ",
692
      ["DOWN_2"] = " -2 ",
693
      ["DOWN_3"] = " -3 ",
694
      ["BOTH_1"] = "+-1 ",
695
      ["BOTH_2"] = "+-2 ",
696
      ["BOTH_3"] = "+-3 "
697
    }
698
    function printBee(beeData)
699
      log(beeData["slot"] < 10 and beeData["slot"].." " or beeData["slot"])
700
      if (beeData["type"] == "princess") then
701
        log("P ")
702
      else
703
        log("d ")
704
      end
705
      log(beeData["speciesPrimary"]:gsub("bees%.species%.",""):sub(1,3)..":"..beeData["speciesSecondary"]:gsub("bees%.species%.",""):sub(1,3).." ")
706
      log(tostring(beeData["fertility"]).." ")
707
      log(beeData["speed"] == 1 and "1.0 " or tostring(beeData["speed"]).." ")
708
      if beeData["diurnal"] then
709
        log("d ")
710
      else
711
        log("  ")
712
      end
713
      if beeData["nocturnal"] then
714
        log("n ")
715
      else
716
        log("  ")
717
      end
718
      if beeData["tolerantFlyer"] then
719
        log("f ")
720
      else
721
        log("  ")
722
      end
723
      if beeData["caveDwelling"] then
724
        log("c ")
725
      else
726
        log("  ")
727
      end
728
      log(toleranceString[beeData["toleranceTemperature"]])
729
      log(toleranceString[beeData["toleranceHumidity"]])
730
      if beeData.score then
731
        logLine(string.format("%5.1d", beeData.score).." ")
732
      else
733
        logLine()
734
      end
735
    end
736
     
737
    function dropExcess(droneData)
738
      print("dropping excess...")
739
      local count = 0
740
      for i = 1, 16 do
741
        if turtle.getItemCount(i) > 0 then
742
          count = count + 1
743
          
744
          -- drop drones over 9 to clear space for newly bred bees and product
745
          if count > 9 then
746
            turtle.select(i)
747
            turtle.dropDown()
748
            count = count - 1
749
          end
750
        end
751
      end  
752
    end
753
     
754
    function isPurebred(princessData, droneData)
755
      -- check if princess and drone are exactly the same and no chance for mutation
756
      if princessData["speciesPrimary"] ~= princessData["speciesSecondary"] then
757
        return false
758
      end
759
      for key, value in pairs(princessData) do
760
        if value ~= droneData[key] and key ~= "territory" and key ~= "type" and key ~= "slot" then
761
          return false
762
        end
763
      end
764
      return true
765
    end
766
     
767
    function getUnknown(princessData, droneData)
768
      -- lists species that are not in the bee graph
769
      local unknownSpecies = {}
770
      if not bees[princessData["speciesPrimary"]] then
771-
		if bees[parents[1]].score < bees[name].score - 2 then
771+
772-
			bees[parents[1]].score = bees[name].score - 2
772+
773
      if not bees[princessData["speciesSecondary"]] then
774
        table.insert(unknownSpecies, princessData["speciesSecondary"])
775-
		if bees[parents[2]].score < bees[name].score - 2 then
775+
776-
			bees[parents[2]].score = bees[name].score - 2
776+
777
        if not bees[beeData["speciesPrimary"]] then
778
          table.insert(unknownSpecies, beeData["speciesPrimary"])
779
        end
780
        if not bees[beeData["speciesSecondary"]] then
781
          table.insert(unknownSpecies, beeData["speciesSecondary"])
782
        end
783
      end
784
      return unknownSpecies
785
    end
786
     
787
788
function scoreBeesIterate(name)
789
	
790
	for i, parents in ipairs(bees[name].mutateFrom) do
791
		if bees[parents[1]].score < bees[name].score - 4 then
792
			bees[parents[1]].score = bees[name].score - 4
793
			scoreBeesIterate(parents[1])
794
		end
795
		if bees[parents[2]].score < bees[name].score - 4 then
796
			bees[parents[2]].score = bees[name].score - 4
797
			scoreBeesIterate(parents[2])
798
		end
799
	end
800
end
801
802
-- program begins, read input---------------------------------------------------
803
804
tArgs = { ... }
805
if #tArgs > 0 then
806
807
	logLine("targeting bee species:")
808
	for i, target in ipairs(tArgs) do
809
		targetedSpecies = target
810
		bees[target].score = 9999
811
		for name, data in pairs(bees) do
812
			if data.score > 1 then
813
				logLine(name .. string.rep(" ", 20-#name), data.score)
814
			end
815
		end
816
	end
817
	  
818
	for name, beeData in pairs(bees) do
819
		if beeData.score == 9999 then
820
			scoreBeesIterate(name)			
821
		end
822
	end
823
else
824
	logLine("Usage Bee [species]")
825
	logFile.close()
826
	return false
827
end
828
     
829
-- breeding loop ---------------------------------------------------------------
830
     
831
logLine("Clearing system...")
832
clearSystem()
833
while true do
834
835
	ditchProduct()
836
	countBees()
837
	scanBees()
838
	princessData, droneData = analyzeBees()
839
840
	if droneData[2].score == 0 then --analyze failed to find a breeding pair
841
		break
842
	end
843
844
	if princessData then
845
846
		if isPurebred(princessData, droneData[2]) then
847
			logLine("Bees are purebred")
848
			turtle.turnRight()
849
			break
850
		end
851
852
		local unknownSpecies = getUnknown(princessData, droneData)
853
		if #unknownSpecies > 0 then
854
			logLine("Please add new species to bee graph:")
855
			for _, species in ipairs(unknownSpecies) do
856
				logLine("  "..species)
857
			end
858
			turtle.turnRight()
859
			break
860
		end
861
862
		breedBees(1, 2)
863
		dropExcess(droneData)
864
	end
865
866
	getBees()
867
	if redstone.getInput("right") then logLine("Execution ended by user.") break end
868
end
869
logFile.close()