· 4 years ago · Mar 21, 2021, 07:36 PM
1-- Mysplit borrowed kindly from the interwebs
2
3function mysplit (inputstr, sep)
4 if sep == nil then
5 sep = "%s"
6 end
7 local t={}
8 for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
9 table.insert(t, str)
10 end
11 return t
12end
13
14
15-- Remove trailing and prefixing whitespaces
16function tail(string)
17 return string.sub(2)
18end
19
20function head(string)
21 return string.sub(1, -1)
22end
23
24function removeTW(string)
25 if string.sub(1, 1) == " " then
26 return removeTW(tail(string))
27 elseif string.sub(-1, -1) == " " then
28 return removeTW(head(string))
29 else
30 return string
31 end
32end
33
34-- Should return a dictionary:
35-- Origin co-ordinates
36-- Chest co-ordinates
37
38
39function ParseConfiguration()
40 local tableT = {}
41
42
43 local fileHandler = io.open("./Configuration.config", 'r')
44
45 local data = fileHandler:read("*all")
46
47 local data_array = mysplit(data, "\n")
48
49 for i,item in ipairs(data_array) do
50 if item.sub(1, 2) ~= "//" then
51 local seperation = mysplit(item, ":")
52
53 seperation[1] = removeTW(seperation[1])
54 seperation[2] = removeTW(seperation[2])
55
56 local coordinates = mysplit(seperation[2], ',')
57 coordinates[1] = tonumber(removeTW(coordinates[1]))
58 coordinates[2] = tonumber(removeTW(coordinates[2]))
59 coordinates[3] = tonumber(removeTW(coordinates[3]))
60
61 tableT[seperation[1]] = coordinates
62 end
63 end
64
65 return tableT
66end
67
68
69function taxicabDistance(vecA, vecB)
70 return math.abs((vecB[1] - vecA[1]) + (vecB[2] - vecA[2]) + (vecB[3] - vecA[3]))
71end
72
73-- -------------------------- Meta Class for Turtle ------------------------- --
74-- I can get away with defining it as 'Turtle' due to the fact that the turtle
75-- API is lowercase
76-- -------------------------------------------------------------------------- --
77
78Turtle = {
79 origin = {0, 0, 0}, -- To be constant
80 savedPositionBuffer = {}, -- To be a dictionary. Key = Tag, Value = Position Coords
81 state = {},
82 selectedSlot = 1
83}
84
85-- --------------------------- Turtle Constructor --------------------------- --
86-- Some key ideas:
87-- In this quarry system, there should exist a chest where items are to be dropped
88-- once the turtle is full. We need the co-ordinates of this chest before we begin.
89--
90-- We also need our own co-ordinates.
91--
92-- We also need the co-ordinates of our desired rest position.
93-- -------------------------------------------------------------------------- --
94
95function Turtle:new()
96 o = {}
97
98 setmetatable(o, self)
99 self.__index = self
100 self.savedPositionBuffer = ParseConfiguration()
101
102 self.state["Orientation"] = 0
103 self.state["Stuck"] = false
104 self.state["Current Position"] = {}
105 self.state["Current Position"][1] = self.savedPositionBuffer["Start Position"][1]
106 self.state["Current Position"][2] = self.savedPositionBuffer["Start Position"][2]
107 self.state["Current Position"][3] = self.savedPositionBuffer["Start Position"][3]
108 self.state["Blocks to move"] = turtle.getFuelLevel()
109 self.savedPositionBuffer["oldPos"] = {}
110 return o
111end
112
113
114-- ----------- Some data on directions and alterations to position ---------- --
115
116directionalLookupTable = {
117 [0] = {0, 1},
118 [1] = {1, 0},
119 [2] = {0, -1},
120 [3] = {-1, 0},
121}
122
123
124
125-- -------------------------------- Movement! ------------------------------- --
126
127function Turtle:attemptPathFix(direction)
128 local actions = {}
129 actions["forward"] = {turtle.attack, turtle.forward}
130 actions["up"] = {turtle.attackUp, turtle.digUp, turtle.up}
131 actions["down"] = {turtle.attackDown, turtle.digDown, turtle.down}
132 actions["back"] = {turtle.attackBack, turtle.digBack, turtle.back}
133
134
135
136 local incidentCounter = 0
137
138 while incidentCounter < 50 do
139 local result = false
140
141 for i,action in ipairs(actions) do
142 result = action[direction]()
143 end
144
145 if not result then
146 incidentCounter = incidentCounter + 1
147 else
148 return
149 end
150 end
151
152 self:Goto(self.savedPositionBuffer["Start Position"])
153 self:Halt("Error 1: Persistent impediment detected in quarry. Returned to home and awaiting instructions.", true)
154end
155
156function Turtle:forward()
157 local result = turtle.forward()
158 if not result then
159 self:attemptPathFix("forward")
160 turtle.forward()
161 end
162
163
164 -- Alter current position dependent on direction
165 local o = self.state["Orientation"]
166
167 self.state["Current Position"][1] = self.state["Current Position"][1] + directionalLookupTable[o][1]
168 self.state["Current Position"][2] = self.state["Current Position"][2] + directionalLookupTable[o][2]
169
170 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
171end
172
173function Turtle:backward()
174 local result = turtle.back()
175
176 if not result then
177 self:attemptPathFix("back")
178 end
179
180 self.state["Current Position"][1] = self.state["Current Position"][1] - directionalLookupTable[self.state["Orientation"]][1]
181 self.state["Current Position"][2] = self.state["Current Position"][2] - directionalLookupTable[self.state["Orientation"]][2]
182
183 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
184
185end
186
187function Turtle:left()
188 local result = turtle.turnLeft()
189 self.state["Orientation"] = (self.state["Orientation"] + 1) % 4
190end
191
192function Turtle:right()
193 local result = turtle.turnRight()
194
195 self.state["Orientation"] = (self.state["Orientation"] - 1) % 4
196end
197
198function Turtle:up()
199 local result = turtle.up()
200 if not result then
201 self:attemptPathFix("up")
202 end
203
204 self.state["Current Position"][3] = self.state["Current Position"][3] + 1
205 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
206
207end
208
209function Turtle:down()
210 local result = turtle.down()
211
212 if not result then
213 self:attemptPathFix("down")
214 end
215
216 self.state["Current Position"][3] = self.state["Current Position"][3] - 1
217 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
218end
219
220function Turtle:dig()
221 turtle.dig()
222end
223
224function Turtle:Orient(direction)
225 while (self.state["Orientation"] ~= direction) do
226 self:left()
227 end
228end
229
230function Turtle:Goto(position, order)
231 order = order or {1, 2, 3}
232 if position[1] == self.state["Current Position"][1] and position[2] == self.state["Current Position"][2] and position[3] == self.state["Current Position"][3] then
233 return
234 end
235
236 for i, item in ipairs(order) do
237 if item == 1 or item == 2 then
238 if self.state["Current Position"][item] < position[item] then
239 print("Small")
240 if item == 1 then
241 self:Orient(1)
242 else
243 self:Orient(0)
244 end
245 for i = 1, position[item] - self.state["Current Position"][item] do
246 self:forward()
247 end
248 else
249 print("Big")
250 if item == 1 then
251 self:Orient(3)
252
253 else
254 self:Orient(2)
255 end
256
257 print(self.state["Current Position"][item] - position[item])
258
259 for i = 1, self.state["Current Position"][item] - position[item] do
260 self:forward()
261 end
262 end
263
264
265 else
266 if self.state["Current Position"][item] < position[item] then
267 for i = 1, position[item] - self.state["Current Position"][item] do
268 self:up()
269 end
270 else
271 for i = 1, self.state["Current Position"][item] - position[item] do
272 self:down()
273 end
274 end
275 end
276 end
277end
278
279function Turtle:CheckNeedToReturn()
280 local d = self.state["Orientation"]
281
282 turtle.refuel()
283
284 self.state["Blocks to move"] = turtle.getFuelLevel()
285 if taxicabDistance(self.state["Current Position"], self.savedPositionBuffer["Refuel Chest Position"]) >= self.state["Blocks to move"] then
286 self.state["Save"] = {}
287 self.state["Save"][1] = self.state["Current Position"][1]
288 self.state["Save"][2] = self.state["Current Position"][2]
289 self.state["Save"][3] = self.state["Current Position"][3]
290 self:Goto(self.savedPositionBuffer["Refuel Chest Position"], {3, 1, 2})
291
292 turtle.select(1)
293 turtle.suck()
294 turtle.refuel()
295
296 if turtle.getFuelLevel() < 500 then
297 self:Halt("Error 2: Fuel levels are low (<500) even after local and global refuel attempt. Please add fuel into slot 1 and continue.", true)
298
299 end
300
301 self:Goto(self.state["Save"], {1, 2, 3})
302 self:Orient(d)
303
304 end
305
306end
307
308function Turtle:CheckNeedToDeposit()
309 print("hello")
310 local d = self.state["Orientation"]
311
312 local counter = 0
313
314 while turtle.getItemCount(self.selectedSlot) > 0 do
315 self.selectedSlot = (self.selectedSlot%16)+1
316
317
318 counter = counter + 1
319
320 if (counter == 16) then
321 self.state["Save"] = {}
322 self.state["Save"][1] = self.state["Current Position"][1]
323 self.state["Save"][2] = self.state["Current Position"][2]
324 self.state["Save"][3] = self.state["Current Position"][3]
325 print(self.state["Save"][2])
326 print(self.state["Current Position"][2])
327 print("we here?")
328 self:Goto(self.savedPositionBuffer["Item Chest Position"], {3, 2, 1})
329
330
331 counter = 0
332 while true do
333 print(counter)
334 self.selectedSlot = (self.selectedSlot%16)+1
335
336 if self.selectedSlot ~= 1 then
337 turtle.select(self.selectedSlot)
338 turtle.drop()
339 end
340 sleep(1)
341
342 counter = counter + 1
343
344 if (counter == 16) then
345 break
346 end
347 end
348 print(self.state["Current Position"][1])
349 print(self.state["Save"][1])
350 self:Goto(self.state["Save"], {1, 2, 3})
351 self:Orient(d)
352 return
353
354 end
355 end
356
357
358end
359
360function Turtle:chunk()
361
362 local x = 3
363 local y = 3
364
365
366 for z = 1, self.savedPositionBuffer["Start Position"][3] - 2 do
367 self:CheckNeedToReturn()
368 turtle.digDown()
369 self:down()
370 self:Orient(2)
371 self.savedPositionBuffer["oldPos"][1] = self.state["Current Position"][1]
372 self.savedPositionBuffer["oldPos"][2] = self.state["Current Position"][2]
373 self.savedPositionBuffer["oldPos"][3] = self.state["Current Position"][3]
374
375 for i = 1, x do
376 for j = 2, y do
377 self:CheckNeedToReturn()
378 self:CheckNeedToDeposit()
379
380
381
382 self:dig()
383 self:forward()
384 end
385
386 if self.state["Orientation"] == 2 then
387
388 self:right()
389 self:dig()
390
391 self:CheckNeedToReturn()
392 self:CheckNeedToDeposit()
393
394
395
396 self:forward()
397
398
399 self:right()
400 else
401 self:left()
402 self:dig()
403
404 self:CheckNeedToReturn()
405 self:CheckNeedToDeposit()
406
407
408 self:forward()
409
410
411 self:left()
412 end
413
414 end
415 self:Goto(self.savedPositionBuffer["oldPos"], {1, 2, 3})
416
417
418 end
419
420 self:Goto(self.savedPositionBuffer["Start Position"], {3, 2, 1})
421 self:Halt("[Log] The turtle has finished operations.")
422end
423
424function Turtle:Halt(message, isError)
425 print("Halted. Given message: "..message)
426
427 if isError then
428 print("You are advised to correct the current error")
429 print("or refer to Mila if you are unsure on what to do.")
430 print("Once you have corrected the error, please press enter.")
431 else
432 print("The system determines that this is not an error. Instead, it is")
433 print("likely a log that requires your attention. Please act on the message")
434 print("or refer to Mila if you are unsure on what to do.")
435
436 end
437 io.read()
438end
439
440t = Turtle:new()
441t:chunk()