Advertisement
happydude11209

Stable Old Circle Code Shape Builder

Aug 19th, 2014
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 52.62 KB | None | 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.     for i = 0, height - 1 do
  647.         navigateTo(0, 0, i)
  648.         if (hollow == "n") then
  649.             platform(width, depth, 0, 0)
  650.         else
  651.             rectangle(width, depth, 0, 0)
  652.         end
  653.     end
  654. end
  655.  
  656. function pyramid(length, hollow)
  657.     -- local height = math.ceil(length / 2) - 1
  658.     i = 0
  659.     while (length > 0) do
  660.         navigateTo(i, i, i)
  661.         if (hollow == "y") then
  662.             rectangle(length, length, i, i)
  663.         else
  664.             platform(length, length, i, i)
  665.         end
  666.         i = i + 1
  667.         length = length - 2
  668.     end
  669. end
  670.  
  671. function stair(width, height, startX, startY) -- Last two might be able to be used to make a basic home-like shape later?
  672.     startX = startX or positionX
  673.     startY = startY or positionY
  674.     endX = startX + width - 1
  675.     endY = startY + height - 1
  676.     forward = true
  677.     for counterY = startY, endY do
  678.         if forward then
  679.             for counterX = startX, endX do
  680.                 navigateTo(counterX, counterY)
  681.                 placeBlock()
  682.             end
  683.         else
  684.             for counterX = endX, startX, -1 do
  685.                 navigateTo(counterX, counterY)
  686.                 placeBlock()
  687.             end
  688.         end
  689.         if counterY ~= endY then
  690.             navigateTo(positionX, positionY, positionZ + 1)
  691.             forward = not forward
  692.         end
  693.     end
  694. end
  695.  
  696. function circle(radius)
  697.     width = radius * 2 + 1
  698.     sqrt3 = 3 ^ 0.5
  699.     boundaryRadius = radius + 1.0
  700.     boundary2 = boundaryRadius ^ 2
  701.     z = radius
  702.     cz2 = (radius - z) ^ 2
  703.     limitOffsetY = (boundary2 - cz2) ^ 0.5
  704.     maxOffestY = math.ceil(limitOffsetY)
  705.     -- We do first the +x side, then the -x side to make movement efficient
  706.     for side = 0, 1 do
  707.         -- On the right we go from small y to large y, on the left reversed
  708.         -- This makes us travel clockwise (from below) around each layer
  709.         if (side == 0) then
  710.             yStart = radius - maxOffestY
  711.             yEnd = radius + maxOffestY
  712.             yStep = 1
  713.         else
  714.             yStart = radius + maxOffestY
  715.             yEnd = radius - maxOffestY
  716.             yStep = -1
  717.         end
  718.         for y = yStart, yEnd, yStep do
  719.             cy2 = (radius - y) ^ 2
  720.             remainder2 = (boundary2 - cz2 - cy2)
  721.             if remainder2 >= 0 then
  722.                 -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
  723.                 maxOffsetX = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
  724.                     -- Only do either the +x or -x side
  725.                 if (side == 0) then
  726.                     -- +x side
  727.                     xStart = radius
  728.                     xEnd = radius + maxOffsetX
  729.                 else
  730.                     -- -x side
  731.                     xStart = radius - maxOffsetX
  732.                     xEnd = radius - 1
  733.                 end
  734.                 -- Reverse direction we traverse xs when in -y side
  735.                 if y > radius then
  736.                     temp = xStart
  737.                     xStart = xEnd
  738.                     xEnd = temp
  739.                     xStep = -1
  740.                 else
  741.                     xStep = 1
  742.                 end
  743.                     for x = xStart, xEnd, xStep do
  744.                     cx2 = (radius - x) ^ 2
  745.                     distanceToCentre = (cx2 + cy2 + cz2) ^ 0.5
  746.                     -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
  747.                     if distanceToCentre < boundaryRadius and distanceToCentre + sqrt3 >= boundaryRadius then
  748.                         offsets = {{0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}}
  749.                         for i=1,6 do
  750.                             offset = offsets[i]
  751.                             dx = offset[1]
  752.                             dy = offset[2]
  753.                             dz = offset[3]
  754.                             if ((radius - (x + dx)) ^ 2 + (radius - (y + dy)) ^ 2 + (radius - (z + dz)) ^ 2) ^ 0.5 >= boundaryRadius then
  755.                                 -- This is a point to use
  756.                                 navigateTo(x, y)
  757.                                 placeBlock()
  758.                                 break
  759.                             end
  760.                         end
  761.                     end
  762.                 end
  763.             end
  764.         end
  765.     end
  766. end
  767.  
  768. function dome(typus, radius)
  769.     -- Main dome and sphere building routine
  770.     width = radius * 2 + 1
  771.     sqrt3 = 3 ^ 0.5
  772.     boundaryRadius = radius + 1.0
  773.     boundary2 = boundaryRadius ^ 2
  774.     if typus == "dome" then
  775.         zstart = radius
  776.     elseif typus == "sphere" then
  777.         zstart = 0
  778.     elseif typus == "bowl" then
  779.         zstart = 0
  780.     end
  781.     if typus == "bowl" then
  782.         zend = radius
  783.     else
  784.         zend = width - 1
  785.     end
  786.  
  787.     -- This loop is for each vertical layer through the sphere or dome.
  788.     for z = zstart,zend do
  789.         if not cost_only and z ~= zstart then
  790.             navigateTo(positionX, positionY, positionZ + 1)
  791.         end
  792.         --writeOut("Layer " .. z)
  793.         cz2 = (radius - z) ^ 2
  794.         limitOffsetY = (boundary2 - cz2) ^ 0.5
  795.         maxOffestY = math.ceil(limitOffsetY)
  796.         -- We do first the +x side, then the -x side to make movement efficient
  797.         for side = 0,1 do
  798.             -- On the right we go from small y to large y, on the left reversed
  799.             -- This makes us travel clockwise (from below) around each layer
  800.             if (side == 0) then
  801.                 yStart = radius - maxOffestY
  802.                 yEnd = radius + maxOffestY
  803.                 yStep = 1
  804.             else
  805.                 yStart = radius + maxOffestY
  806.                 yEnd = radius - maxOffestY
  807.                 yStep = -1
  808.             end
  809.             for y = yStart,yEnd,yStep do
  810.                 cy2 = (radius - y) ^ 2
  811.                 remainder2 = (boundary2 - cz2 - cy2)
  812.                 if remainder2 >= 0 then
  813.                     -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
  814.                     maxOffsetX = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
  815.                     -- Only do either the +x or -x side
  816.                     if (side == 0) then
  817.                         -- +x side
  818.                         xStart = radius
  819.                         xEnd = radius + maxOffsetX
  820.                     else
  821.                         -- -x side
  822.                         xStart = radius - maxOffsetX
  823.                         xEnd = radius - 1
  824.                     end
  825.                     -- Reverse direction we traverse xs when in -y side
  826.                     if y > radius then
  827.                         temp = xStart
  828.                         xStart = xEnd
  829.                         xEnd = temp
  830.                         xStep = -1
  831.                     else
  832.                         xStep = 1
  833.                     end
  834.  
  835.                     for x = xStart,xEnd,xStep do
  836.                         cx2 = (radius - x) ^ 2
  837.                         distanceToCentre = (cx2 + cy2 + cz2) ^ 0.5
  838.                         -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
  839.                         if distanceToCentre < boundaryRadius and distanceToCentre + sqrt3 >= boundaryRadius then
  840.                             offsets = {{0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}}
  841.                             for i=1,6 do
  842.                                 offset = offsets[i]
  843.                                 dx = offset[1]
  844.                                 dy = offset[2]
  845.                                 dz = offset[3]
  846.                                 if ((radius - (x + dx)) ^ 2 + (radius - (y + dy)) ^ 2 + (radius - (z + dz)) ^ 2) ^ 0.5 >= boundaryRadius then
  847.                                     -- This is a point to use
  848.                                     navigateTo(x, y)
  849.                                     placeBlock()
  850.                                     break
  851.                                 end
  852.                             end
  853.                         end
  854.                     end
  855.                 end
  856.             end
  857.         end
  858.     end
  859. end
  860.  
  861. function cylinder(radius, height)
  862.     for i = 1, height do
  863.         circle(radius)
  864.         navigateTo(positionX, positionY, positionZ + 1)
  865.     end
  866. end
  867.  
  868. polygonCornerList = {} -- Public list of corner coords for n-gons, will be used for hexagons, octagons, and future polygons.
  869. -- It should be constructed as a nested list eg. {{x0,y0},{x1,y1},{x2,y2}...}
  870.  
  871. function constructPolygon() -- Uses polygonCornerList to draw sides between each point
  872.     if #polygonCornerList == 0 then
  873.         return false
  874.     end
  875.     for i = 1, #polygonCornerList do
  876.         startX = polygonCornerList[i][1]
  877.         startY = polygonCornerList[i][2]
  878.         if i == #polygonCornerList then
  879.             j = 1
  880.         else
  881.             j = i + 1
  882.         end
  883.         stopX = polygonCornerList[j][1]
  884.         stopY = polygonCornerList[j][2]
  885.         drawLine(stopX, stopY, startX, startY)
  886.     end
  887.     return true
  888. end
  889.  
  890. function arbitraryPolygon(numberOfSides, Radius) -- Future function, this will eventually replace octagon and hexagon functions
  891. end
  892.  
  893. function hexagon(sideLength) -- Fills out polygonCornerList with the points for a hexagon
  894.     sideLength = sideLength - 1
  895.     local changeX = sideLength / 2
  896.     local changeY = round(math.sqrt(3) * changeX, 0)
  897.     changeX = round(changeX, 0)
  898.     polygonCornerList[1] = {changeX, 0}
  899.     polygonCornerList[2] = {(changeX + sideLength), 0}
  900.     polygonCornerList[3] = {((2 * changeX) + sideLength), changeY}
  901.     polygonCornerList[4] = {(changeX + sideLength), (2 * changeY)}
  902.     polygonCornerList[5] = {changeX, (2 * changeY)}
  903.     polygonCornerList[6] = {0, changeY}
  904.     if not constructPolygon() then
  905.         error("This error should never happen.")
  906.     end
  907. end
  908.  
  909. function octagon(sideLength) -- Fills out polygonCornerList with the points for an octagon
  910.     sideLength = sideLength - 1
  911.     local change = round((sideLength - 1) / math.sqrt(2), 0)
  912.     polygonCornerList[1] = {change, 0}
  913.     polygonCornerList[2] = {(change + sideLength), 0}
  914.     polygonCornerList[3] = {((2 * change) + sideLength), change}
  915.     polygonCornerList[4] = {((2 * change) + sideLength), (change + sideLength)}
  916.     polygonCornerList[5] = {(change + sideLength), ((2 * change) + sideLength)}
  917.     polygonCornerList[6] = {change, ((2 * change) + sideLength)}
  918.     polygonCornerList[7] = {0, (change + sideLength)}
  919.     polygonCornerList[8] = {0, change}
  920.     if not constructPolygon() then
  921.         error("This error should never happen.")
  922.     end
  923. end
  924.  
  925. function sixprism(length, height)
  926.     for i = 1, height do
  927.         hexagon(length)
  928.         if i ~= height then
  929.             navigateTo(positionX, positionY, positionZ + 1)
  930.         end
  931.     end
  932. end
  933.  
  934. function eightprism(length, height)
  935.     for i = 1, height do
  936.         octagon(length)
  937.         if i ~= height then
  938.             navigateTo(positionX, positionY, positionZ + 1)
  939.         end
  940.     end
  941. end
  942.  
  943. -- Previous Progress Resuming, Simulation functions, Command Line, and File Backend
  944. -- Will check for a "progress" file.
  945. function CheckForPrevious()
  946.     if fs.exists(progFileName) then
  947.         return true
  948.     else
  949.         return false
  950.     end
  951. end
  952.  
  953. -- 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)
  954. function ProgressFileCreate()
  955.     if not CheckForPrevious() then
  956.         fs.makeDir(progFileName)
  957.         return true
  958.     else
  959.         return false
  960.     end
  961. end
  962.  
  963. -- Deletes the progress file (at the end of the project, or at beginning if user chooses to delete old progress)
  964. function ProgressFileDelete()
  965.     if fs.exists(progFileName) then
  966.         fs.delete(progFileName)
  967.         return true
  968.     else
  969.         return false
  970.     end
  971. end
  972.  
  973. -- To read the shape params from the file.  Shape type, and input params (e.g. "dome" and radius)
  974. function ReadShapeParams()
  975.     -- TODO. Unneeded for now, can just use the table elements directly
  976. end
  977.  
  978. function WriteShapeParams(...) -- The ... lets it take any number of arguments and stores it to the table arg{} | This is still unused anywhere
  979.     local paramTable = arg
  980.     local paramName = "param"
  981.     local paramName2 = paramName
  982.     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!
  983.         paramName2 = paramName .. i
  984.         tempProgTable[paramName2] = v
  985.         progTable[paramName2] = v
  986.     end
  987. end
  988.  
  989. -- function to write the progress to the file (x, y, z)
  990. function writeProgress()
  991.     local progFile
  992.     local progString = ""
  993.     if not (sim_mode or cost_only) then
  994.         progString = textutils.serialize(progTable) -- Put in here to save processing time when in cost_only
  995.         progFile = fs.open(progFileName, "w")
  996.         progFile.write(progString)
  997.         progFile.close()
  998.     end
  999.  
  1000. end
  1001.  
  1002. -- Reads progress from file (shape, x, y, z, facing, blocks, param1, param2, param3)
  1003. function readProgress()
  1004.     local progFile = fs.open(progFileName, "r")
  1005.     local readProgTable = textutils.unserialize(progFile.readAll())
  1006.     progFile.close()
  1007.     return readProgTable
  1008. end
  1009.  
  1010. -- compares the progress read from the file to the current sim progress.  needs all four params
  1011. function compareProgress()
  1012.     local progTableIn = progTable
  1013.     local readProgTable = readProgress()
  1014.     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
  1015.         writeOut("All caught up!")
  1016.         return true -- We're caught up!
  1017.     else
  1018.         return false -- Not there yet...
  1019.     end
  1020. end
  1021.  
  1022. function getGPSInfo() -- TODO: finish this
  1023.     position = gps.locate()
  1024.     gpsPositionX = position.x
  1025.     gpsPositionZ = position.y
  1026.     gpsPositionY = position.z
  1027.    
  1028. end
  1029.  
  1030. function setSimFlags(b)
  1031.     sim_mode = b
  1032.     cost_only = b
  1033.     if cmd_line_cost_only then
  1034.         cost_only = true
  1035.     end
  1036. end
  1037.  
  1038. function simulationCheck() -- checks state of the simulation
  1039.     if sim_mode then
  1040.         if compareProgress() then
  1041.             setSimFlags(false) -- If we're caught up, un-set flags
  1042.         else
  1043.             setSimFlags(true)  -- If not caught up, just re-affirm that the flags are set
  1044.         end
  1045.     end
  1046. end
  1047.  
  1048. function continueQuery()
  1049.     if cmd_line_resume then
  1050.          return true
  1051.     else
  1052.          if not cmd_line then
  1053.              writeOut("Do you want to continue the last job?")
  1054.              local yes = io.read()
  1055.              if yes == "y" then
  1056.                  return true
  1057.              else
  1058.                  return false
  1059.              end
  1060.          end
  1061.     end
  1062. end
  1063.  
  1064. 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
  1065.     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}
  1066.     if not sim_mode then
  1067.         writeProgress()
  1068.     end
  1069. end
  1070.  
  1071.  -- Command Line
  1072. function checkCommandLine() --True if arguments were passed
  1073.     if #argTable > 0 then
  1074.         cmd_line = true
  1075.         return true
  1076.     else
  1077.         cmd_line = false
  1078.         return false
  1079.     end
  1080. end
  1081.  
  1082. function needsHelp() -- True if -h is passed
  1083.     for i, v in pairs(argTable) do
  1084.         if v == "-h" or v == "-help" or v == "--help" then
  1085.             return true
  1086.         else
  1087.             return false
  1088.         end
  1089.     end
  1090. end
  1091.  
  1092. function setFlagsFromCommandLine() -- Sets count_only, chain_next_shape, and sim_mode
  1093.     for i, v in pairs(argTable) do
  1094.         if v == "-c" or v == "-cost" or v == "--cost" then
  1095.             cost_only = true
  1096.             cmd_line_cost_only = true
  1097.             writeOut("Cost Only Mode")
  1098.         end
  1099.         if v == "-z" or v == "-chain" or v == "--chain" then
  1100.             chain_next_shape = true
  1101.             writeOut("Chained Shape Mode")
  1102.         end
  1103.         if v == "-r" or v == "-resume" or v == "--resume" then
  1104.             cmd_line_resume = true
  1105.             writeOut("Resuming")
  1106.         end
  1107.         if v == "-e" or v == "-ender" or v == "--ender" then
  1108.             enderchest_refilling = true
  1109.             tempProgTable.enderchest_refilling = true
  1110.             writeOut("Enderchest Mode")
  1111.         end
  1112.         if v == "-g" or v == "-home" or v == "--home" then
  1113.             return_to_home = true
  1114.             writeOut("Will return home")
  1115.         end
  1116.     end
  1117. end
  1118.  
  1119. function setTableFromCommandLine() -- Sets progTable and tempProgTable from command line arguments
  1120.     progTable.shape = argTable[1]
  1121.     tempProgTable.shape = argTable[1]
  1122.     local paramName = "param"
  1123.     local paramName2 = paramName
  1124.     for i = 2, #argTable do
  1125.         local addOn = tostring(i - 1)
  1126.         paramName2 = paramName .. addOn
  1127.         progTable[paramName2] = argTable[i]
  1128.         tempProgTable[paramName2] = argTable[i]
  1129.     end
  1130. end
  1131.  
  1132. -- Menu, Drawing and Main functions
  1133.  
  1134. function choiceIsValidShape(choice)
  1135.     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"}
  1136.     for i = 1, #validShapes do
  1137.         if choice == validShapes[i] then
  1138.             return true
  1139.         end
  1140.     end
  1141.     return false
  1142. end
  1143.  
  1144. function choiceFunction()
  1145.     if sim_mode == false and cmd_line == false then -- If we are NOT resuming progress
  1146.         local page = 1
  1147.         choice = io.read()
  1148.         choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1149.         while ((choice == "next") or (choice == "back")) do
  1150.             if (choice == "next") then
  1151.                 if page == 1 then
  1152.                     writeMenu2()
  1153.                     page = 2
  1154.                 else
  1155.                     writeMenu()
  1156.                     page = 1
  1157.                 end
  1158.             end
  1159.             if (choice == "back") then
  1160.                 if page == 1 then
  1161.                     writeMenu2()
  1162.                     page = 2
  1163.                 else
  1164.                     writeMenu()
  1165.                     page = 1
  1166.                 end
  1167.             end
  1168.             choice = io.read()
  1169.             choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1170.         end
  1171.         if choice == "end" or choice == "exit" then
  1172.             writeOut("Goodbye.")
  1173.             return
  1174.         end
  1175.         if choice == "help" then
  1176.             getHelp()
  1177.             return
  1178.         end
  1179.         if choice == "credits" then
  1180.             showCredits()
  1181.             return
  1182.         end
  1183.         tempProgTable = {shape = choice}
  1184.         progTable = {shape = choice}
  1185.         if not choiceIsValidShape(choice) then
  1186.             writeOut(choice ..  " is not a valid shape choice.")
  1187.             return
  1188.         end
  1189.         writeOut("Building a "..choice)
  1190.         local yes = getInput("string","Want to just calculate the cost?","y","n")
  1191.         if yes == 'y' then
  1192.             cost_only = true
  1193.         end
  1194.         local yes = getInput("string","Want turtle to return to start after build?","y","n")
  1195.         if yes == 'y' then
  1196.             return_to_home = true
  1197.         end
  1198.         local yes = getInput("string","Want the turtle to refill from enderchest (slot 16)?","y","n")
  1199.         if yes == 'y' then
  1200.             enderchest_refilling = true
  1201.             tempProgTable.enderchest_refilling = true
  1202.         end
  1203.     elseif sim_mode == true then -- If we ARE resuming progress
  1204.         tempProgTable = readProgress()
  1205.         choice = tempProgTable.shape
  1206.         choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1207.         enderchest_refilling =  tempProgTable.enderchest_refilling
  1208.     elseif cmd_line == true then -- If running from command line
  1209.         if needsHelp() then
  1210.             showCmdLineHelp()
  1211.             return
  1212.         end
  1213.         choice = tempProgTable.shape
  1214.         choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
  1215.         enderchest_refilling =  tempProgTable.enderchest_refilling
  1216.         writeOut("Building a "..choice)
  1217.     end
  1218.     if not cost_only then
  1219.         turtle.select(1)
  1220.         activeSlot = 1
  1221.         if turtle.getItemCount(activeSlot) == 0 then
  1222.             if resupply then
  1223.                 writeOut("Please put building blocks in the first slot.")
  1224.             else
  1225.                 writeOut("Please put building blocks in the first slot (and more if you need them)")
  1226.             end
  1227.             while turtle.getItemCount(activeSlot) <= 1 do
  1228.                 os.sleep(.1)
  1229.             end
  1230.         end
  1231.     else
  1232.         activeSlot = 1
  1233.     end
  1234.     -- Shape selection if cascade
  1235.     -- Line based shapes
  1236.     if choice == "rectangle" then
  1237.         local depth = 0
  1238.         local width = 0
  1239.         if sim_mode == false and cmd_line == false then
  1240.             width = getInput("int","How wide does it need to be?")
  1241.             depth = getInput("int","How deep does it need to be?")
  1242.         elseif sim_mode == true or cmd_line == true then
  1243.             width = tempProgTable.param1
  1244.             depth = tempProgTable.param2
  1245.         end
  1246.         tempProgTable.param1 = width
  1247.         tempProgTable.param2 = depth
  1248.         progTable = {param1 = width, param2 = depth} -- THIS is here because we NEED to update the local table!
  1249.         rectangle(width, depth)
  1250.     end
  1251.     if choice == "square" then
  1252.         local sideLength
  1253.         if sim_mode == false and cmd_line == false then
  1254.             sideLength = getInput("int","How long does each side need to be?")
  1255.         elseif sim_mode == true or cmd_line == true then
  1256.             sideLength = tempProgTable.param1
  1257.         end
  1258.         tempProgTable.param1 = sideLength
  1259.         progTable = {param1 = sideLength}
  1260.         square(sideLength)
  1261.     end
  1262.     if choice == "line" then
  1263.         local startX = 0
  1264.         local startY = 0
  1265.         local endX = 0
  1266.         local endY = 0
  1267.         if sim_mode == false and cmd_line == false then
  1268.             writeOut("Note that the turtle's starting position is 0, 0.")
  1269.             startX = getInput("int","Where does the start X need to be?")
  1270.             startY = getInput("int","Where does the start Y need to be?")
  1271.             endX = getInput("int","Where does the end X need to be?")
  1272.             endY = getInput("int","Where does the end Y need to be?")
  1273.         elseif sim_mode == true or cmd_line == true then
  1274.             startX = tempProgTable.param1
  1275.             startY = tempProgTable.param2
  1276.             endX = tempProgTable.param3
  1277.             endY = tempProgTable.param4
  1278.         end
  1279.         tempProgTable.param1 = startX
  1280.         tempProgTable.param2 = startY
  1281.         tempProgTable.param3 = endX
  1282.         tempProgTable.param4 = endY
  1283.         progTable = {param1 = startX, param2 = startY, param3 = endX, param4 = endY}
  1284.         drawLine(endX, endY, startX, startY)
  1285.     end
  1286.     if choice == "wall" then
  1287.         local depth = 0
  1288.         local height = 0
  1289.         if sim_mode == false and cmd_line == false then
  1290.             depth = getInput("int","How deep does it need to be?")
  1291.             height = getInput("int","How high does it need to be?")
  1292.         elseif sim_mode == true or cmd_line == true then
  1293.             depth = tempProgTable.param1
  1294.             height = tempProgTable.param2
  1295.         end        
  1296.         tempProgTable.param1 = depth
  1297.         tempProgTable.param2 = height
  1298.         progTable = {param1 = depth, param2 = height}
  1299.         wall(depth, height)
  1300.     end
  1301.     if choice == "platform" then
  1302.         local width = 0
  1303.         local depth = 0
  1304.         if sim_mode == false and cmd_line == false then
  1305.             width = getInput("int","How wide does it need to be?")
  1306.             depth = getInput("int","How deep does it need to be?")
  1307.         elseif sim_mode == true or cmd_line == true then   
  1308.             width = tempProgTable.param1       
  1309.             depth = tempProgTable.param2
  1310.         end    
  1311.         tempProgTable.param1 = width
  1312.         tempProgTable.param2 = depth
  1313.         progTable = {param1 = width, param2 = depth}
  1314.         platform(width, depth)
  1315.     end
  1316.     if choice == "stair" or choice == "stairs" then
  1317.         local width = 0
  1318.         local height = 0
  1319.         if sim_mode == false and cmd_line == false then
  1320.             width = getInput("int","How wide does it need to be?")
  1321.             height = getInput("int","How high does it need to be?")
  1322.         elseif sim_mode == true or cmd_line == true then
  1323.             width = tempProgTable.param1
  1324.             height = tempProgTable.param2
  1325.         end
  1326.         tempProgTable.param1 = width
  1327.         tempProgTable.param2 = height
  1328.         progTable = {param1 = width, param2 = height}
  1329.         stair(width, height)
  1330.         special_chain = true
  1331.     end
  1332.     if choice == "cuboid" then
  1333.         local width = 0
  1334.         local depth = 0
  1335.         local height = 0
  1336.         local hollow = ""
  1337.         if sim_mode == false and cmd_line == false then
  1338.             width = getInput("int","How wide does it need to be?")
  1339.             depth = getInput("int","How deep does it need to be?")
  1340.             height = getInput("int","How high does it need to be?")
  1341.             hollow = getInput("string","Does it need to be hollow?","y","n")
  1342.         elseif sim_mode == true or cmd_line == true then
  1343.             width = tempProgTable.param1
  1344.             depth = tempProgTable.param2
  1345.             height = tempProgTable.param3
  1346.             hollow = tempProgTable.param4
  1347.         end
  1348.         tempProgTable.param1 = width
  1349.         tempProgTable.param2 = depth
  1350.         tempProgTable.param3 = height
  1351.         tempProgTable.param4 = hollow  
  1352.         progTable = {param1 = width, param2 = depth, param3 = height}
  1353.         cuboid(width, depth, height, hollow)
  1354.     end
  1355.     if choice == "pyramid" then
  1356.         local length = 0
  1357.         local hollow = ""
  1358.         if sim_mode == false and cmd_line == false then
  1359.             length = getInput("int","How long does each side of the base layer need to be?")
  1360.             hollow = getInput("string","Does it need to be hollow?","y","n")
  1361.         elseif sim_mode == true or cmd_line == true then
  1362.             length = tempProgTable.param1
  1363.             hollow = tempProgTable.param2
  1364.         end
  1365.         tempProgTable.param1 = length
  1366.         tempProgTable.param2 = hollow
  1367.         progTable = {param1 = length, param2 = hollow}
  1368.         pyramid(length, hollow)
  1369.     end
  1370.     -- Circle based shapes
  1371.     if choice == "1/2-sphere" or choice == "1/2 sphere" then
  1372.         local radius = 0
  1373.         local half = ""
  1374.         if sim_mode == false and cmd_line == false then
  1375.             radius = getInput("int","What radius does it need to be?")
  1376.             half = getInput("string","What half of the sphere does it need to be?","bottom","top")
  1377.         elseif sim_mode == true or cmd_line == true then
  1378.             radius = tempProgTable.param1
  1379.             half = tempProgTable.param2
  1380.         end
  1381.         tempProgTable.param1 = radius
  1382.         tempProgTable.param2 = half
  1383.         progTable = {param1 = radius, param2 = half}
  1384.         if half == "bottom" then
  1385.             dome("bowl", radius)
  1386.         elseif half == "top" then
  1387.             dome("dome", radius)
  1388.         end
  1389.     end
  1390.     if choice == "dome" then
  1391.         local radius = 0
  1392.         if sim_mode == false and cmd_line == false then
  1393.             radius = getInput("int","What radius does it need to be?")
  1394.         elseif sim_mode == true or cmd_line == true then
  1395.             radius = tempProgTable.param1
  1396.         end
  1397.         tempProgTable.param1 = radius
  1398.         progTable = {param1 = radius}
  1399.         dome("dome", radius)
  1400.     end
  1401.     if choice == "bowl" then
  1402.         local radius = 0
  1403.         if sim_mode == false and cmd_line == false then
  1404.             radius = getInput("int","What radius does it need to be?")
  1405.         elseif sim_mode == true or cmd_line == true then
  1406.             radius = tempProgTable.param1
  1407.         end
  1408.         tempProgTable.param1 = radius
  1409.         progTable = {param1 = radius}
  1410.         dome("bowl", radius)
  1411.     end
  1412.     if choice == "circle" then
  1413.         local radius = 0
  1414.         if sim_mode == false and cmd_line == false then
  1415.             radius = getInput("int","What radius does it need to be?")
  1416.         elseif sim_mode == true or cmd_line == true then
  1417.             radius = tempProgTable.param1
  1418.         end
  1419.         tempProgTable.param1 = radius
  1420.         progTable = {param1 = radius}
  1421.         circle(radius)
  1422.     end
  1423.     if choice == "cylinder" then
  1424.         local radius = 0
  1425.         local height = 0
  1426.         if sim_mode == false and cmd_line == false then
  1427.             radius = getInput("int","What radius does it need to be?")
  1428.             height = getInput("int","How high does it need to be?")
  1429.         elseif sim_mode == true or cmd_line == true then
  1430.             radius = tempProgTable.param1
  1431.             height = tempProgTable.param2
  1432.         end
  1433.         tempProgTable.param1 = radius
  1434.         tempProgTable.param2 = height
  1435.         progTable = {param1 = radius, param2 = height}
  1436.         cylinder(radius, height)
  1437.     end
  1438.     if choice == "sphere" then
  1439.         local radius = 0
  1440.         if sim_mode == false and cmd_line == false then
  1441.             radius = getInput("int","What radius does it need to be?")
  1442.         elseif sim_mode == true or cmd_line == true then
  1443.             radius = tempProgTable.param1
  1444.         end
  1445.         tempProgTable.param1 = radius
  1446.         progTable = {param1 = radius}
  1447.         dome("sphere", radius)
  1448.     end
  1449.     -- Polygon shapes
  1450.     if choice == "hexagon" then
  1451.         local length = 0
  1452.         if sim_mode == false and cmd_line == false then
  1453.             length = getInput("int","How long does each side need to be?")
  1454.         elseif sim_mode == true or cmd_line == true then
  1455.             length = tempProgTable.param1
  1456.         end
  1457.         tempProgTable.param1 = length
  1458.         progTable = {param1 = length}
  1459.         hexagon(length)
  1460.     end
  1461.     if choice == "octagon" then
  1462.         local length = 0
  1463.         if sim_mode == false and cmd_line == false then
  1464.             length = getInput("int","How long does each side need to be?")
  1465.         elseif sim_mode == true or cmd_line == true then
  1466.             length = tempProgTable.param1
  1467.         end
  1468.         tempProgTable.param1 = length
  1469.         progTable = {param1 = length}
  1470.         octagon(length)
  1471.     end
  1472.     if choice == "6-prism" or choice == "6 prism" then
  1473.         local length = 0
  1474.         local height = 0
  1475.         if sim_mode == false and cmd_line == false then
  1476.             length = getInput("int","How long does each side need to be?")
  1477.             height = getInput("int","How high does it need to be?")
  1478.         elseif sim_mode == true or cmd_line == true then
  1479.             length = tempProgTable.param1
  1480.             height = tempProgTable.param2
  1481.         end
  1482.         tempProgTable.param1 = length
  1483.         tempProgTable.param2 = height
  1484.         progTable = {param1 = length, param2 = height}
  1485.         sixprism(length, height)
  1486.     end
  1487.     if choice == "8-prism" or choice == "8 prism" then
  1488.         local length = 0
  1489.         local height = 0
  1490.         if sim_mode == false and cmd_line == false then
  1491.             length = getInput("int","How long does each side need to be?")
  1492.             height = getInput("int","How high does it need to be?")
  1493.         elseif sim_mode == true or cmd_line == true then
  1494.             length = tempProgTable.param1
  1495.             height = tempProgTable.param2
  1496.         end
  1497.         tempProgTable.param1 = length
  1498.         tempProgTable.param2 = height
  1499.         progTable = {param1 = length, param2 = height}
  1500.         eightprism(length, height)
  1501.     end
  1502.     if return_to_home then
  1503.         goHome() -- After all shape building has finished
  1504.     end
  1505.     writeOut("Done") -- Saves a few lines when put here rather than in each if statement
  1506. end
  1507.  
  1508. function writeMenu()
  1509.     term.clear()
  1510.     term.setCursorPos(1, 1)
  1511.     writeOut("Shape Maker 1.7 by Keridos/CupricWolf/pokemane")
  1512.     if resupply then                    -- Any ideas to make this more compact/better looking (in terms of code)?
  1513.         writeOut("Resupply Mode Active")
  1514.     elseif (resupply and can_use_gps) then
  1515.         writeOut("Resupply and GPS Mode Active")
  1516.     elseif can_use_gps then
  1517.         writeOut("GPS Mode Active")
  1518.     else
  1519.         writeOut("Standard Mode Active")
  1520.     end
  1521.     if not cmd_line then
  1522.         writeOut("What shape do you want to build? [page 1/2]");
  1523.         writeOut("next for page 2")
  1524.         writeOut("+---------+-----------+-------+-------+")
  1525.         writeOut("| square  | rectangle | wall  | line  |")
  1526.         writeOut("| cylinder| platform  | stair | cuboid|")
  1527.         writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1528.         writeOut("+---------+-----------+-------+-------+")
  1529.         writeOut("")
  1530.     end
  1531. end
  1532.  
  1533. function writeMenu2()
  1534.     term.clear()
  1535.     term.setCursorPos(1, 1)
  1536.     writeOut("Shape Maker 1.7 by Keridos/CupricWolf/pokemane")
  1537.     if resupply then                    -- Any ideas to make this more compact/better looking (in terms of code)?
  1538.         writeOut("Resupply Mode Active")
  1539.     elseif (resupply and can_use_gps) then
  1540.         writeOut("Resupply and GPS Mode Active")
  1541.     elseif can_use_gps then
  1542.         writeOut("GPS Mode Active")
  1543.     else
  1544.         writeOut("Standard Mode Active")
  1545.     end
  1546.     writeOut("What shape do you want to build? [page 2/2]");
  1547.     writeOut("back for page 1")
  1548.     writeOut("+---------+-----------+-------+-------+")
  1549.     writeOut("| hexagon | octagon   | dome  |       |")
  1550.     writeOut("| 6-prism | 8-prism   | bowl  |       |")
  1551.     writeOut("| help    | credits   | end   |       |")
  1552.     writeOut("+---------+-----------+-------+-------+")
  1553.     writeOut("")
  1554. end
  1555.  
  1556. function showCmdLineHelp()
  1557.     term.clear()
  1558.     term.setCursorPos(1, 1)
  1559.     writeOut("Command line help")
  1560.     writeOut("Usage: shape [shape-type] [param1] [param2] [param3] [param4] [-c] [-h] [-z] [-r]\n")
  1561.     writeOut("-c or -cost or --cost: Activate cost only mode\n")
  1562.     writeOut("-h or -help or --help: Show this information")
  1563.     io.read()
  1564.     writeOut("-z or -chain or --chain: Lets you chain together multiple shapes\n")
  1565.     writeOut("-g or -home or --home: Make turtle go 'home' after build\n")
  1566.     writeOut("-r or -resume or --resume: Resume the last build if possible")
  1567.     io.read()
  1568.     writeOut("-e or -ender or --ender: Activate enderchest refilling\n")
  1569.     writeOut("shape-type can be any of the shapes in the menu\n")
  1570.     writeOut("After shape-type input all of the paramaters for the shape, varies by shape\n")
  1571.     writeOut("Put any flags (-c, -h, etc.) at the end of your command")
  1572. end
  1573.  
  1574. function getHelp()
  1575.     term.clear()
  1576.     term.setCursorPos(1, 1)
  1577.     writeOut("Width is to the right of the turtle. (X-Axis)")
  1578.     writeOut("Depth is to the front of the turtle. (Y-Axis)")
  1579.     writeOut("Height is to the top of the turtle. (Z-Axis)")
  1580.     writeOut("Length is the side length of some shapes. (Squares and Polygons)")
  1581.     io.read()
  1582.     term.clear()
  1583.     term.setCursorPos(1, 1)
  1584.     local page = 1
  1585.     writeOut("What shape do you want help with? [page 1/2]");
  1586.     writeOut("next for page 2")
  1587.     writeOut("+---------+-----------+-------+-------+")
  1588.     writeOut("| square  | rectangle | wall  | line  |")
  1589.     writeOut("| cylinder| platform  | stair | cuboid|")
  1590.     writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1591.     writeOut("+---------+-----------+-------+-------+")
  1592.     writeOut("")
  1593.     choice = io.read()
  1594.     choice = string.lower(choice)
  1595.     while ((choice == "next") or (choice == "back")) do
  1596.         if (choice == "next") then
  1597.             if (page == 1) then
  1598.                 page = 2
  1599.                 term.clear()
  1600.                 term.setCursorPos(1, 1)
  1601.                 writeOut("What shape do you want help wih? [page 2/2]?");
  1602.                 writeOut("back for page 1")
  1603.                 writeOut("+---------+-----------+-------+-------+")
  1604.                 writeOut("| hexagon | octagon   | dome  |       |")
  1605.                 writeOut("| 6-prism | 8-prism   | bowl  |       |")
  1606.                 writeOut("|         |           |       |       |")
  1607.                 writeOut("+---------+-----------+-------+-------+")
  1608.                 writeOut("")
  1609.             else
  1610.                 page = 1
  1611.                 term.clear()
  1612.                 term.setCursorPos(1, 1)
  1613.                 writeOut("What shape do you want help with? [page 1/2]");
  1614.                 writeOut("next for page 2")
  1615.                 writeOut("+---------+-----------+-------+-------+")
  1616.                 writeOut("| square  | rectangle | wall  | line  |")
  1617.                 writeOut("| cylinder| platform  | stair | cuboid|")
  1618.                 writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1619.                 writeOut("+---------+-----------+-------+-------+")
  1620.                 writeOut("")
  1621.             end
  1622.         end
  1623.         if (choice == "back") then
  1624.             if (page == 1) then
  1625.                 page = 2
  1626.                 term.clear()
  1627.                 term.setCursorPos(1, 1)
  1628.                 writeOut("What shape do you want help wih? [page 2/2]?");
  1629.                 writeOut("back for page 1")
  1630.                 writeOut("+---------+-----------+-------+-------+")
  1631.                 writeOut("| hexagon | octagon   | dome  |       |")
  1632.                 writeOut("| 6-prism | 8-prism   | bowl  |       |")
  1633.                 writeOut("|         |           |       |       |")
  1634.                 writeOut("+---------+-----------+-------+-------+")
  1635.                 writeOut("")
  1636.             else
  1637.                 page = 1
  1638.                 term.clear()
  1639.                 term.setCursorPos(1, 1)
  1640.                 writeOut("What shape do you want help with? [page 1/2]");
  1641.                 writeOut("next for page 2")
  1642.                 writeOut("+---------+-----------+-------+-------+")
  1643.                 writeOut("| square  | rectangle | wall  | line  |")
  1644.                 writeOut("| cylinder| platform  | stair | cuboid|")
  1645.                 writeOut("| pyramid | 1/2-sphere| sphere| circle|")
  1646.                 writeOut("+---------+-----------+-------+-------+")
  1647.                 writeOut("")
  1648.             end
  1649.         end
  1650.         choice = io.read()
  1651.         choice = string.lower(choice)
  1652.     end
  1653.     if not choiceIsValidShape(choice) then
  1654.         writeOut(choice ..  " is not a valid shape choice.")
  1655.         return
  1656.     end
  1657.     -- If cascade time!
  1658.     if choice == "rectangle" then
  1659.         term.clear()
  1660.         term.setCursorPos(1, 1)
  1661.         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.")
  1662.     end
  1663.     if choice == "square" then
  1664.         term.clear()
  1665.         term.setCursorPos(1, 1)
  1666.         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.")
  1667.     end
  1668.     if choice == "line" then
  1669.         term.clear()
  1670.         term.setCursorPos(1, 1)
  1671.         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.")
  1672.     end
  1673.     if choice == "wall" then
  1674.         term.clear()
  1675.         term.setCursorPos(1, 1)
  1676.         writeOut("The wall is a vertical plane. The wall takes two parameters (two integers) Depth then Height.")
  1677.     end
  1678.     if choice == "platform" then
  1679.         term.clear()
  1680.         term.setCursorPos(1, 1)
  1681.         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.")
  1682.     end
  1683.     if choice == "stair" or choice == "stairs" then
  1684.         term.clear()
  1685.         term.setCursorPos(1, 1)
  1686.         writeOut("The stair or stairs are an incline of width by height. The stair takes two parameters (two integers) Width then Height.")
  1687.     end
  1688.     if choice == "cuboid" then
  1689.         term.clear()
  1690.         term.setCursorPos(1, 1)
  1691.         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).")
  1692.     end
  1693.     if choice == "1/2-sphere" or choice == "1/2 sphere" then
  1694.         term.clear()
  1695.         term.setCursorPos(1, 1)
  1696.         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).")
  1697.     end
  1698.     if choice == "dome" then
  1699.         term.clear()
  1700.         term.setCursorPos(1, 1)
  1701.         writeOut("The dome shape is a shortcut to the top half sphere. The dome takes one parameter (one integer) Diameter.")
  1702.     end
  1703.     if choice == "bowl" then
  1704.         term.clear()
  1705.         term.setCursorPos(1, 1)
  1706.         writeOut("The bowl shape is a shortcut to the bottom half sphere. The bowl takes one parameter (one integer) Diameter.")
  1707.     end
  1708.     if choice == "sphere" then
  1709.         term.clear()
  1710.         term.setCursorPos(1, 1)
  1711.         writeOut("The sphere is just that, a sphere. It is hollow. The sphere takes one parameter (one integer) Diameter.")
  1712.     end
  1713.     if choice == "circle" then
  1714.         term.clear()
  1715.         term.setCursorPos(1, 1)
  1716.         writeOut("The circle is just that, a circle. It is just a perimeter. The circle takes one parameter (one integer) Diameter.")
  1717.     end
  1718.     if choice == "cylinder" then
  1719.         term.clear()
  1720.         term.setCursorPos(1, 1)
  1721.         writeOut("The cylinder is a cylindrical tube of diameter by height. The cylinder takes two parameters (two integers) Diameter then Height.")
  1722.     end
  1723.     if choice == "pyramid" then
  1724.         term.clear()
  1725.         term.setCursorPos(1, 1)
  1726.         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).")
  1727.     end
  1728.     if choice == "hexagon" then
  1729.         term.clear()
  1730.         term.setCursorPos(1, 1)
  1731.         writeOut("The hexagon is a hexagonal perimeter. The hexagon takes one parameter (one integer) Length.")
  1732.     end
  1733.     if choice == "octagon" then
  1734.         term.clear()
  1735.         term.setCursorPos(1, 1)
  1736.         writeOut("The octagon is and octagonal perimeter. The octagon takes one parameter (one integer) Length.")
  1737.     end
  1738.     if choice == "6-prism" or choice == "6 prism" then
  1739.         term.clear()
  1740.         term.setCursorPos(1, 1)
  1741.         writeOut("The 6 prism is a hexagonal prism shaped tube. The 6 prism takes two parameters (two integers) Length then Height.")
  1742.     end
  1743.     if choice == "8-prism" or choice == "8 prism" then
  1744.         term.clear()
  1745.         term.setCursorPos(1, 1)
  1746.         writeOut("The 8 prism is an octagonal prism shaped tube. The 8 prism takes two parameters (two integers) Length then Height.")
  1747.     end
  1748. end
  1749.  
  1750. function showCredits()
  1751.     term.clear()
  1752.     term.setCursorPos(1, 1)
  1753.     writeOut("Credits for the shape builder:")
  1754.     writeOut("Based on work by Michiel, Vliekkie, and Aeolun")
  1755.     writeOut("Sphere/dome code by IMarvinTPA")
  1756.     writeOut("Additional improvements by Keridos, CupricWolf, and pokemane")
  1757. end
  1758.  
  1759. function main()
  1760.     if wrapModules()=="resupply" then
  1761.         linkToRSStation()
  1762.     end
  1763.     if checkCommandLine() then
  1764.         if needsHelp() then
  1765.             showCmdLineHelp()
  1766.             return -- Close the program after help info is shown
  1767.         end
  1768.         setFlagsFromCommandLine()
  1769.         setTableFromCommandLine()
  1770.     end
  1771.     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
  1772.         if not continueQuery() then -- If the user doesn't want to continue
  1773.             ProgressFileDelete()
  1774.             setSimFlags(false) -- Just to be safe
  1775.             writeMenu()
  1776.             choiceFunction()
  1777.         else    -- If the user wants to continue
  1778.             setSimFlags(true)
  1779.             choiceFunction()
  1780.         end
  1781.     else
  1782.         setSimFlags(false)
  1783.         writeMenu()
  1784.         choiceFunction()
  1785.     end
  1786.     if (blocks ~= 0) and (fuel ~= 0) then -- Do not show on help or credits page or when selecting end
  1787.         writeOut("Blocks used: " .. blocks)
  1788.         writeOut("Fuel used: " .. fuel)
  1789.     end
  1790.     ProgressFileDelete() -- Removes file upon successful completion of a job, or completion of a previous job.
  1791.     progTable = {}
  1792.     tempProgTable = {}
  1793. end
  1794.  
  1795. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement