Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Globals
- local SQUARE_SIZE = 3
- local DOWN_SQUARE = 0
- local UP_SQUARE = 1
- local CONTAINER_SUBSTRINGS = {"chest"}
- local squareType = DOWN_SQUARE
- local height = 1
- local magnet = nil
- local target = nil
- -- http://lua-users.org/wiki/SimpleRound
- local function round(num, numDecimalPlaces)
- local mult = 10^(numDecimalPlaces or 0)
- return math.floor(num * mult + 0.5) / mult
- end
- -- Gets a magnet located on <side> of turtle
- local function getMagnet(side)
- local name = peripheral.getType(side)
- if(not name:lower():find("magnet")) then
- print("No magnet attached to " .. side)
- return nil
- end
- return peripheral.wrap(side)
- end
- -- Determines if the block in front of a turtle is a chest
- local function isChest()
- local status, data = turtle.inspect()
- if(not status) then
- print("No chest available")
- return false
- end
- local itemName = data["name"]:match(":(.+)"):lower()
- for index, container in pairs(CONTAINER_SUBSTRINGS) do
- if(itemName:find(container)) then
- return true
- end
- end
- return false
- end
- -- Attempt to refuel the turtle
- local function attemptRefuel(amount)
- local amount = amount or 1
- if(turtle.getFuelLevel() >= amount) then
- return
- end
- local index = 1
- local hasRefueled = false
- while(index <= 16 and not hasRefueled) do
- turtle.select(index)
- local refuelling = true
- while(refuelling) do
- if(turtle.refuel(0)) then
- if(turtle.getFuelLevel() < amount) then
- turtle.refuel(1)
- else
- refuelling = false
- hasRefueled = true
- end
- else
- refuelling = false
- end
- end
- index = index + 1
- end
- end
- -- Attempt to dump non-fuel items into a chest in front of the turtle
- local function attemptDumpInv()
- if(not isChest()) then
- return
- end
- for index=1, 16 do
- turtle.select(index)
- if(not turtle.refuel(0)) then
- turtle.drop()
- end
- end
- end
- -- Wraps magnet.setTarget to also keep a local target state
- local function setTargetWrapper(x, y, z)
- target = {["x"] = x, ["y"] = y, ["z"] = z}
- magnet.setTarget(x, y, z)
- end
- -- Orbits the magnet around the turtle right or left in 90 deg turns
- local function orbitMagnet(direction)
- attemptRefuel(5)
- local x = target["x"]
- local y = target["y"]
- local z = target["z"]
- local theta = 0
- if(direction == "cw") then
- theta = -math.pi/2
- elseif(direction == "ccw") then
- theta = math.pi/2
- else
- print("Direction: " .. direction .. " not a valid magnet orbit")
- return false
- end
- -- TODO split this out into own function
- if(squareType == DOWN_SQUARE) then
- if(height >= 2) then
- y = 0 -- Drop magnet one block so it doesn't get hit
- end
- else
- if(height <= 2) then
- y = 1 -- Raise magnet one block
- end
- end
- local x_ = round(z * math.cos(theta) + z * -math.sin(theta))
- local z_ = round(x * math.sin(theta) + x * math.cos(theta))
- print(x, " ", y, " ", z, "\t->", x_, " ", y, " ", z_)
- setTargetWrapper(x_, y, z_)
- end
- -- Turns in a direction one or more times, also tries to keep magnet in same orientation. Assumes magnet is behind turtle
- local function turn(direction, turns)
- local turns = tonumber(distance) or 1
- if(direction == "right") then
- turtle.turnRight()
- if(magnet) then
- orbitMagnet("ccw")
- end
- elseif(direction == "left") then
- turtle.turnLeft()
- if(magnet) then
- orbitMagnet("cw")
- end
- else
- print("Direction: " .. direction .. " not a valid rotation")
- return false
- end
- if(turns > 1) then
- turn(direction, turns - 1, magnetAttached)
- end
- os.sleep(5) -- sleep to let magnet catch up
- return true
- end
- -- Move in a direction 1 or more times
- local function move(direction, distance)
- local distance = tonumber(distance) or 1
- attemptRefuel()
- if(direction == "up") then
- turtle.up()
- height = height + 1
- elseif(direction == "down") then
- turtle.down()
- height = height - 1
- elseif(direction == "forward") then
- turtle.forward()
- elseif(direction == "back") then
- turtle.back()
- else
- print("Direction: " .. direction .. " not a valid movement")
- return false
- end
- if(distance > 1) then
- move(direction, distance - 1)
- end
- return true
- end
- -- Dig out a block and move into it
- local function digMove(direction)
- if(direction == "up") then
- turtle.digUp()
- move("up")
- elseif(direction == "down") then
- turtle.digDown()
- move("down")
- elseif(direction == "forward") then
- turtle.dig()
- move("forward")
- elseif(direction == "back") then
- turn("left", 2)
- turtle.dig()
- turn("left", 2)
- move("back")
- else
- print("Direction: " .. direction .. " not a valid movement")
- return false
- end
- return true
- end
- -- Dig out a 3x3 vertical square
- local function tunnelSquare()
- -- Dig out adjacent left and right blocks
- local function tunnelAdjacentLR()
- turn("left")
- turtle.dig()
- turn("left", 2)
- turtle.dig()
- turn("left")
- end
- digMove("forward") -- Move into next vertical square
- for i=1, SQUARE_SIZE do
- tunnelAdjacentLR()
- if(i < 3) then
- if(DOWN_SQUARE == squareType) then
- digMove("up")
- else
- digMove("down")
- end
- end
- end
- if(DOWN_SQUARE == squareType) then
- squareType = UP_SQUARE
- else
- squareType = DOWN_SQUARE
- end
- end
- -- Tunnel
- local function tunnel(distance, tunnelFunc)
- -- Don't bother with tunnelling negative distances
- if(distance < 1) then
- return
- end
- -- Default to tunnelSquare
- local tunnelFunc = tunnelFunc or tunnelSquare
- -- Tunnel over a distance using specified tunneling function
- for i=1, distance do
- tunnelFunc()
- end
- end
- -- Display usage info
- local function help()
- local name = "<name>"
- if(shell) then
- name = shell.getRunningProgram()
- end
- print("Usage: " .. name .. " <distance to tunnel >= 3> [shaft center spacing (- left, + right)]\nAlso, if a chest is placed to the turtle's right it'll dump non-fuel items into that")
- end
- -- Main
- local function main(distance, spacing, magnetSide)
- -- Handle args
- local distance = tonumber(distance) or 0
- local spacing = tonumber(spacing) or 0
- local magnetSide = magnetSide or "left"
- if(distance < 3) then
- -- Small distances cause inaccuracies
- help()
- return
- end
- -- Init the magnet and get the anchor
- attemptRefuel(5)
- magnet = getMagnet(magnetSide)
- magnet.activate()
- setTargetWrapper(-1, 1, 0)
- os.sleep(2)
- magnet.toggle()
- -- Initial tunneling distance
- tunnel(distance)
- magnet.toggle()
- magnet.deactivate()
- -- Tunnel over to return shaft
- move("back")
- if(spacing > 0) then
- turn("right")
- move("forward")
- tunnel(spacing)
- move("back")
- turn("right")
- elseif(spacing < 0) then
- turn("left")
- move("forward")
- tunnel(spacing * -1)
- move("back")
- turn("left")
- else
- turn("left", 2)
- end
- -- Move to edge of return shaft
- move("forward")
- -- Tunnel/move back to start
- if(spacing == 0) then
- move("forward", distance - 2)
- else
- tunnel(distance - 3)
- move("forward")
- end
- if(UP_SQUARE == squareType) then
- move("down", 2)
- end
- -- Spin back around, dump non-fuel into adjacent chest
- turn("left")
- attemptDumpInv()
- turn("left")
- end
- main(unpack({...}))
Advertisement
Add Comment
Please, Sign In to add comment