Advertisement
Keridos

Shape Builder Computercraft

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