Created
February 13, 2015 07:42
-
-
Save JCThePants/db2038b6368d2f231aed to your computer and use it in GitHub Desktop.
Simple ComputerCraft turtle mining script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
args = { ... } | |
-- hasModem hasEnderChest size depth [startDepth] | |
-- Used to denote the current direction relative to the direction the | |
-- turtle was facing when the program starts. The start direction is FORWARD. | |
direction = {} | |
direction.FORWARD = 0 | |
direction.RIGHT = 1 | |
direction.BACKWARD = 2 | |
direction.LEFT = 3 | |
-- Tasks the tutle performs | |
task = {} | |
task.MINESHAFT = 0 | |
task.MINEXZ = 1 | |
task.MINEXZ_TURN = 2 | |
task.NEXT_LEVEL = 3 | |
task.NEXT_LEVEL_TURN = 4 | |
task.FINISH = 5 | |
task.UNLOAD = 6 | |
task.DIG = 7 | |
task.REFUEL = 8 | |
-- Specifies the direction a tutle turns as well as provides the turn value. | |
turnDirection = { | |
LEFT = -1, | |
RIGHT = 1 | |
} | |
-- State variables | |
local size = 0 | |
local depth = 0 | |
local startDepth = 0 | |
local facing = direction.FORWARD | |
local currTask = task.MINESHAFT | |
local xzTurnMoves = 0 | |
local mineDirection = 0 | |
local mineX = 1 | |
local mineZ = 1 | |
local nextLevel = 1 -- counter for digging down to the next mining level | |
local level = 1 | |
local stepsForward = 0 | |
local stepsRight = 0 | |
local stepsDown = 0 | |
local savedForward = 0 | |
local savedRight = 0 | |
local savedDown = 0 | |
local savedFacing = 0 | |
local isPaused = false | |
local hasModem = 0 | |
local hasEnderChest = 0 | |
local maxSlot = 16 | |
-- save the current state to a file | |
function save() | |
local file = fs.open("snapshot", "w") | |
file.writeLine(currTask) | |
file.writeLine(size) | |
file.writeLine(depth) | |
file.writeLine(startDepth) | |
file.writeLine(nextLevel) | |
file.writeLine(mineDirection) | |
file.writeLine(mineX) | |
file.writeLine(mineZ) | |
file.writeLine(xzTurnMoves) | |
file.writeLine(level) | |
file.writeLine(stepsForward) | |
file.writeLine(stepsRight) | |
file.writeLine(stepsDown) | |
file.writeLine(savedForward) | |
file.writeLine(savedRight) | |
file.writeLine(savedDown) | |
file.writeLine(facing) | |
file.writeLine(hasModem) | |
file.writeLine(hasEnderChest) | |
file.writeLine(maxSlot) | |
file.close() | |
end | |
-- resume the state saved in a snapshot file | |
function resume() | |
local file = fs.open("snapshot", "r") | |
if file == nil then | |
print("Failed to open snapshot file. Cannot resume.") | |
return | |
end | |
currTask = tonumber(file.readLine()) | |
size = tonumber(file.readLine()) | |
depth = tonumber(file.readLine()) | |
startDepth = tonumber(file.readLine()) | |
nextLevel = tonumber(file.readLine()) | |
mineDirection = tonumber(file.readLine()) | |
mineX = tonumber(file.readLine()) | |
mineZ = tonumber(file.readLine()) | |
xzTurnMoves = tonumber(file.readLine()) | |
level = tonumber(file.readLine()) | |
stepsForward = tonumber(file.readLine()) | |
stepsRight = tonumber(file.readLine()) | |
stepsDown = tonumber(file.readLine()) | |
savedForward = tonumber(file.readLine()) | |
savedRight = tonumber(file.readLine()) | |
savedDown = tonumber(file.readLine()) | |
facing = tonumber(file.readLine()) | |
hasModem = tonumber(file.readLine()) | |
hasEnderChest = tonumber(file.readLine()) | |
maxSlot = tonumber(file.readLine()) | |
file.close() | |
end | |
-- Parse Arguments | |
if args[1] == "resume" then | |
resume() | |
elseif args[1] == nil or args[2] == nil or args[3] == nil or args[4] == nil then | |
print("hasModem hasEnderChest size depth [startDepth]") | |
print("Ender chest, if any, should be in slot 16") | |
return | |
else | |
hasModem = tonumber(args[1]) | |
hasEnderChest = tonumber(args[2]) | |
size = tonumber(args[3]) | |
depth = tonumber(args[4]) | |
startDepth = 0 | |
if args[5] ~= nil then | |
startDepth = tonumber(args[5]) | |
end | |
if hasEnderChest ~= 0 then | |
maxSlot = 15 | |
end | |
end | |
-- update the direction the turtle is facing | |
function updateFacing(turnDir) | |
facing = facing + turnDir | |
if facing > 3 then | |
facing = 0 | |
elseif facing < 0 then | |
facing = 3 | |
end | |
end | |
-- move the turlte forward one block and dig any block in its path | |
function forward() | |
while not turtle.forward() do | |
os.sleep(0) | |
turtle.dig() | |
end | |
if facing == direction.FORWARD then | |
stepsForward = stepsForward + 1 | |
elseif facing == direction.RIGHT then | |
stepsRight = stepsRight + 1 | |
elseif facing == direction.BACKWARD then | |
stepsForward = stepsForward - 1 | |
elseif facing == direction.LEFT then | |
stepsRight = stepsRight - 1 | |
end | |
save() | |
end | |
-- move the turlte down one block and dig any block in its path | |
function down() | |
count = 0 | |
while not turtle.down() do | |
os.sleep(0) | |
turtle.digDown() | |
if not turtle.digDown() and turtle.detectDown() then | |
currTask = task.FINISH | |
stepsDown = stepsDown - 1 | |
print("Failed to dig down. Going home.") | |
break | |
end | |
count = count + 1 | |
end | |
stepsDown = stepsDown + 1 | |
save() | |
end | |
-- move the turtle up one block and dig any block in its path | |
function up() | |
while not turtle.up() do | |
os.sleep(0) | |
turtle.digUp() | |
end | |
stepsDown = stepsDown - 1 | |
save() | |
end | |
-- turn the turtle to the left | |
function turnLeft() | |
turtle.turnLeft() | |
updateFacing(turnDirection.LEFT) | |
save() | |
end | |
-- turn the turtle to the right | |
function turnRight() | |
turtle.turnRight() | |
updateFacing(turnDirection.RIGHT) | |
save() | |
end | |
-- turn the turtle until it is facing the specified direction. | |
function setFacing(faceDir) | |
while facing ~= faceDir do | |
turnRight(); | |
end | |
end | |
-- save the turtle current position into buffer variables | |
function savePosition() | |
savedForward = stepsForward | |
savedRight = stepsRight | |
savedDown = stepsDown | |
savedFacing = facing | |
end | |
-- start the refuel task | |
function refuel() | |
for turn=1, 3 do | |
local hasInventory = false | |
turnLeft() | |
for slot=1, maxSlot do | |
if turtle.suck() then | |
hasInventory = true | |
end | |
while turtle.refuel(slot) do | |
end | |
end | |
if hasInventory then | |
for slot=1, maxSlot do | |
turtle.select(slot) | |
turtle.drop() | |
end | |
end | |
end | |
if checkNeedsFuel() then | |
currTask = task.FINISH | |
end | |
end | |
-- return to the saved dig location and continue digging | |
function returnToDig() | |
while savedDown ~= stepsDown do | |
if savedDown < stepsDown then | |
up() | |
elseif savedDown > stepsDown then | |
down() | |
end | |
end | |
if savedRight < stepsRight then | |
setFacing(direction.LEFT) | |
elseif savedRight > stepsRight then | |
setFacing(direction.RIGHT) | |
end | |
while savedRight ~= stepsRight do | |
forward() | |
end | |
if savedForward < stepsForward then | |
setFacing(direction.BACKWARD) | |
elseif savedForward > stepsForward then | |
setFacing(direction.FORWARD) | |
end | |
while savedForward ~= stepsForward do | |
forward() | |
end | |
setFacing(savedFacing) | |
currTask = task.MINEXZ | |
end | |
-- unload the turtles ender chest | |
function enderUnload() | |
savePosition() | |
turtle.select(16) | |
turtle.digUp() | |
while not turtle.placeUp() do | |
turtle.digUp() | |
end | |
for slot=1, maxSlot do | |
turtle.select(slot) | |
turtle.dropUp() | |
end | |
turtle.select(16) | |
turtle.drop() | |
turtle.digUp() | |
turtle.select(1) | |
currTask = task.DIG | |
end | |
-- return back to the location the turtle was at when the program was started | |
function returnHome() | |
savePosition() | |
if stepsForward > 0 then | |
setFacing(direction.BACKWARD) | |
elseif stepsForward < 0 then | |
setFacing(direction.FORWARD) | |
end | |
while stepsForward ~= 0 do | |
forward() | |
end | |
if stepsRight > 0 then | |
setFacing(direction.LEFT) | |
elseif stepsRight < 0 then | |
setFacing(direction.RIGHT) | |
end | |
while stepsRight ~= 0 do | |
forward() | |
end | |
while stepsDown ~= 0 do | |
if stepsDown > 0 then | |
up() | |
elseif stepsDown < 0 then | |
down() | |
end | |
end | |
setFacing(direction.BACKWARD) | |
for slot=1, maxSlot do | |
turtle.select(slot) | |
turtle.drop() | |
end | |
if currTask == task.FINISH then | |
setFacing(direction.FORWARD) | |
return | |
end | |
if currTask == task.UNLOAD or currTask == task.REFUEL then | |
currTask = task.DIG | |
refuel() | |
end | |
end | |
-- determine if inventory is full (or near full) | |
function isInventoryFull() | |
local used = 0 | |
for slot=1, maxSlot do | |
used = used + turtle.getItemCount(slot) | |
end | |
if used > 400 then | |
return true | |
end | |
return false | |
end | |
-- estimate the distance, and therefore the amount of fuel needed to return home | |
function estimateDistanceHome() | |
return math.abs(stepsForward) + math.abs(stepsRight) + math.abs(stepsDown) + 16; | |
end | |
-- determine if the turtle should refuel | |
function checkNeedsFuel() | |
local fuel = turtle.getFuelLevel() | |
if fuel ~= nil and fuel <= estimateDistanceHome() + 10 then | |
return true | |
end | |
return false | |
end | |
-- dig along the X/Z axis | |
function mineXZ() | |
local turnFlag = mineDirection % 2 == 1 | |
turtle.digUp() | |
turtle.digDown() | |
forward() | |
turtle.digUp() | |
turtle.digDown() | |
if checkNeedsFuel() then | |
currTask = task.UNLOAD | |
return | |
end | |
if isInventoryFull() then | |
currTask = task.UNLOAD | |
return | |
end | |
mineZ = mineZ + 1 | |
if mineZ >= size then | |
mineZ = 1 | |
mineX = mineX + 1 | |
mineDirection = mineDirection + 1 | |
if mineX > size then | |
currTask = task.NEXT_LEVEL_TURN | |
else | |
currTask = task.MINEXZ_TURN | |
end | |
save() | |
return | |
end | |
if mineX > size then | |
mineX = 1 | |
mineZ = 1 | |
--mineDirection = 0 | |
currTask = task.NEXT_LEVEL | |
save() | |
end | |
end | |
-- turn while digging on the X/Z axis | |
function mineXZ_Turn(moveForward) | |
local turnFlag = mineDirection % 2 == 1 | |
if xzTurnMoves > 4 then | |
xzTurnMoves = 0 | |
currTask = task.MINEXZ | |
return | |
end | |
if turnFlag then | |
if xzTurnMoves == 0 then | |
turnLeft() | |
end | |
if xzTurnMoves == 4 then | |
turnLeft() | |
end | |
else | |
if xzTurnMoves == 0 then | |
turnRight() | |
end | |
if xzTurnMoves == 4 then | |
turnRight() | |
end | |
end | |
if xzTurnMoves == 1 and moveForward then | |
forward() | |
end | |
if xzTurnMoves == 2 then | |
turtle.digUp() | |
end | |
if xzTurnMoves == 3 then | |
turtle.digDown() | |
end | |
xzTurnMoves = xzTurnMoves + 1 | |
end | |
-- dig the initial mineshaft to reach the dig start point | |
function digMineShaft() | |
if stepsDown == startDepth then | |
currTask = task.MINEXZ | |
return | |
end | |
down() | |
end | |
-- move down to the next layer | |
function mineNextLevel() | |
if level >= depth then | |
currTask = task.FINISH | |
return | |
end | |
if nextLevel > 3 then | |
mineX = 1 | |
mineZ = 1 | |
mineDirection = mineDirection + 1 | |
level = level + 1 | |
currTask = task.MINEXZ | |
nextLevel = 1 | |
turtle.digDown() | |
return | |
end | |
nextLevel = nextLevel + 1 | |
down() | |
end | |
-- process messages from wireless computer | |
function processMessages() | |
if hasModem == 0 or hasModem == nil then | |
return | |
end | |
rednet.open("right") | |
local senderId, message = rednet.receive(0.1) | |
if message == nil then | |
return | |
end | |
print("Received " .. message) | |
if message == "finishMining" then | |
isPaused = false | |
currTask = task.FINISH | |
print("Received command to finish.") | |
end | |
if message == "unloadMining" then | |
isPaused = false | |
currTask = task.UNLOAD | |
print("Received command to unload inventory at home base.") | |
end | |
if message == "pauseMining" then | |
isPaused = true | |
save() | |
print("Received command to pause.") | |
end | |
if message == "resumeMining" then | |
isPaused = false | |
print("Received command to resume.") | |
end | |
if message == "refuelMining" then | |
isPaused = false | |
currTask = task.REFUEL | |
print("Received command to refuel.") | |
end | |
rednet.send(senderId, "acknowledged") | |
end | |
-- main program loop | |
while true do | |
if not isPaused then | |
if currTask == task.MINESHAFT then | |
digMineShaft() | |
end | |
if currTask == task.MINEXZ then | |
mineXZ() | |
end | |
if currTask == task.MINEXZ_TURN then | |
mineXZ_Turn(true) | |
end | |
if currTask == task.NEXT_LEVEL then | |
mineNextLevel() | |
end | |
if currTask == task.NEXT_LEVEL_TURN then | |
mineXZ_Turn(false) | |
if currTask == task.MINEXZ then | |
currTask = task.NEXT_LEVEL | |
end | |
end | |
if currTask == task.UNLOAD then | |
if hasEnderChest == 0 then | |
returnHome() | |
else | |
enderUnload() | |
end | |
end | |
if currTask == task.REFUEL then | |
returnHome() | |
end | |
if currTask == task.DIG then | |
returnToDig() | |
end | |
if currTask == task.FINISH then | |
break | |
end | |
end | |
processMessages() | |
if not isPaused then | |
save() | |
end | |
end | |
returnHome() | |
setFacing(direction.FORWARD) | |
save() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Computer script to send wireless commands to mining turtle | |
args = { ... } | |
-- turtleid unload|finish|pause|restart [top|left|right|back] | |
local turtleId = 0 | |
local cmd = "" | |
local position = "top" | |
local ack = nil | |
if args[1] == nil or args[2] == nil then | |
print("turtleId unload|finish|pause|restart [top|left|right|back]") | |
return | |
end | |
turtleId = tonumber(args[1]) | |
cmd = args[2] | |
if args[3] ~= nil then | |
position = args[3] | |
end | |
cmd = cmd .. "Mining" | |
print("Sending command " .. cmd .. " to turtle " .. turtleId .. " on " .. position .. " modem.") | |
rednet.open(position) | |
while true do | |
rednet.send(turtleId, cmd) | |
local senderId, message = rednet.receive(0.5) | |
if message == "acknowledged" then | |
break | |
end | |
os.sleep(0.1) | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment