daily pastebin goal
82%
SHARE
TWEET

Quarry 3.2.3

civilwargeeky Nov 15th, 2013 481 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2. Version 3.2.3
  3. Recent Changes:
  4. 1. Now has session persistence! Just type "quarry -restore"
  5.    and your turtle will pick up where it left off
  6. 2. New Argument: startY to help stop it from getting stuck on those nasty sheep!
  7. 3. Most directional functions take care of invert. Exception is turtle.detect
  8. ]]
  9. --[[ToDo:
  10. 1. Actually get the rednet send back and forth to work
  11. 3. Send basic commands from receiver program e.g. Stop
  12. 6. Add in rednet stuff
  13. 7. Massive update for rednet program
  14. ]]
  15. --Defining things
  16. _G.civilTable = {}; civilTable = nil; setmetatable(civilTable, {__index = _G}); setfenv(1,civilTable)
  17. -------Defaults for Arguments----------
  18. --Arguments assignable by text
  19. x,y,z = 3,3,3 --These are just in case tonumber fails
  20. inverted = false --False goes from top down, true goes from bottom up [Default false]
  21. rednetEnabled = false --Default rednet on or off  [Default false]
  22. --Arguments assignable by tArgs
  23. dropSide = "front" --Side it will eject to when full or done [Default "front"]
  24. careAboutResources = true --Will not stop mining once inventory full if false [Default true]
  25. doCheckFuel = true --Perform fuel check [Default true]
  26. doRefuel = false --Whenever it comes to start location will attempt to refuel from inventory [Default false]
  27. invCheckFreq = 10 --Will check for inventory full every <-- moved spaces [Default 10]
  28. keepOpen = 1 --How many inventory slots it will attempt to keep open at all times [Default 1]
  29. fuelSafety = "moderate" --How much fuel it will ask for: safe, moderate, and loose [Default moderate]
  30. saveFile = "Civil_Quarry_Restore" --Where it saves restore data [Default "Civil_Quarry_Restore"]
  31. doBackup = true --If it will keep backups for session persistence [Default true]
  32. numberOfStacksPerRun = 8 --How many stacks (number of items) the turtle expects (on average) to have before it must dump off. Not in arguments. [Default 8]
  33. gpsEnabled = false -- If option is enabled, will attempt to find position via GPS api [Default false]
  34. gpsTimeout = 3 --The number of seconds the program will wait to get GPS coords. Not in arguments [Default 3]
  35. logging = true --Whether or not the turtle will log mining runs. [Default ...still deciding]
  36. logFolder = "Quarry_Logs" --What folder the turtle will store logs in [Default "Quarry_Logs"]
  37. logExtension = "" --The extension of the file (e.g. ".txt") [Default ""]
  38. --Standard number slots for fuel (you shouldn't care)
  39. fuelTable = { --Will add in this amount of fuel to requirement.
  40. safe = 1000,
  41. moderate = 200,
  42. loose = 0 } --Default 1000, 200, 0
  43. --Standard rednet channels
  44. channels = {
  45. send = os.getComputerID()  ,
  46. receive = os.getComputerID() + 100 ,
  47. confirm = "Confirm"
  48. }
  49.  
  50. local help_paragraph = [[
  51. -DEFAULT: This will ignore all arguments and prompts and use defaults
  52. -vanilla: This will ignore all arguments except for dimensions
  53. -dim: [num] [num] [num] This sets the dimensions of the quarry
  54. -invert: [t/f] This sets whether invert is true or false
  55. -rednet: [t/f] This sets whether it will attempt to make a rednet connection
  56. -sendChannel: [num] This sets the channel the turtle will attempt to send on
  57. -receiveChannel: [num] This sets the channel the turtle will attempt to receive on
  58. -doRefuel: Changes whether or not the turtle will refuel itself with coal when fuel is low (opposite of written config)
  59. -doCheckFuel: Changes whether or not the turtle will check its fuel level before running (opposite of written config)
  60. -chest: [chest side] Changes what side turtle will output to
  61. -startY: [num] Tells the turtle what y coordinate it starts at, to make bedrock checking more accurate (hopefully)
  62. -keepOpen: [num] How many slots of the inventory turtle will try to keep open (Will then auto-empty)
  63. -invCheckFreq: [num] How many blocks before full inventory checks
  64. -saveFile: [word] Changes where the turtle saves its backup to.
  65. -doBackup: [t/f] Whether or not the turtle will backup its current position to a file.
  66. -restore: Turtle will check for a save file. If found will ignore all other arguments.
  67. -fuelSafety: [safe/moderate/loose] How much extra fuel the turtle will request at startup
  68. -GPS: Will toggle whether gps is on or not.
  69.   You must have a valid GPS network set up for this to work. It will take its starting location from this and its first position.
  70.   It will then store these values in its progress file in case your turtle stops for any reason.
  71.   On startup, the turtle will calculate its current position based on a new gps locate.
  72. -log: Turns logging on if not already on.
  73.   Will publish reports of mining runs to its own folder for later reading
  74. Smart Fueling System: As of 3.2.0, the turtle uses a new smart fueling system
  75.   With this new system you can shift click in as many stacks of fuel as you want, and it will take stacks of fuel at a time
  76.   This makes fueling for large jobs on new turtles much, much faster.
  77. Examples [1]:
  78.  The minimum amount necessary to start a turtle automatically would be one of these two
  79.  ---------
  80.  quarry -dim 3 3 3 -invert false -rednet false
  81.  ---------
  82.  quarry -dim 3 3 3 -vanilla
  83.  ---------
  84.  or, if you actually wanted a 3x3x3 then
  85.  ---------
  86.  quarry -DEFAULT
  87. Examples [2]:
  88.  If you wanted start a quarry that has
  89.  rednet on channels 500 and 501, outputs
  90.  to a chest below itself, is inverted,
  91.  and has the dimesions 5x5x21, then here
  92.  is what you would type: (Remember that
  93.  order does not matter)
  94.  ----------
  95.  quarry -receiveChannel 501 -sendChannel 500 -invert true -dim 5 5 21 -chest bottom -rednet true
  96. Examples [2] (cont.):
  97.  Now, this may be very long, but it is meant for people who want to make automated quarries with
  98.  the same settings every time (or with variable setting)
  99. Examples [3]:
  100.  If you are playing softcore then you
  101.  can do
  102.  ---------
  103.  quarry -doCheckFuel false
  104.  ---------
  105.  Followed by any other arguments
  106. Tips:
  107.  You don't actually have to type out "false" or "true" if you don't want. It actaully just checks if the first
  108.  letter is "t", so you (usually) don't have to put anything at all. Putting the whole word just helps with clarity
  109. Internal Config:
  110.  At the top of the program, right below the changelog is a written config. Anything not specified by arguments
  111.  will be taken from here. If you have a quarry setup you use a lot, you could just edit the config and then
  112.  type in the following:
  113.  ----------
  114.  quarry -DEFAULT
  115. ]]
  116.  
  117. --Parsing help for display
  118. --[[The way the help table works:
  119. All help indexes are numbered. There is a help[i].title that contains the title,
  120. and the other lines are in help[i][1] - help[i][#help[i] ]
  121. Different lines (e.g. other than first) start with a space.
  122. As of now, the words are not wrapped, fix that later]]
  123. local help = {}
  124. local i = 0
  125. local titlePattern = ".-%:" --Find the beginning of the line, then characters, then a ":"
  126. local textPattern = "%:.+" --Find a ":", then characters until the end of the line
  127. for a in help_paragraph:gmatch("\n?.-\n") do --Matches in between newlines
  128. local current = string.sub(a,1,-2).."" --Concatenate Trick
  129. if string.sub(current,1,1) ~= " " then
  130. i = i + 1
  131. help[i] = {}
  132. help[i].title = string.sub(string.match(current, titlePattern),1,-2)..""
  133. help[i][1] = string.sub(string.match(current,textPattern) or " ",3,-1)
  134. elseif string.sub(current,1,1) == " " then
  135. table.insert(help[i], string.sub(current,2, -1).."")
  136. end
  137. end
  138.  
  139.  
  140. local supportsRednet = (peripheral.wrap("right") ~= nil)
  141.  
  142. local tArgs = {...}
  143. --You don't care about these
  144.       xPos,yPos,zPos,facing,percent,mined,moved,relxPos, rowCheck, connected, isInPath, layersDone, attacked, startY
  145.     = 0,   1,   1,   0,     0,      0,    0,    1,       "right",  false,     true,     1,          0,        0
  146.  
  147. local totals = {cobble = 0, fuel = 0, other = 0} -- Total for display (cannot go inside function)
  148. local function count() --Done any time inventory dropped and at end
  149. slot = {}        --1: Cobble 2: Fuel 3:Other
  150. for i=1, 16 do   --[1] is type, [2] is number
  151. slot[i] = {}
  152. slot[i][2] = turtle.getItemCount(i)
  153. end
  154. slot[1][1] = 1   -- = Assumes Cobble/Main
  155. for i=1, 16 do   --Cobble Check
  156. turtle.select(i)
  157. if turtle.compareTo(1)  then
  158. slot[i][1] = 1
  159. totals.cobble = totals.cobble + slot[i][2]
  160. elseif turtle.refuel(0) then
  161. slot[i][1] = 2
  162. totals.fuel = totals.fuel + slot[i][2]
  163. else
  164. slot[i][1] = 3
  165. totals.other = totals.other + slot[i][2]
  166. end
  167. end
  168. turtle.select(1)
  169. end
  170.  
  171. local getFuel = turtle.getFuelLevel --This is for cleanup at the end
  172. do --Common variable name...
  173. local flag = turtle.getFuelLevel() == "Unlimited"--Unlimited screws up my calculations
  174. if flag then --Fuel is disabled
  175.   turtle.getFuelLevel = function() return math.huge end --Infinite Fuel
  176. end --There is no "else" because it will already return the regular getFuel
  177. end
  178. local checkFuel = turtle.getFuelLevel --Just an alias for backwards compat
  179.  
  180.  -----------------------------------------------------------------
  181. --Input Phase
  182. local function screen(xPos,yPos)
  183. xPos, yPos = xPos or 1, yPos or 1
  184. term.setCursorPos(xPos,yPos); term.clear(); end
  185. local function screenLine(xPos,yPos)
  186. term.setCursorPos(xPos,yPos); term.clearLine(); end
  187.  
  188. screen(1,1)
  189. print("----- Welcome to Quarry! -----")
  190. print("")
  191.  
  192. local sides = {top = "top", right = "right", left = "left", bottom = "bottom", front = "front"} --Used to whitelist sides
  193. local errorT = {num = "Numbers not recognized", zero = "Variable is out of range", word = "String failed assertion" }
  194. local changedT = {}
  195. changedT.new = function(key, value) changedT[#changedT+1] = {[key] = value} end
  196. changedT.getPair = function(i) for a, b in pairs(changedT[i]) do return a, b end end
  197. local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end
  198. local function assert(condition, message, section) section = section or "[Blank]"; if condition then return condition else error("Error: "..message.."\nin section "..section, 0) end end
  199. local function checkNum(number, section) return assert(tonumber(number),errorT.num, section) end
  200. tArgs.checkStart = function(num) tArgs[tArgs[num]] = num end
  201. for i=1, #tArgs do tArgs.checkStart(i) end
  202.  
  203. --Check if it is a turtle
  204. if not turtle then
  205.   print("This is not a turtle, you must be looking for the \"Companion Rednet Program\" \nCheck My forum thread for that")
  206.   print("Press 'q' to quit, or any other key to start help ")
  207.   if ({os.pullEvent("char")})[2] ~= "q" then tArgs.help = true else error("",0) end
  208. end
  209.  
  210.  
  211. if tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"] then
  212. print("You have selected help, press any key to continue"); print("Use arrow keys to naviate, q to quit"); os.pullEvent("key")
  213. local pos = 1
  214. local key = 0
  215. while pos <= #help and key ~= keys.q do
  216. if pos < 1 then pos = 1 end
  217. screen(1,1)
  218. print(help[pos].title)
  219. for a=1, #help[pos] do print(help[pos][a]) end
  220. repeat
  221. _, key = os.pullEvent("key")
  222. until key == 200 or key == 208 or key == keys.q
  223. if key == 200 then pos = pos - 1 end
  224. if key == 208 then pos = pos + 1 end
  225. end
  226. error("",0)
  227. end
  228.  
  229. --Saving
  230. if tArgs["doBackup"] then doBackup = (string.lower(string.sub(tArgs[tArgs["doBackup"]+1],1,1)) ~= "f") end
  231. if tArgs["saveFile"] then saveFile = tArgs[tArgs["saveFile"]+1] or saveFile end
  232.  
  233. local restoreFound = false
  234. if tArgs["-restore"] or tArgs["-resume"] then
  235. restoreFound = fs.exists(saveFile)
  236. if restoreFound then
  237. file = fs.open(saveFile,"r")
  238. if file.readAll() ~= "" and file.close() then
  239.   os.run(getfenv(1),saveFile)
  240.   if gpsEnabled then --If it had saved gps coordinates
  241.     print("Found GPS Start Coordinates")
  242.     local currLoc = {gps.locate(gpsTimeout)}
  243.     if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using
  244.       print("GPS Position Successfully Read")
  245.       if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order
  246.         xPos, yPos, zPos = 0,1,1
  247.         if facing ~= 0 then turnTo(0) end
  248.         print("Is at start")
  249.       else
  250.         if inverted then --yPos setting
  251.         ------------------------------------------------FIX THIS
  252.         end
  253.         local function copyTable(tab) local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end
  254.         local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience
  255.         if b[3] - a[3] == -1 then--If went north (-Z)
  256.           a[1] = a[1] - 1 --Shift x one to west to create a "zero"
  257.           xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]
  258.         elseif b[1] - a[1] == 1 then--If went east (+X)
  259.           a[3] = a[3] - 1 --Shift z up one to north to create a "zero"
  260.           xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]
  261.         elseif b[3] - a[3] == 1 then--If went south (+Z)
  262.           a[1] = a[1] + 1 --Shift x one to east to create a "zero"
  263.           xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]
  264.         elseif b[1] - a[1] == -1 then--If went west (-X)
  265.           a[3] = a[3] + 1 --Shift z down one to south to create a "zero"
  266.           xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]
  267.         else
  268.           print("Improper Coordinates")
  269.           print("GPS Locate Failed, Using Standard Methods")        ----Maybe clean this up a bit to use flags instead.
  270.         end  
  271.       end
  272.       print("X Pos: ",xPos)
  273.       print("Y Pos: ",yPos)
  274.       print("Z Pos: ",zPos)
  275.       print("Facing: ",facing)
  276.     else
  277.       print("GPS Locate Failed, Using Standard Methods")
  278.     end    
  279.   print("Restore File read successfully. Starting in 3"); sleep(3)
  280.   end
  281.   else
  282.     originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used
  283.   end
  284. else
  285.   fs.delete(saveFile)
  286.   print("Restore file was empty, sorry, aborting")
  287.   error("",0)
  288. end
  289. end
  290.  
  291. if not (tArgs["-DEFAULT"] or restoreFound) then
  292.   --Just a note, the whole error checking section here was more of an
  293.   --experiment than anything else. If its ever changed in the future,
  294.   --it would probably be for the better.
  295. local section = "Dimensions"
  296. --Dimesnions
  297. if tArgs["-dim"] then local num = tArgs["-dim"];
  298. x = checkNum(tArgs[num + 1],section); z = checkNum(tArgs[num + 2],section); y = checkNum(tArgs[num + 3],section)
  299. else
  300. print("What dimensions?")
  301. print("")
  302. --This will protect from negatives, letters, and decimals
  303. term.write("Length: ")
  304. x = math.floor(math.abs(tonumber(io.read()) or x))
  305. term.write("Width: ")
  306. z = math.floor(math.abs(tonumber(io.read()) or z))
  307. term.write("Height: ")
  308. y = math.floor(math.abs(tonumber(io.read()) or y))
  309. end
  310. changedT.new("x",x); changedT.new("z",z); changedT.new("y",y)
  311. assert(x~=0, errorT.zero, section); assert(z~=0, errorT.zero, section); assert(y~=0, errorT.zero, section)
  312. assert(not(x == 1 and y == 1 and z == 1) ,"1, 1, 1 dosen't work well at all, try again", section)
  313. if not tArgs["-vanilla"] then
  314. --Invert
  315. if tArgs["-invert"] then
  316. inverted = (string.lower(string.sub(tArgs[tArgs["-invert"]+1] or "",1,1)) == "t") else
  317. term.write("Inverted? ")
  318. inverted = (string.lower(string.sub(io.read(),1,1)) == "y")
  319. end
  320. changedT.new("Inverted", inverted)
  321. --Rednet
  322. if supportsRednet then
  323. if tArgs["-rednet"] then
  324. rednetEnabled = (string.lower(string.sub(tArgs[tArgs["-rednet"]+1] or "",1,1)) == "t")
  325. else term.write("Rednet? "); rednetEnabled = (string.lower(string.sub(io.read(),1,1)) == "y")
  326. if (tArgs["-GPS"] or tArgs["-gps"]) and not restoreFound and not gpsEnabled then --The not gps enabled makes it so it is toggled
  327. gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array
  328. gpsEnabled = #gpsStartPos > 0 --Checks if location received properly
  329. changedT.new("GPS Location Services", gpsEnabled)
  330. end
  331. changedT.new("Rednet Enabled", rednetEnabled)
  332. end
  333. if tArgs["-sendChannel"] then
  334. channels.send = assert(tonumber(tArgs[tArgs["-sendChannel"]+1]), errorT.num)
  335. assert(channels.send > 0 and channels.send < 65535, errorT.zero)
  336. changedT.new("Send Channel",channels.send) end
  337. if tArgs["-receiveChannel"] then
  338. channels.receive = assert(tonumber(tArgs[tArgs["-receiveChannel"]+1]), errorT.num)
  339. assert(channels.receive > 0 and channels.receive < 65535 and channels.receive ~= channels.send, errorT.zero)
  340. changedT.new("Receive Channel",channels.receive) end
  341. end
  342. --Fuel
  343. if tArgs["-doRefuel"] then doRefuel = not doRefuel; changedT.new("Do Refuel",doRefuel) end
  344. if turtle.getFuelLevel() == "unlimited" then
  345.   doCheckFuel = false
  346. else
  347.   if tArgs["-doCheckFuel"] then
  348.   doCheckFuel = (string.lower(string.sub(tArgs[tArgs["-doCheckFuel"]+1] or "",1,1)) == "t"); changedT.new("Do Check Fuel", doCheckFuel) end
  349. end
  350. if tArgs["-chest"] then
  351. dropSide = sides[tArgs[tArgs["-chest"]+1]] or dropSide; changedT.new("Chest Side",dropSide) end
  352. if tArgs["-fuelSafety"] then local loc = tArgs[tArgs["-fuelSafety"]+1]
  353.   if fuelTable[loc] then
  354.     fuelSafety = loc; changedT.new("Fuel Check Safety", fuelSafety)
  355.   end
  356. end
  357. --Logging
  358. logging = (tArgs["-log"] and true) or logging --The and will set it to true if value, or its original value if nil
  359. if logging then changedT.new("Logging",logging) end
  360. if tArgs["-logFolder"] then logFolder = tArgs[tArgs["-logFolder"]+1] or logFolder; changedT.new("Log Folder",logFolder) end
  361. if tArgs["-logExtension"] then logExtension = tArgs[tArgs["-logExtension"]+1] or logExtension; changedT.new("Log Extension",logExtension) end
  362. --Misc
  363. if tArgs["-startY"] then
  364. startY = math.abs(math.floor(checkNum(tArgs[tArgs["-startY"]+1],"Start Y")))
  365. changedT.new("Start Y Position",startY) end
  366. assert(startY >= 0, errorT.zero, "StartY")
  367. if tArgs["-invCheckFreq"] then
  368. invCheckFreq = math.abs(math.floor(checkNum(tArgs[tArgs["-invCheckFreq"]+1],"Inventory Check Frequency")))
  369. changedT.new("Inventory Check Frequency",invCheckFreq) end
  370. assert(invCheckFreq ~= 0, errorT.zero, "Inventory Check Frequency")
  371. if tArgs["-keepOpen"] then
  372. keepOpen = math.abs(math.floor(checkNum(tArgs[tArgs["-keepOpen"]+1],"Open Slots")))
  373. changedT.new("Slots to keep open", keepOpen) end
  374. assert(keepOpen ~= 0 and keepOpen < 16, errorT.zero, "Open Slots")
  375. if tArgs["-ignoreResources"] then careAboutResources = false; changedT.new("Ignore Resources?", not careAboutResources) end
  376. if tArgs["-saveFile"] then saveFile = tArgs[tArgs["-saveFile"]+1] changedT.new("Save File", saveFile) end
  377. assert(#saveFile >= 2,errorT.word, "Save File")
  378. end; end --First end is for vanilla, second is for DEFAULT
  379.  
  380. local function saveProgress(extras) --Session persistence
  381. if doBackup then
  382. local toWrite = ""
  383. for a,b in pairs(getfenv(1)) do
  384. if type(b) == "string" then b = "\""..b.."\"" end
  385. if type(b) == "table" and a~="modem" then b = textutils.serialize(b) end
  386. if type(b) ~= "function" then
  387. toWrite = toWrite..a.." = "..tostring(b).."\n"
  388. end
  389. end
  390. toWrite = toWrite.."doCheckFuel = false\n" --It has already used fuel, so calculation unnesesary
  391. local file
  392. repeat
  393.   file = fs.open(saveFile,"w")
  394. until file --WHY DOES IT SAY ATTEMPT TO INDEX NIL!!!
  395. file.write(toWrite)
  396. if type(extras) == "table" then
  397.   for a, b in pairs(extras) do
  398.     file.write(a.." = "..tostring(b))
  399.   end
  400. end
  401. file.close()
  402. end
  403. end
  404.  
  405. local area = x*z
  406. local volume = x*y*z
  407. local lastHeight = y%3
  408. local dispY = y
  409. y = math.floor(y/3)*3
  410. local yMult = y/3 + math.ceil(lastHeight/2) --This is basically a smart y/3 for movement
  411. local moveVolume = (area * yMult) --Kept for display percent
  412. --Calculating Needed Fuel--
  413. local exStack = numberOfStacksPerRun --Expected stacks of items before full
  414. neededFuel = yMult * x * z + --This is volume it will run through
  415.       dispY*(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
  416.       (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
  417.       --Original equation: x*z*y/3 + y * 2 + (x+z) * y/3 + (x + z + y) * (1/64*8)
  418. neededFuel = math.ceil(neededFuel)
  419.  
  420. --Getting Fuel
  421. if doCheckFuel and checkFuel() < neededFuel then
  422. neededFuel = neededFuel + fuelTable[fuelSafety] --For safety
  423.   print("Not enough fuel")
  424.   print("Current: ",checkFuel()," Needed: ",neededFuel)
  425.   print("Starting SmartFuel...")
  426.   sleep(2) --So they can read everything.
  427.   term.clear()
  428.   local oneFuel, neededFuelItems
  429.   local currSlot = 0
  430.   local function output(text, x, y) --For displaying fuel
  431.     currX, currY = term.getCursorPos()
  432.     term.setCursorPos(x,y)
  433.     term.clearLine()
  434.     term.write(text)
  435.     term.setCursorPos(currX,currY)
  436.     end
  437.   local function roundTo(num, target) --For stacks of fuel
  438.     if num >= target then return target elseif num < 0 then return 0 else return num end
  439.   end
  440.   local function updateScreen()
  441.     output("Welcome to SmartFuel! Now Refueling...", 1,1)
  442.     output("Currently taking fuel from slot "..currSlot,1,2)
  443.     output("Current single fuel: "..tostring(oneFuel or 0),1,3)
  444.     output("Current estimate of needed fuel: ",1,4)
  445.     output("Single Items: "..math.ceil(neededFuelItems or 0),4,5)
  446.     output("Stacks:       "..math.ceil((neededFuelItems or 0) / 64),4,6)
  447.     output("Needed Fuel: "..tostring(neededFuel),1,12)
  448.     output("Current Fuel: "..tostring(checkFuel()),1,13)
  449.   end
  450.   while checkFuel() <= neededFuel do
  451.     currSlot = currSlot + 1
  452.     turtle.select(currSlot)
  453.     updateScreen()
  454.     while turtle.getItemCount(currSlot) == 0 do sleep(1.5) end
  455.     repeat
  456.       local previous = checkFuel()
  457.       turtle.refuel(1)
  458.       oneFuel = checkFuel() - previous
  459.       updateScreen()
  460.     until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.
  461.     neededFuelItems = (neededFuel - checkFuel()) / oneFuel
  462.     turtle.refuel(roundTo(neededFuelItems, 64)) --Change because can only think about 64 at once.
  463.     if turtle.getItemCount(roundTo(currSlot + 1, 16)) == 0 then --Resets if no more fuel
  464.       currSlot = 0
  465.     end
  466.     neededFuelItems = (neededFuel - checkFuel()) / oneFuel
  467.   end
  468. -- local neededFuel = moveVolume + (math.floor(volume / (64 * 8)) * (x+dispY+z)) --Standard move plus dropping off supplies
  469.                              -- --How many times come back to start| * If it were at the very far side
  470. -- neededFuel = neededFuel + fuelTable[fuelSafety]
  471. -- if neededFuel < 100 then neededFuel = 100; end
  472. -- if checkFuel() < neededFuel then
  473. -- screen(1,1)
  474. -- print("More Fuel Needed")
  475. -- print("Current Fuel: ",checkFuel()," Needed: ",neededFuel)
  476. -- print("Place fuel in Bottom Right")
  477. -- while turtle.getItemCount(16) == 0 do
  478.   -- sleep(1)
  479. -- end
  480. -- turtle.select(16)
  481. -- while checkFuel() < neededFuel do
  482. -- if not turtle.refuel(1) then
  483. -- term.clearLine()
  484. -- print("Still too little fuel")
  485. -- term.clearLine()
  486. -- print("Insert more fuel to resume")
  487. -- while turtle.getItemCount(16) == 0 do
  488.   -- sleep(1)
  489. -- end
  490. -- end
  491. -- local x,y = term.getCursorPos()
  492. -- print(checkFuel().." Fuel")
  493. -- term.setCursorPos(x,y)
  494. -- end
  495. -- print(checkFuel().." Units of Fuel")
  496. -- sleep(3)
  497. -- turtle.select(1)
  498. -- end
  499. end
  500. --Initial Rednet Handshake
  501. if rednetEnabled then
  502. screen(1,1)
  503. print("Rednet is Enabled")
  504. print("The Channel to open is "..channels.send)
  505. modem = peripheral.wrap("right")
  506. modem.open(channels.receive)
  507. local i = 0
  508. repeat
  509. local id = os.startTimer(3)
  510. i=i+1
  511. print("Sending Initial Message "..i)
  512. modem.transmit(channels.send, channels.receive, "{ 'Initial' }")
  513. local message
  514. repeat
  515. local event, idCheck, channel,_,locMessage, distance = os.pullEvent()
  516. message = locMessage
  517. until (event == "timer" and idCheck == id) or (event == "modem_message" and channel == channels.receive and message == channels.confirm)
  518. until message == channels.confirm
  519. connected = true
  520. print("Connection Confirmed!")
  521. sleep(1.5)
  522. end
  523. local function biometrics(sendChannel)
  524. local commands = { Confirm = "Confirm" }
  525. local toSend = { ["x"] = x, ["y"] = (y/3 + math.ceil(lastHeight/2)), ["z"] = z, --The y calc is weird...
  526.     ["xPos"] = xPos, ["yPos"] = yPos, ["zPos"] = zPos,
  527.     ["percent"] = percent, ["mined" ]= mined,
  528.     ["fuel"] = checkFuel(), ["moved"] = moved,
  529.     ["remainingBlocks"] = (volume-mined), ["ID"] = os.getComputerID(),
  530.     ["isInPath"] = isInPath, --Whether it is going back to start
  531.     ["volume"] = volume, ["area"] = area}
  532. modem.transmit(channels.send, channels.receive, textutils.serialize(toSend))
  533. id = os.startTimer(0.1)
  534. local event, message
  535. repeat
  536. local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()
  537. event, message = locEvent, locMessage
  538. until (event == "timer" and idCheck == id) or (event == "modem_message" and confirm == channels.receive)
  539. if event == "modem_message" then connected = true else connected = false end
  540. --Stuff to do for different commands
  541. end
  542. --Showing changes to settings
  543. screen(1,1)
  544. print("Your selected settings:")
  545. if #changedT == 0 then
  546. print("Completely Default")
  547. else
  548. for i=1, #changedT do
  549. local title, value = changedT.getPair(i)
  550. print(capitalize(title)..": ",value)
  551. end
  552. end
  553. print("\nStarting in 3"); sleep(1); print("2"); sleep(1); print("1"); sleep(1.5) --Dramatic pause at end
  554.  
  555.  
  556.  
  557. ----------------------------------------------------------------
  558. --Define ALL THE FUNCTIONS
  559. function display() --This is just the last screen that displays at the end
  560. screen(1,1)
  561. print("Total Blocks Mined: "..mined)
  562. print("Current Fuel Level: "..turtle.getFuelLevel())
  563. print("Cobble: "..totals.cobble)
  564. print("Usable Fuel: "..totals.fuel)
  565. print("Other: "..totals.other)
  566. if rednetEnabled then
  567. print("")
  568. print("Sent Stop Message")
  569. finalTable = {{["Mined: "] = mined}, {["Cobble: "] = totals.cobble}, {["Fuel: "] = totals.fuel},
  570.     {["Other: "] = totals.other}, {["Fuel: "] = checkFuel()} }
  571. modem.transmit(channels.send,channels.receive,"stop")
  572. modem.transmit(channels.send,channels.receive,textutils.serialize(finalTable))
  573. modem.close(channels.receive)
  574. end
  575. if doBackup then fs.delete(saveFile) end
  576. end
  577. function updateDisplay() --Runs in Mine(), display information to the screen in a certain place
  578. screen(1,1)
  579. print("Blocks Mined")
  580. print(mined)
  581. print("Percent Complete")
  582. print(percent.."%")
  583. print("Fuel")
  584. print(checkFuel())
  585.   -- screen(1,1)
  586.   -- print("Xpos: ")
  587.   -- print(xPos)
  588.   -- print("RelXPos: ")
  589.   -- print(relxPos)
  590.   -- print("Z Pos: ")
  591.   -- print(zPos)
  592.   -- print("Y pos: ")
  593.   -- print(yPos)
  594.  
  595. if rednetEnabled then
  596. screenLine(1,7)
  597. print("Connected: "..tostring(connected))
  598. end
  599. end
  600. function logMiningRun(textExtension, extras) --Logging mining runs
  601. if logging then
  602. local number
  603. if not fs.isDir(logFolder) then
  604.   fs.delete(logFolder)
  605.   fs.makeDir(logFolder)
  606.   number = 1
  607. else
  608.   local i = 0
  609.   repeat
  610.     i = i + 1
  611.   until not fs.exists(logFolder.."/Quarry_Log_"..tostring(i)..(textExtension or ""))
  612.   number = i
  613. end
  614. handle = fs.open(logFolder.."/Quarry_Log_"..tostring(number)..(textExtension or ""),"w")
  615. local function write(...)
  616.   for a, b in ipairs({...}) do
  617.     handle.write(tostring(b))
  618.   end
  619.   handle.write("\n")
  620. end
  621. write("Welcome to the Quarry Logs!")
  622. write("Entry Number: ",number)
  623. write("Dimensions (X Z Y): ",x," ",z," ", dispY)
  624. write("Blocks Mined: ", mined)
  625. write("  Cobble: ", totals.cobble)
  626. write("  Usable Fuel: ", totals.fuel)
  627. write("  Other: ",totals.other)
  628. write("Total Fuel Used: ",  (originalFuel or (neededFuel + checkFuel()))- checkFuel()) --Protect against errors with some precision
  629. write("Expected Fuel Use: ", neededFuel)
  630. handle.close()
  631. end
  632. end
  633. function isFull(slots)
  634.   slots = slots or 16
  635.   local numUsed = 0
  636.   sleep(0)
  637.   for i=1, slots do
  638.     if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end
  639.   end
  640.   if numUsed >= slots then
  641.     return true
  642.   end
  643.   return false
  644. end
  645. function dig(doAdd, func)
  646.   doAdd = doAdd or true
  647.   func = func or turtle.dig
  648.   if func() then
  649.     if doAdd then
  650.       mined = mined + 1
  651.     end
  652.     return true
  653.   end
  654.   return false
  655. end
  656. function digUp(doAdd)
  657.     return dig(doAdd,turtle.digUp)
  658. end
  659. function digDown(doAdd)
  660.     return dig(doAdd,turtle.digDown)
  661. end
  662. function relativeXCalc()
  663.   if rowCheck == "right" then relxPos = xPos else relxPos = (x-xPos)+1 end
  664. end
  665. function forward(doAdd)
  666.   if doAdd == nil then doAdd = true end
  667.   if turtle.forward() then
  668.     if doAdd then
  669.       moved = moved + 1
  670.     end
  671.     if facing == 0 then
  672.       xPos = xPos + 1
  673.     elseif facing == 1 then
  674.       zPos = zPos + 1
  675.     elseif facing == 2 then
  676.       xPos = xPos - 1
  677.     elseif facing == 3 then
  678.       zPos = zPos - 1
  679.     else
  680.       error("Function forward, facing should be 0 - 3, got "..tostring(facing),2)
  681.     end
  682.     relativeXCalc()
  683.     return true
  684.   end
  685.   return false
  686. end
  687. function up(sneak)
  688.   sneak = sneak or 1
  689.   if inverted and sneak == 1 then
  690.     down(-1)
  691.   else
  692.     while not turtle.up() do
  693.       if not digUp() then
  694.         attackUp()
  695.         sleep(0.5)
  696.       end
  697.     end
  698.     yPos = yPos - sneak --Oh! I feel so clever
  699.   end                   --This works because inverted :)
  700. end
  701. function down(sneak)
  702.   sneak = sneak or 1
  703.   local count = 0
  704.   if inverted and sneak == 1 then
  705.     up(-1)
  706.   else
  707.     while not turtle.down() do
  708.       count = count + 1
  709.       if not digDown() then
  710.         attackDown()
  711.         sleep(0.2)
  712.       end
  713.       if count > 20 then bedrock() end
  714.     end
  715.     yPos = yPos + sneak
  716.   end
  717. end
  718. function right(num)
  719.   num = num or 1
  720.   for i=1, num do facingF(1); saveProgress(); turtle.turnRight() end
  721. end
  722. function left(num)
  723.   num = num or 1
  724.   for i=1, num do facingF(-1); saveProgress(); turtle.turnLeft() end
  725. end
  726. function attack(doAdd, func)
  727.   doAdd = doAdd or true
  728.   func = func or turtle.attack
  729.   if func() then
  730.     if doAdd then
  731.       attacked = attacked + 1
  732.     end
  733.     return true
  734.   end
  735.   return false
  736. end
  737. function attackUp(doAdd)
  738.   if inverted then
  739.     return attack(doAdd, turtle.attackDown)
  740.   else
  741.     return attack(doAdd, turtle.attackUp)
  742.   end
  743. end
  744. function attackDown(doAdd)
  745.   if inverted then
  746.     return attack(doAdd, turtle.attackUp)
  747.   else
  748.     return attack(doAdd, turtle.attackDown)
  749.   end
  750. end
  751.  
  752.  
  753. function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward
  754. if doCheckInv == nil then doCheckInv = true end
  755. if doDigDown == nil then doDigDown = true end
  756. if doDigUp == nil then doDigUp = true end
  757. if outOfPath == nil then outOfPath = false end
  758. if inverted then
  759.   doDigUp, doDigDown = doDigDown, doDigUp --Just switch the two if inverted
  760. end
  761. if doRefuel and checkFuel() <= fuelTable[fuelSafety]/2 then
  762.   for i=1, 16 do
  763.   if turtle.getItemCount(i) > 0 then
  764.     turtle.select(i)
  765.     if checkFuel() < 200 + fuelTable[fuelSafety] then
  766.       turtle.refuel()
  767.     end
  768.   end
  769.   end
  770. end
  771. local count = 0
  772. while not forward(not outOfPath) do
  773.   sleep(0) --Calls coroutine.yield to prevent errors
  774.   count = count + 1
  775.   if not dig() then
  776.     attack()
  777.   end
  778.   if count > 10 then
  779.     attack()
  780.     sleep(0.2)
  781.   end
  782.   if count > 50 then
  783.     if turtle.getFuelLevel() == 0 then --Don't worry about inf fuel because I modified this function
  784.       saveProgress({doCheckFuel = true})
  785.       error("No more fuel",0)
  786.     elseif yPos > (startY-7) then --If it is near bedrock
  787.       bedrock()
  788.     else --Otherwise just sleep for a bit to avoid sheeps
  789.       sleep(1)
  790.     end
  791.   end
  792. end
  793. --Insanity Checking
  794. if xPos < 0 or xPos > x or zPos < 0 or zPos > z or yPos < 0 then
  795.   print("Oops. Detected that quarry was outside of predefined boundaries.")
  796.   print("Please go to my forum thread and report this with a short description of what happened")
  797.   print("If you could also run \"pastebin put Civil_Quarry_Restore\" and give me that code it would be great")
  798.   error("",0)
  799. end
  800. saveProgress(tab)
  801. if doDigUp then
  802. while turtle.detectUp() do
  803.   sleep(0) --Calls coroutine.yield
  804.   if not digUp() then
  805.     attackUp()
  806.     count = count + 1
  807.   end
  808.   if count > 50 and yPos > (startY-7) then --Same deal with bedrock as above
  809.     bedrock()
  810.   end
  811.   end
  812. end
  813. if doDigDown then
  814.  digDown()
  815. end
  816. percent = math.ceil(moved/moveVolume*100)
  817. updateDisplay()
  818. isInPath = (not outOfPath) --For rednet
  819. if doCheckInv and careAboutResources then
  820. if moved%invCheckFreq == 0 then
  821.  if isFull(16-keepOpen) then dropOff() end
  822. end; end
  823. if rednetEnabled then biometrics() end
  824. end
  825. --Direction: Front = 0, Right = 1, Back = 2, Left = 3
  826. function facingF(num)
  827. facing = facing + num
  828. if facing > 3 then facing = 0 end
  829. if facing < 0 then facing = 3 end
  830. end
  831.  
  832. function turnTo(num, dir)
  833.   num = num or facing
  834.   dir = dir or "left"
  835.   while facing ~= num do
  836.     if dir == "left" then
  837.       left()
  838.     elseif dir == "right" then
  839.       right()
  840.     else
  841.       error("TurnTo: Left or Right expected, got "..tosrting(dir))
  842.       end
  843.   end
  844. end
  845. function goto(x,z,y, toFace)
  846. --Will first go to desired z pos, then x pos, y pos varies
  847. x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing
  848. gotoX,gotoY,gotoZ,gotoFacing = xPos,yPos,zPos,facing --For use in session persistence
  849. if yPos > y then --Will go up first if below position
  850.   while yPos~=y do up() end
  851. end
  852. if zPos > z then
  853.   turnTo(3)
  854. elseif zPos < z then
  855.   turnTo(1)
  856. end
  857. while zPos ~= z do mine(false,false,true,false) end
  858. if xPos > x then
  859.   turnTo(2)
  860. elseif xPos < x then
  861.   turnTo(0)
  862. end
  863. while xPos ~= x do mine(false,false,true,false) end
  864. if yPos < y then --Will go down after if above position
  865.   while yPos~=y do down() end
  866. end
  867. turnTo(toFace,"right")
  868. saveProgress()
  869. gotoX,gotoY,gotoZ,gotoFacing = nil
  870. end
  871. function drop(side, final, allowSkip)
  872. side = sides[side] or "front"    --The final number means that it will
  873. if final then final = 0 else final = 1 end --drop a whole stack at the end
  874. local allowSkip = allowSkip or (final == 0) --This will allow drop(side,t/f, rednetConnected)
  875. count()
  876. if doRefuel then
  877.   for i=1, 16 do
  878.     if slot[i][1] == 2 then
  879.       turtle.select(i); turtle.refuel()
  880.     end
  881.   end
  882.   turtle.select(1)
  883. end
  884. if side == "right" then turnTo(1) end
  885. if side == "left" then turnTo(3) end
  886. local whereDetect, whereDrop1, whereDropAll
  887. local _1 = slot[1][2] - final --All but one if final, all if not final
  888. if side == "top" then
  889. whereDetect = turtle.detectUp ; whereDrop = turtle.dropUp
  890. elseif side == "bottom" then
  891. whereDetect = turtle.detectDown ; whereDrop = turtle.dropDown
  892. else
  893. whereDetect = turtle.detect; whereDrop = turtle.drop
  894. end
  895. local function waitDrop(val) --This will just drop, but wait if it can't
  896.   val = val or 64
  897.   local try = 1
  898.   while not whereDrop(val) do
  899.     print("Chest Full, Try "..try)
  900.     try = try + 1
  901.     sleep(2)
  902.   end
  903. end
  904. repeat
  905. local detected = whereDetect()
  906. if detected then
  907.   waitDrop(_1)
  908.   for i=2, 16 do
  909.     if turtle.getItemCount(i) > 0 then
  910.       turtle.select(i)
  911.       waitDrop()
  912.     end
  913.   end
  914. elseif not allowSkip then
  915.   print("Waiting for chest placement place a chest to continue")
  916.   while not whereDetect() do
  917.     sleep(1)
  918.   end
  919. end
  920. until detected or allowSkip
  921. if not allowSkip then totals.cobble = totals.cobble - 1 end
  922. turtle.select(1)
  923. turnTo(0)
  924. end
  925. function dropOff() --Not local because called in mine()
  926. local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing
  927. goto(0,1,1,2)
  928. drop(dropSide,false)
  929. mine(false,false,true, false)
  930. goto(1,1,1, 0)
  931. goto(currX,currZ,currY,currFacing)
  932. end
  933. function bedrock()
  934. if checkFuel() == 0 then error("No Fuel",0) end
  935. local origin = {x = xPos, y = yPos, z = zPos}
  936. print("Bedrock Detected")
  937. if turtle.detectUp() then
  938. print("Block Above")
  939. local var
  940. if facing == 0 then var = 2 elseif facing == 2 then var = 0 else error("Was facing left or right on bedrock") end
  941. goto(xPos,zPos,yPos,var)
  942. for i=1, relxPos do mine(true,true); end
  943. end
  944. goto(0,1,1,2)
  945. drop(dropSide, true)
  946. display()
  947. print("\nFound bedrock at these coordinates: ")
  948. print(origin.x," Was position in row\n",origin.z," Was row in layer\n",origin.y," Blocks down from start")
  949. error("",0)
  950. end
  951. -------------------------------------------------------------------------------------
  952. --Pre-Mining Stuff dealing with session persistence
  953. local doDigDown, doDigUp = (lastHeight ~= 1), false --Used in lastHeight
  954. if gpsEnabled and not restoreFound then --The initial locate is done in the arguments. This is so I can figure out what quadrant the turtle is in.
  955.   gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.
  956. end
  957. if not restoreFound then --Regularly
  958.   --Check if it is a mining turtle
  959.   if not isMiningTurtle then
  960.     local a, b = turtle.dig()
  961.     if a then mined = mined + 1; isMiningTurtle = true
  962.     elseif b == "Nothing to dig with" then
  963.       print("This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe")
  964.       error("",0)
  965.     end
  966.   end
  967.   if y~= 0 then mine(false, false, true) down() end --Get into quarry
  968. else --restore found
  969.   digUp(); digDown() --Get blocks missed before stopped
  970.   if gotoX then
  971.     goto(gotoX,gotoZ,gotoY,gotoFacing)
  972.   end
  973.   if (relxPos == x or relxPos == 1) and not gotoX and not (facing == 0 or facing == 2) then --If not in goto loop or facing standard direction
  974.     if rowCheck == "right" then --If on odd rows (starting with first)
  975.       turnTo(0) --Face the end so will turn properly
  976.     else
  977.       turnTo(2)
  978.     end
  979.   end
  980. end
  981. --Mining Loops
  982. turtle.select(1)
  983. while layersDone <= y do -------------Height---------
  984. moved = moved + 1 --To account for the first position in row as "moved"
  985. if not restoreFound then rowCheck = "right"; relativeXCalc() end
  986. while zPos <= z do -------------Width----------
  987. while relxPos < x do ------------Length---------
  988. mine()
  989. end ---------------Length End-------
  990. if zPos ~= z then
  991. local func
  992. if rowCheck == "right" and zPos ~= z then --Swithcing to next row
  993. func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
  994.   func()
  995.   saveProgress({zPos = zPos + 1}) --This might make it so it will go back to proper spot z wise
  996.   mine()
  997.   func()
  998. else break
  999. end
  1000. end ---------------Width End--------
  1001. goto(1,1,yPos,0)
  1002. if yPos+1 ~= y then
  1003.   for i=1, 3 do down() end
  1004. end
  1005. layersDone = layersDone + 3
  1006. restoreFound = false --This is done so that rowCheck works properly upon restore
  1007. end ---------------Height End-------
  1008. if lastHeight ~= 0 then ---------LAST ROW--------- (copied from above)
  1009. moved = moved + 1 --To account for the first position in row as "moved"
  1010. if y ~= 0 then --If the basic y == 2 or 1
  1011.   for i=1, 2 do down() end
  1012. end
  1013. if not restoreFound then rowCheck = "right" end
  1014. relativeXCalc()
  1015. while zPos <= z do -------------Width----------
  1016. while relxPos < x do ------------Length---------
  1017. mine(doDigDown,doDigUp)
  1018. end ---------------Length End-------
  1019. if zPos ~= z then
  1020. local func
  1021. if rowCheck == "right" and zPos ~= z then --Swithcing to next row
  1022.   func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
  1023.   func()
  1024.   mine(doDigDown,doDigUp)
  1025.   func()
  1026. else break
  1027. end
  1028. end ---------------Width End--------
  1029. goto(1,1,yPos,0)
  1030. end
  1031. if doDigDown then
  1032.   if inverted then
  1033.     digUp()
  1034.   else
  1035.     digDown()
  1036.   end
  1037. end
  1038. goto(0,1,1,2)
  1039.  
  1040. --Output to a chest or sit there
  1041. drop(dropSide, true)
  1042. --Display was moved above to be used in bedrock function
  1043. display()
  1044. --Log current mining run
  1045. logMiningRun(logExtension)
  1046.  
  1047. --Cleanup
  1048. turtle.getFuelLevel = getFuel
RAW Paste Data
Top