Advertisement
leftler

Quary with fixed rednet

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