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