Advertisement
Guest User

computer craft Mine or and diamond only

a guest
Jan 20th, 2018
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 63.71 KB | None | 0 0
  1. -- ********************************************************************************** --
  2. -- **                                                                              ** --
  3. -- **   Minecraft Mining Turtle Ore Quarry adapted from v0.71 by AustinKK          ** --
  4. -- **   ----------------------------------------------------                       ** --
  5. -- **                                                                              ** --
  6. -- **   How to use:                                                                ** --
  7. -- **   1. refuel turtle                                                           ** --
  8. -- **   2. place a bucket of lava in slot 1                                        ** --
  9. -- **   3. place a stone block in slot 2                                           ** --
  10. -- ********************************************************************************** --
  11.  
  12.  
  13. -- ********************************************************************************** --
  14. -- Note: If you are in a world with flat bedrock, change the value below from 5 to 2.
  15. --       You don't need to change this, but the turtle is slightly faster if you do.
  16. -- ********************************************************************************** --
  17. local bottomLayer = 5 -- The y co-ords of the layer immediately above bedrock
  18.  
  19.  
  20.  
  21. -- Enumeration to store the the different types of message that can be written
  22. messageLevel = { DEBUG=0, INFO=1, WARNING=2, ERROR=3, FATAL=4 }
  23.  
  24. -- Enumeration to store names for the 6 directions
  25. direction = { FORWARD=0, RIGHT=1, BACK=2, LEFT=3, UP=4, DOWN=5 }
  26.  
  27. -- Enumeration of mining states
  28. miningState = { START=0, LAYER=1, EMPTYCHESTDOWN=2, EMPTYINVENTORY=3 }
  29.  
  30. local messageOutputLevel = messageLevel.INFO
  31. local messageOutputFileName
  32. local fuelLevelToRefuelAt = 5
  33. local refuelItemsToUseWhenRefuelling = 63
  34. local emergencyFuelToRetain = 0
  35. local maximumGravelStackSupported = 25 -- The number of stacked gravel or sand blocks supported
  36. local noiseBlocksCount
  37. local returningToStart = false
  38. local lookForChests = false -- Determines if chests should be located as part of the quarrying
  39. local miningOffset -- The offset to the mining layer. This is set depending on whether chests are being looked for or not
  40. local lastEmptySlot -- The last inventory slot that was empty when the program started (is either 15 if not looking for chests or 14 if we are)
  41. local turtleId
  42. local isWirelessTurtle
  43. local currentlySelectedSlot = 0 -- The slot that the last noise block was found in
  44. local lastMoveNeededDig = true -- Determines whether the last move needed a dig first
  45. local haveBeenAtZeroZeroOnLayer -- Determines whether the turtle has been at (0, 0) in this mining layer
  46. local orientationAtZeroZero -- The turtle's orientation when it was at (0, 0)
  47. local levelToReturnTo -- The level that the turtle should return to in order to head back to the start to unload
  48.  
  49. -- Variables used to support a resume
  50. local startupParamsFile = "OreQuarryParams.txt"
  51. local oreQuarryLocation = "OreQuarryLocation.txt"
  52. local returnToStartFile = "OreQuarryReturn.txt"
  53. local startupBackup = "startup_bak"
  54. local supportResume = true -- Determines whether the turtle is being run in the mode that supports resume
  55. local resuming = false -- Determines whether the turtle is currently in the process of resuming
  56. local resumeX
  57. local resumeY
  58. local resumeZ
  59. local resumeOrient
  60. local resumeMiningState
  61.  
  62. -- Variables to store the current location and orientation of the turtle. x is right, left, y is up, down and
  63. -- z is forward, back with relation to the starting orientation. Y is the actual turtle level, x and z are
  64. -- in relation to the starting point (i.e. the starting point is (0, 0))
  65. local currX
  66. local currY
  67. local currZ
  68. local currOrient
  69. local currMiningState = miningState.START
  70.  
  71. -- Command line parameters
  72. local startHeight -- Represents the height (y co-ord) that the turtle started at
  73. local quarryWidth -- Represents the length of the mines that the turtle will dig
  74.  
  75. -- ********************************************************************************** --
  76. -- Writes an output message
  77. -- ********************************************************************************** --
  78. function writeMessage(message, msgLevel)
  79.   if (msgLevel >= messageOutputLevel) then
  80.     print(message)
  81.  
  82.     -- If this turtle has a modem, then write the message to red net
  83.     if (isWirelessTurtle == true) then
  84.       if (turtleId == nil) then
  85.         rednet.broadcast(message)
  86.       else
  87.         -- Broadcast the message (prefixed with the turtle's id)
  88.         rednet.broadcast("[".. turtleId.."] "..message)
  89.       end
  90.     end
  91.  
  92.     if (messageOutputFileName ~= nil) then
  93.       -- Open file, write message and close file (flush doesn't seem to work!)
  94.       local outputFile
  95.       if (fs.exists(messageOutputFileName) == true) then
  96.         outputFile = io.open(messageOutputFileName, "a")
  97.       else
  98.         outputFile = io.open(messageOutputFileName, "w")
  99.       end
  100.  
  101.       outputFile:write(message)
  102.       outputFile:write("\n")
  103.       outputFile:close()
  104.     end
  105.   end
  106. end
  107.  
  108. -- ********************************************************************************** --
  109. -- Ensures that the turtle has fuel
  110. -- ********************************************************************************** --
  111. function ensureFuel()
  112.  
  113.   -- Determine whether a refuel is required
  114.   local fuelLevel = turtle.getFuelLevel()
  115.   if (fuelLevel ~= "unlimited") then
  116.     if (fuelLevel < fuelLevelToRefuelAt) then
  117.       -- Need to refuel
  118.       turtle.select(16)
  119.       currentlySelectedSlot = 16
  120.       local fuelItems = turtle.getItemCount(16)
  121.  
  122.       -- Do we need to impact the emergency fuel to continue? (always  
  123.       -- keep one fuel item in slot 16)
  124.       if (fuelItems == 0) then
  125.         writeMessage("Completely out of fuel!", messageLevel.FATAL)
  126.       elseif (fuelItems == 1) then
  127.         writeMessage("Out of Fuel!", messageLevel.ERROR)
  128.         turtle.refuel()
  129.       elseif (fuelItems <= (emergencyFuelToRetain + 1)) then
  130.         writeMessage("Consuming emergency fuel supply. "..(fuelItems - 2).." emergency fuel items remain", messageLevel.WARNING)
  131.         turtle.refuel(1)
  132.       else
  133.         -- Refuel the lesser of the refuelItemsToUseWhenRefuelling and the number of items more than
  134.         -- the emergency fuel level
  135.         if (fuelItems - (emergencyFuelToRetain + 1) < refuelItemsToUseWhenRefuelling) then
  136.           turtle.refuel(fuelItems - (emergencyFuelToRetain + 1))
  137.         else
  138.           turtle.refuel(refuelItemsToUseWhenRefuelling)
  139.         end
  140.       end
  141.     end
  142.   end
  143. end        
  144.  
  145. -- ********************************************************************************** --
  146. -- Checks that the turtle has inventory space by checking for spare slots and returning
  147. -- to the starting point to empty out if it doesn't.
  148. --
  149. -- Takes the position required to move to in order to empty the turtle's inventory
  150. -- should it be full as arguments
  151. -- ********************************************************************************** --
  152. function ensureInventorySpace()
  153.  
  154.   -- If already returning to start, then don't need to do anything
  155.   if (returningToStart == false) then
  156.  
  157.     -- If the last inventory slot is full, then need to return to the start and empty
  158.     if (turtle.getItemCount(lastEmptySlot) > 0) then
  159.         dumpCrap()
  160.        
  161.     end
  162.   end
  163. end
  164.  
  165. function dumpCrap()
  166.     turtle.digDown()  
  167.     turtle.select(1)
  168.     turtle.placeDown()
  169.     for slot = 3, 16 do
  170.         turtle.select(slot)
  171.         sleep(0.6) -- Small fix for slow pc because i had people problem with this
  172.         local itemData = turtle.getItemDetail()
  173.         if itemData then
  174.             if(itemData.name == 'minecraft:diamond' or itemData.name == 'minecraft:iron_ore'or itemData.name == 'minecraft:gold_ore') then
  175.                 -- do nothing
  176.             else
  177.                 turtle.dropDown()
  178.             end    
  179.         end
  180.     end
  181.     turtle.select(1)
  182.     turtle.placeDown()
  183.     turtle.select(2)
  184. end
  185.  
  186. -- ********************************************************************************** --
  187. -- Function to move to the starting point, call a function that is passed in
  188. -- and return to the same location (if required)
  189. -- ********************************************************************************** --
  190. function returnToStartAndUnload(returnBackToMiningPoint)
  191.  
  192.   writeMessage("returnToStartAndUnload called", messageLevel.DEBUG)
  193.   returningToStart = true
  194.   local storedX, storedY, storedZ, storedOrient
  195.   local prevMiningState = currMiningState
  196.  
  197.   if (resuming == true) then
  198.     -- Get the stored parameters from the necessary file
  199.     local resumeFile = fs.open(returnToStartFile, "r")
  200.     if (resumeFile ~= nil) then
  201.       -- Restore the parameters from the file
  202.       local beenAtZero = resumeFile.readLine()
  203.       if (beenAtZero == "y") then
  204.         haveBeenAtZeroZeroOnLayer = true
  205.       else
  206.         haveBeenAtZeroZeroOnLayer = false
  207.       end
  208.  
  209.       local miningPointFlag = resumeFile.readLine()
  210.       if (miningPointFlag == "y") then
  211.         returnBackToMiningPoint = true
  212.       else
  213.         returnBackToMiningPoint = false
  214.       end
  215.  
  216.       currX = readNumber(resumeFile)
  217.       currY = readNumber(resumeFile)
  218.       currZ = readNumber(resumeFile)
  219.       currOrient = readNumber(resumeFile)
  220.       levelToReturnTo = readNumber(resumeFile)
  221.       prevMiningState = readNumber(resumeFile)
  222.       orientationAtZeroZero = readNumber(resumeFile)
  223.       resumeFile.close()
  224.  
  225.     else
  226.       writeMessage("Failed to read return to start file", messageLevel.ERROR)
  227.     end
  228.   elseif (supportResume == true) then
  229.  
  230.     local outputFile = io.open(returnToStartFile, "w")
  231.  
  232.     if (haveBeenAtZeroZeroOnLayer == true) then
  233.       outputFile:write("y\n")
  234.     else
  235.       outputFile:write("n\n")
  236.     end
  237.     if (returnBackToMiningPoint == true) then
  238.       outputFile:write("y\n")
  239.     else
  240.       outputFile:write("n\n")
  241.     end
  242.  
  243.     outputFile:write(currX)
  244.     outputFile:write("\n")
  245.     outputFile:write(currY)
  246.     outputFile:write("\n")
  247.     outputFile:write(currZ)
  248.     outputFile:write("\n")
  249.     outputFile:write(currOrient)
  250.     outputFile:write("\n")
  251.     outputFile:write(levelToReturnTo)
  252.     outputFile:write("\n")
  253.     outputFile:write(prevMiningState)
  254.     outputFile:write("\n")
  255.     outputFile:write(orientationAtZeroZero)
  256.     outputFile:write("\n")
  257.  
  258.     outputFile:close()
  259.   end
  260.    
  261.   storedX = currX
  262.   storedY = currY
  263.   storedZ = currZ
  264.   storedOrient = currOrient
  265.  
  266.   -- Store the current location and orientation so that it can be returned to
  267.   currMiningState = miningState.EMPTYINVENTORY
  268.   writeMessage("last item count = "..turtle.getItemCount(lastEmptySlot), messageLevel.DEBUG)
  269.  
  270.   if ((turtle.getItemCount(lastEmptySlot) > 0) or (returnBackToMiningPoint == false)) then
  271.  
  272.     writeMessage("Heading back to surface", messageLevel.DEBUG)
  273.  
  274.     -- Move down to the correct layer to return via
  275.     if (currY > levelToReturnTo) then
  276.       while (currY > levelToReturnTo) do
  277.         turtleDown()
  278.       end
  279.     elseif (currY < levelToReturnTo) then
  280.       while (currY < levelToReturnTo) do
  281.         turtleUp()
  282.       end
  283.     end
  284.  
  285.     if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  286.       -- Move back to the correct X position first
  287.       if (currX > 0) then
  288.         turtleSetOrientation(direction.LEFT)
  289.         while (currX > 0) do
  290.           turtleForward()
  291.         end
  292.       elseif (currX < 0) then
  293.         -- This should never happen
  294.         writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  295.       end
  296.  
  297.       -- Then move back to the correct Z position
  298.       if (currZ > 0) then
  299.         turtleSetOrientation(direction.BACK)
  300.         while (currZ > 0) do
  301.           turtleForward()
  302.         end
  303.       elseif (currZ < 0) then
  304.         -- This should never happen
  305.         writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  306.       end
  307.     else
  308.       -- Move back to the correct Z position first
  309.       if (currZ > 0) then
  310.         turtleSetOrientation(direction.BACK)
  311.         while (currZ > 0) do
  312.           turtleForward()
  313.         end
  314.       elseif (currZ < 0) then
  315.         -- This should never happen
  316.         writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  317.       end
  318.  
  319.       -- Then move back to the correct X position
  320.       if (currX > 0) then
  321.         turtleSetOrientation(direction.LEFT)
  322.         while (currX > 0) do
  323.           turtleForward()
  324.         end
  325.       elseif (currX < 0) then
  326.         -- This should never happen
  327.         writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  328.       end
  329.     end
  330.  
  331.     -- Return to the starting layer
  332.     if (currY < startHeight) then
  333.       while (currY < startHeight) do
  334.         turtleUp()
  335.       end
  336.     elseif (currY > startHeight) then
  337.       -- This should never happen
  338.       writeMessage("Current height is greater than start height in returnToStartAndUnload", messageLevel.ERROR)
  339.     end
  340.  
  341.     -- Empty the inventory
  342.     local slotLoop = 1
  343.  
  344.     -- Face the chest
  345.     turtleSetOrientation(direction.BACK)
  346.  
  347.     -- Loop over each of the slots (except the 16th one which stores fuel)
  348.     while (slotLoop < 16) do
  349.       -- If this is one of the slots that contains a noise block, empty all blocks except
  350.       -- one
  351.       turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  352.       if ((slotLoop <= noiseBlocksCount) or ((slotLoop == 15) and (lastEmptySlot == 14))) then
  353.         writeMessage("Dropping (n-1) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)  
  354.         if (turtle.getItemCount(slotLoop) > 0) then
  355.           turtle.drop(turtle.getItemCount(slotLoop) - 1)
  356.         end
  357.       else
  358.         -- Not a noise block, drop all of the items in this slot
  359.         writeMessage("Dropping (all) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)  
  360.         if (turtle.getItemCount(slotLoop) > 0) then
  361.           turtle.drop()
  362.         end
  363.       end
  364.      
  365.       slotLoop = slotLoop + 1
  366.     end
  367.  
  368.     -- While we are here, refill the fuel items if there is capacity
  369.     if (turtle.getItemCount(16) < 64) then
  370.       turtleSetOrientation(direction.LEFT)
  371.       turtle.select(16) -- Don't bother updating selected slot variable as it will set later in this function
  372.       local currFuelItems = turtle.getItemCount(16)
  373.       turtle.suck()
  374.       while ((currFuelItems ~= turtle.getItemCount(16)) and (turtle.getItemCount(16) < 64)) do
  375.         currFuelItems = turtle.getItemCount(16)
  376.         turtle.suck()
  377.       end
  378.  
  379.       slotLoop = noiseBlocksCount + 1
  380.       -- Have now picked up all the items that we can. If we have also picked up some
  381.       -- additional fuel in some of the other slots, then drop it again
  382.       while (slotLoop <= lastEmptySlot) do
  383.         -- Drop any items found in this slot
  384.         if (turtle.getItemCount(slotLoop) > 0) then
  385.           turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  386.           turtle.drop()
  387.         end
  388.         slotLoop = slotLoop + 1
  389.       end
  390.     end
  391.  
  392.     -- Select the 1st slot because sometimes when leaving the 15th or 16th slots selected it can result
  393.     -- in that slot being immediately filled (resulting in the turtle returning to base again too soon)
  394.     turtle.select(1)
  395.     currentlySelectedSlot = 1
  396.   end
  397.  
  398.   -- If required, move back to the point that we were mining at before returning to the start
  399.   if (returnBackToMiningPoint == true) then
  400.  
  401.     -- If resuming, refresh the starting point to be the top of the return shaft
  402.     if (resuming == true) then
  403.       currX = 0
  404.       currY = startHeight
  405.       currZ = 0
  406.       currOrient = resumeOrient
  407.     end
  408.  
  409.     -- Return back to the required layer
  410.     while (currY > levelToReturnTo) do
  411.       turtleDown()
  412.     end
  413.  
  414.     if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  415.       -- Move back to the correct Z position first
  416.       writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  417.       if (storedZ > currZ) then
  418.         writeMessage("Orienting forward", messageLevel.DEBUG)
  419.         writeMessage("Moving in z direction", messageLevel.DEBUG)
  420.         turtleSetOrientation(direction.FORWARD)
  421.         while (storedZ > currZ) do
  422.           turtleForward()
  423.         end
  424.       elseif (storedZ < currZ) then
  425.         -- This should never happen
  426.         writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  427.       end
  428.  
  429.       -- Then move back to the correct X position
  430.       if (storedX > currX) then
  431.         writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  432.         writeMessage("Orienting right", messageLevel.DEBUG)
  433.         writeMessage("Moving in x direction", messageLevel.DEBUG)
  434.         turtleSetOrientation(direction.RIGHT)
  435.         while (storedX > currX) do
  436.           turtleForward()
  437.         end
  438.       elseif (storedX < currX) then
  439.         -- This should never happen
  440.         writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  441.       end
  442.     else
  443.       -- Move back to the correct X position first
  444.       if (storedX > currX) then
  445.         writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  446.         writeMessage("Orienting right", messageLevel.DEBUG)
  447.         writeMessage("Moving in x direction", messageLevel.DEBUG)
  448.         turtleSetOrientation(direction.RIGHT)
  449.         while (storedX > currX) do
  450.           turtleForward()
  451.         end
  452.       elseif (storedX < currX) then
  453.         -- This should never happen
  454.         writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  455.       end
  456.  
  457.       -- Then move back to the correct Z position
  458.       writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  459.       if (storedZ > currZ) then
  460.         writeMessage("Orienting forward", messageLevel.DEBUG)
  461.         writeMessage("Moving in z direction", messageLevel.DEBUG)
  462.         turtleSetOrientation(direction.FORWARD)
  463.         while (storedZ > currZ) do
  464.           turtleForward()
  465.         end
  466.       elseif (storedZ < currZ) then
  467.         -- This should never happen
  468.         writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  469.       end
  470.     end
  471.  
  472.     -- Move back to the correct layer
  473.     if (storedY < currY) then
  474.       while (storedY < currY) do
  475.         turtleDown()
  476.       end
  477.     elseif (storedY > currY) then
  478.       while (storedY > currY) do
  479.         turtleUp()
  480.       end
  481.     end
  482.  
  483.     -- Finally, set the correct orientation
  484.     turtleSetOrientation(storedOrient)
  485.  
  486.     writeMessage("Have returned to the mining point", messageLevel.DEBUG)
  487.   end
  488.  
  489.   -- Store the current location and orientation so that it can be returned to
  490.   currMiningState = prevMiningState
  491.  
  492.   returningToStart = false
  493.  
  494. end
  495.  
  496. -- ********************************************************************************** --
  497. -- Empties a chest's contents
  498. -- ********************************************************************************** --
  499. function emptyChest(suckFn)
  500.  
  501.   local prevInventoryCount = {}
  502.   local inventoryLoop
  503.   local chestEmptied = false
  504.  
  505.   -- Record the number of items in each of the inventory slots
  506.   for inventoryLoop = 1, 16 do
  507.     prevInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  508.   end
  509.  
  510.   while (chestEmptied == false) do
  511.     -- Pick up the next item
  512.     suckFn()
  513.  
  514.     -- Determine the number of items in each of the inventory slots now
  515.     local newInventoryCount = {}
  516.     for inventoryLoop = 1, 16 do
  517.       newInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  518.     end
  519.  
  520.     -- Now, determine whether there have been any items taken from the chest
  521.     local foundDifferentItemCount = false
  522.     inventoryLoop = 1
  523.     while ((foundDifferentItemCount == false) and (inventoryLoop <= 16)) do
  524.       if (prevInventoryCount[inventoryLoop] ~= newInventoryCount[inventoryLoop]) then
  525.         foundDifferentItemCount = true
  526.       else
  527.         inventoryLoop = inventoryLoop + 1
  528.       end
  529.     end
  530.    
  531.     -- If no items have been found with a different item count, then the chest has been emptied
  532.     chestEmptied = not foundDifferentItemCount
  533.  
  534.     if (chestEmptied == false) then
  535.       prevInventoryCount = newInventoryCount
  536.       -- Check that there is sufficient inventory space as may have picked up a block
  537.       ensureInventorySpace()
  538.     end
  539.   end
  540.  
  541.   writeMessage("Finished emptying chest", messageLevel.DEBUG)
  542. end
  543.  
  544. -- ********************************************************************************** --
  545. -- Write the current location to a file
  546. -- ********************************************************************************** --
  547. function saveLocation()
  548.  
  549.   -- Write the x, y, z and orientation to the file
  550.   if ((supportResume == true) and (resuming == false)) then
  551.     local outputFile = io.open(oreQuarryLocation, "w")
  552.     outputFile:write(currMiningState)
  553.     outputFile:write("\n")
  554.     outputFile:write(currX)
  555.     outputFile:write("\n")
  556.     outputFile:write(currY)
  557.     outputFile:write("\n")
  558.     outputFile:write(currZ)
  559.     outputFile:write("\n")
  560.     outputFile:write(currOrient)
  561.     outputFile:write("\n")
  562.     outputFile:close()
  563.   end
  564.  
  565. end
  566.  
  567. -- ********************************************************************************** --
  568. -- If the turtle is resuming and the current co-ordinates, orientation and
  569. -- mining state have been matched, then no longer resuming
  570. -- ********************************************************************************** --
  571. function updateResumingFlag()
  572.  
  573.   if (resuming == true) then
  574.     if ((resumeMiningState == currMiningState) and (resumeX == currX) and (resumeY == currY) and (resumeZ == currZ) and (resumeOrient == currOrient)) then
  575.       resuming = false
  576.     end
  577.   end
  578.  
  579. end
  580.  
  581. -- ********************************************************************************** --
  582. -- Generic function to move the Turtle (pushing through any gravel or other
  583. -- things such as mobs that might get in the way).
  584. --
  585. -- The only thing that should stop the turtle moving is bedrock. Where this is
  586. -- found, the function will return after 15 seconds returning false
  587. -- ********************************************************************************** --
  588. function moveTurtle(moveFn, detectFn, digFn, attackFn, compareFn, suckFn, maxDigCount, newX, newY, newZ)
  589.  
  590.   local moveSuccess = false
  591.  
  592.   -- If we are resuming, then don't do anything in this function other than updating the
  593.   -- co-ordinates as if the turtle had moved
  594.   if (resuming == true) then
  595.     -- Set the move success to true (but don't move) - unless this is below bedrock level
  596.     -- in which case return false
  597.     if (currY <= 0) then
  598.       moveSuccess = false
  599.     else
  600.       moveSuccess = true
  601.     end
  602.  
  603.     -- Update the co-ordinates to reflect the movement
  604.     currX = newX
  605.     currY = newY
  606.     currZ = newZ
  607.  
  608.   else
  609.     local prevX, prevY, prevZ
  610.     prevX = currX
  611.     prevY = currY
  612.     prevZ = currZ
  613.  
  614.     ensureFuel()
  615.  
  616.     -- Flag to determine whether digging has been tried yet. If it has
  617.     -- then pause briefly before digging again to allow sand or gravel to
  618.     -- drop
  619.     local digCount = 0
  620.  
  621.     if (lastMoveNeededDig == false) then
  622.       -- Didn't need to dig last time the turtle moved, so try moving first
  623.  
  624.       currX = newX
  625.       currY = newY
  626.       currZ = newZ
  627.       saveLocation()
  628.  
  629.       moveSuccess = moveFn()
  630.  
  631.       -- If move failed, update the co-ords back to the previous co-ords
  632.       if (moveSuccess == false) then
  633.         currX = prevX
  634.         currY = prevY
  635.         currZ = prevZ
  636.         saveLocation()
  637.       end
  638.  
  639.       -- Don't need to set the last move needed dig. It is already false, if
  640.       -- move success is now true, then it won't be changed
  641.     else    
  642.       -- If we are looking for chests, then check that this isn't a chest before trying to dig it
  643.       if (lookForChests == true) then
  644.         if (isNoiseBlock(compareFn) == false) then
  645.           if (detectFn() == true) then
  646.             -- Determine if it is a chest before digging it
  647.             if (isChestBlock(compareFn) == true) then
  648.               -- Have found a chest, empty it before continuing
  649.               emptyChest (suckFn)
  650.             end
  651.           end
  652.         end
  653.       end
  654.  
  655.       -- Try to dig (without doing a detect as it is quicker)
  656.       local digSuccess = digFn()
  657.       if (digSuccess == true) then
  658.         digCount = 1
  659.       end
  660.  
  661.       currX = newX
  662.       currY = newY
  663.       currZ = newZ
  664.       saveLocation()
  665.  
  666.       moveSuccess = moveFn()
  667.  
  668.       if (moveSuccess == true) then
  669.         lastMoveNeededDig = digSuccess
  670.       else
  671.         currX = prevX
  672.         currY = prevY
  673.         currZ = prevZ
  674.         saveLocation()
  675.       end
  676.  
  677.     end
  678.  
  679.     -- Loop until we've successfully moved
  680.     if (moveSuccess == false) then
  681.       while ((moveSuccess == false) and (digCount < maxDigCount)) do
  682.  
  683.         -- If there is a block in front, dig it
  684.         if (detectFn() == true) then
  685.        
  686.             -- If we've already tried digging, then pause before digging again to let
  687.             -- any sand or gravel drop, otherwise check for a chest before digging
  688.             if(digCount == 0) then
  689.               -- Am about to dig a block - check that it is not a chest if necessary
  690.               -- If we are looking for chests, then check that this isn't a chest before moving
  691.               if (lookForChests == true) then
  692.                 if (isNoiseBlock(compareFn) == false) then
  693.                   if (detectFn() == true) then
  694.                     -- Determine if it is a chest before digging it
  695.                     if (isChestBlock(compareFn) == true) then
  696.                       -- Have found a chest, empty it before continuing
  697.                       emptyChest (suckFn)
  698.                     end
  699.                   end
  700.                 end
  701.               end
  702.             else
  703.               sleep(0.1)
  704.             end
  705.  
  706.             digFn()
  707.             digCount = digCount + 1
  708.         else
  709.            -- Am being stopped from moving by a mob, attack it
  710.            attackFn()
  711.         end
  712.  
  713.         currX = newX
  714.         currY = newY
  715.         currZ = newZ
  716.         saveLocation()
  717.  
  718.         -- Try the move again
  719.         moveSuccess = moveFn()
  720.  
  721.         if (moveSuccess == false) then
  722.           currX = prevX
  723.           currY = prevY
  724.           currZ = prevZ
  725.           saveLocation()
  726.         end
  727.       end
  728.  
  729.       if (digCount == 0) then
  730.         lastMoveNeededDig = false
  731.       else
  732.         lastMoveNeededDig = true
  733.       end
  734.     end
  735.   end
  736.  
  737.   -- If we are resuming and the current co-ordinates and orientation are the resume point
  738.   -- then are no longer resuming
  739.   if (moveSuccess == true) then
  740.     updateResumingFlag()
  741.   end
  742.  
  743.   -- Return the move success
  744.   return moveSuccess
  745.  
  746. end
  747.  
  748. -- ********************************************************************************** --
  749. -- Move the turtle forward one block (updating the turtle's position)
  750. -- ********************************************************************************** --
  751. function turtleForward()
  752.  
  753.   -- Determine the new co-ordinate that the turtle will be moving to
  754.   local newX, newZ
  755.  
  756.   -- Update the current co-ordinates
  757.   if (currOrient == direction.FORWARD) then
  758.     newZ = currZ + 1
  759.     newX = currX
  760.   elseif (currOrient == direction.LEFT) then
  761.     newX = currX - 1
  762.     newZ = currZ
  763.   elseif (currOrient == direction.BACK) then
  764.     newZ = currZ - 1
  765.     newX = currX
  766.   elseif (currOrient == direction.RIGHT) then
  767.     newX = currX + 1
  768.     newZ = currZ
  769.   else
  770.     writeMessage ("Invalid currOrient in turtleForward function", messageLevel.ERROR)
  771.   end
  772.  
  773.   local returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
  774.  
  775.   if (returnVal == true) then
  776.     -- Check that there is sufficient inventory space as may have picked up a block
  777.     ensureInventorySpace()
  778.   end
  779.  
  780.   return returnVal
  781. end
  782.  
  783. -- ********************************************************************************** --
  784. -- Move the turtle up one block (updating the turtle's position)
  785. -- ********************************************************************************** --
  786. function turtleUp()
  787.  
  788.   local returnVal = moveTurtle(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp, turtle.compareUp, turtle.suckUp, maximumGravelStackSupported, currX, currY + 1, currZ)
  789.  
  790.   if (returnVal == true) then
  791.     -- Check that there is sufficient inventory space as may have picked up a block
  792.     ensureInventorySpace()
  793.   end
  794.  
  795.   return returnVal
  796. end
  797.  
  798. -- ********************************************************************************** --
  799. -- Move the turtle down one block (updating the turtle's position)
  800. -- ********************************************************************************** --
  801. function turtleDown()
  802.  
  803.   local returnVal = moveTurtle(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown, turtle.compareDown, turtle.suckDown, 1, currX, currY - 1, currZ)
  804.  
  805.   if (returnVal == true) then
  806.     -- Check that there is sufficient inventory space as may have picked up a block
  807.     ensureInventorySpace()
  808.   end
  809.  
  810.   return returnVal
  811.  
  812. end
  813.  
  814. -- ********************************************************************************** --
  815. -- Move the turtle back one block (updating the turtle's position)
  816. -- ********************************************************************************** --
  817. function turtleBack()
  818.  
  819.   -- Assume that the turtle will move, and switch the co-ords back if it doesn't
  820.   -- (do this so that we can write the co-ords to a file before moving)
  821.   local newX, newZ
  822.   local prevX, prevZ
  823.   prevX = currX
  824.   prevZ = currZ
  825.  
  826.   -- Update the current co-ordinates
  827.   if (currOrient == direction.FORWARD) then
  828.     newZ = currZ - 1
  829.     newX = currX
  830.   elseif (currOrient == direction.LEFT) then
  831.     newX = currX + 1
  832.     newZ = currZ
  833.   elseif (currOrient == direction.BACK) then
  834.     newZ = currZ + 1
  835.     newX = currX
  836.   elseif (currOrient == direction.RIGHT) then
  837.     newX = currX - 1
  838.     newZ = currZ
  839.   else
  840.     writeMessage ("Invalid currOrient in turtleBack function", messageLevel.ERROR)
  841.   end
  842.  
  843.   -- First try to move back using the standard function
  844.  
  845.   currX = newX
  846.   currZ = newZ
  847.   saveLocation()
  848.   local returnVal = turtle.back()
  849.  
  850.   if (returnVal == false) then
  851.     -- Didn't move. Reset the co-ordinates to the previous value
  852.     currX = prevX
  853.     currZ = prevZ
  854.  
  855.     -- Reset the location back to the previous location (because the turn takes 0.8 of a second
  856.     -- so could be stopped before getting to the forward function)
  857.     saveLocation()
  858.  
  859.     turtle.turnRight()
  860.     turtle.turnRight()
  861.  
  862.     -- Try to move by using the forward function (note, the orientation will be set as
  863.     -- the same way as this function started because if the function stops, that is the
  864.     -- direction that we want to consider the turtle to be pointing)
  865.  
  866.     returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
  867.  
  868.     turtle.turnRight()
  869.     turtle.turnRight()
  870.   end
  871.  
  872.   if (returnVal == true) then
  873.     -- Check that there is sufficient inventory space as may have picked up a block
  874.     ensureInventorySpace()
  875.   end
  876.    
  877.   return returnVal
  878. end
  879.  
  880. -- ********************************************************************************** --
  881. -- Turns the turtle (updating the current orientation at the same time)
  882. -- ********************************************************************************** --
  883. function turtleTurn(turnDir)
  884.  
  885.   if (turnDir == direction.LEFT) then
  886.     if (currOrient == direction.FORWARD) then
  887.       currOrient = direction.LEFT
  888.     elseif (currOrient == direction.LEFT) then
  889.       currOrient = direction.BACK
  890.     elseif (currOrient == direction.BACK) then
  891.       currOrient = direction.RIGHT
  892.     elseif (currOrient == direction.RIGHT) then
  893.       currOrient = direction.FORWARD
  894.     else
  895.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  896.     end
  897.  
  898.     -- If we are resuming, just check to see whether have reached the resume point, otherwise
  899.     -- turn
  900.     if (resuming == true) then
  901.       updateResumingFlag()
  902.     else
  903.       -- Write the new orientation and turn
  904.       saveLocation()
  905.       turtle.turnLeft()
  906.     end
  907.  
  908.   elseif (turnDir == direction.RIGHT) then
  909.     if (currOrient == direction.FORWARD) then
  910.       currOrient = direction.RIGHT
  911.     elseif (currOrient == direction.LEFT) then
  912.       currOrient = direction.FORWARD
  913.     elseif (currOrient == direction.BACK) then
  914.       currOrient = direction.LEFT
  915.     elseif (currOrient == direction.RIGHT) then
  916.       currOrient = direction.BACK
  917.     else
  918.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  919.     end
  920.  
  921.     -- If we are resuming, just check to see whether have reached the resume point, otherwise
  922.     -- turn
  923.     if (resuming == true) then
  924.       updateResumingFlag()
  925.  
  926.       writeMessage("["..currMiningState..", "..currX..", "..currY..", "..currZ..", "..currOrient.."]", messageLevel.DEBUG)
  927.     else
  928.       -- Write the new orientation and turn
  929.       saveLocation()
  930.       turtle.turnRight()
  931.     end
  932.   else
  933.     writeMessage ("Invalid turnDir in turtleTurn function", messageLevel.ERROR)
  934.   end
  935. end
  936.  
  937. -- ********************************************************************************** --
  938. -- Sets the turtle to a specific orientation, irrespective of its current orientation
  939. -- ********************************************************************************** --
  940. function turtleSetOrientation(newOrient)
  941.  
  942.   if (currOrient ~= newOrient) then
  943.     if (currOrient == direction.FORWARD) then
  944.       if (newOrient == direction.RIGHT) then
  945.         currOrient = newOrient
  946.  
  947.         -- If resuming, check whether the resume point has been reached, otherwise turn
  948.         if (resuming == true) then
  949.           updateResumingFlag()
  950.         else
  951.           -- Write the new orientation and turn
  952.           saveLocation()
  953.           turtle.turnRight()
  954.         end
  955.       elseif (newOrient == direction.BACK) then
  956.         currOrient = newOrient
  957.  
  958.         -- If resuming, check whether the resume point has been reached, otherwise turn
  959.         if (resuming == true) then
  960.           updateResumingFlag()
  961.         else
  962.           -- Write the new orientation and turn
  963.           saveLocation()
  964.           turtle.turnRight()
  965.           turtle.turnRight()
  966.         end
  967.       elseif (newOrient == direction.LEFT) then
  968.         currOrient = newOrient
  969.  
  970.         -- If resuming, check whether the resume point has been reached, otherwise turn
  971.         if (resuming == true) then
  972.           updateResumingFlag()
  973.         else
  974.           -- Write the new orientation and turn
  975.           saveLocation()
  976.           turtle.turnLeft()
  977.         end
  978.       else
  979.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  980.       end
  981.     elseif (currOrient == direction.RIGHT) then
  982.       if (newOrient == direction.BACK) then
  983.         currOrient = newOrient
  984.  
  985.         -- If resuming, check whether the resume point has been reached, otherwise turn
  986.         if (resuming == true) then
  987.           updateResumingFlag()
  988.         else
  989.           -- Write the new orientation and turn
  990.           saveLocation()
  991.           turtle.turnRight()
  992.         end
  993.       elseif (newOrient == direction.LEFT) then
  994.         currOrient = newOrient
  995.  
  996.         -- If resuming, check whether the resume point has been reached, otherwise turn
  997.         if (resuming == true) then
  998.           updateResumingFlag()
  999.         else
  1000.           -- Write the new orientation and turn
  1001.           saveLocation()
  1002.           turtle.turnRight()
  1003.           turtle.turnRight()
  1004.         end
  1005.       elseif (newOrient == direction.FORWARD) then
  1006.         currOrient = newOrient
  1007.  
  1008.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1009.         if (resuming == true) then
  1010.           updateResumingFlag()
  1011.         else
  1012.           -- Write the new orientation and turn
  1013.           saveLocation()
  1014.           turtle.turnLeft()
  1015.         end
  1016.       else
  1017.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1018.       end
  1019.     elseif (currOrient == direction.BACK) then
  1020.       if (newOrient == direction.LEFT) then
  1021.         currOrient = newOrient
  1022.  
  1023.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1024.         if (resuming == true) then
  1025.           updateResumingFlag()
  1026.         else
  1027.           -- Write the new orientation and turn
  1028.           saveLocation()
  1029.           turtle.turnRight()
  1030.         end
  1031.       elseif (newOrient == direction.FORWARD) then
  1032.         currOrient = newOrient
  1033.  
  1034.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1035.         if (resuming == true) then
  1036.           updateResumingFlag()
  1037.         else
  1038.           -- Write the new orientation and turn
  1039.           saveLocation()
  1040.           turtle.turnRight()
  1041.           turtle.turnRight()
  1042.         end
  1043.       elseif (newOrient == direction.RIGHT) then
  1044.         currOrient = newOrient
  1045.  
  1046.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1047.         if (resuming == true) then
  1048.           updateResumingFlag()
  1049.         else
  1050.           -- Write the new orientation and turn
  1051.           saveLocation()
  1052.           turtle.turnLeft()
  1053.         end
  1054.       else
  1055.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1056.       end
  1057.     elseif (currOrient == direction.LEFT) then
  1058.       if (newOrient == direction.FORWARD) then
  1059.         currOrient = newOrient
  1060.  
  1061.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1062.         if (resuming == true) then
  1063.           updateResumingFlag()
  1064.         else
  1065.           -- Write the new orientation and turn
  1066.           saveLocation()
  1067.           turtle.turnRight()
  1068.         end
  1069.       elseif (newOrient == direction.RIGHT) then
  1070.         currOrient = newOrient
  1071.  
  1072.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1073.         if (resuming == true) then
  1074.           updateResumingFlag()
  1075.         else
  1076.           -- Write the new orientation and turn
  1077.           saveLocation()
  1078.           turtle.turnRight()
  1079.           turtle.turnRight()
  1080.         end
  1081.       elseif (newOrient == direction.BACK) then
  1082.         currOrient = newOrient
  1083.  
  1084.         -- If resuming, check whether the resume point has been reached, otherwise turn
  1085.         if (resuming == true) then
  1086.           updateResumingFlag()
  1087.         else
  1088.           -- Write the new orientation and turn
  1089.           saveLocation()
  1090.           turtle.turnLeft()
  1091.         end
  1092.       else
  1093.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1094.       end
  1095.     else
  1096.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  1097.     end
  1098.   end
  1099. end
  1100.  
  1101. -- ********************************************************************************** --
  1102. -- Determines if a particular block is considered a noise block or not. A noise
  1103. -- block is one that is a standard block in the game (stone, dirt, gravel etc.) and
  1104. -- is one to ignore as not being an ore. Function works by comparing the block
  1105. -- in question against a set of blocks in the turtle's inventory which are known not to
  1106. -- be noise blocks. Param is the function to use to compare the block for a noise block
  1107. -- ********************************************************************************** --
  1108. function isNoiseBlock(compareFn)
  1109.  
  1110.   -- Consider air to be a noise block
  1111.   local returnVal = false
  1112.  
  1113.   if (resuming == true) then
  1114.     returnVal = true
  1115.   else
  1116.     local seamLoop = 1
  1117.     local prevSelectedSlot  
  1118.  
  1119.     -- If the currently selected slot is a noise block, then compare against this first
  1120.     -- so that the slot doesn't need to be selected again (there is a 0.05s cost to do
  1121.     -- this even if it is the currently selected slot)
  1122.     if (currentlySelectedSlot <= noiseBlocksCount) then
  1123.       returnVal = compareFn()
  1124.     end
  1125.  
  1126.     if (returnVal == false) then
  1127.       prevSelectedSlot = currentlySelectedSlot
  1128.       while((returnVal == false) and (seamLoop <= noiseBlocksCount)) do
  1129.         if (seamLoop ~= prevSelectedSlot) then
  1130.           turtle.select(seamLoop)
  1131.           currentlySelectedSlot = seamLoop
  1132.           returnVal = compareFn()
  1133.         end
  1134.         seamLoop = seamLoop + 1
  1135.       end
  1136.     end
  1137.   end
  1138.  
  1139.   -- Return the calculated value
  1140.   return returnVal
  1141.  
  1142. end
  1143.  
  1144. -- ********************************************************************************** --
  1145. -- Determines if a particular block is a chest. Returns false if it is not a chest
  1146. -- or chests are not being detected
  1147. -- ********************************************************************************** --
  1148. function isChestBlock(compareFn)
  1149.  
  1150.   -- Check the block in the appropriate direction to see whether it is a chest. Only
  1151.   -- do this if we are looking for chests
  1152.   local returnVal = false
  1153.   if (lookForChests == true) then
  1154.     turtle.select(15)
  1155.     currentlySelectedSlot = 15
  1156.     returnVal = compareFn()
  1157.   end
  1158.  
  1159.   -- Return the calculated value
  1160.   return returnVal
  1161.  
  1162. end
  1163.  
  1164. -- ********************************************************************************** --
  1165. -- Function to calculate the number of non seam blocks in the turtle's inventory. This
  1166. -- is all of the blocks at the start of the inventory (before the first empty slot is
  1167. -- found
  1168. -- ********************************************************************************** --
  1169. function determineNoiseBlocksCountCount()
  1170.   -- Determine the location of the first empty inventory slot. All items before this represent
  1171.   -- noise items.
  1172.   local foundFirstBlankInventorySlot = false
  1173.   noiseBlocksCount = 1
  1174.   while ((noiseBlocksCount < 16) and (foundFirstBlankInventorySlot == false)) do
  1175.     if (turtle.getItemCount(noiseBlocksCount) > 0) then
  1176.       noiseBlocksCount = noiseBlocksCount + 1
  1177.     else
  1178.       foundFirstBlankInventorySlot = true
  1179.     end
  1180.   end
  1181.   noiseBlocksCount = noiseBlocksCount - 1
  1182.  
  1183.   -- Determine whether a chest was provided, and hence whether we should support
  1184.   -- looking for chests
  1185.   if (turtle.getItemCount(15) > 0) then
  1186.     lookForChests = true
  1187.     lastEmptySlot = 14
  1188.     miningOffset = 0
  1189.     writeMessage("Looking for chests...", messageLevel.DEBUG)
  1190.   else
  1191.     lastEmptySlot = 15
  1192.     miningOffset = 1
  1193.     writeMessage("Ignoring chests...", messageLevel.DEBUG)
  1194.   end
  1195. end
  1196.  
  1197. -- ********************************************************************************** --
  1198. -- Creates a quarry mining out only ores and leaving behind any noise blocks
  1199. -- ********************************************************************************** --
  1200. function createQuarry()
  1201.  
  1202.   -- Determine the top mining layer layer. The turtle mines in layers of 3, and the bottom layer
  1203.   -- is the layer directly above bedrock.
  1204.   --
  1205.   -- The actual layer that the turtle operates in is the middle of these three layers,
  1206.   -- so determine the top layer
  1207.   local topMiningLayer = startHeight + ((bottomLayer - startHeight - 2) % 3) - 1 + miningOffset
  1208.  
  1209.   -- If the top layer is up, then ignore it and move to the next layer
  1210.   if (topMiningLayer > currY) then
  1211.     topMiningLayer = topMiningLayer - 3
  1212.   end
  1213.  
  1214.   local startedLayerToRight = true -- Only used where the quarry is of an odd width
  1215.  
  1216.   -- Loop over each mining row
  1217.   local miningLevel
  1218.   for miningLevel = (bottomLayer + miningOffset), topMiningLayer, 3 do
  1219.     writeMessage("Mining Layer: "..miningLevel, messageLevel.INFO)
  1220.     haveBeenAtZeroZeroOnLayer = false
  1221.  
  1222.     -- While the initial shaft is being dug out, set the level to return to in order to unload
  1223.     -- to the just take the turtle straight back up
  1224.     if (miningLevel == (bottomLayer + miningOffset)) then
  1225.       levelToReturnTo = startHeight
  1226.     end
  1227.  
  1228.     -- Move to the correct level to start mining
  1229.     if (currY > miningLevel) then
  1230.       while (currY > miningLevel) do
  1231.         turtleDown()
  1232.       end
  1233.     elseif (currY < miningLevel) then
  1234.       while (currY < miningLevel) do
  1235.         turtleUp()
  1236.       end
  1237.     end
  1238.  
  1239.     -- Am now mining the levels (update the mining state to reflect that fact)
  1240.     currMiningState = miningState.LAYER
  1241.  
  1242.     -- Set the layer to return via when returning to the surface as the one below the currently
  1243.     -- mined one
  1244.     if (miningLevel == (bottomLayer + miningOffset)) then
  1245.       levelToReturnTo = (bottomLayer + miningOffset)
  1246.     else
  1247.       levelToReturnTo = miningLevel - 3
  1248.     end
  1249.  
  1250.     -- Move turtle into the correct orientation to start mining (if this is the
  1251.     -- first row to be mined, then don't need to turn, otherwise turn towards the next
  1252.     -- mining section)
  1253.  
  1254.     writeMessage("Mining Level: "..miningLevel..", Bottom Layer: "..bottomLayer..", Mining Offset: "..miningOffset, messageLevel.DEBUG)
  1255.  
  1256.     if (miningLevel > (bottomLayer + miningOffset)) then
  1257.       -- Turn towards the next mining layer
  1258.       if (quarryWidth % 2 == 0) then
  1259.         -- An even width quarry, always turn right
  1260.         turtleTurn(direction.RIGHT)
  1261.       else
  1262.         -- Turn the opposite direction to that which we turned before
  1263.         if (startedLayerToRight == true) then
  1264.           turtleTurn(direction.LEFT)
  1265.           startedLayerToRight = false
  1266.         else
  1267.           turtleTurn(direction.RIGHT)
  1268.           startedLayerToRight = true
  1269.         end
  1270.       end
  1271.     end
  1272.  
  1273.     local mineRows
  1274.     local onNearSideOfQuarry = true
  1275.     local diggingAway = true
  1276.     for mineRows = 1, quarryWidth do
  1277.  
  1278.       -- If this is not the first row, then get into position to mine the next row
  1279.       if ((mineRows == 1) and (lookForChests == false)) then
  1280.         -- Not looking for chests, check the block below for being an ore. Only do this
  1281.         -- if we're not looking for chests since the program doesn't support chests in
  1282.         -- bedrock
  1283.         if (isNoiseBlock(turtle.compareDown) == false) then
  1284.           turtle.digDown()
  1285.           ensureInventorySpace()
  1286.         end
  1287.       elseif (mineRows > 1) then
  1288.         -- Move into position for mining the next row
  1289.         if (onNearSideOfQuarry == diggingAway) then
  1290.           if (startedLayerToRight == true) then
  1291.             turtleTurn(direction.LEFT)
  1292.           else
  1293.             turtleTurn(direction.RIGHT)
  1294.           end
  1295.         else
  1296.           if (startedLayerToRight == true) then
  1297.             turtleTurn(direction.RIGHT)
  1298.           else
  1299.             turtleTurn(direction.LEFT)
  1300.           end
  1301.         end
  1302.  
  1303.         turtleForward()
  1304.  
  1305.         -- Before making the final turn, check the block below. Do this
  1306.         -- now because if it is a chest, then we want to back up and
  1307.         -- approach it from the side (so that we don't lose items if we
  1308.         -- have to return to the start through it).
  1309.         --
  1310.         -- This is the point at which it is safe to back up without moving
  1311.         -- out of the quarry area (unless at bedrock in which case don't bother
  1312.         -- as we'll be digging down anyway)
  1313.         if (miningLevel ~= bottomLayer) then
  1314.           if (isNoiseBlock(turtle.compareDown) == false) then
  1315.             -- If we are not looking for chests, then just dig it (it takes
  1316.             -- less time to try to dig and fail as it does to do detect and
  1317.             -- only dig if there is a block there)
  1318.             if (lookForChests == false) then
  1319.               turtle.digDown()
  1320.               ensureInventorySpace()
  1321.             elseif (turtle.detectDown() == true) then
  1322.               if (isChestBlock(turtle.compareDown) == true) then
  1323.                 -- There is a chest block below. Move back and approach
  1324.                 -- from the side to ensure that we don't need to return to
  1325.                 -- start through the chest itself (potentially losing items)
  1326.                 turtleBack()
  1327.                 turtleDown()
  1328.                 currMiningState = miningState.EMPTYCHESTDOWN
  1329.                 emptyChest(turtle.suck)
  1330.                 currMiningState = miningState.LAYER
  1331.                 turtleUp()
  1332.                 turtleForward()
  1333.                 turtle.digDown()
  1334.                 ensureInventorySpace()
  1335.               else
  1336.                 turtle.digDown()
  1337.                 ensureInventorySpace()
  1338.               end
  1339.             end
  1340.           end
  1341.         end
  1342.  
  1343.         -- Move into final position for mining the next row
  1344.         if (onNearSideOfQuarry == diggingAway) then
  1345.           if (startedLayerToRight == true) then
  1346.             turtleTurn(direction.LEFT)
  1347.           else
  1348.             turtleTurn(direction.RIGHT)
  1349.           end
  1350.         else
  1351.           if (startedLayerToRight == true) then
  1352.             turtleTurn(direction.RIGHT)
  1353.           else
  1354.             turtleTurn(direction.LEFT)
  1355.           end
  1356.         end
  1357.       end
  1358.  
  1359.       -- Dig to the other side of the quarry
  1360.       local blocksMined
  1361.       for blocksMined = 0, (quarryWidth - 1) do
  1362.         if (blocksMined > 0) then
  1363.           -- Only move forward if this is not the first space
  1364.           turtleForward()
  1365.         end
  1366.  
  1367.         -- If the current block is (0,0), then record the fact that the
  1368.         -- turtle has been through this block and what it's orientation was and update the layer
  1369.         -- that it should return via to get back to the surface (it no longer needs to go down
  1370.         -- a level to prevent losing ores).
  1371.         if ((currX == 0) and (currZ == 0)) then
  1372.           -- Am at (0, 0). Remember this, and what direction I was facing so that the quickest route
  1373.           -- to the surface can be taken
  1374.           levelToReturnTo = miningLevel
  1375.           haveBeenAtZeroZeroOnLayer = true
  1376.           orientationAtZeroZero = currOrient
  1377.         end
  1378.  
  1379.         -- If currently at bedrock, just move down until the turtle can't go any
  1380.         -- further. This allows the blocks within the bedrock to be mined
  1381.         if (miningLevel == bottomLayer) then
  1382.           -- Temporarily turn off looking for chests to increase bedrock mining speed (this
  1383.           -- means that the program doesn't support chests below level 5 - but I think
  1384.           -- they they don't exist anyway)
  1385.           local lookForChestsPrev = lookForChests
  1386.           lookForChests = false
  1387.  
  1388.           -- Manually set the flag to determine whether the turtle should try to move first or
  1389.           -- dig first. At bedrock, is very rarely any space
  1390.  
  1391.           -- Just above bedrock layer, dig down until can't dig any lower, and then
  1392.           -- come back up. This replicates how the quarry functions
  1393.           lastMoveNeededDig = true
  1394.           local moveDownSuccess = turtleDown()
  1395.           while (moveDownSuccess == true) do
  1396.             moveDownSuccess = turtleDown()
  1397.           end
  1398.  
  1399.           -- Know that we are moving back up through air, therefore set the flag to force the
  1400.           -- turtle to try moving first
  1401.           lastMoveNeededDig = false
  1402.  
  1403.           -- Have now hit bedrock, move back to the mining layer
  1404.           while (currY < bottomLayer) do
  1405.             turtleUp()
  1406.           end
  1407.  
  1408.           -- Now back at the level above bedrock, again reset the flag to tell the turtle to
  1409.           -- try digging again (because it is rare to find air at bedrock level)
  1410.           lastMoveNeededDig = false
  1411.  
  1412.           -- Reset the look for chests value
  1413.           lookForChests = lookForChestsPrev
  1414.         elseif ((blocksMined > 0) and ((currX ~= 0) or (currZ ~= 0))) then
  1415.           -- This isn't the first block of the row, nor are we at (0, 0) so we need to check the
  1416.           -- block below
  1417.  
  1418.           -- Check the block down for being a noise block (don't need to check the first
  1419.           -- block as it has already been checked in the outer loop)
  1420.           if (isNoiseBlock(turtle.compareDown) == false) then
  1421.             -- If we are not looking for chests, then just dig it (it takes
  1422.             -- less time to try to dig and fail as it does to do detect and
  1423.             -- only dig if there is a block there)
  1424.             if (lookForChests == false) then
  1425.               turtle.digDown()
  1426.               ensureInventorySpace()
  1427.             elseif (turtle.detectDown() == true) then
  1428.               if (isChestBlock(turtle.compareDown) == true) then
  1429.                 -- There is a chest block below. Move back and approach
  1430.                 -- from the side to ensure that we don't need to return to
  1431.                 -- start through the chest itself (potentially losing items)
  1432.                 turtleBack()
  1433.                 currMiningState = miningState.EMPTYCHESTDOWN
  1434.                 turtleDown()
  1435.                 emptyChest(turtle.suck)
  1436.                 currMiningState = miningState.LAYER
  1437.                 turtleUp()
  1438.                 turtleForward()
  1439.                 turtle.digDown()
  1440.                 ensureInventorySpace()
  1441.               else
  1442.                 turtle.digDown()
  1443.                 ensureInventorySpace()
  1444.               end
  1445.             end
  1446.           end
  1447.         end
  1448.        
  1449.         -- Check the block above for ores (if we're not a (0, 0) in which case
  1450.         -- we know it's air)
  1451.         if ((currX ~= 0) or (currZ ~= 0)) then
  1452.           if (isNoiseBlock(turtle.compareUp) == false) then
  1453.             -- If we are not looking for chests, then just dig it (it takes
  1454.             -- less time to try to dig and fail as it does to do detect and
  1455.             -- only dig if there is a block there)
  1456.             if (lookForChests == false) then
  1457.               turtle.digUp()
  1458.               ensureInventorySpace()
  1459.             elseif (turtle.detectUp() == true) then
  1460.               -- Determine if it is a chest before digging it
  1461.               if (isChestBlock(turtle.compareUp) == true) then
  1462.                 -- There is a chest block above. Empty it before digging it
  1463.                 emptyChest(turtle.suckUp)
  1464.                 turtle.digUp()
  1465.                 ensureInventorySpace()
  1466.               else
  1467.                 turtle.digUp()
  1468.                 ensureInventorySpace()
  1469.               end
  1470.             end
  1471.           end
  1472.         end
  1473.       end
  1474.  
  1475.       -- Am now at the other side of the quarry
  1476.       onNearSideOfQuarry = not onNearSideOfQuarry
  1477.     end
  1478.  
  1479.     -- If we were digging away from the starting point, will be digging
  1480.     -- back towards it on the next layer
  1481.     diggingAway = not diggingAway
  1482.   end
  1483.  
  1484.   -- Return to the start
  1485.   returnToStartAndUnload(false)
  1486.  
  1487.   -- Face forward
  1488.   turtleSetOrientation(direction.FORWARD)
  1489. end
  1490.  
  1491. -- ********************************************************************************** --
  1492. -- Reads the next number from a given file
  1493. -- ********************************************************************************** --
  1494. function readNumber(inputFile)
  1495.  
  1496.   local returnVal
  1497.   local nextLine = inputFile.readLine()
  1498.   if (nextLine ~= nil) then
  1499.     returnVal = tonumber(nextLine)
  1500.   end
  1501.  
  1502.   return returnVal
  1503. end
  1504.  
  1505. -- ********************************************************************************** --
  1506. -- Startup function to support resuming mining turtle
  1507. -- ********************************************************************************** --
  1508. function isResume()
  1509.  
  1510.   local returnVal = false
  1511.  
  1512.   -- Try to open the resume file
  1513.   local resumeFile = fs.open(startupParamsFile, "r")
  1514.   if (resumeFile == nil) then
  1515.     -- No resume file (presume that we are not supporting it)
  1516.     supportResume = false
  1517.   else
  1518.     writeMessage("Found startup params file", messageLevel.DEBUG)
  1519.  
  1520.     -- Read in the startup params
  1521.     quarryWidth = readNumber(resumeFile)
  1522.     startHeight = readNumber(resumeFile)
  1523.     noiseBlocksCount = readNumber(resumeFile)
  1524.     lastEmptySlot = readNumber(resumeFile)
  1525.     resumeFile.close()
  1526.  
  1527.     -- If the parameters were successfully read, then set the resuming flag to true
  1528.     if ((quarryWidth ~= nil) and (startHeight ~= nil) and (noiseBlocksCount ~= nil) and (lastEmptySlot ~= nil)) then
  1529.  
  1530.       resuming = true
  1531.       writeMessage("Read params", messageLevel.DEBUG)
  1532.  
  1533.       -- Determine the look for chest and mining offset
  1534.       if (lastEmptySlot == 14) then
  1535.         lookForChests = true
  1536.         miningOffset = 0
  1537.       else
  1538.         lookForChests = false
  1539.         miningOffset = 1
  1540.       end
  1541.  
  1542.       -- Get the turtle resume location
  1543.       resumeFile = fs.open(oreQuarryLocation, "r")
  1544.       if (resumeFile ~= nil) then
  1545.  
  1546.         resumeMiningState = readNumber(resumeFile)
  1547.         resumeX = readNumber(resumeFile)
  1548.         resumeY = readNumber(resumeFile)
  1549.         resumeZ = readNumber(resumeFile)
  1550.         resumeOrient = readNumber(resumeFile)
  1551.         resumeFile.close()
  1552.  
  1553.         -- Ensure that the resume location has been found
  1554.         if ((resumeMiningState ~= nil) and (resumeX ~= nil) and (resumeY ~= nil) and (resumeZ ~= nil) and (resumeOrient ~= nil)) then
  1555.           returnVal = true
  1556.           local emptiedInventory = false
  1557.  
  1558.           -- Perform any mining state specific startup
  1559.           if (resumeMiningState == miningState.EMPTYINVENTORY) then
  1560.             -- Am mid way through an empty inventory cycle. Complete it before
  1561.             -- starting the main Quarry function
  1562.             returnToStartAndUnload(true)
  1563.             resuming = true
  1564.  
  1565.             -- Continue from the current position
  1566.             resumeX = currX
  1567.             resumeY = currY
  1568.             levelToReturnTo = resumeY
  1569.             resumeZ = currZ
  1570.             resumeOrient = currOrient
  1571.  
  1572.             writeMessage("Resuming with state of "..currMiningState, messageLevel.DEBUG)
  1573.             resumeMiningState = currMiningState
  1574.             emptiedInventory = true
  1575.           end
  1576.  
  1577.           -- If was emptying a chest when the program stopped, then move back
  1578.           -- to a point which the Quarry
  1579.           if (resumeMiningState == miningState.EMPTYCHESTDOWN) then
  1580.  
  1581.             -- Set the current X, Y, Z and orientation to the true position that
  1582.             -- the turtle is at
  1583.             if (emptiedInventory == false) then
  1584.               currX = resumeX
  1585.               currY = resumeY
  1586.               currZ = resumeZ
  1587.               currOrient = resumeOrient
  1588.             end
  1589.  
  1590.             -- Set the mining state as layer, assume haven't been through zero
  1591.             -- zero and set the level to return to as the one below the current one
  1592.             currMiningState = miningState.LAYER
  1593.             levelToReturnTo = currY - 2
  1594.             haveBeenAtZeroZeroOnLayer = false
  1595.  
  1596.             -- Temporarily disable resuming (so that the new location is written to the file
  1597.             -- in case the program stops again)
  1598.             resuming = false
  1599.             turtleUp()
  1600.             resuming = true
  1601.  
  1602.             resumeY = currY
  1603.             resumeMiningState = miningState.LAYER
  1604.           end
  1605.         end
  1606.       end
  1607.     end
  1608.  
  1609.     if (returnVal == false) then
  1610.       writeMessage("Failed to resume", messageLevel.ERROR)
  1611.     end
  1612.   end
  1613.  
  1614.   return returnVal
  1615. end
  1616.  
  1617. -- ********************************************************************************** --
  1618. -- Main Function                                          
  1619. -- ********************************************************************************** --
  1620. -- Process the input arguments - storing them to global variables
  1621. local args = { ... }
  1622. local paramsOK = true
  1623.  
  1624. -- Detect whether this is a wireless turtle, and if so, open the modem
  1625. local peripheralConnected = peripheral.getType("right")
  1626. if (peripheralConnected == "modem") then
  1627.   isWirelessTurtle = true
  1628. end
  1629.  
  1630. -- If a wireless turtle, open the modem
  1631. if (isWirelessTurtle == true) then
  1632.   turtleId = os.getComputerLabel()
  1633.   rednet.open("right")
  1634. end
  1635.  
  1636. if (#args == 0) then
  1637.   -- Is this a resume?
  1638.   if (isResume() == false) then
  1639.     paramsOK = false
  1640.   end
  1641. elseif (#args == 1) then
  1642.   quarryWidth = tonumber(args[1])
  1643.   local x, y, z = gps.locate(5)
  1644.   startHeight = y
  1645.   if (startHeight == nil) then
  1646.     writeMessage("Can't locate GPS", messageLevel.FATAL)
  1647.     paramsOK = false
  1648.   end
  1649. elseif (#args == 2) then
  1650.   if (args[2] == "/r") then
  1651.     quarryWidth = tonumber(args[1])
  1652.     supportResume = false
  1653.   else
  1654.     quarryWidth = tonumber(args[1])
  1655.     startHeight = tonumber(args[2])
  1656.   end
  1657. elseif (#args == 3) then
  1658.   quarryWidth = tonumber(args[1])
  1659.   startHeight = tonumber(args[2])
  1660.   if (args[3] == "/r") then
  1661.     supportResume = false
  1662.   else
  1663.     paramsOK = false
  1664.   end
  1665. end
  1666.  
  1667. if ((paramsOK == false) and (resuming == false)) then
  1668.   writeMessage("Usage: "..shell.getRunningProgram().." <diameter> [turtleY] [/r]", messageLevel.FATAL)
  1669.   paramsOK = false
  1670. end
  1671.  
  1672. if (paramsOK == true) then
  1673.   if ((startHeight < 6) or (startHeight > 128)) then
  1674.     writeMessage("turtleY must be between 6 and 128", messageLevel.FATAL)
  1675.     paramsOK = false
  1676.   end
  1677.  
  1678.   if ((quarryWidth < 2) or (quarryWidth > 64)) then
  1679.     writeMessage("diameter must be between 2 and 64", messageLevel.FATAL)
  1680.     paramsOK = false
  1681.   end
  1682. end
  1683.  
  1684. if (paramsOK == true) then
  1685.   if (resuming == true) then
  1686.     writeMessage("Resuming Ore Quarry...", messageLevel.INFO)
  1687.   else
  1688.     writeMessage("----------------------------------", messageLevel.INFO)
  1689.     writeMessage("** Ore Quarry v0.71 by AustinKK **", messageLevel.INFO)
  1690.     writeMessage("----------------------------------", messageLevel.INFO)
  1691.   end
  1692.  
  1693.   -- Set the turtle's starting position
  1694.   currX = 0
  1695.   currY = startHeight
  1696.   currZ = 0
  1697.   currOrient = direction.FORWARD
  1698.  
  1699.   -- Calculate which blocks in the inventory signify noise blocks
  1700.   if (resuming == false) then
  1701.     determineNoiseBlocksCountCount()
  1702.   end
  1703.  
  1704.   if ((noiseBlocksCount == 0) or (noiseBlocksCount > 13)) then
  1705.     writeMessage("No noise blocks have been been added. Please place blocks that the turtle should not mine (e.g. Stone, Dirt, Gravel etc.) in the first few slots of the turtle\'s inventory. The first empty slot signifies the end of the noise blocks.", messageLevel.FATAL)
  1706.   else
  1707.     -- If we are supporting resume (and are not currently in the process of resuming)
  1708.     -- then store startup parameters in appropriate files
  1709.     if ((supportResume == true) and (resuming == false)) then
  1710.       -- Write the startup parameters to  file
  1711.       local outputFile = io.open(startupParamsFile, "w")
  1712.       outputFile:write(quarryWidth)
  1713.       outputFile:write("\n")
  1714.       outputFile:write(startHeight)
  1715.       outputFile:write("\n")
  1716.       outputFile:write(noiseBlocksCount)
  1717.       outputFile:write("\n")
  1718.       outputFile:write(lastEmptySlot)
  1719.       outputFile:write("\n")
  1720.       outputFile:close()
  1721.  
  1722.       -- Setup the startup file
  1723.  
  1724.       -- Take a backup of the current startup file
  1725.       if (fs.exists("startup") == true) then
  1726.         fs.copy("startup", startupBackup)
  1727.         outputFile = io.open("startup", "a")
  1728.       else
  1729.         outputFile = io.open("startup", "w")
  1730.       end
  1731.      
  1732.       -- Write an info message so that people know how to get out of auto-resume
  1733.       outputFile:write("\nprint(\"Running auto-restart...\")\n")
  1734.       outputFile:write("print(\"If you want to stop auto-resume and restore original state:\")\n")
  1735.       outputFile:write("print(\"1) Hold Ctrl-T until the program terminates\")\n")
  1736.       outputFile:write("print(\"2) Type \\\"rm startup\\\" (without quotes) and hit Enter\")\n")
  1737.       outputFile:write("print(\"\")\n\n")
  1738.  
  1739.       -- Write the code required to restart the turtle
  1740.       outputFile:write("shell.run(\"")
  1741.       outputFile:write(shell.getRunningProgram())
  1742.       outputFile:write("\")\n")
  1743.       outputFile:close()
  1744.  
  1745.     end
  1746.  
  1747.     -- Create a Quarry
  1748.     turtle.select(1)
  1749.     currentlySelectedSlot = 1
  1750.     createQuarry()
  1751.  
  1752.     -- Restore the file system to its original configuration
  1753.     if (supportResume == true) then
  1754.       fs.delete("startup")
  1755.       if (fs.exists(startupBackup) == true) then
  1756.         fs.move(startupBackup, "startup")
  1757.       end
  1758.  
  1759.       if (fs.exists(startupParamsFile) == true) then
  1760.         fs.delete(startupParamsFile)
  1761.       end
  1762.  
  1763.       if (fs.exists(oreQuarryLocation) == true) then
  1764.         fs.delete(oreQuarryLocation)
  1765.       end
  1766.  
  1767.       if (fs.exists(returnToStartFile) == true) then
  1768.         fs.delete(returnToStartFile)
  1769.       end
  1770.     end
  1771.   end
  1772. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement