· 4 years ago · Mar 21, 2021, 05:52 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) 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 print("a: "..item)
238 if item == 1 then
239 self:Orient(3)
240 else
241 self:Orient(0)
242 end
243 for i = 1, position[item] - self.state["Current Position"][item] do
244 self:forward()
245 end
246 else
247 print("b: "..item)
248
249 if item == 1 then
250 self:Orient(1)
251 else
252 self:Orient(2)
253 end
254
255 print(self.state["Current Position"][item] - position[item])
256
257 for i = 1, self.state["Current Position"][item] - position[item] do
258 print("once")
259 self:forward()
260 end
261 end
262
263
264 else
265 if self.state["Current Position"][item] < position[item] then
266 for i = 1, position[item] - self.state["Current Position"][item] do
267 self:up()
268 end
269 else
270 for i = 1, self.state["Current Position"][item] - position[item] do
271 self:down()
272 end
273 end
274 end
275 end
276end
277
278function Turtle:CheckNeedToReturn()
279 local d = self.state["Orientation"]
280
281 turtle.refuel()
282
283 self.state["Blocks to move"] = turtle.getFuelLevel()
284 if taxicabDistance(self.state["Current Position"], self.savedPositionBuffer["Refuel Chest Position"]) >= self.state["Blocks to move"] then
285 self.state["Save"] = self.state["Current Position"]
286 self:Goto(self.savedPositionBuffer["Refuel Chest Position"], {3, 1, 2})
287
288 turtle.select(1)
289 turtle.suck()
290 turtle.refuel()
291
292 if turtle.getFuelLevel() < 500 then
293 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)
294
295 end
296
297 self:Goto(self.savedPositionBuffer["Save"], {1, 2, 3})
298 self:Orient(d)
299
300 end
301
302end
303
304function Turtle:CheckNeedToDeposit()
305 local d = self.state["Orientation"]
306
307 local counter = 0
308
309 while turtle.getItemCount(self.selectedSlot) > 0 do
310 self.selectedSlot = (self.selectedSlot%16)+1
311
312
313 counter = counter + 1
314
315 if (counter == 16) then
316 self.state["Save"] = self.state["Current Position"]
317 print("we here?")
318 self:Goto(self.savedPositionBuffer["Item Chest Position"], {3, 2, 1})
319
320
321 counter = 0
322 while turtle.getItemCount(self.selectedSlot) > 0 do
323 self.selectedSlot = (self.selectedSlot%16)+1
324
325 if self.selectedSlot ~= 1 then
326 turtle.drop(self.selectedSlot)
327 end
328
329 counter = counter + 1
330
331 if (counter == 16) then
332 return
333 end
334 end
335
336 self:Goto(self.savedPositionBuffer["Save"], {1, 2, 3})
337 self:Orient(d)
338 return
339
340 end
341 end
342
343
344end
345
346function Turtle:chunk()
347
348 local x = 3
349 local y = 3
350
351
352 for z = 1, self.savedPositionBuffer["Start Position"][3] - 2 do
353 self:CheckNeedToReturn()
354 turtle.digDown()
355 self:down()
356 self:Orient(0)
357 self.savedPositionBuffer["oldPos"][1] = self.state["Current Position"][1]
358 self.savedPositionBuffer["oldPos"][2] = self.state["Current Position"][2]
359 self.savedPositionBuffer["oldPos"][3] = self.state["Current Position"][3]
360
361 for i = 1, x do
362 for j = 2, y do
363 self:CheckNeedToReturn()
364 self:CheckNeedToDeposit()
365
366
367
368 self:dig()
369 self:forward()
370 end
371
372 if self.state["Orientation"] == 0 then
373
374 self:right()
375 self:dig()
376
377 self:CheckNeedToReturn()
378 self:CheckNeedToDeposit()
379
380
381
382 self:forward()
383
384
385 self:right()
386 else
387 self:left()
388 self:dig()
389
390 self:CheckNeedToReturn()
391 self:CheckNeedToDeposit()
392
393
394 self:forward()
395
396
397 self:left()
398 end
399
400 end
401 self:Goto(self.savedPositionBuffer["oldPos"], {1, 2, 3})
402
403
404 end
405
406 self:Goto(self.savedPositionBuffer["Start Position"], {3, 2, 1})
407 self:Halt("[Log] The turtle has finished operations.")
408end
409
410function Turtle:Halt(message, isError)
411 print("Halted. Given message: "..message)
412
413 if isError then
414 print("You are advised to correct the current error")
415 print("or refer to Mila if you are unsure on what to do.")
416 print("Once you have corrected the error, please press enter.")
417 else
418 print("The system determines that this is not an error. Instead, it is")
419 print("likely a log that requires your attention. Please act on the message")
420 print("or refer to Mila if you are unsure on what to do.")
421
422 end
423 io.read()
424end
425
426t = Turtle:new()
427t:chunk()