vacnoa

Dibujar

Nov 13th, 2022 (edited)
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 53.29 KB | Gaming | 0 0
  1. -- Variable Setup
  2. -- Command Line input Table
  3. local argTable = {...}
  4.  
  5. -- Flag Variables: These are conditions for different features (all flags are named foo_bar, all other variables are named fooBar)
  6. local cmd_line = false
  7. local cmd_line_resume = false
  8. local cmd_line_cost_only = false
  9. local chain_next_shape = false -- This tells goHome() where to end, if true it goes to (0, 0, positionZ) if false it goes to (-1, -1, 0)
  10. local special_chain = false -- For certain shapes that finish where the next chained shape should start, goHome() will  only turn to face 0 if true
  11. local cost_only = false
  12. local sim_mode = false
  13. local resupply = false
  14. local enderchest_refilling = false
  15. local can_use_gps = false
  16. local return_to_home = false -- whether the turtle shall return to start after build
  17.  
  18. -- Record Keeping Variables: These are for recoding the blocks and fuel used
  19. local blocks = 0
  20. local fuel = 0
  21.  
  22. -- Position Tracking Variables: These are for keeping track of the turtle's position
  23. local positionX = 0
  24. local positionY = 0
  25. local positionZ = 0
  26. local facing = 0
  27. local gpsPositionX = 0
  28. local gpsPositionY = 0
  29. local gpsPositionZ = 0
  30. local gpsFacing = 0
  31.  
  32. -- General Variables: Other variables that don't fit in the other categories
  33. local choice = ""
  34.  
  35. -- Progress Table: These variables are the tables that the turtle's progress is tracked in
  36. local tempProgTable = {}
  37. local progTable = {} --This is the LOCAL table!  used for local stuff only, and is ONLY EVER WRITTEN when sim_mode is FALSE
  38. local progFileName = "ShapesProgressFile"
  39.  
  40. -- Utility functions
  41.  
  42. function writeOut(...) -- ... lets writeOut() pass any arguments to print(). so writeOut(1,2,3) is the same as print(1,2,3). previously writeOut(1,2,3) would have been the same as print(1)
  43.     for i, v in ipairs(arg) do
  44.         print(v)
  45.     end
  46. end
  47.  
  48. function getInput(inputType, message, option1, option2)
  49.     local input = ""
  50.     if inputType == "string" then
  51.         writeOut(message.. "(" ..option1 .. " or "..option2..")" )
  52.         while true do
  53.             input = io.read()
  54.             input = string.lower(input)
  55.             if input ~= option1 and input ~= option2 then
  56.                 writeOut("You didn't enter a valid option. Please try again.")
  57.             else
  58.                 return input
  59.             end
  60.         end
  61.     end
  62.     if inputType == "int" then
  63.         writeOut(message)
  64.         while true do
  65.             input = io.read()
  66.             if tonumber(input) ~= nil then
  67.                 return tonumber(input)
  68.             else
  69.                 writeOut("Need a number. Please try again")
  70.             end
  71.         end
  72.     end
  73. end
  74.  
  75. function wrapModules() -- checks for and wraps turtle modules
  76.     local test = 0
  77.     if peripheral.getType("left" )== "resupply" then
  78.         resupplymodule=peripheral.wrap("left")
  79.         resupply = true
  80.     elseif peripheral.getType("right") == "resupply" then
  81.         resupplymodule=peripheral.wrap("right")
  82.         resupply = true
  83.     end
  84.     if peripheral.getType("left") == "modem" then
  85.         modem=peripheral.wrap("left")
  86.         test, _, _ = gps.locate(1)
  87.         if test ~= nil then
  88.             can_use_gps = true
  89.         end
  90.     elseif peripheral.getType("right") == "modem" then
  91.         modem=peripheral.wrap("right")
  92.         test, _, _ = gps.locate(1)
  93.         if test ~= nil then
  94.             can_use_gps = true
  95.         end
  96.     end
  97.     if resupply then
  98.         return "resupply"
  99.     end
  100. end
  101.  
  102. function linkToRSStation() -- Links to resupply station
  103.     if resupplymodule.link() then
  104.         return true
  105.     else
  106.         writeOut("Please put Resupply Station to the left of the turtle and press Enter to continue")
  107.         io.read()
  108.         linkToRSStation()
  109.     end
  110. end
  111.  
  112. function compareResources()
  113.     if (turtle.compareTo(1) == false) then
  114.         turtle.drop()
  115.     end
  116. end
  117.  
  118. function firstFullSlot()
  119.     for i = 1, 16 do
  120.         if (turtle.getItemCount(i) > 1) then
  121.             return i
  122.         end
  123.     end
  124. end
  125.  
  126. function turtleEmpty()
  127.     for i = 1, 16 do
  128.         if (turtle.getItemCount(i) > 1) then
  129.             return false
  130.         end
  131.     end
  132.     return true
  133. end
  134.  
  135. function checkResources()
  136.     if resupply then
  137.         if turtle.getItemCount(activeSlot) <= 1 then
  138.             while not(resupplymodule.resupply(1)) do
  139.                 os.sleep(0.5)
  140.             end
  141.         end
  142.     elseif enderchest_refilling then
  143.         compareResources()
  144.         while (turtle.getItemCount(activeSlot) <= 1) do
  145.             if (activeSlot == 15) and (turtle.getItemCount(activeSlot)<=1) then
  146.                 turtle.select(16)
  147.                 turtle.digUp()
  148.                 for i = 1, 15 do
  149.                     turtle.select(i)
  150.                     turtle.drop()
  151.                 end
  152.                 turtle.select(16)
  153.                 turtle.placeUp()
  154.                 turtle.select(1)               
  155.                 for i = 1, 15 do
  156.                     turtle.suckUp()
  157.                 end
  158.                 turtle.select(16)
  159.                 turtle.digUp()
  160.                 activeSlot = 1
  161.                 turtle.select(activeSlot)
  162.             else
  163.                 activeSlot = activeSlot + 1
  164.                 -- writeOut("Turtle slot empty, trying slot "..activeSlot)
  165.                 turtle.select(activeSlot)
  166.             end
  167.             compareResources()
  168.             os.sleep(0.2)
  169.         end
  170.     else
  171.         compareResources()
  172.         while (turtle.getItemCount(activeSlot) <= 1) do
  173.             if turtleEmpty() then
  174.                 writeOut("Turtle is empty, please put building block in slots and press enter to continue")
  175.                 io.read()
  176.                 activeSlot = 1
  177.                 turtle.select(activeSlot)
  178.             else
  179.                 activeSlot = firstFullSlot()
  180.                 turtle.select(activeSlot)
  181.             end
  182.             compareResources()
  183.         end
  184.     end
  185. end
  186.  
  187. function checkFuel()
  188.     if (not(tonumber(turtle.getFuelLevel()) == nil)) then
  189.         while turtle.getFuelLevel() < 50 do
  190.             writeOut("Turtle almost out of fuel, pausing. Please drop fuel in inventory. And press enter.")
  191.             io.read()
  192.             turtle.refuel()
  193.         end
  194.     end
  195. end
  196.  
  197. function placeBlock()
  198.     blocks = blocks + 1
  199.     simulationCheck()
  200.     if cost_only then
  201.         return
  202.     end
  203.     if turtle.detectDown() and not turtle.compareDown() then
  204.         turtle.digDown()
  205.     end
  206.     checkResources()
  207.     turtle.placeDown()
  208.     progressUpdate()
  209. end
  210.  
  211. function round(toBeRounded, decimalPlace) -- Needed for hexagon and octagon
  212.     local multiplier = 10^(decimalPlace or 0)
  213.     return math.floor(toBeRounded * multiplier + 0.5) / multiplier
  214. end
  215.  
  216. -- Navigation functions
  217. -- Allow the turtle to move while tracking its position
  218. -- This allows us to just give a destination point and have it go there
  219.  
  220. function turnRightTrack()
  221.     simulationCheck()
  222.     facing = facing + 1
  223.     if facing >= 4 then
  224.         facing = 0
  225.     end
  226.     progressUpdate()
  227.     if cost_only then
  228.         return
  229.     end
  230.     turtle.turnRight()
  231. end
  232.  
  233. function turnLeftTrack()
  234.     simulationCheck()
  235.     facing = facing - 1
  236.     if facing < 0 then
  237.         facing = 3
  238.     end
  239.     progressUpdate()
  240.     if cost_only then
  241.         return
  242.     end
  243.     turtle.turnLeft()
  244. end
  245.  
  246. function turnAroundTrack()
  247.     turnLeftTrack()
  248.     turnLeftTrack()
  249. end
  250.  
  251. function turnToFace(direction)
  252.     if (direction < 0) then
  253.         return false
  254.     end
  255.     direction = direction % 4
  256.     while facing ~= direction do
  257.         turnRightTrack()
  258.     end
  259.     return true
  260. end
  261.  
  262. function safeForward()
  263.     simulationCheck()
  264.     if facing == 0 then
  265.         positionY = positionY + 1
  266.     elseif facing == 1 then
  267.         positionX = positionX + 1
  268.     elseif facing == 2 then
  269.         positionY = positionY - 1
  270.     elseif facing == 3 then
  271.         positionX = positionX - 1
  272.     end
  273.     fuel = fuel + 1
  274.     progressUpdate()
  275.     if cost_only then
  276.         return
  277.     end
  278.     checkFuel()
  279.     local success = false
  280.     local tries = 0
  281.     while not success do
  282.         success = turtle.forward()
  283.         if not success then
  284.             while (not success) and tries < 6 do
  285.                 tries = tries + 1
  286.                 turtle.dig()
  287.                 success = turtle.forward()
  288.                 sleep(0.3)
  289.             end
  290.             if not success then
  291.                 writeOut("Blocked attempting to move forward.")
  292.                 writeOut("Please clear and press enter to continue.")
  293.                 io.read()
  294.             end
  295.         end
  296.     end
  297. end
  298.  
  299. function safeBack()
  300.     simulationCheck()
  301.     if facing == 0 then
  302.         positionY = positionY - 1
  303.     elseif facing == 1 then
  304.         positionX = positionX - 1
  305.     elseif facing == 2 then
  306.         positionY = positionY + 1
  307.     elseif facing == 3 then
  308.         positionX = positionX + 1
  309.     end
  310.     fuel = fuel + 1
  311.     progressUpdate()
  312.     if cost_only then
  313.         return
  314.     end
  315.     checkFuel()
  316.     local success = false
  317.     local tries = 0
  318.     while not success do
  319.         success = turtle.back()
  320.         if not success then
  321.             turnAroundTrack()
  322.             while turtle.detect() and tries < 6 do
  323.                 tries = tries + 1
  324.                 if turtle.dig() then
  325.                     break
  326.                 end
  327.                 sleep(0.3)
  328.             end
  329.             turnAroundTrack()
  330.             success = turtle.back()
  331.             if not success then
  332.                 writeOut("Blocked attempting to move back.")
  333.                 writeOut("Please clear and press enter to continue.")
  334.                 io.read()
  335.             end
  336.         end
  337.     end
  338. end
  339.  
  340. function safeUp()
  341.     simulationCheck()
  342.     positionZ = positionZ + 1
  343.     fuel = fuel + 1
  344.     progressUpdate()
  345.     if cost_only then
  346.         return
  347.     end
  348.     checkFuel()
  349.     local success = false
  350.     while not success do
  351.         success = turtle.up()
  352.         if not success then
  353.             while turtle.detectUp() do
  354.                 if not turtle.digUp() then
  355.                     writeOut("Blocked attempting to move up.")
  356.                     writeOut("Please clear and press enter to continue.")
  357.                     io.read()
  358.                 end
  359.             end
  360.         end
  361.     end
  362. end
  363.  
  364. function safeDown()
  365.     simulationCheck()
  366.     positionZ = positionZ - 1
  367.     fuel = fuel + 1
  368.     progressUpdate()
  369.     if cost_only then
  370.         return
  371.     end
  372.     checkFuel()
  373.     local success = false
  374.     while not success do
  375.         success = turtle.down()
  376.         if not success then
  377.             while turtle.detectDown() do
  378.                 if not turtle.digDown() then
  379.                     writeOut("Blocked attempting to move down.")
  380.                     writeOut("Please clear and press enter to continue.")
  381.                     io.read()
  382.                 end
  383.             end
  384.         end
  385.     end
  386. end
  387.  
  388. function moveY(targetY)
  389.     if targetY == positionY then
  390.         return
  391.     end
  392.     if (facing ~= 0 and facing ~= 2) then -- Check axis
  393.         turnRightTrack()
  394.     end
  395.     while targetY > positionY do
  396.         if facing == 0 then
  397.             safeForward()
  398.         else
  399.             safeBack()
  400.         end
  401.     end
  402.     while targetY < positionY do
  403.         if facing == 2 then
  404.             safeForward()
  405.         else
  406.             safeBack()
  407.         end
  408.     end
  409. end
  410.  
  411. function moveX(targetX)
  412.     if targetX == positionX then
  413.         return
  414.     end
  415.     if (facing ~= 1 and facing ~= 3) then -- Check axis
  416.         turnRightTrack()
  417.     end
  418.     while targetX > positionX do
  419.         if facing == 1 then
  420.             safeForward()
  421.         else
  422.             safeBack()
  423.         end
  424.     end
  425.     while targetX < positionX do
  426.         if facing == 3 then
  427.             safeForward()
  428.         else
  429.             safeBack()
  430.         end
  431.     end
  432. end
  433.  
  434. function moveZ(targetZ)
  435.     if targetZ == positionZ then
  436.         return
  437.     end
  438.     while targetZ < positionZ do
  439.         safeDown()
  440.     end
  441.     while targetZ > positionZ do
  442.         safeUp()
  443.     end
  444. end
  445.  
  446. -- I *HIGHLY* suggest formatting all shape subroutines to use the format that dome() uses;  specifically, navigateTo(x,y,[z]) then placeBlock().  This should ensure proper "data recording" and also makes readability better
  447. function navigateTo(targetX, targetY, targetZ, move_z_first)
  448.     targetZ = targetZ or positionZ -- If targetZ isn't used in the function call, it defaults to its current z position, this should make it compatible with all previous implementations of navigateTo()
  449.     move_z_first = move_z_first or false -- Defaults to moving z last, if true is passed as 4th argument, it moves vertically first
  450.    
  451.     if move_z_first then
  452.         moveZ(targetZ)
  453.     end
  454.    
  455.     if facing == 0 or facing == 2 then -- Y axis
  456.         moveY(targetY)
  457.         moveX(targetX)
  458.     else
  459.         moveX(targetX)
  460.         moveY(targetY)
  461.     end
  462.    
  463.     if not move_z_first then
  464.         moveZ(targetZ)
  465.     end
  466. end
  467.  
  468. function goHome()
  469.     if chain_next_shape then
  470.         if not special_chain then
  471.             navigateTo(0, 0) -- So another program can chain multiple shapes together to create bigger structures
  472.         end
  473.     else
  474.         navigateTo(-1, -1, 0) -- So the user can collect the turtle when it is done, not 0,0,0 because some shapes use the 0,0 column
  475.     end
  476.     turnToFace(0)
  477. end
  478.  
  479. -- Shape Building functions
  480.  
  481. function drawLine(endX, endY, startX, startY)
  482.     startX = startX or positionX
  483.     startY = startY or positionY
  484.     deltaX = math.abs(endX - startX)
  485.     deltaY = math.abs(endY - startY)
  486.     errorVar = 0
  487.     if deltaX >= deltaY then
  488.         deltaErr = math.abs(deltaY/deltaX)
  489.         if startX < endX then
  490.             if startY < endY then
  491.                 counterY = startY
  492.                 for counterX = startX, endX do
  493.                     navigateTo(counterX, counterY)
  494.                     placeBlock()
  495.                     errorVar = errorVar + deltaErr
  496.                     if errorVar >= 0.5 then
  497.                         counterY = counterY + 1
  498.                         errorVar = errorVar - 1
  499.                     end
  500.                 end
  501.             else
  502.                 counterY = startY
  503.                 for counterX = startX, endX do
  504.                     navigateTo(counterX, counterY)
  505.                     placeBlock()
  506.                     errorVar = errorVar + deltaErr
  507.                     if errorVar >= 0.5 then
  508.                         counterY = counterY - 1
  509.                         errorVar = errorVar - 1
  510.                     end
  511.                 end
  512.             end
  513.         else
  514.             if startY < endY then
  515.                 counterY = startY
  516.                 for counterX = startX, endX, -1 do
  517.                     navigateTo(counterX, counterY)
  518.                     placeBlock()
  519.                     errorVar = errorVar + deltaErr
  520.                     if errorVar >= 0.5 then
  521.                         counterY = counterY + 1
  522.                         errorVar = errorVar - 1
  523.                     end
  524.                 end
  525.             else
  526.                 counterY = startY
  527.                 for counterX = startX, endX, -1 do
  528.                     navigateTo(counterX, counterY)
  529.                     placeBlock()
  530.                     errorVar = errorVar + deltaErr
  531.                     if errorVar >= 0.5 then
  532.                         counterY = counterY - 1
  533.                         errorVar = errorVar - 1
  534.                     end
  535.                 end
  536.             end
  537.         end
  538.     else
  539.         deltaErr = math.abs(deltaX/deltaY)
  540.         if startY < endY then
  541.             if startX < endX then
  542.                 counterX = startX
  543.                 for counterY = startY, endY do
  544.                     navigateTo(counterX, counterY)
  545.                     placeBlock()
  546.                     errorVar = errorVar + deltaErr
  547.                     if errorVar >= 0.5 then
  548.                         counterX = counterX + 1
  549.                         errorVar = errorVar - 1
  550.                     end
  551.                 end
  552.             else
  553.                 counterX = startX
  554.                 for counterY = startY, endY do
  555.                     navigateTo(counterX, counterY)
  556.                     placeBlock()
  557.                     errorVar = errorVar + deltaErr
  558.                     if errorVar >= 0.5 then
  559.                         counterX = counterX - 1
  560.                         errorVar = errorVar - 1
  561.                     end
  562.                 end
  563.             end
  564.         else
  565.             if startX < endX then
  566.                 counterX = startX
  567.                 for counterY = startY, endY, -1 do
  568.                     navigateTo(counterX, counterY)
  569.                     placeBlock()
  570.                     errorVar = errorVar + deltaErr
  571.                     if errorVar >= 0.5 then
  572.                         counterX = counterX + 1
  573.                         errorVar = errorVar - 1
  574.                     end
  575.                 end
  576.             else
  577.                 counterX = startX
  578.                 for counterY = startY, endY, -1 do
  579.                     navigateTo(counterX, counterY)
  580.                     placeBlock()
  581.                     errorVar = errorVar + deltaErr
  582.                     if errorVar >= 0.5 then
  583.                         counterX = counterX - 1
  584.                         errorVar = errorVar - 1
  585.                     end
  586.                 end
  587.             end
  588.         end
  589.     end
  590. end
  591.  
  592. function rectangle(width, depth, startX, startY)
  593.     startX = startX or positionX
  594.     startY = startY or positionY
  595.     endX = startX + width - 1
  596.     endY = startY + depth - 1
  597.     drawLine(startX, endY, startX, startY)
  598.     drawLine(endX, endY, startX, endY)
  599.     drawLine(endX, startY, endX, endY)
  600.     drawLine(startX, startY, endX, startY)
  601. end
  602.  
  603. function square(length, startX, startY)
  604.     startX = startX or positionX
  605.     startY = startY or positionY
  606.     rectangle(length, length, startX, startY)
  607. end
  608.  
  609. function wall(depth, height)
  610.     for i = 1, depth do
  611.         for j = 1, height do
  612.             placeBlock()
  613.             if j < height then
  614.                 navigateTo(positionX, positionY, positionZ + 1)
  615.             end
  616.         end
  617.         if (i ~= depth) then
  618.             navigateTo(positionX, positionY + 1, 0)
  619.         end
  620.     end
  621. end
  622.  
  623. function platform(width, depth, startX, startY)
  624.     startX = startX or positionX
  625.     startY = startY or positionY
  626.     endX = startX + width - 1
  627.     endY = startY + depth - 1
  628.     forward = true
  629.     for counterY = startY, endY do
  630.         if forward then
  631.             for counterX = startX, endX do
  632.                 navigateTo(counterX, counterY)
  633.                 placeBlock()
  634.             end
  635.         else
  636.             for counterX = endX, startX, -1 do
  637.                 navigateTo(counterX, counterY)
  638.                 placeBlock()
  639.             end
  640.         end
  641.         forward = not forward
  642.     end
  643. end
  644.  
  645. function cuboid(width, depth, height, hollow)
  646.     platform(width, depth, 0, 0)
  647.     for i = 1, height - 1 do
  648.         navigateTo(0, 0, i)
  649.         if (hollow == "n") then
  650.             platform(width, depth, 0, 0)
  651.         else
  652.             rectangle(width, depth, 0, 0)
  653.         end
  654.     end
  655.     navigateTo(0,0,height)
  656.     platform(width, depth, 0, 0)
  657. end
  658.  
  659. function pyramid(length, hollow)
  660.     -- local height = math.ceil(length / 2) - 1
  661.     i = 0
  662.     while (length > 0) do
  663.         navigateTo(i, i, i)
  664.         if (hollow == "y") then
  665.             rectangle(length, length, i, i)
  666.         else
  667.             platform(length, length, i, i)
  668.         end
  669.         i = i + 1
  670.         length = length - 2
  671.     end
  672. end
  673.  
  674. function stair(width, height, startX, startY) -- Last two might be able to be used to make a basic home-like shape later?
  675.     startX = startX or positionX
  676.     startY = startY or positionY
  677.     endX = startX + width - 1
  678.     endY = startY + height - 1
  679.     forward = true
  680.     for counterY = startY, endY do
  681.         if forward then
  682.             for counterX = startX, endX do
  683.                 navigateTo(counterX, counterY)
  684.                 placeBlock()
  685.             end
  686.         else
  687.             for counterX = endX, startX, -1 do
  688.                 navigateTo(counterX, counterY)
  689.                 placeBlock()
  690.             end
  691.         end
  692.         if counterY ~= endY then
  693.             navigateTo(positionX, positionY, positionZ + 1)
  694.             forward = not forward
  695.         end
  696.     end
  697. end
  698.  
  699. function circle(diameter)
  700.     odd = not (math.fmod(diameter, 2) == 0)
  701.     radius = diameter / 2;
  702.     if odd then
  703.         width = (2 * math.ceil(radius)) + 1;
  704.         offset = math.floor(width/2);
  705.     else
  706.         width = (2 * math.ceil(radius)) + 2;
  707.         offset = math.floor(width/2) - 0.5;    
  708.     end
  709.     --diameter --radius * 2 + 1
  710.     sqrt3 = 3 ^ 0.5
  711.     boundaryRadius = radius + 1.0
  712.     boundary2 = boundaryRadius ^ 2
  713.     radius2 = radius ^ 2
  714.     z = math.floor(radius)
  715.     cz2 = (radius - z) ^ 2
  716.     limitOffsetY = (boundary2 - cz2) ^ 0.5
  717.     maxOffsetY = math.ceil(limitOffsetY)
  718.     -- We do first the +x side, then the -x side to make movement efficient
  719.     for side = 0,1 do
  720.             -- On the right we go from small y to large y, on the left reversed
  721.             -- This makes us travel clockwise (from below) around each layer
  722.             if (side == 0) then
  723.                 yStart = math.floor(radius) - maxOffsetY
  724.                 yEnd = math.floor(radius) + maxOffsetY
  725.                 yStep = 1
  726.             else
  727.                 yStart = math.floor(radius) + maxOffsetY
  728.                 yEnd = math.floor(radius) - maxOffsetY
  729.                 yStep = -1
  730.             end
  731.             for y = yStart,yEnd,yStep do
  732.                 cy2 = (radius - y) ^ 2
  733.                 remainder2 = (boundary2 - cz2 - cy2)
  734.                 if remainder2 >= 0 then
  735.                     -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
  736.                     maxOffsetX = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
  737.                     -- Only do either the +x or -x side
  738.                     if (side == 0) then
  739.                         -- +x side
  740.                         xStart = math.floor(radius)
  741.                         xEnd = math.floor(radius) + maxOffsetX
  742.                     else
  743.                         -- -x side
  744.                         xStart = math.floor(radius) - maxOffsetX
  745.                         xEnd = math.floor(radius) - 1
  746.                     end
  747.                     -- Reverse direction we traverse xs when in -y side
  748.                     if y > math.floor(radius) then
  749.                         temp = xStart
  750.                         xStart = xEnd
  751.                         xEnd = temp
  752.                         xStep = -1
  753.                     else
  754.                         xStep = 1
  755.                     end
  756.  
  757.                     for x = xStart,xEnd,xStep do
  758.                         -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
  759.                         if isSphereBorder(offset, x, y, z, radius2) then
  760.                             navigateTo(x, y)
  761.                             placeBlock()
  762.                         end
  763.                     end
  764.                 end
  765.             end
  766.         end
  767. end
  768.  
  769. function blockInSphereIsFull(offset, x, y, z, radiusSq)
  770.     x = x - offset
  771.     y = y - offset
  772.     z = z - offset
  773.     x = x ^ 2
  774.     y = y ^ 2
  775.     z = z ^ 2
  776.     return x + y + z <= radiusSq
  777. end
  778.  
  779. function isSphereBorder(offset, x, y, z, radiusSq)
  780.     spot = blockInSphereIsFull(offset, x, y, z, radiusSq)
  781.     if spot then
  782.         spot = not blockInSphereIsFull(offset, x, y - 1, z, radiusSq) or
  783.             not blockInSphereIsFull(offset, x, y + 1, z, radiusSq) or
  784.             not blockInSphereIsFull(offset, x - 1, y, z, radiusSq) or
  785.             not blockInSphereIsFull(offset, x + 1, y, z, radiusSq) or
  786.             not blockInSphereIsFull(offset, x, y, z - 1, radiusSq) or
  787.             not blockInSphereIsFull(offset, x, y, z + 1, radiusSq)
  788.     end
  789.     return spot
  790. end
  791.  
  792. function dome(typus, diameter)
  793.     -- Main dome and sphere building routine
  794.     odd = not (math.fmod(diameter, 2) == 0)
  795.     radius = diameter / 2;
  796.     if odd then
  797.         width = (2 * math.ceil(radius)) + 1;
  798.         offset = math.floor(width/2);
  799.     else
  800.         width = (2 * math.ceil(radius)) + 2;
  801.         offset = math.floor(width/2) - 0.5;    
  802.     end
  803.     --diameter --radius * 2 + 1
  804.     sqrt3 = 3 ^ 0.5
  805.     boundaryRadius = radius + 1.0
  806.     boundary2 = boundaryRadius ^ 2
  807.     radius2 = radius ^ 2
  808.    
  809.     if typus == "dome" then
  810.         zstart = math.ceil(radius)
  811.     elseif typus == "sphere" then
  812.         zstart = 1
  813.     elseif typus == "bowl" then
  814.         zstart = 1
  815.     end
  816.     if typus == "bowl" then
  817.         zend = math.floor(radius)
  818.     else
  819.         zend = width - 1
  820.     end
  821.  
  822.     -- This loop is for each vertical layer through the sphere or dome.
  823.     for z = zstart,zend do
  824.         if not cost_only and z ~= zstart then
  825.             navigateTo(positionX, positionY, positionZ + 1)
  826.         end
  827.         --writeOut("Layer " .. z)
  828.         cz2 = (radius - z) ^ 2
  829.         limitOffsetY = (boundary2 - cz2) ^ 0.5
  830.         maxOffsetY = math.ceil(limitOffsetY)
  831.         -- We do first the +x side, then the -x side to make movement efficient
  832.         for side = 0,1 do
  833.             -- On the right we go from small y to large y, on the left reversed
  834.             -- This makes us travel clockwise (from below) around each layer
  835.             if (side == 0) then
  836.                 yStart = math.floor(radius) - maxOffsetY
  837.                 yEnd = math.floor(radius) + maxOffsetY
  838.                 yStep = 1
  839.             else
  840.                 yStart = math.floor(radius) + maxOffsetY
  841.                 yEnd = math.floor(radius) - maxOffsetY
  842.                 yStep = -1
  843.             end
  844.             for y = yStart,yEnd,yStep do
  845.                 cy2 = (radius - y) ^ 2
  846.                 remainder2 = (boundary2 - cz2 - cy2)
  847.                 if remainder2 >= 0 then
  848.                     -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
  849.                     maxOffsetX = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
  850.                     -- Only do either the +x or -x side
  851.                     if (side == 0) then
  852.                         -- +x side
  853.                         xStart = math.floor(radius)
  854.                         xEnd = math.floor(radius) + maxOffsetX
  855.                     else
  856.                         -- -x side
  857.                         xStart = math.floor(radius) - maxOffsetX
  858.                         xEnd = math.floor(radius) - 1
  859.                     end
  860.                     -- Reverse direction we traverse xs when in -y side
  861.                     if y > math.floor(radius) then
  862.                         temp = xStart
  863.                         xStart = xEnd
  864.                         xEnd = temp
  865.                         xStep = -1
  866.                     else
  867.                         xStep = 1
  868.                     end
  869.  
  870.                     for x = xStart,xEnd,xStep do
  871.                         -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
  872.                         if isSphereBorder(offset, x, y, z, radius2) then
  873.                             navigateTo(x, y)
  874.                             placeBlock()
  875.                         end
  876.                     end
  877.                 end
  878.             end
  879.         end
  880.     end
  881. end
  882.  
  883. function cylinder(diameter, height)
  884.     for i = 1, height do
  885.         circle(diameter)
  886.         navigateTo(positionX, positionY, positionZ + 1)
  887.     end
  888. end
  889.  
  890. polygonCornerList = {} -- Public list of corner coords for n-gons, will be used for hexagons, octagons, and future polygons.
  891. -- It should be constructed as a nested list eg. {{x0,y0},{x1,y1},{x2,y2}...}
  892.  
  893. function constructPolygon() -- Uses polygonCornerList to draw sides between each point
  894.     if #polygonCornerList == 0 then
  895.         return false
  896.     end
  897.     for i = 1, #polygonCornerList do
  898.         startX = polygonCornerList[i][1]
  899.         startY = polygonCornerList[i][2]
  900.         if i == #polygonCornerList then
  901.             j = 1
  902.         else
  903.             j = i + 1
  904.         end
  905.         stopX = polygonCornerList[j][1]
  906.         stopY = polygonCornerList[j][2]
  907.         drawLine(stopX, stopY, startX, startY)
  908.     end
  909.     return true
  910. end
  911.  
  912. function arbitraryPolygon(numberOfSides, Radius) -- Future function, this will eventually replace octagon and hexagon functions
  913. end
  914.  
  915. function hexagon(sideLength) -- Fills out polygonCornerList with the points for a hexagon
  916.     sideLength = sideLength - 1
  917.     local changeX = sideLength / 2
  918.     local changeY = round(math.sqrt(3) * changeX, 0)
  919.     changeX = round(changeX, 0)
  920.     polygonCornerList[1] = {changeX, 0}
  921.     polygonCornerList[2] = {(changeX + sideLength), 0}
  922.     polygonCornerList[3] = {((2 * changeX) + sideLength), changeY}
  923.     polygonCornerList[4] = {(changeX + sideLength), (2 * changeY)}
  924.     polygonCornerList[5] = {changeX, (2 * changeY)}
  925.     polygonCornerList[6] = {0, changeY}
  926.     if not constructPolygon() then
  927.         error("This error should never happen.")
  928.     end
  929. end
  930.  
  931. function octagon(sideLength) -- Fills out polygonCornerList with the points for an octagon
  932.     sideLength = sideLength - 1
  933.     local change = round((sideLength - 1) / math.sqrt(2), 0)
  934.     polygonCornerList[1] = {change, 0}
  935.     polygonCornerList[2] = {(change + sideLength), 0}
  936.     polygonCornerList[3] = {((2 * change) + sideLength), change}
  937.     polygonCornerList[4] = {((2 * change) + sideLength), (change + sideLength)}
  938.     polygonCornerList[5] = {(change + sideLength), ((2 * change) + sideLength)}
  939.     polygonCornerList[6] = {change, ((2 * change) + sideLength)}
  940.     polygonCornerList[7] = {0, (change + sideLength)}
  941.     polygonCornerList[8] = {0, change}
  942.     if not constructPolygon() then
  943.         error("This error should never happen.")
  944.     end
  945. end
  946.  
  947. function sixprism(length, height)
  948.     for i = 1, height do
  949.         hexagon(length)
  950.         if i ~= height then
  951.             navigateTo(positionX, positionY, positionZ + 1)
  952.         end
  953.     end
  954. end
  955.  
  956. function eightprism(length, height)
  957.     for i = 1, height do
  958.         octagon(length)
  959.         if i ~= height then
  960.             navigateTo(positionX, positionY, positionZ + 1)
  961.         end
  962.     end
  963. end
  964.  
  965. -- Previous Progress Resuming, Simulation functions, Command Line, and File Backend
  966. -- Will check for a "progress" file.
  967. function CheckForPrevious()
  968.     if fs.exists(progFileName) then
  969.         return true
  970.     else
  971.         return false
  972.     end
  973. end
  974.  
  975. -- Creates a progress file, containing a serialized table consisting of the shape type, shape input params, and the last known x, y, and z coords of the turtle (beginning of build project)
  976. function ProgressFileCreate()
  977.     if not CheckForPrevious() then
  978.         fs.makeDir(progFileName)
  979.         return true
  980.     else
  981.         return false
  982.     end
  983. end
  984.  
  985. -- Deletes the progress file (at the end of the project, or at beginning if user chooses to delete old progress)
  986. function ProgressFileDelete()
  987.     if fs.exists(progFileName) then
  988.         fs.delete(progFileName)
  989.         return true
  990.     else
  991.         return false
  992.     end
  993. end
  994.  
  995. -- To read the shape params from the file.  Shape type, and input params (e.g. "dome" and radius)
  996. function ReadShapeParams()
  997.     -- TODO. Unneeded for now, can just use the table elements directly
  998. end
  999.  
  1000. function WriteShapeParams(...) -- The ... lets it take any number of arguments and stores it to the table arg{} | This is still unused anywhere
  1001.     local paramTable = arg
  1002.     local paramName = "param"
  1003.     local paramName2 = paramName
  1004.     for i, v in ipairs(paramTable) do -- Iterates through the args passed to the function, ex. paramTable[1] i = 1 so paramName2 should be "param1", tested and works!
  1005.         paramName2 = paramName .. i
  1006.         tempProgTable[paramName2] = v
  1007.         progTable[paramName2] = v
  1008.     end
  1009. end
  1010.  
  1011. -- function to write the progress to the file (x, y, z)
  1012. function writeProgress()
  1013.     local progFile
  1014.     local progString = ""
  1015.     if not (sim_mode or cost_only) then
  1016.         progString = textutils.serialize(progTable) -- Put in here to save processing time when in cost_only
  1017.         progFile = fs.open(progFileName, "w")
  1018.         progFile.write(progString)
  1019.         progFile.close()
  1020.     end
  1021.  
  1022. end
  1023.  
  1024. -- Reads progress from file (shape, x, y, z, facing, blocks, param1, param2, param3)
  1025. function readProgress()
  1026.     local progFile = fs.open(progFileName, "r")
  1027.     local readProgTable = textutils.unserialize(progFile.readAll())
  1028.     progFile.close()
  1029.     return readProgTable
  1030. end
  1031.  
  1032. -- compares the progress read from the file to the current sim progress.  needs all four params
  1033. function compareProgress()
  1034.     local progTableIn = progTable
  1035.     local readProgTable = readProgress()
  1036.     if (progTableIn.shape == readProgTable.shape and progTableIn.x == readProgTable.x and progTableIn.y == readProgTable.y and progTableIn.blocks == readProgTable.blocks and progTableIn.facing == readProgTable.facing) then
  1037.         writeOut("All caught up!")
  1038.         return true -- We're caught up!
  1039.     else
  1040.         return false -- Not there yet...
  1041.     end
  1042. end
  1043.  
  1044. function getGPSInfo() -- TODO: finish this
  1045.     position = gps.locate()
  1046.     gpsPositionX = position.x
  1047.     gpsPositionZ = position.y
  1048.     gpsPositionY = position.z
  1049.    
  1050. end
  1051.  
  1052. function setSimFlags(b)
  1053.     sim_mode = b
  1054.     cost_only = b
  1055.     if cmd_line_cost_only then
  1056.         cost_only = true
  1057.     end
  1058. end
  1059.  
  1060. function simulationCheck() -- checks state of the simulation
  1061.     if sim_mode then
  1062.         if compareProgress() then
  1063.             setSimFlags(false) -- If we're caught up, un-set flags
  1064.         else
  1065.             setSimFlags(true)  -- If not caught up, just re-affirm that the flags are set
  1066.         end
  1067.     end
  1068. end
  1069.  
  1070. function continueQuery()
  1071.     if cmd_line_resume then
  1072.          return true
  1073.     else
  1074.          if not cmd_line then
  1075.              writeOut("Do you want to continue the last job?")
  1076.              local yes = io.read()
  1077.              if yes == "y" then
  1078.                  return true
  1079.              else
  1080.                  return false
  1081.              end
  1082.          end
  1083.     end
  1084. end
  1085.  
  1086. function progressUpdate()  -- This ONLY updates the local table variable.  Writing is handled above. -- I want to change this to allow for any number of params
  1087.     progTable = {shape = choice, enderchest_refilling = tempProgTable.enderchest_refilling, param1 = tempProgTable.param1, param2 = tempProgTable.param2, param3 = tempProgTable.param3, param4 = tempProgTable.param4, x = positionX, y = positionY, z = positionZ, facing = facing, blocks = blocks}
  1088.     if not sim_mode then
  1089.         writeProgress()
  1090.     end
  1091. end
  1092.  
  1093.  -- Command Line
  1094. function checkCommandLine() --True if arguments were passed
  1095.     if #argTable > 0 then
  1096.         cmd_line = true
  1097.         return true
  1098.     else
  1099.         cmd_line = false
  1100.         return false
  1101.     end
  1102. end
  1103.  
  1104. function needsHelp() -- True if -h is passed
  1105.     for i, v in pairs(argTable) do
  1106.         if v == "-h" or v == "-help" or v == "--help" then
  1107.             return true
  1108.         else
  1109.             return false
  1110.         end
  1111.     end
  1112. end
  1113.  
  1114. function setFlagsFromCommandLine() -- Sets count_only, chain_next_shape, and sim_mode
  1115.     for i, v in pairs(argTable) do
  1116.         if v == "-c" or v == "-cost" or v == "--cost" then
  1117.             cost_only = true
  1118.             cmd_line_cost_only = true
  1119.             writeOut("Cost Only Mode")
  1120.         end
  1121.         if v == "-z" or v == "-chain" or v == "--chain" then
  1122.             chain_next_shape = true
  1123.             writeOut("Chained Shape Mode")
  1124.         end
  1125.         if v == "-r" or v == "-resume" or v == "--resume" then
  1126.             cmd_line_resume = true
  1127.             writeOut("Resuming")
  1128.         end
  1129.         if v == "-e" or v == "-ender" or v == "--ender" then
  1130.             enderchest_refilling = true
  1131.             tempProgTable.enderchest_refilling = true
  1132.             writeOut("Enderchest Mode")
  1133.         end
  1134.         if v == "-g" or v == "-home" or v == "--home" then
  1135.             return_to_home = true
  1136.             writeOut("Will return home")
  1137.         end
  1138.     end
  1139. end
  1140.  
  1141. function setTableFromCommandLine() -- Sets progTable and tempProgTable from command line arguments
  1142.     progTable.shape = argTable[1]
  1143.     tempProgTable.shape = argTable[1]
  1144.     local paramName = "param"
  1145.     local paramName2 = paramName
  1146.     for i = 2, #argTable do
  1147.         local addOn = tostring(i - 1)
  1148.         paramName2 = paramName .. addOn
  1149.         progTable[paramName2] = argTable[i]
  1150.         tempProgTable[paramName2] = argTable[i]
  1151.     end
  1152. end
  1153.  
  1154. -- Menu, Drawing and Main functions
  1155.  
  1156. function choiceIsValidShape(choice)
  1157.     local validShapes = {"rectangle", "square", "line", "wall", "platform", "stair", "stairs", "cuboid", "1/2-sphere", "1/2 sphere", "dome", "bowl", "sphere", "circle", "cylinder", "pyramid", "hexagon", "octagon", "6-prism", "6 prism", "8-prism", "8 prism"}
  1158.     for i = 1, #validShapes do
  1159.         if choice == validShapes[i] then
  1160.             return true
  1161.         end
  1162.     end
  1163.     return false
  1164. end
  1165.  
  1166. function choiceFunction()
  1167.     if sim_mode == false and cmd_line == false then -- If we are NOT resuming progress
  1168.         local page = 1
  1169.         choice = io.read()
  1170.         choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1171.         while ((choice == "next") or (choice == "back")) do
  1172.             if (choice == "next") then
  1173.                 if page == 1 then
  1174.                     writeMenu2()
  1175.                     page = 2
  1176.                 else
  1177.                     writeMenu()
  1178.                     page = 1
  1179.                 end
  1180.             end
  1181.             if (choice == "back") then
  1182.                 if page == 1 then
  1183.                     writeMenu2()
  1184.                     page = 2
  1185.                 else
  1186.                     writeMenu()
  1187.                     page = 1
  1188.                 end
  1189.             end
  1190.             choice = io.read()
  1191.             choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1192.         end
  1193.         if choice == "end" or choice == "exit" then
  1194.             writeOut("Goodbye.")
  1195.             return
  1196.         end
  1197.         if choice == "help" then
  1198.             getHelp()
  1199.             return
  1200.         end
  1201.         if choice == "credits" then
  1202.             showCredits()
  1203.             return
  1204.         end
  1205.         tempProgTable = {shape = choice}
  1206.         progTable = {shape = choice}
  1207.         if not choiceIsValidShape(choice) then
  1208.             writeOut(choice ..  " is not a valid shape choice.")
  1209.             return
  1210.         end
  1211.         writeOut("Building a "..choice)
  1212.         local yes = getInput("string","Want to just calculate the cost?","y","n")
  1213.         if yes == 'y' then
  1214.             cost_only = true
  1215.         end
  1216.         local yes = getInput("string","Want turtle to return to start after build?","y","n")
  1217.         if yes == 'y' then
  1218.             return_to_home = true
  1219.         end
  1220.         local yes = getInput("string","Want the turtle to refill from enderchest (slot 16)?","y","n")
  1221.         if yes == 'y' then
  1222.             enderchest_refilling = true
  1223.             tempProgTable.enderchest_refilling = true
  1224.         end
  1225.     elseif sim_mode == true then -- If we ARE resuming progress
  1226.         tempProgTable = readProgress()
  1227.         choice = tempProgTable.shape
  1228.         choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1229.         enderchest_refilling =  tempProgTable.enderchest_refilling
  1230.     elseif cmd_line == true then -- If running from command line
  1231.         if needsHelp() then
  1232.             showCmdLineHelp()
  1233.             return
  1234.         end
  1235.         choice = tempProgTable.shape
  1236.         choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1237.         enderchest_refilling =  tempProgTable.enderchest_refilling
  1238.         writeOut("Building a "..choice)
  1239.     end
  1240.     if not cost_only then
  1241.         turtle.select(1)
  1242.         activeSlot = 1
  1243.         if turtle.getItemCount(activeSlot) == 0 then
  1244.             if resupply then
  1245.                 writeOut("Please put building blocks in the first slot.")
  1246.             else
  1247.                 writeOut("Please put building blocks in the first slot (and more if you need them)")
  1248.             end
  1249.             while turtle.getItemCount(activeSlot) <= 1 do
  1250.                 os.sleep(.1)
  1251.             end
  1252.         end
  1253.     else
  1254.         activeSlot = 1
  1255.     end
  1256.     -- Shape selection if cascade
  1257.     -- Line based shapes
  1258.     if choice == "rectangle" then
  1259.         local depth = 0
  1260.         local width = 0
  1261.         if sim_mode == false and cmd_line == false then
  1262.             width = getInput("int","How wide does it need to be?")
  1263.             depth = getInput("int","How deep does it need to be?")
  1264.         elseif sim_mode == true or cmd_line == true then
  1265.             width = tempProgTable.param1
  1266.             depth = tempProgTable.param2
  1267.         end
  1268.         tempProgTable.param1 = width
  1269.         tempProgTable.param2 = depth
  1270.         progTable = {param1 = width, param2 = depth} -- THIS is here because we NEED to update the local table!
  1271.         rectangle(width, depth)
  1272.     end
  1273.     if choice == "square" then
  1274.         local sideLength
  1275.         if sim_mode == false and cmd_line == false then
  1276.             sideLength = getInput("int","How long does each side need to be?")
  1277.         elseif sim_mode == true or cmd_line == true then
  1278.             sideLength = tempProgTable.param1
  1279.         end
  1280.         tempProgTable.param1 = sideLength
  1281.         progTable = {param1 = sideLength}
  1282.         square(sideLength)
  1283.     end
  1284.     if choice == "line" then
  1285.         local startX = 0
  1286.         local startY = 0
  1287.         local endX = 0
  1288.         local endY = 0
  1289.         if sim_mode == false and cmd_line == false then
  1290.             writeOut("Note that the turtle's starting position is 0, 0.")
  1291.             startX = getInput("int","Where does the start X need to be?")
  1292.             startY = getInput("int","Where does the start Y need to be?")
  1293.             endX = getInput("int","Where does the end X need to be?")
  1294.             endY = getInput("int","Where does the end Y need to be?")
  1295.         elseif sim_mode == true or cmd_line == true then
  1296.             startX = tempProgTable.param1
  1297.             startY = tempProgTable.param2
  1298.             endX = tempProgTable.param3
  1299.             endY = tempProgTable.param4
  1300.         end
  1301.         tempProgTable.param1 = startX
  1302.         tempProgTable.param2 = startY
  1303.         tempProgTable.param3 = endX
  1304.         tempProgTable.param4 = endY
  1305.         progTable = {param1 = startX, param2 = startY, param3 = endX, param4 = endY}
  1306.         drawLine(endX, endY, startX, startY)
  1307.     end
  1308.     if choice == "wall" then
  1309.         local depth = 0
  1310.         local height = 0
  1311.         if sim_mode == false and cmd_line == false then
  1312.             depth = getInput("int","How deep does it need to be?")
  1313.             height = getInput("int","How high does it need to be?")
  1314.         elseif sim_mode == true or cmd_line == true then
  1315.             depth = tempProgTable.param1
  1316.             height = tempProgTable.param2
  1317.         end        
  1318.         tempProgTable.param1 = depth
  1319.         tempProgTable.param2 = height
  1320.         progTable = {param1 = depth, param2 = height}
  1321.         wall(depth, height)
  1322.     end
  1323.     if choice == "platform" then
  1324.         local width = 0
  1325.         local depth = 0
  1326.         if sim_mode == false and cmd_line == false then
  1327.             width = getInput("int","How wide does it need to be?")
  1328.             depth = getInput("int","How deep does it need to be?")
  1329.         elseif sim_mode == true or cmd_line == true then   
  1330.             width = tempProgTable.param1       
  1331.             depth = tempProgTable.param2
  1332.         end    
  1333.         tempProgTable.param1 = width
  1334.         tempProgTable.param2 = depth
  1335.         progTable = {param1 = width, param2 = depth}
  1336.         platform(width, depth)
  1337.     end
  1338.     if choice == "stair" or choice == "stairs" then
  1339.         local width = 0
  1340.         local height = 0
  1341.         if sim_mode == false and cmd_line == false then
  1342.             width = getInput("int","How wide does it need to be?")
  1343.             height = getInput("int","How high does it need to be?")
  1344.         elseif sim_mode == true or cmd_line == true then
  1345.             width = tempProgTable.param1
  1346.             height = tempProgTable.param2
  1347.         end
  1348.         tempProgTable.param1 = width
  1349.         tempProgTable.param2 = height
  1350.         progTable = {param1 = width, param2 = height}
  1351.         stair(width, height)
  1352.         special_chain = true
  1353.     end
  1354.     if choice == "cuboid" then
  1355.         local width = 0
  1356.         local depth = 0
  1357.         local height = 0
  1358.         local hollow = ""
  1359.         if sim_mode == false and cmd_line == false then
  1360.             width = getInput("int","How wide does it need to be?")
  1361.             depth = getInput("int","How deep does it need to be?")
  1362.             height = getInput("int","How high does it need to be?")
  1363.             hollow = getInput("string","Does it need to be hollow?","y","n")
  1364.         elseif sim_mode == true or cmd_line == true then
  1365.             width = tempProgTable.param1
  1366.             depth = tempProgTable.param2
  1367.             height = tempProgTable.param3
  1368.             hollow = tempProgTable.param4
  1369.         end
  1370.         tempProgTable.param1 = width
  1371.         tempProgTable.param2 = depth
  1372.         tempProgTable.param3 = height
  1373.         tempProgTable.param4 = hollow  
  1374.         progTable = {param1 = width, param2 = depth, param3 = height}
  1375.         cuboid(width, depth, height, hollow)
  1376.     end
  1377.     if choice == "pyramid" then
  1378.         local length = 0
  1379.         local hollow = ""
  1380.         if sim_mode == false and cmd_line == false then
  1381.             length = getInput("int","How long does each side of the base layer need to be?")
  1382.             hollow = getInput("string","Does it need to be hollow?","y","n")
  1383.         elseif sim_mode == true or cmd_line == true then
  1384.             length = tempProgTable.param1
  1385.             hollow = tempProgTable.param2
  1386.         end
  1387.         tempProgTable.param1 = length
  1388.         tempProgTable.param2 = hollow
  1389.         progTable = {param1 = length, param2 = hollow}
  1390.         pyramid(length, hollow)
  1391.     end
  1392.     -- Circle based shapes
  1393.     if choice == "1/2-sphere" or choice == "1/2 sphere" then
  1394.         local diameter = 0
  1395.         local half = ""
  1396.         if sim_mode == false and cmd_line == false then
  1397.             diameter = getInput("int","What diameter does it need to be?")
  1398.             half = getInput("string","What half of the sphere does it need to be?","bottom","top")
  1399.         elseif sim_mode == true or cmd_line == true then
  1400.             diameter = tempProgTable.param1
  1401.             half = tempProgTable.param2
  1402.         end
  1403.         tempProgTable.param1 = diameter
  1404.         tempProgTable.param2 = half
  1405.         progTable = {param1 = diameter, param2 = half}
  1406.         if half == "bottom" then
  1407.             dome("bowl", diameter)
  1408.         elseif half == "top" then
  1409.             dome("dome", diameter)
  1410.         end
  1411.     end
  1412.     if choice == "dome" then
  1413.         local diameter = 0
  1414.         if sim_mode == false and cmd_line == false then
  1415.             diameter = getInput("int","What diameter does it need to be?")
  1416.         elseif sim_mode == true or cmd_line == true then
  1417.             diameter = tempProgTable.param1
  1418.         end
  1419.         tempProgTable.param1 = diameter
  1420.         progTable = {param1 = diameter}
  1421.         dome("dome", diameter)
  1422.     end
  1423.     if choice == "bowl" then
  1424.         local diameter = 0
  1425.         if sim_mode == false and cmd_line == false then
  1426.             diameter = getInput("int","What diameter does it need to be?")
  1427.         elseif sim_mode == true or cmd_line == true then
  1428.             diameter = tempProgTable.param1
  1429.         end
  1430.         tempProgTable.param1 = diameter
  1431.         progTable = {param1 = diameter}
  1432.         dome("bowl", diameter)
  1433.     end
  1434.     if choice == "sphere" then
  1435.         local diameter = 0
  1436.         if sim_mode == false and cmd_line == false then
  1437.             diameter = getInput("int","What diameter does it need to be?")
  1438.         elseif sim_mode == true or cmd_line == true then
  1439.             diameter = tempProgTable.param1
  1440.         end
  1441.         tempProgTable.param1 = diameter
  1442.         progTable = {param1 = diameter}
  1443.         dome("sphere", diameter)
  1444.     end
  1445.     if choice == "circle" then
  1446.         local diameter = 0
  1447.         if sim_mode == false and cmd_line == false then
  1448.             diameter = getInput("int","What diameter does it need to be?")
  1449.         elseif sim_mode == true or cmd_line == true then
  1450.             diameter = tempProgTable.param1
  1451.         end
  1452.         tempProgTable.param1 = diameter
  1453.         progTable = {param1 = diameter}
  1454.         circle(diameter)
  1455.     end
  1456.     if choice == "cylinder" then
  1457.         local diameter = 0
  1458.         local height = 0
  1459.         if sim_mode == false and cmd_line == false then
  1460.             diameter = getInput("int","What diameter does it need to be?")
  1461.             height = getInput("int","How high does it need to be?")
  1462.         elseif sim_mode == true or cmd_line == true then
  1463.             diameter = tempProgTable.param1
  1464.             height = tempProgTable.param2
  1465.         end
  1466.         tempProgTable.param1 = diameter
  1467.         tempProgTable.param2 = height
  1468.         progTable = {param1 = diameter, param2 = height}
  1469.         cylinder(diameter, height)
  1470.     end
  1471.     -- Polygon shapes
  1472.     if choice == "hexagon" then
  1473.         local length = 0
  1474.         if sim_mode == false and cmd_line == false then
  1475.             length = getInput("int","How long does each side need to be?")
  1476.         elseif sim_mode == true or cmd_line == true then
  1477.             length = tempProgTable.param1
  1478.         end
  1479.         tempProgTable.param1 = length
  1480.         progTable = {param1 = length}
  1481.         hexagon(length)
  1482.     end
  1483.     if choice == "octagon" then
  1484.         local length = 0
  1485.         if sim_mode == false and cmd_line == false then
  1486.             length = getInput("int","How long does each side need to be?")
  1487.         elseif sim_mode == true or cmd_line == true then
  1488.             length = tempProgTable.param1
  1489.         end
  1490.         tempProgTable.param1 = length
  1491.         progTable = {param1 = length}
  1492.         octagon(length)
  1493.     end
  1494.     if choice == "6-prism" or choice == "6 prism" then
  1495.         local length = 0
  1496.         local height = 0
  1497.         if sim_mode == false and cmd_line == false then
  1498.             length = getInput("int","How long does each side need to be?")
  1499.             height = getInput("int","How high does it need to be?")
  1500.         elseif sim_mode == true or cmd_line == true then
  1501.             length = tempProgTable.param1
  1502.             height = tempProgTable.param2
  1503.         end
  1504.         tempProgTable.param1 = length
  1505.         tempProgTable.param2 = height
  1506.         progTable = {param1 = length, param2 = height}
  1507.         sixprism(length, height)
  1508.     end
  1509.     if choice == "8-prism" or choice == "8 prism" then
  1510.         local length = 0
  1511.         local height = 0
  1512.         if sim_mode == false and cmd_line == false then
  1513.             length = getInput("int","How long does each side need to be?")
  1514.             height = getInput("int","How high does it need to be?")
  1515.         elseif sim_mode == true or cmd_line == true then
  1516.             length = tempProgTable.param1
  1517.             height = tempProgTable.param2
  1518.         end
  1519.         tempProgTable.param1 = length
  1520.         tempProgTable.param2 = height
  1521.         progTable = {param1 = length, param2 = height}
  1522.         eightprism(length, height)
  1523.     end
  1524.     if return_to_home then
  1525.         goHome() -- After all shape building has finished
  1526.     end
  1527.     writeOut("Done") -- Saves a few lines when put here rather than in each if statement
  1528. end
  1529.  
  1530. function writeMenu()
  1531.     term.clear()
  1532.     term.setCursorPos(1, 1)
  1533.     writeOut("Shape Maker 1.7 by Keridos/CupricWolf/pokemane")
  1534.     if resupply then                    -- Any ideas to make this more compact/better looking (in terms of code)?
  1535.         writeOut("Resupply Mode Active")
  1536.     elseif (resupply and can_use_gps) then
  1537.         writeOut("Resupply and GPS Mode Active")
  1538.     elseif can_use_gps then
  1539.         writeOut("GPS Mode Active")
  1540.     else
  1541.         writeOut("Standard Mode Active")
  1542.     end
  1543.     if not cmd_line then
  1544.         writeOut("What shape do you want to build? [page 1/2]");
  1545.         writeOut("next for page 2")
  1546.         writeOut("+---------+-----------+-------+-------+")
  1547.         writeOut("| square  | rectangle | wall  | line  |")
  1548.         writeOut("| cylinder| platform  | stair | cuboid|")
  1549.         writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1550.         writeOut("+---------+-----------+-------+-------+")
  1551.         writeOut("")
  1552.     end
  1553. end
  1554.  
  1555. function writeMenu2()
  1556.     term.clear()
  1557.     term.setCursorPos(1, 1)
  1558.     writeOut("Shape Maker 1.7 by Keridos/CupricWolf/pokemane")
  1559.     if resupply then                    -- Any ideas to make this more compact/better looking (in terms of code)?
  1560.         writeOut("Resupply Mode Active")
  1561.     elseif (resupply and can_use_gps) then
  1562.         writeOut("Resupply and GPS Mode Active")
  1563.     elseif can_use_gps then
  1564.         writeOut("GPS Mode Active")
  1565.     else
  1566.         writeOut("Standard Mode Active")
  1567.     end
  1568.     writeOut("What shape do you want to build? [page 2/2]");
  1569.     writeOut("back for page 1")
  1570.     writeOut("+---------+-----------+-------+-------+")
  1571.     writeOut("| hexagon | octagon   | dome  |       |")
  1572.     writeOut("| 6-prism | 8-prism   | bowl  |       |")
  1573.     writeOut("| help    | credits   | end   |       |")
  1574.     writeOut("+---------+-----------+-------+-------+")
  1575.     writeOut("")
  1576. end
  1577.  
  1578. function showCmdLineHelp()
  1579.     term.clear()
  1580.     term.setCursorPos(1, 1)
  1581.     writeOut("Command line help")
  1582.     writeOut("Usage: shape [shape-type] [param1] [param2] [param3] [param4] [-c] [-h] [-z] [-r]\n")
  1583.     writeOut("-c or -cost or --cost: Activate cost only mode\n")
  1584.     writeOut("-h or -help or --help: Show this information")
  1585.     io.read()
  1586.     writeOut("-z or -chain or --chain: Lets you chain together multiple shapes\n")
  1587.     writeOut("-g or -home or --home: Make turtle go 'home' after build\n")
  1588.     writeOut("-r or -resume or --resume: Resume the last build if possible")
  1589.     io.read()
  1590.     writeOut("-e or -ender or --ender: Activate enderchest refilling\n")
  1591.     writeOut("shape-type can be any of the shapes in the menu\n")
  1592.     writeOut("After shape-type input all of the paramaters for the shape, varies by shape\n")
  1593.     writeOut("Put any flags (-c, -h, etc.) at the end of your command")
  1594. end
  1595.  
  1596. function getHelp()
  1597.     term.clear()
  1598.     term.setCursorPos(1, 1)
  1599.     writeOut("Width is to the right of the turtle. (X-Axis)")
  1600.     writeOut("Depth is to the front of the turtle. (Y-Axis)")
  1601.     writeOut("Height is to the top of the turtle. (Z-Axis)")
  1602.     writeOut("Length is the side length of some shapes. (Squares and Polygons)")
  1603.     io.read()
  1604.     term.clear()
  1605.     term.setCursorPos(1, 1)
  1606.     local page = 1
  1607.     writeOut("What shape do you want help with? [page 1/2]");
  1608.     writeOut("next for page 2")
  1609.     writeOut("+---------+-----------+-------+-------+")
  1610.     writeOut("| square  | rectangle | wall  | line  |")
  1611.     writeOut("| cylinder| platform  | stair | cuboid|")
  1612.     writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1613.     writeOut("+---------+-----------+-------+-------+")
  1614.     writeOut("")
  1615.     choice = io.read()
  1616.     choice = string.lower(choice)
  1617.     while ((choice == "next") or (choice == "back")) do
  1618.         if (choice == "next") then
  1619.             if (page == 1) then
  1620.                 page = 2
  1621.                 term.clear()
  1622.                 term.setCursorPos(1, 1)
  1623.                 writeOut("What shape do you want help wih? [page 2/2]?");
  1624.                 writeOut("back for page 1")
  1625.                 writeOut("+---------+-----------+-------+-------+")
  1626.                 writeOut("| hexagon | octagon   | dome  |       |")
  1627.                 writeOut("| 6-prism | 8-prism   | bowl  |       |")
  1628.                 writeOut("|         |           |       |       |")
  1629.                 writeOut("+---------+-----------+-------+-------+")
  1630.                 writeOut("")
  1631.             else
  1632.                 page = 1
  1633.                 term.clear()
  1634.                 term.setCursorPos(1, 1)
  1635.                 writeOut("What shape do you want help with? [page 1/2]");
  1636.                 writeOut("next for page 2")
  1637.                 writeOut("+---------+-----------+-------+-------+")
  1638.                 writeOut("| square  | rectangle | wall  | line  |")
  1639.                 writeOut("| cylinder| platform  | stair | cuboid|")
  1640.                 writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1641.                 writeOut("+---------+-----------+-------+-------+")
  1642.                 writeOut("")
  1643.             end
  1644.         end
  1645.         if (choice == "back") then
  1646.             if (page == 1) then
  1647.                 page = 2
  1648.                 term.clear()
  1649.                 term.setCursorPos(1, 1)
  1650.                 writeOut("What shape do you want help wih? [page 2/2]?");
  1651.                 writeOut("back for page 1")
  1652.                 writeOut("+---------+-----------+-------+-------+")
  1653.                 writeOut("| hexagon | octagon   | dome  |       |")
  1654.                 writeOut("| 6-prism | 8-prism   | bowl  |       |")
  1655.                 writeOut("|         |           |       |       |")
  1656.                 writeOut("+---------+-----------+-------+-------+")
  1657.                 writeOut("")
  1658.             else
  1659.                 page = 1
  1660.                 term.clear()
  1661.                 term.setCursorPos(1, 1)
  1662.                 writeOut("What shape do you want help with? [page 1/2]");
  1663.                 writeOut("next for page 2")
  1664.                 writeOut("+---------+-----------+-------+-------+")
  1665.                 writeOut("| square  | rectangle | wall  | line  |")
  1666.                 writeOut("| cylinder| platform  | stair | cuboid|")
  1667.                 writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1668.                 writeOut("+---------+-----------+-------+-------+")
  1669.                 writeOut("")
  1670.             end
  1671.         end
  1672.         choice = io.read()
  1673.         choice = string.lower(choice)
  1674.     end
  1675.     if not choiceIsValidShape(choice) then
  1676.         writeOut(choice ..  " is not a valid shape choice.")
  1677.         return
  1678.     end
  1679.     -- If cascade time!
  1680.     if choice == "rectangle" then
  1681.         term.clear()
  1682.         term.setCursorPos(1, 1)
  1683.         writeOut("The rectangle is a perimiter of width by depth. Use platform if you want a filled in rectangle. The rectangle takes two parameters (two integers) Width then Depth.")
  1684.     end
  1685.     if choice == "square" then
  1686.         term.clear()
  1687.         term.setCursorPos(1, 1)
  1688.         writeOut("The square is a perimiter of length by length. Use platform if you want a filled in square. The square takes one parameter (one integer) Length.")
  1689.     end
  1690.     if choice == "line" then
  1691.         term.clear()
  1692.         term.setCursorPos(1, 1)
  1693.         writeOut("The line is drawn between the start and end points given. The turtle's initial position is 0, 0 so that must by taken into account. The line takes four parameters (four integers) Start X then Start Y then End X then End Y.")
  1694.     end
  1695.     if choice == "wall" then
  1696.         term.clear()
  1697.         term.setCursorPos(1, 1)
  1698.         writeOut("The wall is a vertical plane. The wall takes two parameters (two integers) Depth then Height.")
  1699.     end
  1700.     if choice == "platform" then
  1701.         term.clear()
  1702.         term.setCursorPos(1, 1)
  1703.         writeOut("The platform is a horizontal plane of width by depth. Use rectangle or square if you want just a perimeter. The platform takes two parameters (two integers) Width then Depth.")
  1704.     end
  1705.     if choice == "stair" or choice == "stairs" then
  1706.         term.clear()
  1707.         term.setCursorPos(1, 1)
  1708.         writeOut("The stair or stairs are an incline of width by height. The stair takes two parameters (two integers) Width then Height.")
  1709.     end
  1710.     if choice == "cuboid" then
  1711.         term.clear()
  1712.         term.setCursorPos(1, 1)
  1713.         writeOut("The cuboid is a rectangular prism of width by depth by height. The hollow parameter determines if the shape is solid or like a rectangular tube. The cuboid takes four parameters (three intergers and one y/n) Width then Depth then Height then Hollow(y/n).")
  1714.     end
  1715.     if choice == "1/2-sphere" or choice == "1/2 sphere" then
  1716.         term.clear()
  1717.         term.setCursorPos(1, 1)
  1718.         writeOut("The half sphere is the top or bottom half of a sphere. The half parameter determines of the top or bottom half of the sphere built. The half sphere takes two parameters (one integer and one top/bottom) Diameter then half(top/bottom).")
  1719.     end
  1720.     if choice == "dome" then
  1721.         term.clear()
  1722.         term.setCursorPos(1, 1)
  1723.         writeOut("The dome shape is a shortcut to the top half sphere. The dome takes one parameter (one integer) Diameter.")
  1724.     end
  1725.     if choice == "bowl" then
  1726.         term.clear()
  1727.         term.setCursorPos(1, 1)
  1728.         writeOut("The bowl shape is a shortcut to the bottom half sphere. The bowl takes one parameter (one integer) Diameter.")
  1729.     end
  1730.     if choice == "sphere" then
  1731.         term.clear()
  1732.         term.setCursorPos(1, 1)
  1733.         writeOut("The sphere is just that, a sphere. It is hollow. The sphere takes one parameter (one integer) Diameter.")
  1734.     end
  1735.     if choice == "circle" then
  1736.         term.clear()
  1737.         term.setCursorPos(1, 1)
  1738.         writeOut("The circle is just that, a circle. It is just a perimeter. The circle takes one parameter (one integer) Diameter.")
  1739.     end
  1740.     if choice == "cylinder" then
  1741.         term.clear()
  1742.         term.setCursorPos(1, 1)
  1743.         writeOut("The cylinder is a cylindrical tube of diameter by height. The cylinder takes two parameters (two integers) Diameter then Height.")
  1744.     end
  1745.     if choice == "pyramid" then
  1746.         term.clear()
  1747.         term.setCursorPos(1, 1)
  1748.         writeOut("The pyramid is a four sided pyramid with base length by length. The hollow parameter determines if the inside is filled. The pyramid takes two parameters (one integer and one y/n) Base Length then Hollow(y/n).")
  1749.     end
  1750.     if choice == "hexagon" then
  1751.         term.clear()
  1752.         term.setCursorPos(1, 1)
  1753.         writeOut("The hexagon is a hexagonal perimeter. The hexagon takes one parameter (one integer) Length.")
  1754.     end
  1755.     if choice == "octagon" then
  1756.         term.clear()
  1757.         term.setCursorPos(1, 1)
  1758.         writeOut("The octagon is and octagonal perimeter. The octagon takes one parameter (one integer) Length.")
  1759.     end
  1760.     if choice == "6-prism" or choice == "6 prism" then
  1761.         term.clear()
  1762.         term.setCursorPos(1, 1)
  1763.         writeOut("The 6 prism is a hexagonal prism shaped tube. The 6 prism takes two parameters (two integers) Length then Height.")
  1764.     end
  1765.     if choice == "8-prism" or choice == "8 prism" then
  1766.         term.clear()
  1767.         term.setCursorPos(1, 1)
  1768.         writeOut("The 8 prism is an octagonal prism shaped tube. The 8 prism takes two parameters (two integers) Length then Height.")
  1769.     end
  1770. end
  1771.  
  1772. function showCredits()
  1773.     term.clear()
  1774.     term.setCursorPos(1, 1)
  1775.     writeOut("Credits for the shape builder:")
  1776.     writeOut("Based on work by Michiel, Vliekkie, and Aeolun")
  1777.     writeOut("Sphere/dome code by IMarvinTPA")
  1778.     writeOut("Additional improvements by Keridos, CupricWolf, and pokemane")
  1779. end
  1780.  
  1781. function main()
  1782.     if wrapModules()=="resupply" then
  1783.         linkToRSStation()
  1784.     end
  1785.     if checkCommandLine() then
  1786.         if needsHelp() then
  1787.             showCmdLineHelp()
  1788.             return -- Close the program after help info is shown
  1789.         end
  1790.         setFlagsFromCommandLine()
  1791.         setTableFromCommandLine()
  1792.     end
  1793.     if (CheckForPrevious()) then  -- Will check to see if there was a previous job and gps is enabled, and if so, ask if the user would like to re-initialize to current progress status
  1794.         if not continueQuery() then -- If the user doesn't want to continue
  1795.             ProgressFileDelete()
  1796.             setSimFlags(false) -- Just to be safe
  1797.             writeMenu()
  1798.             choiceFunction()
  1799.         else    -- If the user wants to continue
  1800.             setSimFlags(true)
  1801.             choiceFunction()
  1802.         end
  1803.     else
  1804.         setSimFlags(false)
  1805.         writeMenu()
  1806.         choiceFunction()
  1807.     end
  1808.     if (blocks ~= 0) and (fuel ~= 0) then -- Do not show on help or credits page or when selecting end
  1809.         writeOut("Blocks used: " .. blocks)
  1810.         writeOut("Fuel used: " .. fuel)
  1811.     end
  1812.     ProgressFileDelete() -- Removes file upon successful completion of a job, or completion of a previous job.
  1813.     progTable = {}
  1814.     tempProgTable = {}
  1815. end
  1816.  
  1817. main()
Add Comment
Please, Sign In to add comment