Advertisement
Guest User

ComputerCraft Turtle Tower Builder

a guest
Sep 24th, 2012
4,568
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.77 KB | None | 0 0
  1.  
  2. -- Tower builder by Eli Delventhal aka demonpants, v 0.6
  3.  
  4. local tArgs = { ... }
  5. if #tArgs < 2
  6. then
  7.     print( "Usage: tower <#diameter> <#height> [round|square] [#roofHeight] [#roofDiameter] [crenellation|saddleback|apex|flat]" )
  8.     return
  9. end
  10.  
  11. -- If our diameter is too small, kick out
  12.  
  13. local diameter = tonumber( tArgs[1] )
  14. local radius = diameter / 2
  15. if radius < 1
  16. then
  17.     print( "Tower diameter must be positive" )
  18.     return
  19. end
  20.  
  21. -- If our height is too small, kick out
  22.  
  23. local height = tonumber( tArgs[2] )
  24. if height < 1
  25. then
  26.     print( "Tower height must be positive" )
  27.     return
  28. end
  29.  
  30. -- check optional parameters
  31.  
  32. local towerType = "round"
  33. if #tArgs >= 3
  34. then
  35.     towerType = tArgs[3]
  36.     if towerType ~= "round" and towerType ~= "square"
  37.     then
  38.         print("Tower type must be round or square "..towerType)
  39.         return
  40.     end
  41. end
  42.  
  43. local roofHeight = 0
  44. if #tArgs >= 4
  45. then
  46.     roofHeight = tonumber( tArgs[4] )
  47. end
  48.  
  49. local roofDiameter = 0
  50. if #tArgs >= 5
  51. then
  52.     roofDiameter = tonumber( tArgs[5] )
  53. end
  54.  
  55. local roofType = "crenellation"
  56. if roofHeight > 0 and #tArgs >= 6
  57. then
  58.     roofType = tArgs[6]
  59.     if roofType ~= "crenellation" and roofType ~= "saddleback" and roofType ~= "apex" and roofType ~= "flat"
  60.     then
  61.         print("Tower roof type myst be crenellation, saddleback, or apex")
  62.         return
  63.     end
  64. end
  65.  
  66. -- we need to store off our position and which way we're
  67. -- facing so that we can move along our way correctly
  68.  
  69. local centerX = math.floor(radius)
  70. local centerZ = centerX
  71. local startDirX = 0
  72. local startDirZ = 1
  73. local xPos = centerX
  74. local yPos = 0
  75. local zPos = centerZ
  76. local xDir = startDirX
  77. local zDir = startDirZ
  78. local placedBlockCount = 0
  79. local xPoints = {}
  80. local xPointsLength = 0
  81. local zPoints = {}
  82. local zPointsLength = 0
  83.  
  84. -- Builds below the current position if that spot is free.
  85. -- If a block is already there and it's not the same type as what's
  86. -- in our active slot, the block is dug and a new one is placed
  87. -- If we have no blocks left, returns false, otherwise returns true.
  88.  
  89. local function build()
  90.  
  91.     local itemSlot = -1
  92.     local freeSlot = -1
  93.    
  94.     -- store off the first empty slot and the first slot we can pull an item from
  95.     for n=1,9
  96.     do
  97.         if turtle.getItemCount(n) > 0
  98.         then
  99.             if itemSlot < 0
  100.             then
  101.                 itemSlot = n
  102.             end
  103.         elseif freeSlot < 0
  104.             then
  105.             freeSlot = n
  106.         end
  107.     end
  108.    
  109.     -- we have items in any slot, go ahead and build
  110.     if itemSlot >= 0
  111.     then
  112.         -- this block is not the same type as what we have, dig it out
  113.         if turtle.detectDown() and not turtle.compareDown()
  114.         then
  115.             turtle.digDown()
  116.             -- if we had a free slot and now have only 1 item in it, throw that out
  117.             if freeSlot >= 0 and turtle.getItemCount(freeSlot) == 1
  118.             then
  119.                 turtle.select(freeSlot)
  120.                 turtle.drop(1)
  121.             end
  122.         end
  123.         -- we know we have an empty spot, place the block
  124.         turtle.select(itemSlot)
  125.         turtle.placeDown()
  126.         placedBlockCount = placedBlockCount + 1
  127.         return true
  128.     end
  129.    
  130.     -- no items in any slots, we can't build
  131.     return false
  132. end
  133.  
  134. -- sorts the movement coordinates so that the turtle is moving optimally
  135.  
  136. local function sortMovementCoordinates()
  137.    
  138.     -- first find the one closest to the turtle and put that in front
  139.     --[[ local closest = 0
  140.     local closestDist = math.abs( xPoints[closest] - xPos ) + math.abs( zPoints[closest] - zPos )
  141.     for i = 1, xPointsLength - 1
  142.     do
  143.         local dist = math.abs( xPoints[i] - xPos ) + math.abs( zPoints[i] - zPos )
  144.         if dist < closestDist
  145.         then
  146.             closest = i
  147.             closestDist = dist
  148.         end
  149.     end
  150.     local swap = xPoints[0]
  151.     xPoints[0] = xPoints[closest]
  152.     xPoints[closest] = swap
  153.     swap = zPoints[0]
  154.     zPoints[0] = zPoints[closest]
  155.     zPoints[closest] = swap ]]
  156.    
  157.     -- next sort all points to be the one closest to the previous point
  158.     for i = 0, xPointsLength - 2
  159.     do
  160.         closest = i + 1
  161.         closestDist = math.abs( xPoints[closest] - xPoints[i] ) + math.abs( zPoints[closest] - zPoints[i] )
  162.        
  163.         for j = i + 2, xPointsLength - 1
  164.         do
  165.             local dist = math.abs( xPoints[j] - xPoints[i] ) + math.abs( zPoints[j] - zPoints[i] )
  166.             if dist < closestDist
  167.             then
  168.                 closest = j
  169.                 closestDist = dist
  170.             end
  171.         end
  172.         swap = xPoints[i+1]
  173.         xPoints[i+1] = xPoints[closest]
  174.         xPoints[closest] = swap
  175.         swap = zPoints[i+1]
  176.         zPoints[i+1] = zPoints[closest]
  177.         zPoints[closest] = swap
  178.     end
  179. end
  180.  
  181. -- populates the two lists of movement coordinates with X and Y coordinates for a round tower
  182.  
  183. local function populateMovementCoordinatesRound()
  184.     xPoints = {}
  185.     xPointsLength = 0
  186.     zPoints = {}
  187.     zPointsLength = 0
  188.     local d = 3 - (2 * radius)
  189.     local x = 0
  190.     local z = math.floor(radius);
  191.    
  192.     -- use the midpoint circle algorithm to construct a list of exactly which points we need
  193.     repeat
  194.         xPoints[xPointsLength] = centerX + x;
  195.         zPoints[zPointsLength] = centerZ + z;
  196.         xPointsLength = xPointsLength + 1
  197.         zPointsLength = zPointsLength + 1
  198.        
  199.         xPoints[xPointsLength] = centerX + x;
  200.         zPoints[zPointsLength] = centerZ - z;
  201.         xPointsLength = xPointsLength + 1
  202.         zPointsLength = zPointsLength + 1
  203.        
  204.         xPoints[xPointsLength] = centerX - x;
  205.         zPoints[zPointsLength] = centerZ + z;
  206.         xPointsLength = xPointsLength + 1
  207.         zPointsLength = zPointsLength + 1
  208.        
  209.         xPoints[xPointsLength] = centerX - x;
  210.         zPoints[zPointsLength] = centerZ - z;
  211.         xPointsLength = xPointsLength + 1
  212.         zPointsLength = zPointsLength + 1
  213.        
  214.         xPoints[xPointsLength] = centerX + z;
  215.         zPoints[zPointsLength] = centerZ + x;
  216.         xPointsLength = xPointsLength + 1
  217.         zPointsLength = zPointsLength + 1
  218.        
  219.         xPoints[xPointsLength] = centerX + z;
  220.         zPoints[zPointsLength] = centerZ - x;
  221.         xPointsLength = xPointsLength + 1
  222.         zPointsLength = zPointsLength + 1
  223.        
  224.         xPoints[xPointsLength] = centerX - z;
  225.         zPoints[zPointsLength] = centerZ + x;
  226.         xPointsLength = xPointsLength + 1
  227.         zPointsLength = zPointsLength + 1
  228.        
  229.         xPoints[xPointsLength] = centerX - z;
  230.         zPoints[zPointsLength] = centerZ - x;
  231.         xPointsLength = xPointsLength + 1
  232.         zPointsLength = zPointsLength + 1
  233.        
  234.         if d < 0
  235.         then
  236.             d = d + (4 * x) + 6
  237.         else
  238.             d = d + 4 * (x - z) + 10
  239.             z = z - 1
  240.         end
  241.        
  242.         x = x + 1
  243.     until x > z
  244. end
  245.  
  246. -- populates the two lists of movement coordinates with X and Y coordinates for a square tower
  247.  
  248. local function populateMovementCoordinatesSquare()
  249.     xPoints = {}
  250.     xPointsLength = 0
  251.     zPoints = {}
  252.     zPointsLength = 0
  253.    
  254.     local left = math.floor( diameter / 2)
  255.     local right = math.ceil( diameter / 2)
  256.    
  257.     for i = 0, diameter - 1
  258.     do
  259.         xPoints[xPointsLength] = 0
  260.         zPoints[zPointsLength] = i
  261.         xPointsLength = xPointsLength + 1
  262.         zPointsLength = zPointsLength + 1
  263.        
  264.         xPoints[xPointsLength] = diameter - 1
  265.         zPoints[zPointsLength] = i
  266.         xPointsLength = xPointsLength + 1
  267.         zPointsLength = zPointsLength + 1
  268.        
  269.         xPoints[xPointsLength] = i
  270.         zPoints[zPointsLength] = 0
  271.         xPointsLength = xPointsLength + 1
  272.         zPointsLength = zPointsLength + 1
  273.  
  274.         xPoints[xPointsLength] = i
  275.         zPoints[zPointsLength] = diameter - 1
  276.         xPointsLength = xPointsLength + 1
  277.         zPointsLength = zPointsLength + 1
  278.     end
  279. end
  280.  
  281. -- populates the two lists of movement coordinates with X and Y coordinates for crenellations
  282.  
  283. local function populateMovementCoordinatesRoofCrenellations()
  284.    
  285. end
  286.  
  287. -- the turtle will turn towards the passed direction
  288. -- returns true if he is facing that way, false if he needs to keep turning
  289.  
  290. local function turnTo( x, z )
  291.    
  292.     --       0,1
  293.     -- -1,0      1,0
  294.     --      0,-1
  295.    
  296.     -- early out in case we're already facing that way
  297.     if xDir == x and zDir == z
  298.     then
  299.         return true
  300.     end
  301.    
  302.     -- facing up or down
  303.     if xDir == 0
  304.     then
  305.         -- want to face right
  306.         if x == 1
  307.         then
  308.             if zDir == -1
  309.             then
  310.                 turtle.turnLeft()
  311.             else
  312.                 turtle.turnRight()
  313.             end
  314.             xDir = 1
  315.             zDir = 0
  316.         -- want to face left
  317.         else
  318.             if zDir == -1
  319.             then
  320.                 turtle.turnRight()
  321.             else
  322.                 turtle.turnLeft()
  323.             end
  324.             xDir = -1
  325.             zDir = 0
  326.         end
  327.     -- facing left or right
  328.     else
  329.         -- want to face up
  330.         if z == 1
  331.         then
  332.             if xDir == -1
  333.             then
  334.                 turtle.turnRight()
  335.             else
  336.                 turtle.turnLeft()
  337.             end
  338.             xDir = 0
  339.             zDir = 1
  340.         -- want to face down
  341.         else
  342.             if xDir == -1
  343.             then
  344.                 turtle.turnLeft()
  345.             else
  346.                 turtle.turnRight()
  347.             end
  348.             xDir = 0
  349.             zDir = -1
  350.         end
  351.     end
  352.    
  353.     -- if we're now facing that way, return true
  354.     if xDir == x and zDir == z
  355.     then
  356.         return true
  357.     end
  358.    
  359.     return false
  360.    
  361. end
  362.  
  363. -- the turtle will attempt to move to the passed location
  364. -- returns true if he got there or was blocked, false if he needs to keep moving
  365.  
  366. local function moveTo( x, z )
  367.        
  368.     -- early out in case we're already there
  369.     if xPos == x and zPos == z
  370.     then
  371.         return true
  372.     end
  373.        
  374.     -- first move along x, then along z
  375.     if xPos ~= x
  376.     then
  377.         if xPos > x
  378.         then
  379.             if turnTo(-1,0)
  380.             then
  381.                 if turtle.forward()
  382.                 then
  383.                     xPos = xPos - 1
  384.                 end
  385.             end
  386.         else
  387.             if turnTo(1,0)
  388.             then
  389.                 if turtle.forward()
  390.                 then
  391.                     xPos = xPos + 1
  392.                 end
  393.             end
  394.         end
  395.     elseif zPos ~= z
  396.     then
  397.         if zPos > z
  398.         then
  399.             if turnTo(0,-1)
  400.             then
  401.                 if turtle.forward()
  402.                 then
  403.                     zPos = zPos - 1
  404.                 end
  405.             end
  406.         else
  407.             if turnTo(0,1)
  408.             then
  409.                 if turtle.forward()
  410.                 then
  411.                     zPos = zPos + 1
  412.                 end
  413.             end
  414.         end
  415.     end
  416.        
  417.     if xPos == x and zPos == z
  418.     then
  419.         return true
  420.     end
  421.    
  422.     return false
  423.    
  424. end
  425.  
  426. -- //////////////////////////// start of real program ///////////////////////////// --
  427.  
  428. -- populate the list of points of where we need to go
  429.  
  430. if towerType == "round"
  431. then
  432.     populateMovementCoordinatesRound()
  433. else
  434.     populateMovementCoordinatesSquare()
  435. end
  436.  
  437. sortMovementCoordinates()
  438.  
  439. -- loop through our height until we finish, run out of blocks, or get stuck
  440.  
  441. local success = true
  442. for yPos = 0, height - 1
  443. do
  444.     -- we will be building below for easy unobstructed movement
  445.     turtle.up()
  446.     yPos = yPos + 1
  447.        
  448.     -- move to all the points
  449.     for i = 0, xPointsLength - 1
  450.     do
  451.         -- keep trying to move to the nearest point
  452.         local tries = 0
  453.        
  454.         while not moveTo(xPoints[i], zPoints[i])
  455.         do
  456.             tries = tries + 1
  457.             if tries > diameter * 2
  458.             then
  459.                 print( "Failed to reach destination, giving up." )
  460.                 success = false
  461.                 break
  462.             end
  463.         end
  464.        
  465.         if not success
  466.         then
  467.             break
  468.         end
  469.        
  470.         -- we are at the next point, build
  471.         if not build()
  472.         then
  473.             print( "Ran out of blocks, stopping.")
  474.             success = false
  475.             break
  476.         end
  477.     end
  478.    
  479.     if not success
  480.     then
  481.         break
  482.     end
  483.    
  484.     -- we finished this floor successfully, yay
  485.    
  486. end
  487.  
  488. -- we have built the entire tower, now build the roof
  489.  
  490. if success and roofHeight > 0
  491. then
  492.     print("Walls completed. Building roof.")
  493.    
  494.    
  495. end
  496.  
  497. -- move back to the center
  498.  
  499. local tries = 0
  500. while not moveTo(centerX, centerZ) or not turnTo(startDirX, startDirZ)
  501. do
  502.     tries = tries + 1
  503.     if tries > diameter * 2
  504.     then
  505.         break
  506.     end
  507. end
  508.  
  509. if success
  510. then
  511.     print("Tower completed.")
  512. else
  513.     turtle.down() -- go down so we can try again
  514. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement