Jameelo

Turtle Quarry v3

Mar 4th, 2024 (edited)
1,116
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.83 KB | Gaming | 0 0
  1. --[[
  2.     Idea is the same as the last quarry program, except this one can save & resume progress, and handles rectangular quarries.
  3.     Digs an WIDTH by LENGTH hole, DEPTH blocks deep; specified by the input. Input can also be an argument
  4.     Calculates fuel expenditure
  5.     Recognises a full inventory & dumps excess into ender chest
  6.     If the turtle is restarted, the program should be able to resume.
  7.     TODO:
  8.     - Maybe fix the single restriction:
  9.         - Length must be more than 1
  10.     - Fix/overhaul saving protocol
  11.         - Maybe by generating toolpath per layer? Then it'll store turns as well?
  12.                
  13. ]]
  14.  
  15. os.loadAPI("common/systemLib.lua")
  16. os.loadAPI("common/storageLib.lua")
  17. os.loadAPI("common/mineLib.lua")
  18.  
  19. local args = {...}
  20.  
  21. -- Quarry progress save file ID
  22. QSAVEPATH = "common/QPROG"
  23. saveExists = false -- fs.exists(QSAVEPATH)
  24.  
  25. -- Forward and perpendicular widths
  26. forwardAxis = 0
  27. perpendicularAxis = 0
  28.  
  29. local function getInputInt(inputName,restriction) -- assign an integer input with restrictions, checking for validity
  30.     local illegalInput = true
  31.  
  32.     if restriction == nil then -- Default
  33.         restriction = 0
  34.     end
  35.  
  36.     while illegalInput do
  37.         print(string.format("How %s should the quarry be?",inputName))
  38.         input = tonumber(read())
  39.  
  40.         if input ~= nil and input > restriction then
  41.             illegalInput = false
  42.         else
  43.             term.clear()
  44.             print(string.format("%s must be an integer larger than %i"),inputName,restriction)
  45.         end
  46.     end
  47.  
  48.     return input
  49. end
  50.  
  51. local function quarrySetup() -- Get user specified dimensions
  52.     -- Assume the turtle is facing the same direction as user
  53.  
  54.     -- Width (Left)
  55.     WIDTH = getInputInt("Wide")
  56.     QSAVE["width"] = WIDTH
  57.  
  58.     -- Length (Forwards)
  59.     LENGTH = getInputInt("Long",1)
  60.     QSAVE["length"] = LENGTH
  61.  
  62.     -- Depth (Up/Down)
  63.     DEPTH = getInputInt("Deep")
  64.     QSAVE["depth"] = DEPTH
  65. end
  66.  
  67. local function upDownReturn() -- determine direction and return choice
  68.     -- Up or down?
  69.     print("Shall I go up, or down?")
  70.     local directionChoice = string.lower(tostring((read())))
  71.     local acceptedResponses = {"up","down", -- store binary decisions in even-odd pairs
  72.                                 "u","d"}
  73.     for index,value in pairs(acceptedResponses) do -- find out what they said
  74.         if directionChoice == value then
  75.             if index%2==1 then
  76.                 UPWARDS = true
  77.             else
  78.                 UPWARDS = false
  79.             end
  80.         end
  81.     end
  82.  
  83.     QSAVE["upwards"] = UPWARDS
  84.  
  85.     print("Shall I return to the original height?")
  86.     local returnResponse = string.lower(tostring(read()))
  87.     local acceptedConditions = {"yes","no",
  88.                                 "true","false",
  89.                                 "1","0",
  90.                                 "y","n",
  91.                                 "yeah","nah"}
  92.     for k,v in pairs(acceptedConditions) do
  93.         if returnResponse == v then
  94.             if k%2==1 then
  95.                 RETURNCOND = 1
  96.             else
  97.                 RETURNCOND = 0
  98.             end
  99.         end
  100.     end
  101.  
  102.     QSAVE["retCon"] = RETURNCOND
  103. end
  104.  
  105. local function calculateFuelExpenditure() -- Calculate how much fuel will be taken from the quarry volume.
  106.  
  107.     local distance = DEPTH*WIDTH*LENGTH -- minimum distance travelled is the volume of the cuboid
  108.  
  109.     if RETURNCOND == true then -- Use this decision tree if a return journey is needed.
  110.         distance = distance + DEPTH
  111.         if math.fmod(WIDTH,2) == 1 then
  112.             -- ODD width, ANY length
  113.             if math.fmod(DEPTH,2) == 1 then
  114.                 distance = distance + LENGTH + WIDTH - 2
  115.             end
  116.         elseif math.fmod(LENGTH,2) == 1 then
  117.             if math.fmod(DEPTH,2) == 1 then
  118.                 distance = distance + WIDTH - 1
  119.             else
  120.                 distance = distance + LENGTH - 1
  121.             end
  122.         else
  123.             -- EVEN width, EVEN length
  124.             if math.fmod(DEPTH,4) == 1 then
  125.                 distance = distance + WIDTH - 1
  126.             elseif math.fmod(DEPTH,4) == 2 then
  127.                 distance = distance + LENGTH + WIDTH - 2
  128.             elseif math.fmod(DEPTH,4) == 3 then
  129.                 distance = distance + LENGTH - 1
  130.             end
  131.         end
  132.     end
  133.  
  134.     if turtle.getFuelLevel() > distance then
  135.         return true
  136.     else
  137.         return false
  138.     end
  139. end
  140.  
  141. local function mineLayer(layer) -- Mines a layer of blocks LENGTH forwards & WIDTH to the right
  142.     -- Odometer method.
  143.  
  144.     turtle.digDown()
  145.     turtle.down()
  146.  
  147.     -- Determine which dimension is the axis being travelled down, and which is perpendicular to the bot.
  148.     if math.fmod(WIDTH,2) == 1 then
  149.         -- if the width is odd
  150.         forwardAxis = LENGTH
  151.         perpendicularAxis = WIDTH
  152.     else-- if the width is even
  153.         if math.fmod(LENGTH,2) == 1 then -- if the length is odd
  154.             forwardAxis = WIDTH
  155.             perpendicularAxis = LENGTH
  156.             if layer == 1 then
  157.                 forwardAxis = LENGTH
  158.                 perpendicularAxis = WIDTH
  159.             end
  160.         else -- if the length is even
  161.             if math.fmod(layer,2) == 0 then
  162.                 forwardAxis = WIDTH
  163.                 perpendicularAxis = LENGTH
  164.             else
  165.                 forwardAxis = LENGTH
  166.                 perpendicularAxis = WIDTH
  167.             end
  168.         end
  169.     end
  170.  
  171.     for block = 2,WIDTH*LENGTH,1 do
  172.         -- On every multiple + 1, turn around
  173.         if math.fmod(block,forwardAxis) ~= 1 then
  174.             mineLib.digForward()
  175.         else
  176.             local goingLeft = false
  177.             -- if odd multiple of LENGTH, turn right. else left.
  178.             if math.fmod((block-1)/forwardAxis,2) == 0 then
  179.                 goingLeft = true
  180.             end
  181.  
  182.             if goingLeft then
  183.                 turtle.turnLeft()
  184.                 mineLib.digForward()
  185.                 turtle.turnLeft()
  186.             else
  187.                 turtle.turnRight()
  188.                 mineLib.digForward()
  189.                 turtle.turnRight()
  190.             end
  191.         end
  192.         systemLib.saveFile(QSAVE,QSAVEPATH)
  193.     end
  194.  
  195.     if math.fmod(perpendicularAxis,2) == 1 then
  196.         turtle.turnLeft()
  197.         turtle.turnLeft()
  198.     else
  199.         turtle.turnRight()
  200.     end
  201. end
  202.  
  203. local function returnToStart()
  204.     -- Returns below the same spot it started in, then moves upwards.
  205.     -- When it comes to saving here, overwrite the WHOLE FILE to indicate that the program needs to resume here.
  206.  
  207.     if math.fmod(WIDTH,2) == 1 then
  208.         -- ODD width, ANY length
  209.         if math.fmod(DEPTH,2) == 1 then
  210.             mineLib.digForward(LENGTH-1)
  211.             turtle.turnRight()
  212.             mineLib.digForward(WIDTH-1)
  213.             turtle.turnRight()
  214.         end
  215.     elseif math.fmod(LENGTH,2) == 1 then
  216.         -- EVEN width, ODD length
  217.         if math.fmod(DEPTH,2) == 1 then
  218.             mineLib.digForward(WIDTH-1)
  219.             turtle.turnRight()
  220.         else
  221.             turtle.turnRight()
  222.             mineLib.digForward(LENGTH-1)
  223.             turtle.turnRight()
  224.             turtle.turnRight()
  225.         end
  226.     else
  227.         -- EVEN width, EVEN length
  228.         if math.fmod(DEPTH,4) == 1 then
  229.             mineLib.digForward(WIDTH-1)
  230.             turtle.turnRight()
  231.         elseif math.fmod(DEPTH,4) == 2 then
  232.             mineLib.digForward(LENGTH-1)
  233.             turtle.turnRight()
  234.             mineLib.digForward(WIDTH-1)
  235.             turtle.turnRight()
  236.         elseif math.fmod(DEPTH,4) == 3 then
  237.             turtle.turnRight()
  238.             mineLib.digForward(LENGTH-1)
  239.             turtle.turnRight()
  240.             turtle.turnRight()
  241.         end
  242.     end
  243.  
  244.     for _ = 1,DEPTH,1 do
  245.         turtle.up()
  246.     end
  247. end
  248.  
  249. local function main()
  250.     if saveExists then
  251.         startIndex = QSAVE["currentLayer"]
  252.         -- Check to see if the robot is on the return journey.
  253.     else
  254.         startIndex = 1
  255.         stBlock = nil
  256.     end
  257.  
  258.     term.clear()
  259.  
  260.     for i = startIndex,DEPTH,1 do
  261.         QSAVE["currentLayer"] = i
  262.         systemLib.saveFile(QSAVE,QSAVEPATH)
  263.  
  264.         mineLayer(i)
  265.     end
  266.  
  267.     if RETURNCOND == 1 then
  268.         returnToStart()
  269.     end
  270.  
  271.     storageLib.saveFile()
  272. end
  273.  
  274. -- Save file declaration
  275. if saveExists then -- load the existing save
  276.     QSAVE = systemLib.loadFile(QSAVEPATH)
  277.  
  278.     WIDTH  = QSAVE.width
  279.     LENGTH = QSAVE.length
  280.     DEPTH  = QSAVE.depth
  281.  
  282.     UPWARDS = QSAVE.upwards
  283.     RETURNCOND = QSAVE.retCon
  284.  
  285.     main()
  286. else -- make a new save
  287.     QSAVE = {["width"] = 0,["length"] = 0, ["depth"] = 0, ["currentLayer"] = 0, ["currentBlock"] = 0, ["upwards"] = false, ["retCon"] = 0} -- In order: width, length, depth, current layer, current block, upwards, returncond
  288. end
  289.  
  290. if saveExists == false then
  291.     if #args == 3 then
  292.         WIDTH = args[1]
  293.         QSAVE["width"] = WIDTH
  294.         LENGTH = args[2]
  295.         QSAVE["length"] = LENGTH
  296.         DEPTH = args[3]
  297.         QSAVE["depth"] = DEPTH
  298.     elseif #args > 0 then
  299.         print("If you want to use arguments with this program, use the following three:")
  300.         print("Width, Length then Depth.")
  301.         quarrySetup()
  302.     else
  303.         quarrySetup()
  304.     end
  305.  
  306.     upDownReturn()
  307.  
  308.     if calculateFuelExpenditure() == true then -- I know about the '== true' thing but it doesn't work otherwise :))
  309.         main()
  310.     else
  311.         if storageLib.refuelChestSafe() == true then
  312.             if calculateFuelExpenditure() == true then
  313.                 main()
  314.             else
  315.                 print("Refuel attempt insufficient, shutting down...")
  316.             end
  317.         else
  318.             print("Failed refuel attempt, shutting down...")
  319.         end
  320.     end
  321. end
  322.  
  323. shell.run(string.format("delete %s",QSAVEPATH)) -- remove save file once the program is complete
  324. write("Execution complete, fuel remaining: ")
  325. print(turtle.getFuelLevel())
Advertisement
Comments
Add Comment
Please, Sign In to add comment