View difference between Paste ID: 080KjTXP and Y6KJagKj
SHOW: | | - or go back to the newest paste.
1
SLOT_CROPS = 1
2
SLOT_ANALYSER = 2
3
SLOT_SEEDS = 3
4
5
ACTIVATOR_PULSE_DURATION = 1	
6
7
-- Interval at which the turtle checks if a plant has matured (in seconds)
8
MATURE_SLEEP_DURATION = 5
9
SPREAD_SLEEP_DURATION = 5
10
ANALYSE_SLEEP_DURATION = 1 -- interval for which to check if analyse process is finsished
11
12
-- If "true", excess non-10/10/10 seeds will get trashed
13
TRASH_EXCESS_SEEDS = true
14
15
-- the seed analyser uses absolute facing directions, adjust these depending on your setup
16
ANALYSER_LOWER_FACE = "WEST"
17
ANALYSER_UPPER_FACE = "EAST"
18
19
STATE_NORMAL = "normal"
20
STATE_ALTERNATE = "alternate" 
21
22
CROP_LOWER_RIGHT = { x = 2, y = 1 }
23
CROP_LOWER_LEFT = { x = 1, y = 1 }
24
CROP_UPPER_RIGHT = { x = 2, y = 2 }
25
CROP_UPPER_LEFT = { x = 1, y = 2 }
26
27
ANALYSER_LOWER_RIGHT = { x = 2, y = 0 }
28
ANALYSER_LOWER_LEFT = { x = 1, y = 0 }
29
ANALYSER_UPPER_RIGHT = { x = 2, y = 3 }
30
ANALYSER_UPPER_LEFT = { x = 1, y = 3 }
31
32
ACTIVATOR_LOWER_RIGHT = { x = 3, y = 1 }
33
ACTIVATOR_LOWER_LEFT = { x = 0, y = 1 }
34
ACTIVATOR_UPPER_RIGHT = { x = 3, y = 2 }
35
ACTIVATOR_UPPER_LEFT = { x = 0, y = 2 }
36
37
ANALYSER_MAIN = { x = 2, y = -1 }
38
CHEST = { x = 1, y = -1 }
39
TRASH = { x = 3, y = -1 }
40
41
LOWER_RIGHT = {
42
  crop = CROP_LOWER_RIGHT,
43
  analyser = ANALYSER_LOWER_RIGHT,
44
  analyserFace = ANALYSER_LOWER_FACE,
45
  activator = ACTIVATOR_LOWER_RIGHT
46
}
47
48
LOWER_LEFT = {
49
  crop = CROP_LOWER_LEFT,
50
  analyser = ANALYSER_LOWER_LEFT,
51
  analyserFace = ANALYSER_LOWER_FACE,
52
  activator = ACTIVATOR_LOWER_LEFT
53
}
54
55
UPPER_RIGHT = {
56
  crop = CROP_UPPER_RIGHT,
57
  analyser = ANALYSER_UPPER_RIGHT,
58
  analyserFace = ANALYSER_UPPER_FACE,
59
  activator = ACTIVATOR_UPPER_RIGHT
60
}
61
62
UPPER_LEFT = {
63
  crop = CROP_UPPER_LEFT,
64
  analyser = ANALYSER_UPPER_LEFT,
65
  analyserFace = ANALYSER_UPPER_FACE,
66
  activator = ACTIVATOR_UPPER_LEFT
67
}
68
69
POS_Y = 1
70
POS_X = 2
71
NEG_Y = 3
72
NEG_X = 4
73
74
currentFace = POS_Y
75
currentPos = { x = 1, y = -1 } -- same as the chest
76
currentState = STATE_NORMAL
77
78
STATES = {
79
  normal = { LOWER_RIGHT, UPPER_LEFT },
80
  alternate = { LOWER_LEFT, UPPER_RIGHT }
81
}
82
83
--
84
-- State management
85
--
86
function flipCurrentState()
87
  if currentState == STATE_NORMAL then
88
    currentState = STATE_ALTERNATE
89
  else
90
    currentState = STATE_NORMAL
91
  end
92
end
93
94
function currentField1()
95
  return STATES[currentState][1]
96
end
97
98
function currentField2()
99
  return STATES[currentState][2]
