Illprotectjew

mine

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