View difference between Paste ID: Y6KJagKj and CN3XTnXU
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.2
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
  turtle.placeDown()
248
249
  return peripheral.wrap("bottom")
250
end
251
252
function waitForPlantToMature(face)
253
  analyser = placeAnalyser()
254
  while not analyser.isMature(face) do
255
    sleep(MATURE_SLEEP_DURATION)
256
  end
257
258
  turtle.digDown()
259
end
260
261
function waitForPlantToSpread(face)
262
  analyser = placeAnalyser()
263
  while not analyser.hasPlant(face) do
264
    sleep(SPREAD_SLEEP_DURATION)
265
  end
266
267
  turtle.digDown()
268
end
269
270
function waitForMaturePlant(field)
271
  moveTo(field.analyser)
272
  waitForPlantToMature(field.analyserFace)
273
end
274
275
function waitForSpread(field)
276
  moveTo(field.analyser)
277
  waitForPlantToSpread(field.analyserFace)
278
end
279
280
function harvest(field)
281
  moveTo(field.crop)
282
  turtle.select(SLOT_CROPS)
283
  turtle.digDown()
284
end
285
286
-- true if item at slot i should get dumped
287
-- returns true for everything that doesnt contain the word "seed" in the technical name
288
function dumpItem(i)
289
  local item = turtle.getItemDetail(i)
290
  if item == nil then
291
    return false
292
  end
293
294
  return string.find(string.lower(item.name), "seed") == nil
295
end
296
297
-- dumps all items that are not seeds into chest below, also returns slot numbers for the 2 collected seeds
298
function dumpHarvest()
299
  moveTo(CHEST)
300
301
  local s1 = nil
302
  local s2 = nil
303
304
  for i=3,16 do
305
    if dumpItem(i) then
306
      turtle.select(i)
307
      turtle.dropDown()
308
    elseif turtle.getItemDetail(i) ~= nil then
309
      if s1 == nil then
310
        s1 = i
311
      else
312
        s2 = i
313
      end
314
    end
315
  end
316
  return s1, s2
317
end
318
319
function analyseSlotGetStats(slot)
320
  analyser = placeAnalyser()
321
  turtle.select(slot)
322
  turtle.dropDown()
323
  analyser.analyze()
324
325
  while not analyser.isAnalyzed() do
326
    sleep(ANALYSER_SLEEP_DURATION)
327
  end
328
329
  gr, ga, str = analyser.getSpecimenStats()
330
331
  turtle.suckDown()
332
  turtle.select(SLOT_ANALYSER)
333
  turtle.digDown()
334
335
  return ((gr + ga + str) == 30)
336
end
337
338
339
function analyseSlotAndStore(slot)
340
  if slot == nil then
341
    return false
342
  end
343
344
  moveTo(ANALYSER_MAIN)
345
  local has30 = analyseSlotGetStats(slot)
346
347
  if has30 then
348
    moveTo(CHEST)
349
  else
350
    moveTo(TRASH)
351
  end
352
353
  turtle.select(slot)
354
  turtle.dropDown()
355
  return has30
356
end
357
358
function analyseHarvest(s1, s2)
359
  local s1Has30 = analyseSlotAndStore(s1)
360
  local s2Has30 = analyseSlotAndStore(s2)
361
362
  return s1Has30 or s2Has30
363
end
364
365
function main()
366
  placeCropAndSeed(currentField1())
367
  placeCropAndSeed(currentField2())
368
369
  local finishedBreeding = false
370
371
  while not finishedBreeding do
372
    waitForMaturePlant(currentField1())
373
    waitForMaturePlant(currentField2())
374
375
    placeCropAndCrossCrop(oppositeField1())
376
    placeCropAndCrossCrop(oppositeField2())
377
378
    waitForSpread(oppositeField1())
379
    waitForSpread(oppositeField2())
380
381
    harvest(currentField1())
382
    harvest(currentField2())
383
384
    s1, s2 = dumpHarvest()
385
    finishedBreeding = analyseHarvest(s1, s2)
386
387
    flipCurrentState()
388
  end
389
390
  -- harvest remaining 2 and store them
391
  harvest(currentField1())
392
  harvest(currentField2())
393
  s1, s2 = dumpHarvest()
394
  analyseHarvest(s1, s2)
395
396
  -- reset position
397
  moveTo(CHEST)
398
  turnToFace(POS_Y)
399
end
400
401
main()