100
end
101
102
function oppositeState()
103
  return currentState == STATE_NORMAL and STATE_ALTERNATE or STATE_NORMAL
104
end
105
106
function oppositeField1()
107
  return STATES[oppositeState()][1]
108
end
109
110
function oppositeField2()
111
  return STATES[oppositeState()][2]
112
end
113
114
--
115
-- Movement and orientation
116
--
117
function turnLeft()
118
  turtle.turnLeft()
119
  currentFace = currentFace - 1
120
  if currentFace < POS_Y then
121
    currentFace = NEG_X
122
  end
123
end
124
125
function turnRight()
126
  turtle.turnRight()
127
  currentFace = currentFace + 1
128
  if currentFace > NEG_X then
129
    currentFace = POS_Y
130
  end
131
end
132
133
function turnToFace(face)
134
  local diff = currentFace - face
135
  if diff == 0 then
136
    return
137
  end
138
139
  if math.abs(diff) == 2 then
140
    turnLeft()
141
    turnLeft()
142
  elseif diff == 1 or diff == -3 then
143
    turnLeft()
144
  elseif diff == -1 or diff == 3 then
145
    turnRight()
146
  else
147
    error("Invalid difference: " + diff)
148
  end
149
end
150
151
function moveForward(times)
152
  while times > 0 do
153
    turtle.forward()
154
    adjustCurrentPos()
155
    times = times - 1
156
  end
157
end
158
159
function adjustCurrentPos()
160
  if currentFace == POS_Y then
161
    currentPos.y = currentPos.y + 1
162
  elseif currentFace == POS_X then
163
    currentPos.x = currentPos.x + 1
164
  elseif currentFace == NEG_Y then
165
    currentPos.y = currentPos.y - 1
166
  elseif currentFace == NEG_X then
167
    currentPos.x = currentPos.x - 1
168
  else
169
    error("Invald face: " + currentFace)
170
  end
171
end
172
173
function moveTo(pos)
174
  local diffx = currentPos.x - pos.x
175
  local diffy = currentPos.y - pos.y
176
  local facex = diffx > 0 and NEG_X or POS_X
177
  local facey = diffy > 0 and NEG_Y or POS_Y
178
  local absx = math.abs(diffx)
179
  local absy = math.abs(diffy)
180
181
  if currentFace == facex then
182
    moveForward(absx)
183
    if absy > 0 then
184
      turnToFace(facey)
185
      moveForward(absy)
186
    end
187
  elseif currentFace == facey then
188
    moveForward(absy)
189
    if absx > 0 then
190
      turnToFace(facex)
191
      moveForward(absx)
192
    end
193
  else
194
    if absx > 0 then
195
      turnToFace(facex)
196
      moveForward(absx)
197
    end
198
    if absy > 0 then
199
      turnToFace(facey)
200
      moveForward(absy)
201
    end
202
  end
203
end
204
205
--
206
-- Planting
207
--
208
209
function placeCropAndSeed(field)
210
  moveTo(field.crop)
211
  placeSingleCrop()
212
  moveTo(field.activator)
213
  placeSeed()
214
end
215
216
function placeCropAndCrossCrop(field)
217
  moveTo(field.crop)
218
  placeSingleCrop()
219
  moveTo(field.activator)
220
  placeCrossCrop()
221
end
222
223
function placeSingleCrop()
224
  turtle.select(SLOT_CROPS)
225
  turtle.placeDown()
226
end
227
228
function placeViaActivator(slot)
229
  turtle.select(slot)
230
  turtle.dropDown(1)
231
232
  rs.setOutput("bottom", true)
233
  os.sleep(ACTIVATOR_PULSE_DURATION)
234
  rs.setOutput("bottom", false)
235
end
236
237
function placeCrossCrop()
238
  placeViaActivator(SLOT_CROPS)
239
end
240
241
function placeSeed()
242
  placeViaActivator(SLOT_SEEDS)
243
end
244
245
function placeAnalyser()
246
  turtle.select(SLOT_ANALYSER)
247
  sleep(1)
248
  turtle.placeDown()
249
  sleep(1)
250
251
  return peripheral.wrap("bottom")
