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