goldfiction

OreQuarryHTTPV2

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