252
end
253
254
function waitForPlantToMature(face)
255
  analyser = placeAnalyser()
256
  while not analyser.isMature(face) do
257
    sleep(MATURE_SLEEP_DURATION)
258
  end
259
260
  turtle.digDown()
261
end
262
263
function waitForPlantToSpread(face)
264
  analyser = placeAnalyser()
265
  while not analyser.hasPlant(face) do
266
    sleep(SPREAD_SLEEP_DURATION)
267
  end
268
269
  turtle.digDown()
270
end
271
272
function waitForMaturePlant(field)
273
  moveTo(field.analyser)
274
  waitForPlantToMature(field.analyserFace)
275
end
276
277
function waitForSpread(field)
278
  moveTo(field.analyser)
279
  waitForPlantToSpread(field.analyserFace)
280
end
281
282
function harvest(field)
283
  moveTo(field.crop)
284
  turtle.select(SLOT_CROPS)
285
  turtle.digDown()
286
end
287
288
-- true if item at slot i should get dumped
289
-- returns true for everything that doesnt contain the word "seed" in the technical name
290
function dumpItem(i)
291
  local item = turtle.getItemDetail(i)
292
  if item == nil then
293
    return false
294
  end
295
296
  return string.find(string.lower(item.name), "seed") == nil
297
end
298
299
-- dumps all items that are not seeds into chest below, also returns slot numbers for the 2 collected seeds
300
function dumpHarvest()
301
  moveTo(CHEST)
302
303
  local s1 = nil
304
  local s2 = nil
305
306
  for i=3,16 do
307
    if dumpItem(i) then
308
      turtle.select(i)
309
      turtle.dropDown()
310
    elseif turtle.getItemDetail(i) ~= nil then
311
      if s1 == nil then
312
        s1 = i
313
      else
314
        s2 = i
315
      end
316
    end
317
  end
318
  return s1, s2
319
end
320
321
function analyseSlotGetStats(slot)
322
  analyser = placeAnalyser()
323
  turtle.select(slot)
324
  turtle.dropDown()
325
  analyser.analyze()
326
327
  while not analyser.isAnalyzed() do
328
    sleep(ANALYSER_SLEEP_DURATION)
329
  end
330
331
  gr, ga, str = analyser.getSpecimenStats()
332
333
  turtle.suckDown()
334
  turtle.select(SLOT_ANALYSER)
335
  turtle.digDown()
336
337
  return ((gr + ga + str) == 30)
338
end
339
340
341
function analyseSlotAndStore(slot)
342
  if slot == nil then
343
    return false
344
  end
345
346
  moveTo(ANALYSER_MAIN)
347
  local has30 = analyseSlotGetStats(slot)
348
349
  if has30 then
350
    moveTo(CHEST)
351
  else
352
    moveTo(TRASH)
353
  end
354
355
  turtle.select(slot)
356
  turtle.dropDown()
357
  return has30
358
end
359
360
function analyseHarvest(s1, s2)
361
  local s1Has30 = analyseSlotAndStore(s1)
362
  local s2Has30 = analyseSlotAndStore(s2)
363
364
  return s1Has30 or s2Has30
365
end
366
367
function main()
368
  placeCropAndSeed(currentField1())
369
  placeCropAndSeed(currentField2())
370
371
  local finishedBreeding = false
372
373
  while not finishedBreeding do
374
    waitForMaturePlant(currentField1())
375
    waitForMaturePlant(currentField2())
376
377
    placeCropAndCrossCrop(oppositeField1())
378
    placeCropAndCrossCrop(oppositeField2())
379
380
    waitForSpread(oppositeField1())
381
    waitForSpread(oppositeField2())
382
383
    harvest(currentField1())
384
    harvest(currentField2())
385
386
    s1, s2 = dumpHarvest()
387
    finishedBreeding = analyseHarvest(s1, s2)
388
389
    flipCurrentState()
390
  end
391
392
  -- harvest remaining 2 and store them
393
  harvest(currentField1())
394
  harvest(currentField2())
395
  s1, s2 = dumpHarvest()
396
  analyseHarvest(s1, s2)
397
398
  -- reset position
399
  moveTo(CHEST)
400
  turnToFace(POS_Y)
401
end
402
403
main()