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