dealingwith

Tower Builder

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