first canonical version of miner script
This commit is contained in:
commit
4e25323753
1 changed files with 314 additions and 0 deletions
314
mine.lua
Normal file
314
mine.lua
Normal file
|
|
@ -0,0 +1,314 @@
|
||||||
|
-- Mine a hole of depth by width by heigth, starting from 0, 0, -1 relative to
|
||||||
|
-- current position and facing
|
||||||
|
|
||||||
|
-- +x = right of start, +y = forward of start, +z = up of start
|
||||||
|
local FORWARD, RIGHT, BACK, LEFT = 0, 1, 2, 3
|
||||||
|
local mode = { x = 0, y = 0, z = 0, facing = FORWARD }
|
||||||
|
mode.mine = { forward = true }
|
||||||
|
local block = {}
|
||||||
|
|
||||||
|
function mineSides ()
|
||||||
|
if mode.mine.left then
|
||||||
|
turtle.turnLeft()
|
||||||
|
turtle.dig()
|
||||||
|
turtle.turnRight()
|
||||||
|
end
|
||||||
|
if mode.mine.right then
|
||||||
|
turtle.turnRight()
|
||||||
|
turtle.dig()
|
||||||
|
turtle.turnLeft()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function moveInLine (delta)
|
||||||
|
mineSides()
|
||||||
|
while delta > 0 do
|
||||||
|
if mode.mine.forward then
|
||||||
|
turtle.dig()
|
||||||
|
end
|
||||||
|
turtle.forward()
|
||||||
|
mineSides()
|
||||||
|
delta = delta - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function moveUpDown (delta)
|
||||||
|
local delta = delta
|
||||||
|
while delta > 0 do
|
||||||
|
if mode.mine.forward then
|
||||||
|
turtle.digUp()
|
||||||
|
end
|
||||||
|
turtle.up()
|
||||||
|
delta = delta - 1
|
||||||
|
-- mineSides()
|
||||||
|
end
|
||||||
|
while delta < 0 do
|
||||||
|
if mode.mine.forward then
|
||||||
|
turtle.digDown()
|
||||||
|
end
|
||||||
|
turtle.down()
|
||||||
|
delta = delta + 1
|
||||||
|
-- mineSides()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function turnToFace (new_direction)
|
||||||
|
local delta = new_direction - mode.facing
|
||||||
|
if delta > 2 then
|
||||||
|
delta = delta - 4
|
||||||
|
elseif delta < -2 then
|
||||||
|
delta = delta + 4
|
||||||
|
end
|
||||||
|
while delta > 0 do
|
||||||
|
turtle.turnRight()
|
||||||
|
delta = delta - 1
|
||||||
|
end
|
||||||
|
while delta < 0 do
|
||||||
|
turtle.turnLeft()
|
||||||
|
delta = delta + 1
|
||||||
|
end
|
||||||
|
mode.facing = new_direction
|
||||||
|
end
|
||||||
|
|
||||||
|
-- move to a specific point
|
||||||
|
function moveAbs (x, y, z)
|
||||||
|
-- print(string.format("Moving to (%d, %d, %d)", x, y, z))
|
||||||
|
move(x - mode.x, y - mode.y, z - mode.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- move relative to the turtle's current location
|
||||||
|
function move (x, y, z)
|
||||||
|
-- x
|
||||||
|
if x > 0 then
|
||||||
|
turnToFace(RIGHT)
|
||||||
|
moveInLine(x)
|
||||||
|
elseif x < 0 then
|
||||||
|
turnToFace(LEFT)
|
||||||
|
moveInLine(-x)
|
||||||
|
end
|
||||||
|
mode.x = mode.x + x
|
||||||
|
-- y
|
||||||
|
if y > 0 then
|
||||||
|
turnToFace(FORWARD)
|
||||||
|
moveInLine(y)
|
||||||
|
end
|
||||||
|
if y < 0 then
|
||||||
|
turnToFace(BACK)
|
||||||
|
moveInLine(-y)
|
||||||
|
end
|
||||||
|
mode.y = mode.y + y
|
||||||
|
-- z
|
||||||
|
moveUpDown(z)
|
||||||
|
mode.z = mode.z + z
|
||||||
|
end
|
||||||
|
|
||||||
|
function dropOffItems (go_back)
|
||||||
|
-- Turn off mining
|
||||||
|
local mine_state = mode.mine
|
||||||
|
mode.mine = {}
|
||||||
|
-- Note current position (assuming facing FORWARD)
|
||||||
|
local pos_state = { x = mode.x, y = mode.y, z = mode.z }
|
||||||
|
-- Return to origin, facing BACK
|
||||||
|
moveAbs(mode.x, mode.y, 0)
|
||||||
|
moveAbs(0, 0, 0)
|
||||||
|
turnToFace(BACK)
|
||||||
|
-- deposit items
|
||||||
|
for slot = 2, 16 do
|
||||||
|
turtle.select(slot)
|
||||||
|
turtle.drop()
|
||||||
|
end
|
||||||
|
turtle.select(1)
|
||||||
|
-- Return to current position, facing forward
|
||||||
|
if go_back then moveAbs(pos_state.x, pos_state.y, pos_state.z) end
|
||||||
|
-- Turn mining back on, if it was on
|
||||||
|
mode.mine = mine_state
|
||||||
|
end
|
||||||
|
|
||||||
|
function inventoryFull ()
|
||||||
|
-- leave a little extra space just in case
|
||||||
|
return turtle.getItemCount(15) > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function moveAndCheck (x, y, z)
|
||||||
|
move(x, y, z)
|
||||||
|
if inventoryFull() then dropOffItems(true) end
|
||||||
|
if turtle.getFuelLevel() < 100 then turtle.refuel(8) end
|
||||||
|
end
|
||||||
|
|
||||||
|
function generateNextSteps (w, l)
|
||||||
|
-- assumptions:
|
||||||
|
-- 0 for l or w means don't move in that axis
|
||||||
|
-- 1 for w means mine on right side, -1 means left side
|
||||||
|
-- any greater absolute value of w assumes that the turtle starts in a
|
||||||
|
-- column of three and can mine on both sides out of the gate
|
||||||
|
local DIRECTION = {}
|
||||||
|
if w < 0 then DIRECTION.X = -1 else DIRECTION.X = 1 end
|
||||||
|
if l < 0 then DIRECTION.Y = -1 else DIRECTION.Y = 1 end
|
||||||
|
local remaining_width = math.abs(w) + 1
|
||||||
|
local column_len = math.abs(l)
|
||||||
|
local step_buffer = {}
|
||||||
|
return function ()
|
||||||
|
local next_step = {}
|
||||||
|
if #step_buffer == 0 then
|
||||||
|
if remaining_width < 1 then return nil end
|
||||||
|
-- Algorithm:
|
||||||
|
-- 1. mine l blocks in the y-direction
|
||||||
|
next_step = { x = 0, y = DIRECTION.Y * column_len }
|
||||||
|
next_step.mine = { forward = true, left = true, right = true }
|
||||||
|
if remaining_width == 2 then
|
||||||
|
local delta = DIRECTION.Y + DIRECTION.X
|
||||||
|
if delta == 0 then
|
||||||
|
next_step.mine.right = false
|
||||||
|
else
|
||||||
|
next_step.mine.left = false
|
||||||
|
end
|
||||||
|
elseif remaining_width == 1 then
|
||||||
|
next_step.mine.left = false
|
||||||
|
next_step.mine.right = false
|
||||||
|
end
|
||||||
|
table.insert(step_buffer, next_step)
|
||||||
|
|
||||||
|
-- setup position for next minePlane
|
||||||
|
if remaining_width == 1 and math.abs(w) > 1 then
|
||||||
|
next_step = { x = -DIRECTION.X, y = 0 }
|
||||||
|
next_step.mine = {}
|
||||||
|
table.insert(step_buffer, next_step)
|
||||||
|
end
|
||||||
|
|
||||||
|
DIRECTION.Y = -DIRECTION.Y
|
||||||
|
|
||||||
|
remaining_width = remaining_width - 3
|
||||||
|
|
||||||
|
next_step = { x = 0, y = 0 }
|
||||||
|
next_step.mine = { forward = true }
|
||||||
|
if remaining_width >= 3 then
|
||||||
|
-- 2. go in x-direction to mine a 3-wide column
|
||||||
|
next_step.x = DIRECTION.X * 3
|
||||||
|
table.insert(step_buffer, next_step)
|
||||||
|
elseif remaining_width > 0 then
|
||||||
|
-- or move for a finishing pass
|
||||||
|
next_step.x = DIRECTION.X * 2
|
||||||
|
table.insert(step_buffer, next_step)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next_step = table.remove(step_buffer, 1)
|
||||||
|
return next_step.x, next_step.y, next_step.mine
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function minePlane (w, l)
|
||||||
|
-- mine a plane starting from the current location l blocks in the
|
||||||
|
-- y-direction and w blocks in the x-direction
|
||||||
|
print(string.format("Mining a plane of %d by %d", w, l))
|
||||||
|
mode.mine = { forward = true }
|
||||||
|
for x, y, mine in generateNextSteps(w, l) do
|
||||||
|
mode.mine = mine
|
||||||
|
-- print(string.format("Moving %d, %d relative to current pos.",
|
||||||
|
-- x, y))
|
||||||
|
moveAndCheck(x, y, 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mine (block)
|
||||||
|
-- fuel and go to starting corner
|
||||||
|
if turtle.getFuelLevel() < 100 then turtle.refuel(8) end
|
||||||
|
mode.mine = { forward = true }
|
||||||
|
moveAbs(block.x, block.y, block.z)
|
||||||
|
-- Set up for next plane
|
||||||
|
-- 1. move in if necessary
|
||||||
|
local width = math.abs(block.xoff) + 1
|
||||||
|
local x_dir
|
||||||
|
if block.xoff < 0 then x_dir = -1 else x_dir = 1 end
|
||||||
|
if width > 2 then
|
||||||
|
move(x_dir, 0, 0)
|
||||||
|
end
|
||||||
|
-- Start mining planes
|
||||||
|
local h_remaining = function ()
|
||||||
|
return math.abs(block.z + block.zoff - mode.z)
|
||||||
|
end
|
||||||
|
-- initial pass without moving down
|
||||||
|
minePlane(block.xoff, block.yoff)
|
||||||
|
local z_dir
|
||||||
|
if block.zoff > 1 then z_dir = 1 else z_dir = -1 end
|
||||||
|
while h_remaining() > 0 do
|
||||||
|
-- calculate orientation of next plane
|
||||||
|
local w, l
|
||||||
|
if mode.y == block.y then
|
||||||
|
turnToFace(FORWARD)
|
||||||
|
l = block.yoff
|
||||||
|
else
|
||||||
|
turnToFace(BACK)
|
||||||
|
l = -block.yoff
|
||||||
|
end
|
||||||
|
local diff_from_start = math.abs(mode.x - block.x)
|
||||||
|
-- print(string.format("Distance from start: %d", diff_from_start))
|
||||||
|
if diff_from_start > 1 and width > 3 then
|
||||||
|
w = -block.xoff
|
||||||
|
else
|
||||||
|
w = block.xoff
|
||||||
|
end
|
||||||
|
move(0, 0, z_dir)
|
||||||
|
minePlane(w, l)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function calculateBlock (x1, y1, z1, x2, y2, z2)
|
||||||
|
-- Using the coordinates, construct a block of certain dimensions, a
|
||||||
|
-- certain distance away.
|
||||||
|
local block = {}
|
||||||
|
local normalize = function (dim, c1, c2)
|
||||||
|
-- pick the closest point
|
||||||
|
-- offset goes to the other point
|
||||||
|
local corner, offset
|
||||||
|
if math.abs(c1) <= math.abs(c2) then
|
||||||
|
corner, offset = c1, c2 - c1
|
||||||
|
else
|
||||||
|
corner, offset = c2, c1 - c2
|
||||||
|
end
|
||||||
|
block[dim] = corner
|
||||||
|
block[dim .. "off"] = offset
|
||||||
|
end
|
||||||
|
normalize("x", x1, x2)
|
||||||
|
normalize("y", y1, y2)
|
||||||
|
normalize("z", z1, z2)
|
||||||
|
return block
|
||||||
|
end
|
||||||
|
|
||||||
|
function run (x1, y1, z1, x2, y2, z2)
|
||||||
|
local block = calculateBlock(x1, y1, z1, x2, y2, z2)
|
||||||
|
mine(block)
|
||||||
|
-- return to base
|
||||||
|
mode.mine = {}
|
||||||
|
dropOffItems()
|
||||||
|
turnToFace(FORWARD)
|
||||||
|
end
|
||||||
|
|
||||||
|
function usage ()
|
||||||
|
print("Usage: mine x1 y1 z1 x2 y2 z2 OR mine x1 y1 z1")
|
||||||
|
print("Mine from the first set of coordinates to the second in a \
|
||||||
|
rectangular prism.")
|
||||||
|
print("The coordinates are relative to the facing of the turtle at the \
|
||||||
|
start of the program.")
|
||||||
|
print("If invoked with only three arguments, act as if they are the last \
|
||||||
|
three arguments and substitute 0 0 -1 for the first three.")
|
||||||
|
end
|
||||||
|
|
||||||
|
function argsToNumbers ()
|
||||||
|
local num_args = {}
|
||||||
|
for i, v in ipairs(arg) do
|
||||||
|
num_args[i] = tonumber(v)
|
||||||
|
end
|
||||||
|
return num_args
|
||||||
|
end
|
||||||
|
|
||||||
|
local arg = argsToNumbers()
|
||||||
|
if #arg == 3 then
|
||||||
|
-- TODO make the 3 arg version the same as it used to be
|
||||||
|
-- i.e. `mine 2 3 1` digs a 2-wide, 3-long, 1-deep hole starting under the
|
||||||
|
-- bot
|
||||||
|
run(0, 0, -1, arg[1], arg[2], arg[3])
|
||||||
|
elseif #arg == 6 then
|
||||||
|
run(arg[1], arg[2], arg[3], arg[4], arg[5], arg[6])
|
||||||
|
else
|
||||||
|
usage()
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue