Advertisement
Guest User

OreQuarry mod by keepmind

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