Advertisement
psi_overtake

OreQuarry with Depth

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