· 4 years ago · Mar 25, 2021, 07:56 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.dig, 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[direction]) do
142 result = action()
143 end
144
145 if not result then
146 incidentCounter = incidentCounter + 1
147 else
148 return
149 end
150 end
151 save = {}
152 save[1] = self.state["Current Position"][1]
153 save[2] = self.state["Current Position"][2]
154 save[3] = self.state["Current Position"][3]
155 print(save[1])
156 print("hi")
157 self:Goto(self.savedPositionBuffer["Fuel Chest Position"])
158 self:Halt("Error 1: Persistent impediment detected in quarry. Returned to home and awaiting instructions.", true)
159 self:Goto(save, {3, 1, 2})
160 print("Exited!")
161end
162
163function Turtle:forward()
164 local result = turtle.forward()
165 if not result then
166 self:attemptPathFix("forward")
167 end
168
169
170 -- Alter current position dependent on direction
171 local o = self.state["Orientation"]
172
173 self.state["Current Position"][1] = self.state["Current Position"][1] + directionalLookupTable[o][1]
174 self.state["Current Position"][2] = self.state["Current Position"][2] + directionalLookupTable[o][2]
175
176 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
177end
178
179function Turtle:backward()
180 local result = turtle.back()
181
182 if not result then
183 self:attemptPathFix("back")
184 end
185
186 self.state["Current Position"][1] = self.state["Current Position"][1] - directionalLookupTable[self.state["Orientation"]][1]
187 self.state["Current Position"][2] = self.state["Current Position"][2] - directionalLookupTable[self.state["Orientation"]][2]
188
189 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
190
191end
192
193function Turtle:left()
194 print("this is bad")
195 local result = turtle.turnLeft()
196 self.state["Orientation"] = (self.state["Orientation"] + 1) % 4
197end
198
199function Turtle:right()
200 local result = turtle.turnRight()
201
202 self.state["Orientation"] = (self.state["Orientation"] - 1) % 4
203end
204
205function Turtle:up()
206 local result = turtle.up()
207 if not result then
208 self:attemptPathFix("up")
209 end
210
211 self.state["Current Position"][3] = self.state["Current Position"][3] + 1
212 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
213
214end
215
216function Turtle:down()
217 local result = turtle.down()
218
219 if not result then
220 self:attemptPathFix("down")
221 end
222
223 self.state["Current Position"][3] = self.state["Current Position"][3] - 1
224 self.state["Blocks to move"] = self.state["Blocks to move"] - 1
225end
226
227function Turtle:dig()
228 turtle.dig()
229end
230
231function Turtle:Orient(direction)
232 while (self.state["Orientation"] ~= direction) do
233 self:left()
234 end
235end
236
237function Turtle:Goto(position, order)
238 print("Going to: ["..position[1]..", "..position[2]..", "..position[3].."]")
239 order = order or {1, 2, 3}
240 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
241 return
242 end
243
244 for i, item in ipairs(order) do
245 if item == 1 or item == 2 then
246 if self.state["Current Position"][item] < position[item] then
247 if item == 1 then
248 self:Orient(1)
249 else
250 self:Orient(0)
251 end
252 for i = 1, position[item] - self.state["Current Position"][item] do
253 self:forward()
254 end
255 else
256 if item == 1 then
257 self:Orient(3)
258
259 else
260 self:Orient(2)
261 end
262
263 print(self.state["Current Position"][item] - position[item])
264
265 for i = 1, self.state["Current Position"][item] - position[item] do
266 self:forward()
267 end
268 end
269
270
271 else
272 if self.state["Current Position"][item] < position[item] then
273 for i = 1, position[item] - self.state["Current Position"][item] do
274 self:up()
275 end
276 else
277 for i = 1, self.state["Current Position"][item] - position[item] do
278 self:down()
279 end
280 end
281 end
282 end
283end
284
285function Turtle:CheckNeedToReturn()
286 local d = self.state["Orientation"]
287
288 turtle.refuel()
289
290 self.state["Blocks to move"] = turtle.getFuelLevel()
291 if taxicabDistance(self.state["Current Position"], self.savedPositionBuffer["Refuel Chest Position"]) >= self.state["Blocks to move"] then
292 self.state["Save"] = {}
293 self.state["Save"][1] = self.state["Current Position"][1]
294 self.state["Save"][2] = self.state["Current Position"][2]
295 self.state["Save"][3] = self.state["Current Position"][3]
296 self:Goto(self.savedPositionBuffer["Refuel Chest Position"], {3, 2, 1})
297 print(self.state["Save"][1])
298 turtle.select(1)
299 turtle.suck()
300 turtle.refuel()
301
302 if turtle.getFuelLevel() < 500 then
303 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)
304 end
305
306 self:Goto(self.state["Save"], {1, 2, 3})
307 self:Orient(d)
308
309 end
310
311end
312
313function Turtle:CheckNeedToDeposit()
314 print("hello")
315 local d = self.state["Orientation"]
316
317 local counter = 0
318
319 while turtle.getItemCount(self.selectedSlot) > 0 do
320 self.selectedSlot = (self.selectedSlot%16)+1
321
322
323 counter = counter + 1
324
325 if (counter == 16) then
326 self.state["Save"] = {}
327 self.state["Save"][1] = self.state["Current Position"][1]
328 self.state["Save"][2] = self.state["Current Position"][2]
329 self.state["Save"][3] = self.state["Current Position"][3]
330 print(self.state["Save"][2])
331 print(self.state["Current Position"][2])
332 print("we here?")
333 self:Goto(self.savedPositionBuffer["Item Chest Position"], {3, 1, 2})
334
335
336 counter = 0
337 while true do
338 print(counter)
339 self.selectedSlot = (self.selectedSlot%16)+1
340
341 if self.selectedSlot ~= 1 then
342 turtle.select(self.selectedSlot)
343 turtle.drop()
344 end
345 sleep(1)
346
347 counter = counter + 1
348
349 if (counter == 16) then
350 break
351 end
352 end
353 print(self.state["Current Position"][1])
354 print(self.state["Save"][1])
355 self:Goto(self.state["Save"], {1, 2, 3})
356 self:Orient(d)
357 return
358
359 end
360 end
361
362
363end
364
365function Turtle:chunk()
366
367 local x = 16
368 local y = 16
369
370
371 for z = 1, self.savedPositionBuffer["Start Position"][3] - 2 do
372 self:CheckNeedToReturn()
373 turtle.digDown()
374 self:down()
375 self:Orient(2)
376 self.savedPositionBuffer["oldPos"][1] = self.state["Current Position"][1]
377 self.savedPositionBuffer["oldPos"][2] = self.state["Current Position"][2]
378 self.savedPositionBuffer["oldPos"][3] = self.state["Current Position"][3]
379
380 for i = 1, x do
381 for j = 2, y do
382 self:CheckNeedToReturn()
383 self:CheckNeedToDeposit()
384
385
386
387 self:dig()
388 self:forward()
389 end
390
391 if self.state["Orientation"] == 0 then
392
393 self:right()
394 self:dig()
395
396 self:CheckNeedToReturn()
397 self:CheckNeedToDeposit()
398
399
400
401 self:forward()
402
403
404 self:right()
405 else
406 self:left()
407 self:dig()
408
409 self:CheckNeedToReturn()
410 self:CheckNeedToDeposit()
411
412
413 self:forward()
414
415
416 self:left()
417 end
418
419 end
420 self:Goto(self.savedPositionBuffer["oldPos"], {1, 2, 3})
421
422
423 end
424
425 self:Goto(self.savedPositionBuffer["Start Position"], {3, 2, 1})
426 self:Halt("[Log] The turtle has finished operations.")
427end
428
429function Turtle:Halt(message, isError)
430 print("Halted. Given message: "..message)
431
432 if isError then
433 print("You are advised to correct the current error")
434 print("or refer to Mila if you are unsure on what to do.")
435 print("Once you have corrected the error, please press enter.")
436 else
437 print("The system determines that this is not an error. Instead, it is")
438 print("likely a log that requires your attention. Please act on the message")
439 print("or refer to Mila if you are unsure on what to do.")
440
441 end
442 io.read()
443end
444
445t = Turtle:new()
446t:chunk()