Advertisement
civilwargeeky

Quarry 3.4.4

Mar 21st, 2014
4,497
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 53.07 KB | None | 0 0
  1. --[[
  2. Version 3.4.4
  3. Recent Changes:
  4.   Improved session restoring for those using fuel
  5.   Improved refueling algorithm
  6.   Added New Rednet Support
  7.   New Arguments!
  8.     -atChest [force] Using this with -resume will tell the turtle that it is at its chest, and needs to go back to where it was
  9.     -maxTries [number 1-9000] This is the number of times the turtle will try to mine something before it checks for bedrock
  10.   Arguments are no longer ignored if you use "-default", you just won't be prompted for anything.
  11.   Boolean (t/f) arguments now accept "yes" as well as "true"
  12. ]]
  13. --Defining things
  14. civilTable = nil; _G.civilTable = {}; setmetatable(civilTable, {__index = _G}); setfenv(1,civilTable)
  15. -------Defaults for Arguments----------
  16. --Arguments assignable by text
  17. x,y,z = 3,3,3 --These are just in case tonumber fails
  18. inverted = false --False goes from top down, true goes from bottom up [Default false]
  19. rednetEnabled = false --Default rednet on or off  [Default false]
  20. --Arguments assignable by tArgs
  21. dropSide = "front" --Side it will eject to when full or done [Default "front"]
  22. careAboutResources = true --Will not stop mining once inventory full if false [Default true]
  23. doCheckFuel = true --Perform fuel check [Default true]
  24. doRefuel = false --Whenever it comes to start location will attempt to refuel from inventory [Default false]
  25. invCheckFreq = 10 --Will check for inventory full every <-- moved spaces [Default 10]
  26. keepOpen = 1 --How many inventory slots it will attempt to keep open at all times [Default 1]
  27. fuelSafety = "moderate" --How much fuel it will ask for: safe, moderate, and loose [Default moderate]
  28. saveFile = "Civil_Quarry_Restore" --Where it saves restore data [Default "Civil_Quarry_Restore"]
  29. doBackup = true --If it will keep backups for session persistence [Default true]
  30. uniqueExtras = 8 --How many different items (besides cobble) the turtle expects. [Default 8]
  31. maxTries = 50 --How many times turtle will try to dig a block before it "counts" bedrock [Default 50]
  32. gpsEnabled = false -- If option is enabled, will attempt to find position via GPS api [Default false]
  33. gpsTimeout = 3 --The number of seconds the program will wait to get GPS coords. Not in arguments [Default 3]
  34. logging = true --Whether or not the turtle will log mining runs. [Default ...still deciding]
  35. logFolder = "Quarry_Logs" --What folder the turtle will store logs in [Default "Quarry_Logs"]
  36. logExtension = "" --The extension of the file (e.g. ".txt") [Default ""]
  37. startDown = 0 --How many blocks to start down from the top of the mine [Default 0]
  38. enderChestEnabled = false --Whether or not to use an ender chest [Default false]
  39. enderChestSlot = 16 --What slot to put the ender chest in [Default 16]
  40. --Standard number slots for fuel (you shouldn't care)
  41. fuelTable = { --Will add in this amount of fuel to requirement.
  42. safe = 1000,
  43. moderate = 200,
  44. loose = 0 } --Default 1000, 200, 0
  45. --Standard rednet channels
  46. channels = {
  47. send = os.getComputerID() + 1  ,
  48. receive = os.getComputerID() + 101 ,
  49. confirm = "Turtle Quarry Receiver",
  50. message = "Civil's Quarry",
  51. }
  52.  
  53. local help_paragraph = [[
  54. Welcome!: Welcome to quarry help. Below are help entries for all parameters. Examples and tips are at the bottom.
  55. -Default: This will force no prompts. If you use this and nothing else, only defaults will be used.
  56. -dim: [length] [width] [height] This sets the dimensions for the quarry
  57. -invert: [t/f] If true, quarry will be inverted (go up instead of down)
  58. -rednet: [t/f] If true and you have a wireless modem on the turtle, will attempt to make a rednet connection for sending important information to a screen
  59. -restore / -resume: If your quarry stopped in the middle of its run, use this to resume at the point where the turtle was. Not guarenteed to work properly. For more accurate location finding, check out the -GPS parameter
  60. -atChest: [force] This is for use with "-restore," this will tell the restarting turtle that it is at its home chest, so that if it had gotten lost, it now knows where it is.
  61. -doRefuel: [t/f] If true, the turtle will refuel itself with coal and planks it finds on its mining run
  62. -doCheckFuel: [t/f] If you for some reason don't want the program to check fuel usage, set to false. This is honestly a hold-over from when the refueling algorithm was awful...
  63. -uniqueExtras: [number] The expected number of slots filled with low-stacking items like ore. Higher numbers request more fuel.
  64. -chest: [side] This specifies what side the chest at the end will be on. You can say "top", "bottom", "front", "left", or "right"
  65. -enderChest: This one is special. If you use "-enderChest true" then it will use an enderChest in the default slot. However, you can also do "-enderChest [slot]" then it will take the ender chest from whatever slot you tell it to. Like 7... or 14... or whatever.
  66. -GPS: [force] If you use "-GPS" and there is a GPS network, then the turtle will record its first two positions to precisly calculate its position if it has to restart. This will only take two GPS readings
  67. -sendChannel: [number] This is what channel your turtle will send rednet messages on
  68. -receiveChannel: [number] This is what channel your turtle will receive rednet messages on
  69. -startY: [current Y coord] Randomly encountering bedrock? This is the parameter for you! Just give it what y coordinate you are at right now. If it is not within bedrock range, it will never say it found bedrock
  70. -maxTries: [number] This is the number of times the turtle will try to dig before deciding its run into bedrock.
  71. -logging: [t/f] If true, will record information about its mining run in a folder at the end of the mining run
  72. -doBackup: [t/f] If false, will not back up important information and cannot restore, but will not make an annoying file (Actually I don't really know why anyone would use this...)
  73. -saveFile: [word] This is what the backup file will be called
  74. -logFolder: [word] The folder that quarry logs will be stored in
  75. -logExtension: [word] The extension given to each quarry log (e.g. ".txt" or ".notepad" or whatever)
  76. -invCheckFreq: [number] This is how often the turtle will check if it has the proper amount of slots open
  77. -keepOpen: [number] This is the number of the slots the turtle will make sure are open. It will check every invCheckFreq blocks
  78. -careAboutResources: [t/f] Who cares about the materials! If set to false, it will just keep mining when its inventory is full
  79. -startDown: [number] If you set this, the turtle will go down this many blocks from the start before starting its quarry
  80.   =
  81.   C _ |
  82.       |
  83.       |
  84.       |
  85.       |_ _ _ _ >
  86. -manualPos: [xPos] [zPos] [yPos] [facing] This is for advanced use. If the server reset when the turtle was in the middle of a 100x100x100 quarry, fear not, you can now manually set the position of the turtle. yPos is always positive. The turtle's starting position is 0, 1, 1, 0. Facing is measured 0 - 3. 0 is forward, and it progresses clockwise. Example- "-manualPos 65 30 30 2"
  87. -help: Thats what this is :D
  88. Examples: Everything below is examples and tips for use
  89. Important Note:
  90.  None of the above parameters are necessary. They all have default values, and the above are just if you want to change them.
  91. Examples [1]:
  92.  Want to just start a quarry from the interface, without going through menus? It's easy! Just use some parameters. Assume you called the program "quarry." To start a 10x6x3 quarry, you just type in "quarry -dim 10 6 3 -default".
  93.   You just told it to start a quarry with dimensions 10x6x3, and "-default" means it won't prompt you about invert or rednet. Wasn't that easy?
  94. Examples [2]:
  95.   Okay, so you've got the basics of this now, so if you want, you can type in really long strings of stuff to make the quarry do exactly what you want. Now, say you want a 40x20x9, but you want it to go down to diamond level, and you're on the surface (at y = 64). You also want it to send rednet messages to your computer so you can see how its doing.
  96. Examples [2] [cont.]:
  97.   Oh yeah! You also want it to use an ender chest in slot 12 and restart if the server crashes. Yeah, you can do that. You would type
  98.   "quarry -dim 40x20x9 -invert false -startDown 45 -rednet true -enderChest 12 -restore"
  99.   BAM. Now you can just let that turtle do it's thing
  100. Tips:
  101.  The order of the parameters doesn't matter. "quarry -invert false -rednet true" is the same as "quarry -rednet true -invert false"
  102.  
  103.   Capitalization doesn't matter. "quarry -iNVErt FALSe" does the same thing as "quarry -invert false"
  104. Tips [cont.]:
  105.  For [t/f] parameters, you can also use "yes" and "no" so "quarry -invert yes"
  106.  
  107.  For [t/f] parameters, it only cares about the first letter. So you can use "quarry -invert t" or "quarry -invert y"
  108. Tips [cont.]:
  109.  If you are playing with fuel turned off, the program will automatically change settings for you so you don't have to :D
  110.  
  111.   If you want, you can load this program onto a computer, and use "quarry -help" so you can have help with the parameters whenever you want.
  112. Internal Config:
  113.   At the top of this program is an internal configuration file. If there is some setup that you use all the time, you can just change the config value at the top and run "quarry -default" for a quick setup.
  114.  
  115.   You can also use this if there are settings that you don't like the default value of.
  116. ]]
  117.  
  118. --Parsing help for display
  119. --[[The way the help table works:
  120. All help indexes are numbered. There is a help[i].title that contains the title,
  121. and the other lines are in help[i][1] - help[i][#help[i] ]
  122. Different lines (e.g. other than first) start with a space.
  123. As of now, the words are not wrapped, fix that later]]
  124. local help = {}
  125. local i = 0
  126. local titlePattern = ".-%:" --Find the beginning of the line, then characters, then a ":"
  127. local textPattern = "%:.+" --Find a ":", then characters until the end of the line
  128. for a in help_paragraph:gmatch("\n?.-\n") do --Matches in between newlines
  129. local current = string.sub(a,1,-2).."" --Concatenate Trick
  130. if string.sub(current,1,1) ~= " " then
  131. i = i + 1
  132. help[i] = {}
  133. help[i].title = string.sub(string.match(current, titlePattern),1,-2)..""
  134. help[i][1] = string.sub(string.match(current,textPattern) or " ",3,-1)
  135. elseif string.sub(current,1,1) == " " then
  136. table.insert(help[i], string.sub(current,2, -1).."")
  137. end
  138. end
  139.  
  140.  
  141. local supportsRednet = (peripheral.wrap("right") ~= nil)
  142.  
  143. local tArgs = {...}
  144. --You don't care about these
  145.       xPos,yPos,zPos,facing,percent,mined,moved,relxPos, rowCheck, connected, isInPath, layersDone, attacked, startY, chestFull, gotoDest, atChest, fuelLevel, numDropOffs
  146.     = 0,   1,   1,   0,     0,      0,    0,    1,       true   ,  false,     true,     1,          0,        0,      false,     "",       false,   0,         0
  147.    
  148. --NOTE: rowCheck is a bit. true = "right", false = "left"
  149.    
  150. local foundBedrock = false
  151.  
  152. local totals = {cobble = 0, fuel = 0, other = 0} -- Total for display (cannot go inside function)
  153. local function count() --Done any time inventory dropped and at end
  154. slot = {}        --1: Cobble 2: Fuel 3:Other
  155. for i=1, 16 do   --[1] is type, [2] is number
  156. slot[i] = {}
  157. slot[i][2] = turtle.getItemCount(i)
  158. end
  159. slot[1][1] = 1   -- = Assumes Cobble/Main
  160. for i=1, 16 do   --Cobble Check
  161. turtle.select(i)
  162. if turtle.compareTo(1)  then
  163. slot[i][1] = 1
  164. totals.cobble = totals.cobble + slot[i][2]
  165. elseif turtle.refuel(0) then
  166. slot[i][1] = 2
  167. totals.fuel = totals.fuel + slot[i][2]
  168. else
  169. slot[i][1] = 3
  170. totals.other = totals.other + slot[i][2]
  171. end
  172. end
  173. turtle.select(1)
  174. end
  175.  
  176. local getFuel, checkFuel
  177. if turtle then
  178.   getFuel = turtle.getFuelLevel  --This is for cleanup at the end
  179.   do --Common variable name...
  180.   local flag = turtle.getFuelLevel() == "unlimited"--Unlimited screws up my calculations
  181.   if flag then --Fuel is disabled
  182.     turtle.getFuelLevel = function() return math.huge end --Infinite Fuel
  183.   end --There is no "else" because it will already return the regular getFuel
  184.   end
  185.   checkFuel = turtle.getFuelLevel --Just an alias for backwards compat
  186. end
  187.  
  188.  -----------------------------------------------------------------
  189. --Input Phase
  190. local function screen(xPos,yPos)
  191. xPos, yPos = xPos or 1, yPos or 1
  192. term.setCursorPos(xPos,yPos); term.clear(); end
  193. local function screenLine(xPos,yPos)
  194. term.setCursorPos(xPos,yPos); term.clearLine(); end
  195.  
  196. screen(1,1)
  197. print("----- Welcome to Quarry! -----")
  198. print("")
  199.  
  200. local sides = {top = "top", right = "right", left = "left", bottom = "bottom", front = "front"} --Used to whitelist sides
  201. local changedT, tArgsWithUpper = {}, {}
  202. changedT.new = function(key, value) table.insert(changedT,{key, value}) end --Numeric list of lists
  203. local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end
  204. for i=1, #tArgs do tArgsWithUpper[i] = tArgs[i]; tArgsWithUpper[tArgsWithUpper[i]] = i; tArgs[i] = tArgs[i]:lower(); tArgs[tArgs[i]] = i end --My signature key-value pair system, now with upper
  205.  
  206. local restoreFound, restoreFoundSwitch = false --Initializing so they are in scope
  207. function addParam(name, displayText, formatString, forcePrompt, trigger, variableOverride) --To anyone that doesn't understand this very well, probably not your best idea to go in here.
  208.   if trigger == nil then trigger = true end --Defaults to being able to run
  209.   if not trigger then return end --This is what the trigger is for. Will not run if trigger not there
  210.   if restoreFoundSwitch or tArgs["-default"] then forcePrompt = false end --Don't want to prompt if these
  211.   local toGetText = name:lower() --Because all params are now lowered
  212.   local formatType = formatString:match("^%a+"):lower() or error("Format String Unknown: "..formatString) --Type of format string
  213.   local args = formatString:sub(({formatString:find(formatType)})[2] + 2).."" --Everything in formatString but the type and space
  214.   local variable = variableOverride or name --Goes first to the override for name
  215.   local func = loadstring("return "..variable)
  216.   setfenv(func,getfenv(1))
  217.   local originalValue = assert(func)() --This is the default value, for checking to add to changed table
  218.   if originalValue == nil then error("From addParam, \""..variable.."\" returned nil",2) end --I may have gotten a wrong variable name
  219.   local givenValue, toRet --Initializing for use
  220.   if tArgs["-"..toGetText] then
  221.     givenValue = tArgsWithUpper[tArgs["-"..toGetText]+1] --This is the value after the desired parameter
  222.   elseif forcePrompt then
  223.     write(displayText.."? ")
  224.     givenValue = io.read()
  225.   end
  226.   if formatType == "force" then --This is the one exception. Should return true if givenValue is nothing
  227.     toRet = (tArgs["-"..toGetText] and true) or false --Will return true if param exists, otherwise false
  228.   end
  229.   if not (givenValue or toRet) then return end --Don't do anything if you aren't given anything. Leave it as default, except for "force"
  230.   if formatType == "boolean" then --All the format strings will be basically be put through a switch statement
  231.     toRet = givenValue:sub(1,1):lower() == "y" or givenValue:sub(1,1):lower() == "t" --Accepts true or yes
  232.     if formatString == "boolean special" then
  233.       toRet = givenValue:sub(1,1):lower() ~= "n" and givenValue:sub(1,1):lower() ~= "f" --Accepts anything but false or no
  234.     end
  235.   elseif formatType == "string" then
  236.     toRet = givenValue:match("^[%w%.]+") --Basically anything not a space or control character etc
  237.   elseif formatType == "number" then
  238.     toRet = tonumber(givenValue) --Note this is a local, not the above so we don't change anything
  239.     if not toRet then return end --We need a number... Otherwise compare errors
  240.     toRet = math.abs(math.floor(toRet)) --Get proper integers
  241.     local startNum, endNum = formatString:match("(%d+)%-(%d+)") --Gets range of numbers
  242.     startNum, endNum = tonumber(startNum), tonumber(endNum)
  243.     if not ((toRet >= startNum) and (toRet <= endNum)) then return end --Can't use these
  244.   elseif formatType == "side" then
  245.     local exclusionTab = {} --Ignore the wizardry here. Just getting arguments without format string
  246.     for a in args:gmatch("%S+") do exclusionTab[a] = true end --This makes a list of the sides to not include
  247.     if not exclusionTab[givenValue] then toRet = sides[givenValue] end --If side is not excluded
  248.   elseif formatType == "list" then
  249.     toRet = {}
  250.     for a in args:gmatch("[^,]") do
  251.       table.insert(toRet,a)
  252.     end
  253.   elseif formatType == "force" then --Do nothing, everything is already done
  254.   else error("Improper formatType",2)
  255.   end
  256.   if toRet == nil then return end --Don't want to set variables to nil... That's bad
  257.   tempParam = toRet --This is what loadstring will see :D
  258.   local func = loadstring(variable.." = tempParam")
  259.   setfenv(func, getfenv(1))
  260.   func()
  261.   tempParam = nil --Cleanup of global
  262.   if toRet ~= originalValue then
  263.     changedT.new(displayText, tostring(toRet))
  264.   end
  265.   return toRet
  266. end
  267.  
  268. --Check if it is a turtle
  269. if not(turtle or tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"]) then --If all of these are false then
  270.   print("This is not a turtle, you might be looking for the \"Companion Rednet Program\" \nCheck My forum thread for that")
  271.   print("Press 'q' to quit, or any other key to start help ")
  272.   if ({os.pullEvent("char")})[2] ~= "q" then tArgs.help = true else error("",0) end
  273. end
  274.  
  275. if tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"] then
  276. print("You have selected help, press any key to continue"); print("Use arrow keys to naviate, q to quit"); os.pullEvent("key")
  277. local pos = 1
  278. local key = 0
  279. while pos <= #help and key ~= keys.q do
  280. if pos < 1 then pos = 1 end
  281. screen(1,1)
  282. print(help[pos].title)
  283. for a=1, #help[pos] do print(help[pos][a]) end
  284. repeat
  285. _, key = os.pullEvent("key")
  286. until key == 200 or key == 208 or key == keys.q
  287. if key == 200 then pos = pos - 1 end
  288. if key == 208 then pos = pos + 1 end
  289. end
  290. error("",0)
  291. end
  292.  
  293. --Saving
  294. addParam("doBackup", "Backup Save File", "boolean")
  295. addParam("saveFile", "Save File Name", "string")
  296.  
  297. restoreFound = fs.exists(saveFile)
  298. restoreFoundSwitch = (tArgs["-restore"] or tArgs["-resume"] or tArgs["-atchest"]) and restoreFound
  299. if restoreFoundSwitch then
  300.   local file = fs.open(saveFile,"r")
  301.   local test = file.readAll() ~= ""
  302.   file.close()
  303.   if test then
  304.     os.run(getfenv(1),saveFile) --This is where the actual magic happens
  305.     if turtle.getFuelLevel() ~= math.huge then --If turtle uses fuel
  306.       if fuelLevel - turtle.getFuelLevel() == 1 then
  307.         if facing == 0 then xPos = xPos + 1
  308.         elseif facing == 2 then xPos = xPos - 1
  309.         elseif facing == 1 then zPos = zPos + 1
  310.         elseif facing == 3 then zPos = zPos - 1 end
  311.       elseif fuelLevel - turtle.getFuelLevel() ~= 0 then
  312.         print("Very Strange Fuel in Restore Section...")
  313.         print("Current: ",turtle.getFuelLevel())
  314.         print("Saved: ",fuelLevel)
  315.         print("Difference: ",fuelLevel - turtle.getFuelLevel())
  316.         os.pullEvent("char")
  317.       end
  318.      end
  319.     if gpsEnabled then --If it had saved gps coordinates
  320.       print("Found GPS Start Coordinates")
  321.       local currLoc = {gps.locate(gpsTimeout)} or {}
  322.       local backupPos = {xPos, yPos, zPos} --This is for comparing to later
  323.       if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using
  324.         print("GPS Position Successfully Read")
  325.         if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order
  326.           xPos, yPos, zPos = 0,1,1
  327.           if facing ~= 0 then turnTo(0) end
  328.           print("Is at start")
  329.         else
  330.           if inverted then --yPos setting
  331.           ------------------------------------------------FIX THIS
  332.           end
  333.           local function copyTable(tab) local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end
  334.           local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience
  335.           if b[3] - a[3] == -1 then--If went north (-Z)
  336.             a[1] = a[1] - 1 --Shift x one to west to create a "zero"
  337.             xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]
  338.           elseif b[1] - a[1] == 1 then--If went east (+X)
  339.             a[3] = a[3] - 1 --Shift z up one to north to create a "zero"
  340.             xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]
  341.           elseif b[3] - a[3] == 1 then--If went south (+Z)
  342.             a[1] = a[1] + 1 --Shift x one to east to create a "zero"
  343.             xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]
  344.           elseif b[1] - a[1] == -1 then--If went west (-X)
  345.             a[3] = a[3] + 1 --Shift z down one to south to create a "zero"
  346.             xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]
  347.           else
  348.             print("Improper Coordinates")
  349.             print("GPS Locate Failed, Using Standard Methods")        ----Maybe clean this up a bit to use flags instead.
  350.           end  
  351.         end
  352.         print("X Pos: ",xPos)
  353.         print("Y Pos: ",yPos)
  354.         print("Z Pos: ",zPos)
  355.         print("Facing: ",facing)
  356.         for i=1, 3, 2 do --We want 1 and 3, but 2 could be coming back to start.
  357.           if backupPos[i] ~= currLoc[i] then
  358.             events = {} --We want to remove event queue if not in proper place, so won't turn at end of row or things.
  359.           end
  360.         end
  361.       else
  362.         print("GPS Locate Failed, Using Standard Methods")
  363.       end    
  364.     print("Restore File read successfully. Starting in 3"); sleep(3)
  365.     end
  366.   else
  367.     fs.delete(saveFile)
  368.     print("Restore file was empty, sorry, aborting")
  369.     error("",0)
  370.   end
  371. else --If turtle is just starting
  372.   events = {} --This is the event queue :D
  373.   originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used
  374. end
  375.  
  376. --Dimensions
  377. if tArgs["-dim"] then
  378.   local a,b,c = x,y,z
  379.   local num = tArgs["-dim"]
  380.   x = tonumber(tArgs[num + 1]) or x; z = tonumber(tArgs[num + 2]) or z; y = tonumber(tArgs[num + 3]) or y
  381.   if a ~= x then changedT.new("Length", x) end
  382.   if c ~= z then changedT.new("Width", z) end
  383.   if b ~= y then changedT.new("Height", y) end
  384. elseif not (tArgs["-default"] or restoreFoundSwitch) then
  385.   print("What dimensions?")
  386.   print("")
  387.   --This will protect from negatives, letters, and decimals
  388.   term.write("Length? ")
  389.   x = math.floor(math.abs(tonumber(io.read()) or x))
  390.   term.write("Width? ")
  391.   z = math.floor(math.abs(tonumber(io.read()) or z))
  392.   term.write("Height? ")
  393.   y = math.floor(math.abs(tonumber(io.read()) or y))
  394.   changedT.new("Length",x); changedT.new("Width",z); changedT.new("Height",y)
  395. end
  396. --Invert
  397. addParam("invert", "Inverted","boolean", true, nil, "inverted")
  398. addParam("startDown","Start Down","number 1-256")
  399. --Inventory
  400. addParam("chest", "Chest Drop Side", "side front", nil, nil, "dropSide")
  401. addParam("enderChest","Ender Chest Enabled","boolean special", nil, nil, "enderChestEnabled") --This will accept anything (including numbers) thats not "f" or "n"
  402. addParam("enderChest", "Ender Chest Slot", "number 1-16", nil, nil, "enderChestSlot") --This will get the number slot if given
  403. --Rednet
  404. addParam("rednet", "Rednet Enabled","boolean",true, supportsRednet, "rednetEnabled")
  405. addParam("gps", "GPS Location Services", "force", nil, (not restoreFoundSwitch) and supportsRednet, "gpsEnabled" ) --Has these triggers so that does not record position if restarted.
  406. if gpsEnabled and not restoreFoundSwitch then
  407.   gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array
  408.   gpsEnabled = #gpsStartPos > 0 --Checks if location received properly. If not, position is not saved
  409. end
  410. addParam("sendChannel", "Rednet Send Channel", "number 1-65535", false, supportsRednet, "channels.send")
  411. addParam("receiveChannel","Rednet Receive Channel", "number 1-65535", false, supportsRednet, "channels.receive")
  412. --Fuel
  413. addParam("uniqueExtras","Unique Items", "number 0-15")
  414. addParam("doRefuel", "Refuel from Inventory","boolean", nil, turtle.getFuelLevel() ~= math.huge) --math.huge due to my changes
  415. addParam("doCheckFuel", "Check Fuel", "boolean", nil, turtle.getFuelLevel() ~= math.huge)
  416. --Logging
  417. addParam("logging", "Logging", "boolean")
  418. addParam("logFolder", "Log Folder", "string")
  419. addParam("logExtension","Log Extension", "string")
  420. --Misc
  421. addParam("startY", "Start Y","number 1-256")
  422. addParam("invCheckFreq","Inventory Check Frequency","number 1-342")
  423. addParam("keepOpen", "Slots to Keep Open", "number 1-15")
  424. addParam("careAboutResources", "Care About Resources","boolean")
  425. addParam("maxTries","Tries Before Bedrock", "number 1-9001")
  426. --Manual Position
  427. if tArgs["-manualpos"] then --Gives current coordinates in xPos,zPos,yPos, facing
  428.   local a = tArgs["-manualpos"]
  429.   xPos, zPos, yPos, facing = tonumber(tArgs[a+1]) or xPos, tonumber(tArgs[a+2]) or zPos, tonumber(tArgs[a+3]) or yPos, tonumber(tArgs[a+4]) or facing
  430.   changedT.new("xPos",xPos); changedT.new("zPos",zPos); changedT.new("yPos",yPos); changedT.new("facing",facing)
  431.   restoreFoundSwitch = true --So it doesn't do beginning of quarry behavior
  432. end
  433. if addParam("atChest", "Is at Chest", "force") then --This sets position to 0,1,1, facing forward, and queues the turtle to go back to proper row.
  434.   local neededLayer = math.floor((yPos+1)/3)*3-1 --Make it a proper layer, +- because mining rows are 2, 5, etc.
  435.   if neededLayer > 2 and neededLayer%3 ~= 2 then --If turtle was not on a proper mining layer
  436.     print("Last known pos was not in proper layer, restarting quarry")
  437.     sleep(4)
  438.     neededLayer = 2
  439.   end
  440.   xPos, zPos, yPos, facing, rowCheck, layersDone = 0,1,1, 0, true, math.ceil(neededLayer/3)
  441.   events = {{"goto",1,1,neededLayer, 0}}
  442. end
  443.  
  444.  
  445. local function saveProgress(extras) --Session persistence
  446. exclusions = { modem = true, }
  447. if doBackup then
  448. local toWrite = ""
  449. for a,b in pairs(getfenv(1)) do
  450.   if not exclusions[a] then
  451.       --print(a ,"   ", b, "   ", type(b)) --Debug
  452.     if type(b) == "string" then b = "\""..b.."\"" end
  453.     if type(b) == "table" then b = textutils.serialize(b) end
  454.     if type(b) ~= "function" then
  455.       toWrite = toWrite..a.." = "..tostring(b).."\n"
  456.     end
  457.   end
  458. end
  459. toWrite = toWrite.."doCheckFuel = false\n" --It has already used fuel, so calculation unnesesary
  460. local file
  461. repeat
  462.   file = fs.open(saveFile,"w")
  463. until file --WHY DOES IT SAY ATTEMPT TO INDEX NIL!!!
  464. file.write(toWrite)
  465. if type(extras) == "table" then
  466.   for a, b in pairs(extras) do
  467.     file.write(a.." = "..tostring(b))
  468.   end
  469. end
  470. if turtle.getFuelLevel() ~= math.huge then --Used for location comparing
  471.   file.write("fuelLevel = "..tostring(turtle.getFuelLevel()))
  472. end
  473. file.close()
  474. end
  475. end
  476.  
  477. local area = x*z
  478. local volume = x*y*z
  479. local lastHeight = y%3
  480. layers = math.ceil(y/3)
  481. local yMult = layers --This is basically a smart y/3 for movement
  482. local moveVolume = (area * yMult) --Kept for display percent
  483. --Calculating Needed Fuel--
  484. do --Because many local variables unneeded elsewhere
  485.   local numItems = uniqueExtras --Convenience
  486.   local itemSize = extrasStackSize
  487.   local changeYFuel = 2*(y + startDown)
  488.   local dropOffSupplies = 2*(x + z + y + startDown) --Assumes turtle as far away as possible, and coming back
  489.   local frequency = math.floor(((volume/(64*(16-numItems))) ) --This is complicated: volume / inventory space of turtle, defined as (16-num unique stacks)
  490.                                  * (layers/y)) --This is the ratio of height to actual height mined. Close to 1/3 usually, so divide above by 3
  491.   if enderChestEnabled then frequency = 0 end
  492.   neededFuel = moveVolume + changeYFuel + frequency * dropOffSupplies
  493. end
  494.  
  495.  
  496. --[[
  497. local exStack = numberOfStacksPerRun --Expected stacks of items before full
  498. neededFuel = yMult * x * z + --This is volume it will run through
  499.       (startDown + y)*(2+1/(64*exStack)) + --This is simplified and includes the y to get up times up and down + how many times it will drop stuff off
  500.       (x+z)*(yMult + 1/(64*exStack))  --Simplified as well: It is getting to start of row plus getting to start of row how many times will drop off stuff
  501.       --Original equation: x*z*y/3 + y * 2 + (x+z) * y/3 + (x + z + y) * (1/64*8)
  502. neededFuel = math.ceil(neededFuel)
  503. ]]
  504. --Getting Fuel
  505. if doCheckFuel and checkFuel() < neededFuel then
  506. neededFuel = neededFuel + fuelTable[fuelSafety] --For safety
  507.   print("Not enough fuel")
  508.   print("Current: ",checkFuel()," Needed: ",neededFuel)
  509.   print("Starting SmartFuel...")
  510.   sleep(2) --So they can read everything.
  511.   term.clear()
  512.   local oneFuel, neededFuelItems
  513.   local currSlot = 0
  514.   local function output(text, x, y) --For displaying fuel
  515.     local currX, currY = term.getCursorPos()
  516.     term.setCursorPos(x,y)
  517.     term.clearLine()
  518.     term.write(text)
  519.     term.setCursorPos(currX,currY)
  520.     end
  521.   local function roundTo(num, target) --For stacks of fuel
  522.     if num >= target then return target elseif num < 0 then return 0 else return num end
  523.   end
  524.   local function updateScreen()
  525.     output("Welcome to SmartFuel! Now Refueling...", 1,1)
  526.     output("Currently taking fuel from slot "..currSlot,1,2)
  527.     output("Current single fuel: "..tostring(oneFuel or 0),1,3)
  528.     output("Current estimate of needed fuel: ",1,4)
  529.     output("Single Items: "..math.ceil(neededFuelItems or 0),4,5)
  530.     output("Stacks:       "..math.ceil((neededFuelItems or 0) / 64),4,6)
  531.     output("Needed Fuel: "..tostring(neededFuel),1,12)
  532.     output("Current Fuel: "..tostring(checkFuel()),1,13)
  533.   end
  534.   while checkFuel() <= neededFuel do
  535.     currSlot = currSlot + 1
  536.     turtle.select(currSlot)
  537.     updateScreen()
  538.     while turtle.getItemCount(currSlot) == 0 do sleep(1.5) end
  539.     repeat
  540.       local previous = checkFuel()
  541.       turtle.refuel(1)
  542.       oneFuel = checkFuel() - previous
  543.       updateScreen()
  544.     until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.
  545.     neededFuelItems = (neededFuel - checkFuel()) / oneFuel
  546.     turtle.refuel(math.ceil(roundTo(neededFuelItems, 64))) --Change because can only think about 64 at once.
  547.     if turtle.getItemCount(roundTo(currSlot + 1, 16)) == 0 then --Resets if no more fuel
  548.       currSlot = 0
  549.     end
  550.     neededFuelItems = (neededFuel - checkFuel()) / oneFuel
  551.   end
  552. end
  553. --Ender Chest Obtaining
  554. function promptEnderChest()
  555.   while turtle.getItemCount(enderChestSlot) ~= 1 do
  556.     screen(1,1)
  557.     print("You have decided to use an Ender Chest!")
  558.     print("Please place one Ender Chest in slot ",enderChestSlot)
  559.     sleep(1)
  560.   end
  561.   print("Ender Chest in slot ",enderChestSlot, " checks out")
  562. end
  563. if enderChestEnabled then
  564.     if restoreFoundSwitch and turtle.getItemCount(enderChestSlot) == 0 then --If the turtle was stopped while dropping off items.
  565.       turtle.select(enderChestSlot)
  566.       turtle.dig()
  567.       turtle.select(1)
  568.     end
  569.   promptEnderChest()
  570.   sleep(2)
  571. end
  572. --Initial Rednet Handshake
  573. if rednetEnabled then
  574. screen(1,1)
  575. print("Rednet is Enabled")
  576. print("The Channel to open is "..channels.send)
  577. modem = peripheral.wrap("right")
  578. modem.open(channels.receive)
  579. local i = 0
  580.   repeat
  581.     local id = os.startTimer(3)
  582.     i=i+1
  583.     print("Sending Initial Message "..i)
  584.     modem.transmit(channels.send, channels.receive, channels.message)
  585.     local message
  586.     repeat
  587.       local event, idCheck, channel,_,locMessage, distance = os.pullEvent()
  588.       message = locMessage
  589.     until (event == "timer" and idCheck == id) or (event == "modem_message" and channel == channels.receive and message == channels.confirm)
  590.   until message == channels.confirm
  591. connected = true
  592. print("Connection Confirmed!")
  593. sleep(1.5)
  594. end
  595. function biometrics(isAtBedrock)
  596.   local toSend = { label = os.getComputerLabel() or "No Label", id = os.getComputerID(),
  597.     percent = percent, relxPos = relxPos, zPos = zPos, xPos = xPos, yPos = yPos,
  598.     layersDone = layersDone, x = x, z = z, layers = layers,
  599.     openSlots = getNumOpenSlots(), mined = mined, moved = moved,
  600.     chestFull = chestFull, isAtChest = (xPos == 0 and yPos == 1 and zPos == 1),
  601.     isGoingToNextLayer = (gotoDest == "layerStart"), foundBedrock = foundBedrock,
  602.     fuel = turtle.getFuelLevel(), volume = volume,
  603.     }
  604.   modem.transmit(channels.send, channels.receive, textutils.serialize(toSend))
  605.   id = os.startTimer(0.1)
  606.   local event, message
  607.   repeat
  608.     local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()
  609.     event, message = locEvent, locMessage
  610.   until (event == "timer" and idCheck == id) or (event == "modem_message" and confirm == channels.receive)
  611.   if event == "modem_message" then connected = true else connected = false end
  612.   message = message or ""
  613.   message = message:lower()
  614.   if message == "stop" then error("Rednet said to stop...",0) end
  615.   if message == "return" then
  616.     endingProcedure()
  617.     error('Rednet said go back to start...',0)
  618.   end
  619.   if message == "drop" then
  620.     dropOff()
  621.   end
  622. end
  623. --Showing changes to settings
  624. screen(1,1)
  625. print("Your selected settings:")
  626. if #changedT == 0 then
  627. print("Completely Default")
  628. else
  629. for i=1, #changedT do
  630. print(changedT[i][1],": ",changedT[i][2]) --Name and Value
  631. end
  632. end
  633. print("\nStarting in 3"); sleep(1); print("2"); sleep(1); print("1"); sleep(1.5) --Dramatic pause at end
  634.  
  635.  
  636.  
  637. ----------------------------------------------------------------
  638. --Define ALL THE FUNCTIONS
  639. function eventAdd(...)
  640.   return table.insert(events,1, {...}) or true
  641. end
  642. function eventGet(pos)
  643.   return events[tonumber(pos) or #events]
  644. end
  645. function eventPop(pos)
  646.   return table.remove(events,tonumber(pos) or #events) or false --This will return value popped, tonumber returns nil if fail, so default to end
  647. end
  648. function eventRun(value, ...)
  649.   local argsList = {...}
  650.   if type(value) == "string" then
  651.     if value:sub(-1) ~= ")" then --So supports both "up()" and "up"
  652.       value = value .. "("
  653.       for a, b in pairs(argsList) do --Appending arguments
  654.         local toAppend
  655.         if type(b) == "table" then toAppend = textutils.serialize(b)
  656.         elseif type(b) == "string" then toAppend = "\""..tostring(b).."\"" --They weren't getting strings around them
  657.         else toAppend = tostring(b) end
  658.         value = value .. (toAppend or "true") .. ", "
  659.       end
  660.       if value:sub(-1) ~= "(" then --If no args, do not want to cut off
  661.         value = value:sub(1,-3)..""
  662.       end
  663.       value = value .. ")"
  664.     end
  665.     --print(value) --Debug
  666.     local func = loadstring(value)
  667.     setfenv(func, getfenv(1))
  668.     return func()
  669.   end
  670. end
  671.  
  672. function eventClear(pos)
  673.   if pos then events[pos] = nil else events = {} end
  674. end
  675.      
  676. function runAllEvents()
  677.   while #events > 0 do
  678.     local toRun = eventGet()
  679.     --print(toRun[1]) --Debug
  680.     eventRun(unpack(toRun))
  681.     eventPop()
  682.   end
  683. end
  684.  
  685. function display() --This is just the last screen that displays at the end
  686.   screen(1,1)
  687.   print("Total Blocks Mined: "..mined)
  688.   print("Current Fuel Level: "..turtle.getFuelLevel())
  689.   print("Cobble: "..totals.cobble)
  690.   print("Usable Fuel: "..totals.fuel)
  691.   print("Other: "..totals.other)
  692.   if rednetEnabled then
  693.     print("")
  694.     print("Sent Stop Message")
  695.     local finalTable = {mined = mined, cobble = totals.cobble, fuelblocks = totals.fuel,
  696.         other = totals.other, fuel = checkFuel() }
  697.     modem.transmit(channels.send,channels.receive,"stop")
  698.     sleep(0.5)
  699.     modem.transmit(channels.send,channels.receive,textutils.serialize(finalTable))
  700.     modem.close(channels.receive)
  701.   end
  702.   if doBackup then fs.delete(saveFile) end
  703. end
  704. function updateDisplay() --Runs in Mine(), display information to the screen in a certain place
  705. screen(1,1)
  706. print("Blocks Mined")
  707. print(mined)
  708. print("Percent Complete")
  709. print(percent.."%")
  710. print("Fuel")
  711. print(checkFuel())
  712.   -- screen(1,1)
  713.   -- print("Xpos: ")
  714.   -- print(xPos)
  715.   -- print("RelXPos: ")
  716.   -- print(relxPos)
  717.   -- print("Z Pos: ")
  718.   -- print(zPos)
  719.   -- print("Y pos: ")
  720.   -- print(yPos)
  721. if rednetEnabled then
  722. screenLine(1,7)
  723. print("Connected: "..tostring(connected))
  724. end
  725. end
  726. function logMiningRun(textExtension, extras) --Logging mining runs
  727. if logging then
  728. local number
  729. if not fs.isDir(logFolder) then
  730.   fs.delete(logFolder)
  731.   fs.makeDir(logFolder)
  732.   number = 1
  733. else
  734.   local i = 0
  735.   repeat
  736.     i = i + 1
  737.   until not fs.exists(logFolder.."/Quarry_Log_"..tostring(i)..(textExtension or ""))
  738.   number = i
  739. end
  740. handle = fs.open(logFolder.."/Quarry_Log_"..tostring(number)..(textExtension or ""),"w")
  741. local function write(...)
  742.   for a, b in ipairs({...}) do
  743.     handle.write(tostring(b))
  744.   end
  745.   handle.write("\n")
  746. end
  747. write("Welcome to the Quarry Logs!")
  748. write("Entry Number: ",number)
  749. write("Dimensions (X Z Y): ",x," ",z," ", y)
  750. write("Blocks Mined: ", mined)
  751. write("  Cobble: ", totals.cobble)
  752. write("  Usable Fuel: ", totals.fuel)
  753. write("  Other: ",totals.other)
  754. write("Total Fuel Used: ",  (originalFuel or (neededFuel + checkFuel()))- checkFuel()) --Protect against errors with some precision
  755. write("Expected Fuel Use: ", neededFuel)
  756. handle.close()
  757. end
  758. end
  759. function isFull(slots)
  760.   slots = slots or 16
  761.   local numUsed = 0
  762.   sleep(0)
  763.   for i=1, 16 do
  764.     if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end
  765.   end
  766.   if numUsed > slots then
  767.     return true
  768.   end
  769.   return false
  770. end
  771. function dig(doAdd, func)
  772.   doAdd = doAdd or true
  773.   func = func or turtle.dig
  774.   if func() then
  775.     if doAdd then
  776.       mined = mined + 1
  777.     end
  778.     return true
  779.   end
  780.   return false
  781. end
  782. if not inverted then --Regular functions :) I switch definitions for optimizatoin (I thinK)
  783.   function digUp(doAdd)
  784.     return dig(doAdd,turtle.digUp)
  785.   end
  786.   function digDown(doAdd)
  787.     return dig(doAdd,turtle.digDown)
  788.   end
  789. else
  790.   function digDown(doAdd)
  791.     return dig(doAdd,turtle.digUp)
  792.   end
  793.   function digUp(doAdd)
  794.     return dig(doAdd,turtle.digDown)
  795.   end
  796. end
  797. function setRowCheckFromPos()
  798.   rowCheck = (zPos % 2 == 1) --It will turn right at odd rows
  799. end
  800. function relxCalc()
  801.   if rowCheck then relxPos = xPos else relxPos = (x-xPos)+1 end
  802. end
  803. function forward(doAdd)
  804.   if doAdd == nil then doAdd = true end
  805.   if turtle.forward() then
  806.     if doAdd then
  807.       moved = moved + 1
  808.     end
  809.     if facing == 0 then
  810.       xPos = xPos + 1
  811.     elseif facing == 1 then
  812.       zPos = zPos + 1
  813.     elseif facing == 2 then
  814.       xPos = xPos - 1
  815.     elseif facing == 3 then
  816.       zPos = zPos - 1
  817.     else
  818.       error("Function forward, facing should be 0 - 3, got "..tostring(facing),2)
  819.     end
  820.     relxCalc()
  821.     return true
  822.   end
  823.   return false
  824. end
  825. function up(sneak)
  826.   sneak = sneak or 1
  827.   if inverted and sneak == 1 then
  828.     down(-1)
  829.   else
  830.     while not turtle.up() do --Absolute dig, not relative
  831.       if not dig(true, turtle.digUp) then
  832.         attackUp()
  833.         sleep(0.5)
  834.       end
  835.     end
  836.     yPos = yPos - sneak --Oh! I feel so clever
  837.   end                   --This works because inverted :)
  838.   saveProgress()
  839.   if rednetEnabled then biometrics() end
  840. end
  841. function down(sneak)
  842.   sneak = sneak or 1
  843.   local count = 0
  844.   if inverted and sneak == 1 then
  845.     up(-1)
  846.   else
  847.     while not turtle.down() do
  848.       count = count + 1
  849.       if not dig(true, turtle.digDown) then --This is absolute dig down, not relative
  850.         attackDown()
  851.         sleep(0.2)
  852.       end
  853.       if count > 20 then bedrock() end
  854.     end
  855.     yPos = yPos + sneak
  856.   end
  857.   saveProgress()
  858.   if rednetEnabled then biometrics() end
  859. end
  860. function right(num)
  861.   num = num or 1
  862.   for i=1, num do facing = coterminal(facing+1); saveProgress(); turtle.turnRight() end
  863. end
  864. function left(num)
  865.   num = num or 1
  866.   for i=1, num do facing = coterminal(facing-1); saveProgress(); turtle.turnLeft() end
  867. end
  868. function attack(doAdd, func)
  869.   doAdd = doAdd or true
  870.   func = func or turtle.attack
  871.   if func() then
  872.     if doAdd then
  873.       attacked = attacked + 1
  874.     end
  875.     return true
  876.   end
  877.   return false
  878. end
  879. function attackUp(doAdd)
  880.   if inverted then
  881.     return attack(doAdd, turtle.attackDown)
  882.   else
  883.     return attack(doAdd, turtle.attackUp)
  884.   end
  885. end
  886. function attackDown(doAdd)
  887.   if inverted then
  888.     return attack(doAdd, turtle.attackUp)
  889.   else
  890.     return attack(doAdd, turtle.attackDown)
  891.   end
  892. end
  893.  
  894.  
  895. function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward
  896.   if doCheckInv == nil then doCheckInv = true end
  897.   if doDigDown == nil then doDigDown = true end
  898.   if doDigUp == nil then doDigUp = true end
  899.   if outOfPath == nil then outOfPath = false end
  900.   isInPath = (not outOfPath) --For rednet
  901.   if inverted then
  902.     doDigUp, doDigDown = doDigDown, doDigUp --Just Switch the two if inverted
  903.   end
  904.   if doRefuel and checkFuel() <= fuelTable[fuelSafety]/2 then
  905.     for i=1, 16 do
  906.     if turtle.getItemCount(i) > 0 then
  907.       turtle.select(i)
  908.       if checkFuel() < 200 + fuelTable[fuelSafety] then
  909.         turtle.refuel()
  910.       end
  911.     end
  912.     end
  913.     turtle.select(1)
  914.   end
  915.   local count = 0
  916.   while not forward(not outOfPath) do
  917.     sleep(0) --Calls coroutine.yield to prevent errors
  918.     count = count + 1
  919.     if not dig() then
  920.       attack()
  921.     end
  922.     if count > 10 then
  923.       attack()
  924.       sleep(0.2)
  925.     end
  926.     if count > maxTries then
  927.       if turtle.getFuelLevel() == 0 then --Don't worry about inf fuel because I modified this function
  928.         saveProgress({doCheckFuel = true})
  929.         error("No more fuel",0)
  930.       elseif yPos > (startY-7) and turtle.detect() then --If it is near bedrock
  931.         bedrock()
  932.       else --Otherwise just sleep for a bit to avoid sheeps
  933.         sleep(1)
  934.       end
  935.     end
  936.   end
  937.   checkSanity() --Not kidding... This is necessary
  938.   saveProgress(tab)
  939.   if doDigUp then
  940.   while turtle.detectUp() do
  941.     sleep(0) --Calls coroutine.yield
  942.     if not dig(true,turtle.digUp) then --This needs to be an absolute, because we are switching doDigUp/Down
  943.       attackUp()
  944.       count = count + 1
  945.     end
  946.     if count > 50 and yPos > (startY-7) then --Same deal with bedrock as above
  947.       bedrock()
  948.     end
  949.     end
  950.   end
  951.   if doDigDown then
  952.    dig(true,turtle.digDown) --This needs to be absolute as well
  953.   end
  954.   percent = math.ceil(moved/moveVolume*100)
  955.   updateDisplay()
  956.   if doCheckInv and careAboutResources then
  957.     if moved%invCheckFreq == 0 then
  958.      if isFull(16-keepOpen) then dropOff() end
  959.     end
  960.   end
  961.   if rednetEnabled then biometrics() end
  962. end
  963. --Insanity Checking
  964. function checkSanity()
  965.   if not isInPath then --I don't really care if its not in the path.
  966.     return true
  967.   end
  968.   if not (facing == 0 or facing == 2) and #events == 0 then --If mining and not facing proper direction and not in a turn
  969.     turnTo(0)
  970.     rowCheck = true
  971.   end
  972.   if xPos < 0 or xPos > x or zPos < 0 or zPos > z or yPos < 0 then
  973.     saveProgress()
  974.     print("I have gone outside boundaries, attempting to fix (maybe)")
  975.     if xPos > x then goto(x, zPos, yPos, 2) end --I could do this with some fancy math, but this is much easier
  976.     if xPos < 0 then goto(1, zPos, yPos, 0) end
  977.     if zPos > z then goto(xPos, z, yPos, 3) end
  978.     if zPos < 0 then goto(xPos, 1, yPos, 1) end
  979.     setRowCheckFromPos() --Row check right (maybe left later)
  980.     relxCalc() --Get relxPos properly
  981.     eventClear()
  982.    
  983.     --[[
  984.     print("Oops. Detected that quarry was outside of predefined boundaries.")
  985.     print("Please go to my forum thread and report this with a short description of what happened")
  986.     print("If you could also run \"pastebin put Civil_Quarry_Restore\" and give me that code it would be great")
  987.     error("",0)]]
  988.   end
  989. end
  990.  
  991. local function fromBoolean(input) --Like a calculator
  992. if input then return 1 end
  993. return 0
  994. end
  995. local function multBoolean(first,second) --Boolean multiplication
  996. return (fromBoolean(first) * fromBoolean(second)) == 1
  997. end
  998. function coterminal(num, limit) --I knew this would come in handy :D
  999. limit = limit or 4 --This is for facing
  1000. return math.abs((limit*fromBoolean(num < 0))-(math.abs(num)%limit))
  1001. end
  1002. if tArgs["-manualpos"] then
  1003.   facing = coterminal(facing) --Done to improve support for "-manualPos"
  1004.   if facing == 0 then rowCheck = true elseif facing == 2 then rowCheck = false end --Ditto
  1005.   relxCalc() --Ditto
  1006. end
  1007.  
  1008. --Direction: Front = 0, Right = 1, Back = 2, Left = 3
  1009.  
  1010. function turnTo(num)
  1011.   num = num or facing
  1012.   num = coterminal(num) --Prevent errors
  1013.   local turnRight = true
  1014.   if facing-num == 1 or facing-num == -3 then turnRight = false end --0 - 1 = -3, 1 - 0 = 1, 2 - 1 = 1
  1015.   while facing ~= num do          --The above is used to smartly turn
  1016.     if turnRight then
  1017.       right()
  1018.     else
  1019.       left()
  1020.     end
  1021.   end
  1022. end
  1023. function goto(x,z,y, toFace, destination)
  1024.   --Will first go to desired z pos, then x pos, y pos varies
  1025.   x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing
  1026.   gotoDest = destination or "" --This is used by biometrics
  1027.   --Possible destinations: layerStart, quarryStart
  1028.   if yPos > y then --Will go up first if below position
  1029.     while yPos~=y do up() end
  1030.   end
  1031.   if zPos > z then
  1032.     turnTo(3)
  1033.   elseif zPos < z then
  1034.     turnTo(1)
  1035.   end
  1036.   while zPos ~= z do mine(false,false,true,false) end
  1037.   if xPos > x then
  1038.     turnTo(2)
  1039.   elseif xPos < x then
  1040.     turnTo(0)
  1041.   end
  1042.   while xPos ~= x do mine(false,false,true,false) end
  1043.   if yPos < y then --Will go down after if above position
  1044.     while yPos~=y do down() end
  1045.   end
  1046.   turnTo(toFace)
  1047.   saveProgress()
  1048.   gotoDest = ""
  1049. end
  1050. function getNumOpenSlots()
  1051.   local toRet = 0
  1052.   for i=1, 16 do
  1053.     if turtle.getItemCount(i) == 0 then
  1054.       toRet = toRet + 1
  1055.     end
  1056.   end
  1057.   return toRet
  1058. end
  1059. function drop(side, final, allowSkip)
  1060. side = sides[side] or "front"    --The final number means that it will
  1061. if final then final = 0 else final = 1 end --drop a whole stack at the end
  1062. local allowSkip = allowSkip or (final == 0) --This will allow drop(side,t/f, rednetConnected)
  1063. count()
  1064. if doRefuel then
  1065.   for i=1, 16 do
  1066.     if slot[i][1] == 2 then
  1067.       turtle.select(i); turtle.refuel()
  1068.     end
  1069.   end
  1070.   turtle.select(1)
  1071. end
  1072. if side == "right" then turnTo(1) end
  1073. if side == "left" then turnTo(3) end
  1074. local whereDetect, whereDrop1, whereDropAll
  1075. local _1 = slot[1][2] - final --All but one if final, all if not final
  1076. if side == "top" then
  1077. whereDetect = turtle.detectUp ; whereDrop = turtle.dropUp
  1078. elseif side == "bottom" then
  1079. whereDetect = turtle.detectDown ; whereDrop = turtle.dropDown
  1080. else
  1081. whereDetect = turtle.detect; whereDrop = turtle.drop
  1082. end
  1083. local function waitDrop(val) --This will just drop, but wait if it can't
  1084.   val = val or 64
  1085.   local try = 1
  1086.   while not whereDrop(val) do
  1087.     print("Chest Full, Try "..try)
  1088.     chestFull = true
  1089.     if rednetEnabled then --To send that the chest is full
  1090.       biometrics()
  1091.     end
  1092.     try = try + 1
  1093.     sleep(2)
  1094.   end
  1095.   chestFull = false
  1096. end
  1097. repeat
  1098. local detected = whereDetect()
  1099. if detected then
  1100.   waitDrop(_1)
  1101.   for i=1, 2 do --This is so I quit flipping missing items when chests are partially filled
  1102.     for i=2, 16 do
  1103.       if turtle.getItemCount(i) > 0 then
  1104.         turtle.select(i)
  1105.         waitDrop(nil, i)
  1106.       end
  1107.     end
  1108.   end
  1109. elseif not allowSkip then
  1110.   print("Waiting for chest placement place a chest to continue")
  1111.   while not whereDetect() do
  1112.     sleep(1)
  1113.   end
  1114. end
  1115. until detected or allowSkip
  1116. if not allowSkip then totals.cobble = totals.cobble - 1 end
  1117. turtle.select(1)
  1118. end
  1119. function dropOff() --Not local because called in mine()
  1120.   local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing
  1121.   if careAboutResources then
  1122.     if not enderChestEnabled then --Regularly
  1123.       eventAdd("goto", 1,1,currY,2) --Need this step for "-startDown"
  1124.       eventAdd("goto(0,1,1,2)")
  1125.       eventAdd("drop", dropSide,false)
  1126.       eventAdd("turnTo(0)")
  1127.       eventAdd("mine",false,false,true,false)
  1128.       eventAdd("goto(1,1,1, 0)")
  1129.       eventAdd("goto", 1, 1, currY, 0)
  1130.       eventAdd("goto", currX,currZ,currY,currFacing)
  1131.     else --If using an enderChest
  1132.       if turtle.getItemCount(enderChestSlot) ~= 1 then eventAdd("promptEnderChest()") end
  1133.       eventAdd("turnTo",currFacing-2)
  1134.       eventAdd("dig",false)
  1135.       eventAdd("turtle.select",enderChestSlot)
  1136.       eventAdd("turtle.place")
  1137.       eventAdd("drop","front",false)
  1138.       eventAdd("turtle.select", enderChestSlot)
  1139.       eventAdd("dig",false)
  1140.       eventAdd("turnTo",currFacing)
  1141.       eventAdd("turtle.select(1)")
  1142.     end
  1143.   runAllEvents()
  1144.   numDropOffs = numDropOffs + 1 --Analytics tracking
  1145.   end
  1146. return true
  1147. end
  1148. function endingProcedure() --Used both at the end and in "biometrics"
  1149.   eventAdd("goto",1,1,yPos,2,"quarryStart") --Allows for startDown variable
  1150.   eventAdd("goto",0,1,1,2, "quarryStart") --Go back to base
  1151.   runAllEvents()
  1152.   --Output to a chest or sit there
  1153.   if enderChestEnabled then
  1154.     while turtle.detect() do dig(false) end --This gets rid of blocks in front of the turtle.
  1155.     eventAdd("turtle.select",enderChestSlot)
  1156.     eventAdd("turtle.place")
  1157.     eventAdd("turtle.select(1)")
  1158.   end
  1159.   eventAdd("drop",dropSide, true)
  1160.   eventAdd("turnTo(0)")
  1161.  
  1162.   --Display was moved above to be used in bedrock function
  1163.   eventAdd("display")
  1164.   --Log current mining run
  1165.   eventAdd("logMiningRun",logExtension)
  1166.   toQuit = true --I'll use this flag to clean up
  1167.   runAllEvents()
  1168.   --Cleanup
  1169.   turtle.getFuelLevel = getFuel
  1170. end
  1171. function bedrock()
  1172.   foundBedrock = true --Let everyone know
  1173.   if rednetEnabled then biometrics() end
  1174.   if checkFuel() == 0 then error("No Fuel",0) end
  1175.   local origin = {x = xPos, y = yPos, z = zPos}
  1176.   print("Bedrock Detected")
  1177.   if turtle.detectUp() then
  1178.     print("Block Above")
  1179.     local var
  1180.     if facing == 0 then var = 2 elseif facing == 2 then var = 0 else error("Was facing left or right on bedrock") end
  1181.     goto(xPos,zPos,yPos,var)
  1182.     for i=1, relxPos do mine(false, false); end
  1183.   end
  1184.   goto(xPos,zPos,yPos-3,0) --This will make the turtle go up three before it tries going to start of layer.
  1185.   eventClear() --Get rid of any excess events that may be run. Don't want that.
  1186.   endingProcedure()
  1187.   print("\nFound bedrock at these coordinates: ")
  1188.   print(origin.x," Was position in row\n",origin.z," Was row in layer\n",origin.y," Blocks down from start")
  1189.   error("",0)
  1190. end
  1191.  
  1192. function endOfRowTurn(startZ, wasFacing, mineFunctionTable)
  1193. local halfFacing = 1
  1194. local toFace = coterminal(wasFacing + 2) --Opposite side
  1195. if zPos == startZ then
  1196.   if facing ~= halfFacing then turnTo(halfFacing) end
  1197.   mine(unpack(mineFunctionTable or {}))
  1198. end
  1199. if facing ~= toFace then
  1200.   turnTo(toFace)
  1201. end
  1202. end
  1203.  
  1204. -------------------------------------------------------------------------------------
  1205. --Pre-Mining Stuff dealing with session persistence
  1206. runAllEvents()
  1207. if toQuit then error("",0) end --This means that it was stopped coming for its last drop
  1208.  
  1209. local doDigDown, doDigUp = (lastHeight ~= 1), (lastHeight == 0) --Used in lastHeight
  1210. if not restoreFoundSwitch then --Regularly
  1211.   --Check if it is a mining turtle
  1212.   if not isMiningTurtle then
  1213.     local a, b = turtle.dig()
  1214.     if a then mined = mined + 1; isMiningTurtle = true
  1215.     elseif b == "Nothing to dig with" then
  1216.       print("This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe")
  1217.       error("",0)
  1218.     end
  1219.   end
  1220.   mine(false,false,true) --Get into quarry by going forward one
  1221.   if gpsEnabled and not restoreFoundSwitch then --The initial locate is done in the arguments. This is so I can figure out what quadrant the turtle is in.
  1222.     gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.
  1223.   end
  1224.   for i = 1, startDown do
  1225.     eventAdd("down") --Add a bunch of down events to get to where it needs to be.
  1226.   end
  1227.   runAllEvents()
  1228.   if not(y == 1 or y == 2) then down() end --Go down. If y is one or two, it doesn't need to do this.
  1229. else --restore found
  1230.   if not(layersDone == layers and not doDigDown) then digDown() end
  1231.   if not(layersDone == layers and not doDigUp) then digUp() end  --Get blocks missed before stopped
  1232. end
  1233. --Mining Loops--------------------------------------------------------------------------
  1234. turtle.select(1)
  1235. while layersDone <= layers do -------------Height---------
  1236. local lastLayer = layersDone == layers --If this is the last layer
  1237. local secondToLastLayer = (layersDone + 1) == layers --This is for the going down at the end of a layer.
  1238. moved = moved + 1 --To account for the first position in row as "moved"
  1239. if not(layersDone == layers and not doDigDown) then digDown() end --This is because it doesn't mine first block in layer
  1240. if not restoreFoundSwitch then rowCheck = true end
  1241. relxCalc()
  1242. while zPos <= z do -------------Width----------
  1243. while relxPos < x do ------------Length---------
  1244. mine(not lastLayer or (doDigDown and lastLayer), not lastLayer or (doDigUp and lastLayer)) --This will be the idiom that I use for the mine function
  1245. end ---------------Length End-------
  1246. if zPos ~= z then --If not on last row of section
  1247.   local func
  1248.   if rowCheck == true then --Swithcing to next row
  1249.   func = "right"; rowCheck = false; else func = false; rowCheck = true end --Which way to turn
  1250.     eventAdd("endOfRowTurn", zPos, facing , {not lastLayer or (doDigDown and lastLayer), not lastLayer or (doDigUp and lastLayer)}) --The table is passed to the mine function
  1251.     runAllEvents()
  1252. else break
  1253. end
  1254. end ---------------Width End--------
  1255. eventAdd("goto",1,1,yPos,0, "layerStart") --Goto start of layer
  1256. if not lastLayer then --If there is another layer
  1257.   for i=1, 2+fromBoolean(not(lastHeight~=0 and secondToLastLayer)) do eventAdd("down()") end --The fromBoolean stuff means that if lastheight is 1 and last and layer, will only go down two
  1258. end
  1259. eventAdd("setRowCheckFromPos")
  1260. eventAdd("relxCalc")
  1261. layersDone = layersDone + 1
  1262. restoreFoundSwitch = false --This is done so that rowCheck works properly upon restore
  1263. runAllEvents()
  1264. end ---------------Height End-------
  1265.  
  1266. endingProcedure() --This takes care of getting to start, dropping in chest, and displaying ending screen
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement