cypren

OreMiner with Bounds

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