Guest User

Quarry 3.2.0

a guest
Sep 19th, 2013
383
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 37.49 KB | None | 0 0
  1. --[[
  2. Version 3.2.0
  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, endRow, startY
  145.     = 0,   1,   1,   0,     0,      0,    0,    1,       "right",  false,     true,     1,          0,        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
  172. turtle.getFuelLevel = function() --Unlimited screws up my calculations
  173. if doCheckFuel then --Also, this may or may not screw it up for other programs that run...
  174.   return getFuel()
  175. else
  176.   return math.huge --Lol... Should work for my purposes
  177. end
  178. end
  179. local checkFuel = turtle.getFuelLevel --Just an alias for backwards compat
  180.  
  181.  -----------------------------------------------------------------
  182. --Input Phase
  183. local function screen(xPos,yPos)
  184. xPos, yPos = xPos or 1, yPos or 1
  185. term.setCursorPos(xPos,yPos); term.clear(); end
  186. local function screenLine(xPos,yPos)
  187. term.setCursorPos(xPos,yPos); term.clearLine(); end
  188.  
  189. screen(1,1)
  190. print("----- Welcome to Quarry! -----")
  191. print("")
  192.  
  193. local sides = {top = "top", right = "right", left = "left", bottom = "bottom", front = "front"} --Used to whitelist sides
  194. local errorT = {num = "Numbers not recognized", zero = "Variable is out of range", word = "String failed assertion" }
  195. local changedT = {}
  196. changedT.new = function(key, value) changedT[#changedT+1] = {[key] = value} end
  197. changedT.getPair = function(i) for a, b in pairs(changedT[i]) do return a, b end end
  198. local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end
  199. 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
  200. local function checkNum(number, section) return assert(tonumber(number),errorT.num, section) end
  201. tArgs.checkStart = function(num) tArgs[tArgs[num]] = num end
  202. for i=1, #tArgs do tArgs.checkStart(i) end
  203.  
  204. --Check if it is a turtle
  205. if not turtle then
  206.   print("This is not a turtle, you must be looking for the \"Companion Rednet Program\" \nCheck My forum thread for that")
  207.   print("Press 'q' to quit, or any other key to start help ")
  208.   if ({os.pullEvent("char")})[2] ~= "q" then tArgs.help = true else error("",0) end
  209. end
  210.  
  211.  
  212. if tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"] then
  213. print("You have selected help, press any key to continue"); print("Use arrow keys to naviate, q to quit"); os.pullEvent("key")
  214. local pos = 1
  215. local key = 0
  216. while pos <= #help and key ~= keys.q do
  217. if pos < 1 then pos = 1 end
  218. screen(1,1)
  219. print(help[pos].title)
  220. for a=1, #help[pos] do print(help[pos][a]) end
  221. repeat
  222. _, key = os.pullEvent("key")
  223. until key == 200 or key == 208 or key == keys.q
  224. if key == 200 then pos = pos - 1 end
  225. if key == 208 then pos = pos + 1 end
  226. end
  227. error("",0)
  228. end
  229.  
  230. --Check if it is a mining turtle
  231. if not isMiningTurtle then
  232.   local a, b = turtle.dig()
  233.   if a then mined = mined + 1; isMiningTurtle = true
  234.   elseif b == "Nothing to dig with" then
  235.     print("This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe")
  236.     error("",0)
  237.   end
  238. end
  239.  
  240. --Saving
  241. if tArgs["doBackup"] then doBackup = (string.lower(string.sub(tArgs[tArgs["doBackup"]+1],1,1)) ~= "f") end
  242. if tArgs["saveFile"] then saveFile = tArgs[tArgs["saveFile"]+1] or saveFile end
  243.  
  244. local restoreFound = false
  245. if tArgs["-restore"] or tArgs["-resume"] then
  246. restoreFound = fs.exists(saveFile)
  247. if restoreFound then
  248. os.run(getfenv(1),saveFile)
  249. if gpsEnabled then --If it had saved gps coordinates
  250.   print("Found GPS Start Coordinates")
  251.   local currLoc = {gps.locate(gpsTimeout)}
  252.   if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using
  253.     print("GPS Position Successfully Read")
  254.     if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order
  255.       xPos, yPos, zPos = 0,1,1
  256.       if facing ~= 0 then turnTo(0) end
  257.       print("Is at start")
  258.     else
  259.       if inverted then --yPos setting
  260.       ------------------------------------------------FIX THIS
  261.       end
  262.       local function copyTable(tab) local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end
  263.       local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience
  264.       if b[3] - a[3] == -1 then--If went north (-Z)
  265.         a[1] = a[1] - 1 --Shift x one to west to create a "zero"
  266.         xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]
  267.       elseif b[1] - a[1] == 1 then--If went east (+X)
  268.         a[3] = a[3] - 1 --Shift z up one to north to create a "zero"
  269.         xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]
  270.       elseif b[3] - a[3] == 1 then--If went south (+Z)
  271.         a[1] = a[1] + 1 --Shift x one to east to create a "zero"
  272.         xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]
  273.       elseif b[1] - a[1] == -1 then--If went west (-X)
  274.         a[3] = a[3] + 1 --Shift z down one to south to create a "zero"
  275.         xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]
  276.       else
  277.         print("Improper Coordinates")
  278.         print("GPS Locate Failed, Using Standard Methods")        ----Maybe clean this up a bit to use flags instead.
  279.       end  
  280.     end
  281.     print("X Pos: ",xPos)
  282.     print("Y Pos: ",yPos)
  283.     print("Z Pos: ",zPos)
  284.     print("Facing: ",facing)
  285.   else
  286.     print("GPS Locate Failed, Using Standard Methods")
  287.   end    
  288. print("Restore File read successfully. Starting in 3"); sleep(3)
  289. end
  290. end
  291. else
  292.   originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used
  293. end
  294.  
  295. if not (tArgs["-DEFAULT"] or restoreFound) then
  296.   --Just a note, the whole error checking section here was more of an
  297.   --experiment than anything else. If its ever changed in the future,
  298.   --it would probably be for the better.
  299. local section = "Dimensions"
  300. --Dimesnions
  301. if tArgs["-dim"] then local num = tArgs["-dim"];
  302. x = checkNum(tArgs[num + 1],section); z = checkNum(tArgs[num + 2],section); y = checkNum(tArgs[num + 3],section)
  303. else
  304. print("What dimensions?")
  305. print("")
  306. --This will protect from negatives, letters, and decimals
  307. term.write("Length: ")
  308. x = math.floor(math.abs(tonumber(io.read()) or x))
  309. term.write("Width: ")
  310. z = math.floor(math.abs(tonumber(io.read()) or z))
  311. term.write("Height: ")
  312. y = math.floor(math.abs(tonumber(io.read()) or y))
  313. end
  314. changedT.new("x",x); changedT.new("z",z); changedT.new("y",y)
  315. assert(x~=0, errorT.zero, section); assert(z~=0, errorT.zero, section); assert(y~=0, errorT.zero, section)
  316. assert(not(x == 1 and y == 1 and z == 1) ,"1, 1, 1 dosen't work well at all, try again", section)
  317. if not tArgs["-vanilla"] then
  318. --Invert
  319. if tArgs["-invert"] then
  320. inverted = (string.lower(string.sub(tArgs[tArgs["-invert"]+1] or "",1,1)) == "t") else
  321. term.write("Inverted? ")
  322. inverted = (string.lower(string.sub(io.read(),1,1)) == "y")
  323. end
  324. changedT.new("Inverted", inverted)
  325. --Rednet
  326. if supportsRednet then
  327. if tArgs["-rednet"] then
  328. rednetEnabled = (string.lower(string.sub(tArgs[tArgs["-rednet"]+1] or "",1,1)) == "t")
  329. else term.write("Rednet? "); rednetEnabled = (string.lower(string.sub(io.read(),1,1)) == "y")
  330. if (tArgs["-GPS"] or tArgs["-gps"]) and not restoreFound and not gpsEnabled then --The not gps enabled makes it so it is toggled
  331. gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array
  332. gpsEnabled = #gpsStartPos > 0 --Checks if location received properly
  333. changedT.new("GPS Location Services", gpsEnabled)
  334. end
  335. changedT.new("Rednet Enabled", rednetEnabled)
  336. end
  337. if tArgs["-sendChannel"] then
  338. channels.send = assert(tonumber(tArgs[tArgs["-sendChannel"]+1]), errorT.num)
  339. assert(channels.send > 0 and channels.send < 65535, errorT.zero)
  340. changedT.new("Send Channel",channels.send) end
  341. if tArgs["-receiveChannel"] then
  342. channels.receive = assert(tonumber(tArgs[tArgs["-receiveChannel"]+1]), errorT.num)
  343. assert(channels.receive > 0 and channels.receive < 65535 and channels.receive ~= channels.send, errorT.zero)
  344. changedT.new("Receive Channel",channels.receive) end
  345. end
  346. --Fuel
  347. if tArgs["-doRefuel"] then doRefuel = not doRefuel; changedT.new("Do Refuel",doRefuel) end
  348. if turtle.getFuelLevel() == "unlimited" then
  349.   doCheckFuel = false
  350. else
  351.   if tArgs["-doCheckFuel"] then
  352.   doCheckFuel = (string.lower(string.sub(tArgs[tArgs["-doCheckFuel"]+1] or "",1,1)) == "t"); changedT.new("Do Check Fuel", doCheckFuel) end
  353. end
  354. if tArgs["-chest"] then
  355. dropSide = sides[tArgs[tArgs["-chest"]+1]] or dropSide; changedT.new("Chest Side",dropSide) end
  356. if tArgs["-fuelSafety"] then local loc = tArgs[tArgs["-fuelSafety"]+1]
  357.   if fuelTable[loc] then
  358.     fuelSafety = loc; changedT.new("Fuel Check Safety", fuelSafety)
  359.   end
  360. end
  361. --Logging
  362. logging = (tArgs["-log"] and true) or logging --The and will set it to true if value, or its original value if nil
  363. if logging then changedT.new("Logging",logging) end
  364. if tArgs["-logFolder"] then logFolder = tArgs[tArgs["-logFolder"]+1] or logFolder; changedT.new("Log Folder",logFolder) end
  365. if tArgs["-logExtension"] then logExtension = tArgs[tArgs["-logExtension"]+1] or logExtension; changedT.new("Log Extension",logExtension) end
  366. --Misc
  367. if tArgs["-startY"] then
  368. startY = math.abs(math.floor(checkNum(tArgs[tArgs["-startY"]+1],"Start Y")))
  369. changedT.new("Start Y Position",startY) end
  370. assert(startY >= 0, errorT.zero, "StartY")
  371. if tArgs["-invCheckFreq"] then
  372. invCheckFreq = math.abs(math.floor(checkNum(tArgs[tArgs["-invCheckFreq"]+1],"Inventory Check Frequency")))
  373. changedT.new("Inventory Check Frequency",invCheckFreq) end
  374. assert(invCheckFreq ~= 0, errorT.zero, "Inventory Check Frequency")
  375. if tArgs["-keepOpen"] then
  376. keepOpen = math.abs(math.floor(checkNum(tArgs[tArgs["-keepOpen"]+1],"Open Slots")))
  377. changedT.new("Slots to keep open", keepOpen) end
  378. assert(keepOpen ~= 0 and keepOpen < 16, errorT.zero, "Open Slots")
  379. if tArgs["-ignoreResources"] then careAboutResources = false; changedT.new("Ignore Resources?", not careAboutResources) end
  380. if tArgs["-saveFile"] then saveFile = tArgs[tArgs["-saveFile"]+1] changedT.new("Save File", saveFile) end
  381. assert(#saveFile >= 2,errorT.word, "Save File")
  382. end; end --First end is for vanilla, second is for DEFAULT
  383.  
  384. local function saveProgress(extras) --Session persistence
  385. if doBackup then
  386. local file = fs.open(saveFile,"w")
  387. for a,b in pairs(getfenv(1)) do
  388. if type(b) == "string" then b = "\""..b.."\"" end
  389. if type(b) == "table" and a~="modem" then b = textutils.serialize(b) end
  390. if type(b) ~= "function" then
  391. file.write(a.." = "..tostring(b).."\n")
  392. end
  393. end
  394. file.write("doCheckFuel = false\n") --It has already used fuel, so calculation unnesesary
  395. if type(extras) == "table" then
  396.   for a, b in pairs(extras) do
  397.     file.write(a.." = "..tostring(b))
  398.   end
  399. end
  400. file.close()
  401. end
  402. end
  403.  
  404. local area = x*z
  405. local volume = x*y*z
  406. local lastHeight = y%3
  407. local dispY = y
  408. y = math.floor(y/3)*3
  409. local yMult = y/3 + math.ceil(lastHeight/2) --This is basically a smart y/3 for movement
  410. local moveVolume = (area * yMult) --Kept for display percent
  411. --Calculating Needed Fuel--
  412. local exStack = numberOfStacksPerRun --Expected stacks of items before full
  413. neededFuel = yMult * x * z + --This is volume it will run through
  414.       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
  415.       (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
  416.       --Original equation: x*z*y/3 + y * 2 + (x+z) * y/3 + (x + z + y) * (1/64*8)
  417. neededFuel = math.ceil(neededFuel)
  418.  
  419. --Getting Fuel
  420. if doCheckFuel and checkFuel() < neededFuel then
  421. neededFuel = neededFuel + fuelTable[fuelSafety] --For safety
  422.   print("Not enough fuel")
  423.   print("Current: ",checkFuel()," Needed: ",neededFuel)
  424.   print("Starting SmartFuel")
  425.   sleep(1) --So they can read everything.
  426.   term.clear()
  427.   local oneFuel, neededFuelItems
  428.   local currSlot = 0
  429.   local function output(text, x, y) --For displaying fuel
  430.     currX, currY = term.getCursorPos()
  431.     term.setCursorPos(x,y)
  432.     term.clearLine()
  433.     term.write(text)
  434.     term.setCursorPos(currX,currY)
  435.     end
  436.   local function roundTo(num, target) --For stacks of fuel
  437.     if num >= target then return target else return num end
  438.   end
  439.   local function updateScreen()
  440.     output("Welcome to SmartFuel! Now Refueling...", 1,1)
  441.     output("Currently taking fuel from slot "..currSlot,1,2)
  442.     output("Current single fuel: "..tostring(oneFuel or 0),1,3)
  443.     output("Current estimate of needed fuel: ",1,4)
  444.     output("Single Items: "..math.floor(neededFuelItems or 0),4,5)
  445.     output("Stacks:       "..math.ceil((neededFuelItems or 0) / 64),4,6)
  446.     output("Needed Fuel: "..tostring(neededFuel),1,12)
  447.     output("Current Fuel: "..tostring(checkFuel()),1,13)
  448.   end
  449.   while checkFuel() <= neededFuel do
  450.     currSlot = currSlot + 1
  451.     turtle.select(currSlot)
  452.     updateScreen()
  453.     while turtle.getItemCount(currSlot) == 0 do sleep(1.5) end
  454.     repeat
  455.       local previous = checkFuel()
  456.       turtle.refuel(1)
  457.       oneFuel = checkFuel() - previous
  458.       updateScreen()
  459.     until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.
  460.     neededFuelItems = (neededFuel - checkFuel()) / oneFuel
  461.     turtle.refuel(roundTo(neededFuelItems, 64)) --Change because can only think about 64 at once.
  462.     if turtle.getItemCount(roundTo(currSlot + 1, 16)) == 0 then --Resets if no more fuel
  463.       currSlot = 0
  464.     end
  465.   end
  466. -- local neededFuel = moveVolume + (math.floor(volume / (64 * 8)) * (x+dispY+z)) --Standard move plus dropping off supplies
  467.                              -- --How many times come back to start| * If it were at the very far side
  468. -- neededFuel = neededFuel + fuelTable[fuelSafety]
  469. -- if neededFuel < 100 then neededFuel = 100; end
  470. -- if checkFuel() < neededFuel then
  471. -- screen(1,1)
  472. -- print("More Fuel Needed")
  473. -- print("Current Fuel: ",checkFuel()," Needed: ",neededFuel)
  474. -- print("Place fuel in Bottom Right")
  475. -- while turtle.getItemCount(16) == 0 do
  476.   -- sleep(1)
  477. -- end
  478. -- turtle.select(16)
  479. -- while checkFuel() < neededFuel do
  480. -- if not turtle.refuel(1) then
  481. -- term.clearLine()
  482. -- print("Still too little fuel")
  483. -- term.clearLine()
  484. -- print("Insert more fuel to resume")
  485. -- while turtle.getItemCount(16) == 0 do
  486.   -- sleep(1)
  487. -- end
  488. -- end
  489. -- local x,y = term.getCursorPos()
  490. -- print(checkFuel().." Fuel")
  491. -- term.setCursorPos(x,y)
  492. -- end
  493. -- print(checkFuel().." Units of Fuel")
  494. -- sleep(3)
  495. -- turtle.select(1)
  496. -- end
  497. end
  498. --Initial Rednet Handshake
  499. if rednetEnabled then
  500. screen(1,1)
  501. print("Rednet is Enabled")
  502. print("The Channel to open is "..channels.send)
  503. modem = peripheral.wrap("right")
  504. modem.open(channels.receive)
  505. local i = 0
  506. repeat
  507. local id = os.startTimer(3)
  508. i=i+1
  509. print("Sending Initial Message "..i)
  510. modem.transmit(channels.send, channels.receive, "{ 'Initial' }")
  511. local message
  512. repeat
  513. local event, idCheck, channel,_,locMessage, distance = os.pullEvent()
  514. message = locMessage
  515. until (event == "timer" and idCheck == id) or (event == "modem_message" and channel == channels.receive and message == channels.confirm)
  516. until message == channels.confirm
  517. connected = true
  518. print("Connection Confirmed!")
  519. sleep(1.5)
  520. end
  521. local function biometrics(sendChannel)
  522. local commands = { Confirm = "Confirm" }
  523. local toSend = { ["x"] = x, ["y"] = (y/3 + math.ceil(lastHeight/2)), ["z"] = z, --The y calc is weird...
  524.     ["xPos"] = xPos, ["yPos"] = yPos, ["zPos"] = zPos,
  525.     ["percent"] = percent, ["mined" ]= mined,
  526.     ["fuel"] = checkFuel(), ["moved"] = moved,
  527.     ["remainingBlocks"] = (volume-mined), ["ID"] = os.getComputerID(),
  528.     ["isInPath"] = isInPath, --Whether it is going back to start
  529.     ["volume"] = volume, ["area"] = area}
  530. modem.transmit(channels.send, channels.receive, textutils.serialize(toSend))
  531. id = os.startTimer(0.1)
  532. local event, message
  533. repeat
  534. local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()
  535. event, message = locEvent, locMessage
  536. until (event == "timer" and idCheck == id) or (event == "modem_message" and confirm == channels.receive)
  537. if event == "modem_message" then connected = true else connected = false end
  538. --Stuff to do for different commands
  539. end
  540. --Showing changes to settings
  541. screen(1,1)
  542. print("Your selected settings:")
  543. if #changedT == 0 then
  544. print("Completely Default")
  545. else
  546. for i=1, #changedT do
  547. local title, value = changedT.getPair(i)
  548. print(capitalize(title)..": ",value)
  549. end
  550. end
  551. print("\nStarting in 3"); sleep(1); print("2"); sleep(1); print("1"); sleep(1.5) --Dramatic pause at end
  552.  
  553.  
  554.  
  555. ----------------------------------------------------------------
  556. --Define ALL THE FUNCTIONS
  557. function display() --This is just the last screen that displays at the end
  558. screen(1,1)
  559. print("Total Blocks Mined: "..mined)
  560. print("Current Fuel Level: "..turtle.getFuelLevel())
  561. print("Cobble: "..totals.cobble)
  562. print("Usable Fuel: "..totals.fuel)
  563. print("Other: "..totals.other)
  564. if rednetEnabled then
  565. print("")
  566. print("Sent Stop Message")
  567. finalTable = {{["Mined: "] = mined}, {["Cobble: "] = totals.cobble}, {["Fuel: "] = totals.fuel},
  568.     {["Other: "] = totals.other}, {["Fuel: "] = checkFuel()} }
  569. modem.transmit(channels.send,channels.receive,"stop")
  570. modem.transmit(channels.send,channels.receive,textutils.serialize(finalTable))
  571. modem.close(channels.receive)
  572. end
  573. if doBackup then fs.delete(saveFile) end
  574. end
  575. function updateDisplay() --Runs in Mine(), display information to the screen in a certain place
  576. screen(1,1)
  577. print("Blocks Mined")
  578. print(mined)
  579. print("Percent Complete")
  580. print(percent.."%")
  581. print("Fuel")
  582. print(checkFuel())
  583. if rednetEnabled then
  584. screenLine(1,7)
  585. print("Connected: "..tostring(connected))
  586. end
  587. end
  588. function logMiningRun(textExtension, extras) --Logging mining runs
  589. if logging then
  590. local number
  591. if not fs.isDir(logFolder) then
  592.   fs.delete(logFolder)
  593.   fs.makeDir(logFolder)
  594.   number = 1
  595. else
  596.   local i = 0
  597.   repeat
  598.     i = i + 1
  599.   until not fs.exists(logFolder.."/Quarry_Log_"..tostring(i)..(textExtension or ""))
  600.   number = i
  601. end
  602. handle = fs.open(logFolder.."/Quarry_Log_"..tostring(number)..(textExtension or ""),"w")
  603. local function write(...)
  604.   for a, b in ipairs({...}) do
  605.     handle.write(tostring(b))
  606.   end
  607.   handle.write("\n")
  608. end
  609. write("Welcome to the Quarry Logs!")
  610. write("Entry Number: ",number)
  611. write("Dimensions (X Z Y): ",x," ",z," ", dispY)
  612. write("Blocks Mined: ", mined)
  613. write("  Cobble: ", totals.cobble)
  614. write("  Usable Fuel: ", totals.fuel)
  615. write("  Other: ",totals.other)
  616. write("Total Fuel Used: ",  originalFuel- checkFuel())
  617. write("Expected Fuel Use: ", neededFuel)
  618. handle.close()
  619. end
  620. end
  621. function isFull(slots)
  622.   slots = slots or 16
  623.   local numUsed = 0
  624.   sleep(0)
  625.   for i=1, slots do
  626.     if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end
  627.   end
  628.   if numUsed >= slots then
  629.     return true
  630.   end
  631.   return false
  632. end
  633. function dig(doAdd, func)
  634.   doAdd = doAdd or true
  635.   func = func or turtle.dig
  636.   if func() then
  637.     if doAdd then
  638.       mined = mined + 1
  639.     end
  640.     return true
  641.   end
  642.   return false
  643. end
  644. function digUp(doAdd)
  645.     return dig(doAdd,turtle.digUp)
  646. end
  647. function digDown(doAdd)
  648.     return dig(doAdd,turtle.digDown)
  649. end
  650. function relativeXCalc()
  651.   if rowCheck == "right" then relxPos = xPos else relxPos = (x-xPos)+1 end
  652. end
  653. function forward(doAdd)
  654.   if doAdd == nil then doAdd = true end
  655.   if turtle.forward() then
  656.     if doAdd then
  657.       moved = moved + 1
  658.     end
  659.    if facing == 0 then
  660.       xPos = xPos + 1
  661.     elseif facing == 1 then
  662.       zPos = zPos + 1
  663.     elseif facing == 2 then
  664.       xPos = xPos - 1
  665.     elseif facing == 3 then
  666.       zPos = zPos - 1
  667.     else
  668.       error("Function forward, facing should be 0 - 3, got "..tostring(facing),2)
  669.     end
  670.     relativeXCalc()
  671.     return true
  672.   end
  673.   return false
  674. end
  675. function up(sneak)
  676.   sneak = sneak or 1
  677.   if inverted and sneak == 1 then
  678.     down(-1)
  679.   else
  680.     while not turtle.up() do
  681.       if not digUp() then
  682.         attackUp()
  683.         sleep(0.5)
  684.       end
  685.     end
  686.     yPos = yPos - sneak --Oh! I feel so clever
  687.   end                   --This works because inverted :)
  688. end
  689. function down(sneak)
  690.   sneak = sneak or 1
  691.   local count = 0
  692.   if inverted and sneak == 1 then
  693.     up(-1)
  694.   else
  695.     while not turtle.down() do
  696.       count = count + 1
  697.       if not digDown() then
  698.         attackDown()
  699.         sleep(0.2)
  700.       end
  701.       if count > 20 then bedrock() end
  702.     end
  703.     yPos = yPos + sneak
  704.   end
  705. end
  706. function right(num)
  707.   num = num or 1
  708.   for i=1, num do facingF(1); saveProgress(); turtle.turnRight() end
  709. end
  710. function left(num)
  711.   num = num or 1
  712.   for i=1, num do facingF(-1); saveProgress(); turtle.turnLeft() end
  713. end
  714. function attack(doAdd, func)
  715.   doAdd = doAdd or true
  716.   func = func or turtle.attack
  717.   if func() then
  718.     if doAdd then
  719.       attacked = attacked + 1
  720.     end
  721.     return true
  722.   end
  723.   return false
  724. end
  725. function attackUp(doAdd)
  726.   if inverted then
  727.     return attack(doAdd, turtle.attackDown)
  728.   else
  729.     return attack(doAdd, turtle.attackUp)
  730.   end
  731. end
  732. function attackDown(doAdd)
  733.   if inverted then
  734.     return attack(doAdd, turtle.attackUp)
  735.   else
  736.     return attack(doAdd, turtle.attackDown)
  737.   end
  738. end
  739.  
  740.  
  741. function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward
  742. if doCheckInv == nil then doCheckInv = true end
  743. if doDigDown == nil then doDigDown = true end
  744. if doDigUp == nil then doDigUp = true end
  745. if outOfPath == nil then outOfPath = false end
  746. if inverted then
  747.   doDigUp, doDigDown = doDigDown, doDigUp --Just switch the two if inverted
  748. end
  749. if doRefuel and checkFuel() <= fuelTable[fuelSafety]/2 then
  750.   for i=1, 16 do
  751.   if turtle.getItemCount(i) > 0 then
  752.     turtle.select(i)
  753.     if checkFuel() < 200 + fuelTable[fuelSafety] then
  754.       turtle.refuel()
  755.     end
  756.   end
  757.   end
  758. end
  759. local count = 0
  760. while not forward(not outOfPath) do
  761.   sleep(0) --Calls coroutine.yield to prevent errors
  762.   count = count + 1
  763.   if not dig() then
  764.     attack()
  765.   end
  766.   if count > 10 then
  767.     attack()
  768.     sleep(0.2)
  769.   end
  770.   if count > 50 then
  771.     if turtle.getFuelLevel() == 0 then --Don't worry about inf fuel because I modified this function
  772.       saveProgress()
  773.       error("No more fuel",0)
  774.     elseif yPos > (startY-7) then --If it is near bedrock
  775.       bedrock()
  776.     else --Otherwise just sleep for a bit to avoid sheeps
  777.       sleep(1)
  778.     end
  779.   end
  780. end
  781. local tab = {} --This registers a change in the saveProgress file
  782. if facing == 0 then --I do this because when it restores, it always
  783.   tab.xPos = xPos + 1-- Thinks it is one position back, for some reason
  784. elseif facing == 1 then-- This overwrites that.
  785.   tab.zPos = zPos + 1
  786. elseif facing == 2 then
  787.   tab.xPos = xPos - 1
  788. elseif facing == 3 then
  789.   tab.zPos = zPos - 1
  790. end
  791. saveProgress(tab)
  792. if doDigUp then
  793. while turtle.detectUp() do
  794.   sleep(0) --Calls coroutine.yield
  795.   if not digUp() then
  796.     attackUp()
  797.     count = count + 1
  798.   end
  799.   if count > 50 and yPos > (startY-7) then --Same deal with bedrock as above
  800.     bedrock()
  801.   end
  802.   end
  803. end
  804. if doDigDown then
  805.  digDown()
  806. end
  807. percent = math.ceil(moved/moveVolume*100)
  808. updateDisplay()
  809. isInPath = (not outOfPath) --For rednet
  810. if doCheckInv and careAboutResources then
  811. if moved%invCheckFreq == 0 then
  812.  if isFull(16-keepOpen) then dropOff() end
  813. end; end
  814. if rednetEnabled then biometrics() end
  815. end
  816. --Direction: Front = 0, Right = 1, Back = 2, Left = 3
  817. function facingF(num)
  818. facing = facing + num
  819. if facing > 3 then facing = 0 end
  820. if facing < 0 then facing = 3 end
  821. end
  822.  
  823. function turnTo(num, dir)
  824.   num = num or facing
  825.   dir = dir or "left"
  826.   while facing ~= num do
  827.     if dir == "left" then
  828.       left()
  829.     elseif dir == "right" then
  830.       right()
  831.     else
  832.       error("TurnTo: Left or Right expected, got "..tosrting(dir))
  833.       end
  834.   end
  835. end
  836. function goto(x,z,y, toFace)
  837. --Will first go to desired z pos, then x pos, y pos varies
  838. x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing
  839. gotoX,gotoY,gotoZ,gotoFacing = xPos,yPos,zPos,facing --For use in session persistence
  840. if yPos > y then --Will go up first if below position
  841.   while yPos~=y do up() end
  842. end
  843. if zPos > z then
  844.   turnTo(3)
  845. elseif zPos < z then
  846.   turnTo(1)
  847. end
  848. while zPos ~= z do mine(false,false,true,false) end
  849. if xPos > x then
  850.   turnTo(2)
  851. elseif xPos < x then
  852.   turnTo(0)
  853. end
  854. while xPos ~= x do mine(false,false,true,false) end
  855. if yPos < y then --Will go down after if above position
  856.   while yPos~=y do down() end
  857. end
  858. turnTo(toFace,"right")
  859. saveProgress()
  860. gotoX,gotoY,gotoZ,gotoFacing = nil
  861. end
  862. function drop(side, final, allowSkip)
  863. side = sides[side] or "front"    --The final number means that it will
  864. if final then final = 0 else final = 1 end --drop a whole stack at the end
  865. local allowSkip = allowSkip or (final == 0) --This will allow drop(side,t/f, rednetConnected)
  866. count()
  867. if doRefuel then
  868.   for i=1, 16 do
  869.     if slot[i][1] == 2 then
  870.       turtle.select(i); turtle.refuel()
  871.     end
  872.   end
  873.   turtle.select(1)
  874. end
  875. if side == "right" then turnTo(1) end
  876. if side == "left" then turnTo(3) end
  877. local whereDetect, whereDrop1, whereDropAll
  878. local _1 = slot[1][2] - final --All but one if final, all if not final
  879. if side == "top" then
  880. whereDetect = turtle.detectUp ; whereDrop = turtle.dropUp
  881. elseif side == "bottom" then
  882. whereDetect = turtle.detectDown ; whereDrop = turtle.dropDown
  883. else
  884. whereDetect = turtle.detect; whereDrop = turtle.drop
  885. end
  886. local function waitDrop(val) --This will just drop, but wait if it can't
  887.   val = val or 64
  888.   local try = 1
  889.   while not whereDrop(val) do
  890.     print("Chest Full, Try "..try)
  891.     try = try + 1
  892.     sleep(2)
  893.   end
  894. end
  895. repeat
  896. local detected = whereDetect()
  897. if detected then
  898.   waitDrop(_1)
  899.   for i=2, 16 do
  900.     if turtle.getItemCount(i) > 0 then
  901.       turtle.select(i)
  902.       waitDrop()
  903.     end
  904.   end
  905. elseif not allowSkip then
  906.   print("Waiting for chest placement place a chest to continue")
  907.   while not whereDetect() do
  908.     sleep(1)
  909.   end
  910. end
  911. until detected or allowSkip
  912. if not allowSkip then totals.cobble = totals.cobble - 1 end
  913. turtle.select(1)
  914. turnTo(0)
  915. end
  916. function dropOff() --Not local because called in mine()
  917. local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing
  918. goto(0,1,1,2)
  919. drop(dropSide,false)
  920. mine(false,false,true, false)
  921. goto(1,1,1, 0)
  922. goto(currX,currZ,currY,currFacing)
  923. end
  924. function bedrock()
  925. if checkFuel() == 0 then error("No Fuel",0) end
  926. local origin = {x = xPos, y = yPos, z = zPos}
  927. print("Bedrock Detected")
  928. if turtle.detectUp() then
  929. print("Block Above")
  930. local var
  931. if facing == 0 then var = 2 elseif facing == 2 then var = 0 else error("Was facing left or right on bedrock") end
  932. goto(xPos,zPos,yPos,var)
  933. for i=1, relxPos do mine(true,true); end
  934. end
  935. goto(0,1,1,2)
  936. drop(dropSide, true)
  937. display()
  938. print("\nFound bedrock at these coordinates: ")
  939. print(origin.x," Was position in row\n",origin.z," Was row in layer\n",origin.y," Blocks down from start")
  940. error("",0)
  941. end
  942. -------------------------------------------------------------------------------------
  943. --Pre-Mining Stuff dealing with session persistence
  944. local doDigDown, doDigUp = (lastHeight ~= 1), false --Used in lastHeight
  945. if not restoreFound then mine(false,false, true) else digUp(); digDown() end --Get it into the quarry
  946. 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.
  947.   gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.
  948. end
  949. if restoreFound then
  950.   if gotoX then
  951.     goto(gotoX,gotoZ,gotoY,gotoFacing)
  952.   end
  953.   local func
  954.   if rowCheck == "left" then func = right else func = left end
  955.   if endRow == 1 then
  956.     mine()
  957.     func()
  958.   elseif endRow == 2 then
  959.     func()
  960.   end
  961. end
  962. if y ~= 0 and not restoreFound then down() end
  963. --Mining Loops
  964. turtle.select(1)
  965. while layersDone <= y do -------------Height---------
  966. moved = moved + 1 --To account for the first position in row as "moved"
  967. if not restoreFound then rowCheck = "right" end
  968. relativeXCalc()
  969. while zPos <= z do -------------Width----------
  970. while relxPos < x do ------------Length---------
  971. mine()
  972. end ---------------Length End-------
  973. if zPos ~= z then
  974. local func
  975. if rowCheck == "right" and zPos ~= z then --Swithcing to next row
  976.   func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
  977.   func()
  978.   endRow = 1
  979.   mine()
  980.   endRow = 2
  981.   func()
  982.   endRow = 0
  983. else break
  984. end
  985. end ---------------Width End--------
  986. goto(1,1,yPos,0)
  987. if yPos+1 ~= y then
  988.   for i=1, 3 do down() end
  989. end
  990. layersDone = layersDone + 3
  991. restoreFound = false --This is done so that rowCheck works properly upon restore
  992. end ---------------Height End-------
  993. if lastHeight ~= 0 then ---------LAST ROW--------- (copied from above)
  994. moved = moved + 1 --To account for the first position in row as "moved"
  995. if y ~= 0 then --If the basic y == 2 or 1
  996.   for i=1, 2 do down() end
  997. end
  998. if not restoreFound then rowCheck = "right" end
  999. relativeXCalc()
  1000. while zPos <= z do -------------Width----------
  1001. while relxPos < x do ------------Length---------
  1002. mine(doDigDown,doDigUp)
  1003. end ---------------Length End-------
  1004. if zPos ~= z then
  1005. local func
  1006. if rowCheck == "right" and zPos ~= z then --Swithcing to next row
  1007.   func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
  1008.   func()
  1009.   endRow = 1
  1010.   mine(doDigDown,doDigUp)
  1011.   endRow = 2
  1012.   func()
  1013.   endRow = 0
  1014. else break
  1015. end
  1016. end ---------------Width End--------
  1017. goto(1,1,yPos,0)
  1018. end
  1019. if doDigDown then
  1020.   if inverted then
  1021.     digUp()
  1022.   else
  1023.     digDown()
  1024.   end
  1025. end
  1026. goto(0,1,1,2)
  1027.  
  1028. --Output to a chest or sit there
  1029. drop(dropSide, true)
  1030. --Display was moved above to be used in bedrock function
  1031. display()
  1032. --Log current mining run
  1033. logMiningRun(logExtension)
  1034.  
  1035. --Cleanup
  1036. turtle.getFuelLevel = getFuel
Add Comment
Please, Sign In to add comment