-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlavafarm.lua
287 lines (239 loc) · 8.08 KB
/
lavafarm.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
local tArgs = { ... };
local MAX_DIST = 20;
local MAX_FUEL = 20000;
-- The different orientations (DOWN is +Y and UP is -Y)
local NORTH = 0; -- -Z
local EAST = 1; -- +X
local SOUTH = 2; -- +Z
local WEST = 3; -- -X
-- The different directions
local UP = 4;
local DOWN = 5;
local FORWARD = 6;
local RIGHT = 7;
local BACK = 8;
local LEFT = 9;
-- The starting position and orientation
local orientation = NORTH;
-- Directions to get back to start
local returnStack = {};
-- --------------------------------- --
-- STACK FUNCTIONS --
-- --------------------------------- --
--
-- Put a new value on the stack
--
-- @param stack - The stack to add the value to
-- @param val - The value to push onto the stack.
--
function push(stack, val)
if (stack["length"] == nil) then
stack["length"] = 1;
else
stack["length"] = stack["length"] + 1;
end
stack[stack["length"]] = val;
end
--
-- Pops the next value off the top of the stack.
--
-- @param stack - The stack to take the value from.
-- @return Returns the value from the top of the stack or nil if there are no items.
--
function pop(stack)
if (stack["length"] == nil or stack["length"] == 0) then
return nil;
else
local val = stack[stack["length"]];
stack["length"] = stack["length"] - 1;
return val;
end
end
--
-- Finds the size of a stack.
--
-- @param stack - The stack to find the size of.
-- @return Returns the number of items on the provided stack.
--
function size(stack)
if (stack["length"] == nil) then
return 0;
else
return stack["length"];
end
end
-- --------------------------------- --
-- MOVEMENT FUNCTIONS --
-- --------------------------------- --
--
-- Used to move the turtle in the specified direction. If something is blocking it, the turtle
-- will continue to attack and attempt to move until it completes. If moving BACK, the turtle
-- will not attack between attempting to move. Regardless of where it moves, the turtle will
-- end with the same orientation that it started with
--
-- @param dir - The direction or orientation to move the turtle
--
function move(dir)
if (dir == FORWARD) then
while (not(turtle.forward())) do turtle.attack(); end;
elseif (dir == BACK) then
while (not(turtle.back())) do os.sleep(.1); end;
elseif (dir == UP) then
while (not(turtle.up())) do turtle.attackUp(); end;
elseif (dir == DOWN) then
while (not(turtle.down())) do turtle.attackDown(); end;
elseif (dir == RIGHT) then
turn(RIGHT);
move(FORWARD);
turn(LEFT);
elseif (dir == LEFT) then
turn(LEFT);
move(FORWARD);
turn(RIGHT);
elseif (dir == NORTH or dir == EAST or dir == SOUTH or dir == WEST) then
local oldOrient = orientation;
turn(dir);
move(FORWARD);
turn(oldOrient);
end
end
--
-- Used to turn the turtle the specified direction or to the orientation provided
--
-- @param dir - The direction or orientation to turn the turtle
--
function turn(dir)
if (dir == RIGHT) then
turtle.turnRight();
orientation = (orientation + 1) % 4;
elseif (dir == LEFT) then
turtle.turnLeft();
orientation = (orientation + 3) % 4; -- mathematically, a left turn is the same as 3 right turns
elseif (dir == NORTH or dir == EAST or dir == SOUTH or dir == WEST) then
local numLeftTurns = ((4 + orientation) - dir) % 4;
if (numLeftTurns == 3) then -- it's shorter to do just one right turn for this case
turtle.turnRight();
else
for i=1,numLeftTurns do turtle.turnLeft(); end -- perform left turns to new orientation
end
orientation = dir;
end
end
-- --------------------------------- --
-- UTILITY FUNCTIONS --
-- --------------------------------- --
--
-- Used to collect lava from a specific direction. This function does not maintain the original
-- turtle orientation. The turtle will be facing whichever direction it was told to collected from.
--
-- @param dir - The direction or orientation to collect from
-- @return Will return true if lava was actually collected and used.
--
function collectFuel(dir)
-- attempt to pick up lava from the specified location
if (dir == FORWARD) then
turtle.place();
elseif (dir == UP) then
turtle.placeUp();
elseif (dir == DOWN) then
turtle.placeDown();
elseif (dir == NORTH or dir == EAST or dir == SOUTH or dir == WEST) then
turn(dir);
turtle.place();
else
return false;
end
-- check if lava was actually collected
if (not(turtle.compareTo(2))) then
return false;
end
turtle.refuel();
return true;
end
-- --------------------------------- --
-- STARTING THE PROGRAM... --
-- --------------------------------- --
term.clear();
term.setCursorPos(1,1);
turtle.select(1);
-- Check if they specified a different maximum travel distance
if (#tArgs == 1) then
MAX_DIST = tonumber(tArgs[1]);
end
MAX_FUEL = turtle.getFuelLimit();
-- Do an initial fuel check and end the program if it is below the required level
if (MAX_FUEL == "unlimited") then
print("Turtles are not configured to require fuel on this server. Ending program to avoid wasting lava.");
return;
elseif (turtle.getFuelLevel()<2) then
print("You must have a fuel level of at least 2 before running this program.");
return;
end
-- Make sure the turtle is labeled
if (os.getComputerLabel() == nil) then
print("This turtle has not yet been labeled. Setting turtle name to Murtle so the fuel won't be lost");
os.setComputerLabel("Murtle");
end
-- Make sure there are 2 buckets in the first slot
if (turtle.getItemCount(1) ~= 2 and turtle.getItemSpace(1) ~= 14) then
print("Please place 2 empty buckets in slot 1.");
while (turtle.getItemCount(1) ~= 2 and turtle.getItemSpace(1) ~= 14) do os.sleep(.1); end
end
-- Make sure there is nothing in the second slot
if (turtle.getItemCount(2) ~= 0) then
print("Please remove any items from slot 2.");
while (turtle.getItemCount(2) ~= 0) do os.sleep(.1); end
end
-- Check to make sure we started directly above lava and collect one bucket of lava to use for comparison
turtle.placeDown();
if (turtle.getItemCount(1) ~= 1 and turtle.getItemCount(2) ~= 1) then
print("The turtle must be one block directly above lava before starting this program.");
return;
end
-- take an initial step down to where we collected the first bucket of lava from
move(DOWN);
push(returnStack,UP);
-- The main collection logic starts here
-- TODO: Because the move() function preserves orientation, there may be an optimization that
-- prevents the need to check all the sides again after you backtrack.
while (size(returnStack) > 0) do
local lavaCollected = false;
-- still room for more fuel and not too far away yet
if (((MAX_FUEL - 1000) > turtle.getFuelLevel()) and size(returnStack)<MAX_DIST) then
-- check if there is lava below us and move down if there is
if ( collectFuel(DOWN) ) then
move(DOWN);
push(returnStack,UP);
lavaCollected = true;
else
-- check all around us for lava and move there if you find some
for i=1,4 do
if ( collectFuel(FORWARD) ) then
move(FORWARD);
push(returnStack, ((orientation+2) % 4));
lavaCollected = true;
break;
else
turn(RIGHT);
end
end
-- if we haven't found any lava around us yet, then check above us
if (not(lavaCollected)) then
if ( collectFuel(UP) ) then
move(UP);
push(returnStack, DOWN);
lavaCollected = true;
end
end
end
end
-- if there's no more lava around our current position, let's backtrack
if (not(lavaCollected)) then
move( pop(returnStack) );
end
end
-- Use the one bucket of lava in the second slot
turtle.select(2);
turtle.refuel();
turtle.transferTo(1);
print("The final fuel level is: " .. turtle.getFuelLevel());