Advertisement
princejoogie

builder.lua

Apr 25th, 2025 (edited)
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.26 KB | Source Code | 0 0
  1. --width and height of maze, must be odd
  2. w = 15
  3. h = 9
  4. d = 15
  5.  
  6. --To keep track of current position within the maze
  7. --Z is height
  8. curX = 0
  9. curY = 0
  10. curZ = 0 -- maze relative z
  11. worldZ = 0 --world relative z
  12.  
  13. --These are maze relative N/S/E/W
  14. --Wherever you turtle is pointing when you start the maze is "north"
  15. --Turtle will start in the 'Southwest' corner of the maze
  16. -- 0=N 1=E 2=S 3=W
  17. curRotation = 0
  18.  
  19. math.randomseed(os.time())
  20. --math.randomseed(5)
  21.  
  22. --The light field below is only for debugging purposes
  23. --You can remove it for performance reasons
  24. cells = {}
  25. --initialize cells
  26. for i = 0, w - 1 do
  27.     cells[i] = {}
  28.     for j = 0, d - 1 do
  29.         cells[i][j] = {}
  30.         for k = 0, h - 1 do
  31.             cell = { visited = false, x = i, y = j, z = k, light = false }
  32.             cells[i][j][k] = cell
  33.         end
  34.     end
  35. end
  36.  
  37. --neighbors are two and only two cells away in cardinal directions
  38. --this leaves the perimeter maze walls solid
  39. --we tag each neighbor as vertical or not so we can go vertical less often
  40. --for a more pleasant to navigate maze
  41. function getNeighbors(cell)
  42.     neighbors = {}
  43.     count = 0
  44.     x = cell.x
  45.     y = cell.y
  46.     z = cell.z
  47.     if x + 2 < w - 1 then
  48.         neighbor = { cell = cells[x + 2][y][z], vertical = false }
  49.         neighbors[count] = neighbor
  50.         count = count + 1
  51.     end
  52.     if x - 2 >= 1 then
  53.         neighbor = { cell = cells[x - 2][y][z], vertical = false }
  54.         neighbors[count] = neighbor
  55.         count = count + 1
  56.     end
  57.     if y + 2 < d - 1 then
  58.         neighbor = { cell = cells[x][y + 2][z], vertical = false }
  59.         neighbors[count] = neighbor
  60.         count = count + 1
  61.     end
  62.     if y - 2 >= 1 then
  63.         neighbor = { cell = cells[x][y - 2][z], vertical = false }
  64.         neighbors[count] = neighbor
  65.         count = count + 1
  66.     end
  67.     if z + 2 < h - 1 then
  68.         neighbor = { cell = cells[x][y][z + 2], vertical = true }
  69.         neighbors[count] = neighbor
  70.         count = count + 1
  71.     end
  72.     if z - 2 >= 1 then
  73.         neighbor = { cell = cells[x][y][z - 2], vertical = true }
  74.         neighbors[count] = neighbor
  75.         count = count + 1
  76.     end
  77.  
  78.     return neighbors
  79. end
  80.  
  81. --get a random neighbor cell that is unvisited
  82. function getRandomUnvisitedNeighbor(cell)
  83.     neighbors = getNeighbors(cell)
  84.     unvisitedNeighbors = {}
  85.     count = 0
  86.  
  87.     for k, v in pairs(neighbors) do
  88.         if v.cell.visited == false then
  89.             unvisitedNeighbors[count] = v
  90.             count = count + 1
  91.         end
  92.     end
  93.  
  94.     --This holds off on vertical path choices until the last minute
  95.     --So there are less up and down movements which are tiresome
  96.     --for the player to navigate
  97.     --you can just toss this if you prefer not to do this
  98.     if count > 2 then
  99.         for i = count - 1, 0, -1 do
  100.             neighbor = unvisitedNeighbors[i]
  101.             if neighbor.vertical == true then
  102.                 table.remove(unvisitedNeighbors, i)
  103.                 count = count - 1
  104.             end
  105.         end
  106.     end
  107.  
  108.     if count == 0 then
  109.         return nil
  110.     end
  111.  
  112.     --get a random neihgbor
  113.     r = math.random(count) - 1
  114.     return unvisitedNeighbors[r].cell
  115. end
  116.  
  117. --given two neighboring cells, get the cell between them
  118. function cellBetween(cell1, cell2)
  119.     if cell1.x > cell2.x then
  120.         return cells[cell1.x - 1][cell1.y][cell1.z]
  121.     end
  122.  
  123.     if cell1.x < cell2.x then
  124.         return cells[cell1.x + 1][cell1.y][cell1.z]
  125.     end
  126.  
  127.     if cell1.y > cell2.y then
  128.         return cells[cell1.x][cell1.y - 1][cell1.z]
  129.     end
  130.  
  131.     if cell1.y < cell2.y then
  132.         return cells[cell1.x][cell1.y + 1][cell1.z]
  133.     end
  134.  
  135.     if cell1.z > cell2.z then
  136.         return cells[cell1.x][cell1.y][cell1.z - 1]
  137.     end
  138.  
  139.     if cell1.z < cell2.z then
  140.         return cells[cell1.x][cell1.y][cell1.z + 1]
  141.     end
  142. end
  143.  
  144. --the main recursive function to traverse the maze
  145. function recur(curCell)
  146.     --mark current cell as visited
  147.     curCell.visited = true
  148.  
  149.     --check each neighbor cell
  150.     for i = 1, 6 do
  151.         nCell = getRandomUnvisitedNeighbor(curCell)
  152.         if nCell ~= nil then
  153.             -- clear the cell between the neighbors
  154.             bCell = cellBetween(curCell, nCell)
  155.             bCell.visited = true
  156.             --push current cell onto the stack and move on the neighbor cell
  157.             recur(nCell)
  158.         end
  159.     end
  160. end
  161.  
  162. --start point needs to be inside the perimeter
  163. --and odd
  164. recur(cells[1][1][1])
  165.  
  166. --Now we are done with the maze algorithm, and have a maze complete
  167. --in memory in the cells table
  168. --We must being building it with our turtle
  169.  
  170. lightSlot = 1 --inventory slot for lights
  171. ladderSlot = 2 --inventory slot for ladders
  172. lightCount = 0 --how many blocks since we last placed a light?
  173. lightThreshold = 4 --how often to place lights
  174.  
  175. --For debugging
  176. function printWorldLocation()
  177.     print("World: (" .. curX .. "," .. curY .. "," .. worldZ .. ")")
  178. end
  179.  
  180. function printMazeLocation()
  181.     print("Maze: (" .. curX .. "," .. curY .. "," .. curZ .. ")")
  182. end
  183.  
  184. --find a slot with building material in it
  185. function selectBlock()
  186.     for i = 3, 16 do
  187.         if turtle.getItemCount(i) > 0 then
  188.             turtle.select(i)
  189.             return true
  190.         end
  191.     end
  192.     return false
  193. end
  194.  
  195. --Place a block, first checking inventory
  196. function blockDown()
  197.     checkInventory()
  198.     turtle.select(3)
  199.     if turtle.getItemCount() == 0 then
  200.         selectBlock()
  201.     end
  202.     turtle.placeDown()
  203. end
  204.  
  205. --light can be anything that will place down on the floors
  206. function placeLight()
  207.     if lightCount > lightThreshold then
  208.         if curZ + 1 < h then
  209.             --we have to much sure this current block has no vertical passage
  210.             --above or below it as torch will interfere with ladder
  211.             if cells[curX][curY][curZ + 1].visited == false then
  212.                 if cells[curX][curY][curZ - 1].visited == false then
  213.                     turtle.select(lightSlot)
  214.                     turtle.placeDown()
  215.  
  216.                     --below is for debugging only
  217.                     cells[curX][curY][curZ].light = true
  218.  
  219.                     lightCount = 0
  220.                 end
  221.             end
  222.         end
  223.     else
  224.         lightCount = lightCount + 1
  225.     end
  226. end
  227.  
  228. --We always use these to turn to keep track of rotation
  229. function turnRight()
  230.     turtle.turnRight()
  231.     curRotation = (curRotation + 1) % 4
  232. end
  233.  
  234. function turnLeft()
  235.     turtle.turnLeft()
  236.     curRotation = (curRotation - 1) % 4
  237. end
  238.  
  239. --Will orient to the direction specified
  240. function orient(direction)
  241.     while curRotation ~= direction do
  242.         turnRight()
  243.     end
  244. end
  245.  
  246. --We use this to go forward to keep track of our x/y position
  247. function forward()
  248.     turtle.forward()
  249.     if curRotation == 0 then
  250.         curY = curY + 1
  251.     elseif curRotation == 2 then
  252.         curY = curY - 1
  253.     elseif curRotation == 1 then
  254.         curX = curX + 1
  255.     elseif curRotation == 3 then
  256.         curX = curX - 1
  257.     end
  258. end
  259.  
  260. --And we use these to go up and down to keep track of our Z position
  261. function up()
  262.     worldZ = worldZ + 1
  263.     turtle.up()
  264. end
  265.  
  266. function down()
  267.     worldZ = worldZ - 1
  268.     turtle.down()
  269. end
  270.  
  271. function turnAroundOut()
  272.     --if pointing "north" turn right
  273.     if curRotation == 0 then
  274.         turnRight()
  275.         forward()
  276.         turnRight()
  277.     else
  278.         turnLeft()
  279.         forward()
  280.         turnLeft()
  281.     end
  282. end
  283.  
  284. --when going back the other way
  285. function turnAroundIn()
  286.     if curRotation == 2 then
  287.         turnRight()
  288.         forward()
  289.         turnRight()
  290.     else
  291.         turnLeft()
  292.         forward()
  293.         turnLeft()
  294.     end
  295. end
  296.  
  297. --Descends into vertical passages
  298. --places ladders as it comes back up
  299. function placeLadder()
  300.     checkInventory()
  301.     turtle.select(ladderSlot)
  302.     down()
  303.     down()
  304.     turtle.placeDown()
  305.     up()
  306.     turtle.placeDown()
  307.     up()
  308.     turtle.placeDown()
  309. end
  310.  
  311. function placeFloorLayerOut()
  312.     print("FloorLayerOut")
  313.  
  314.     if curZ ~= 0 then
  315.         up()
  316.         turnRight()
  317.         turnRight()
  318.     end
  319.     for x = 0, w - 1 do
  320.         for y = 0, d - 1 do
  321.             if cells[curX][curY][curZ].visited == false then
  322.                 blockDown()
  323.             end
  324.             if y < d - 1 then
  325.                 forward()
  326.             end
  327.         end
  328.         if x < w - 1 then
  329.             turnAroundOut()
  330.         end
  331.     end
  332. end
  333.  
  334. function placeFloorLayerIn()
  335.     print("FloorLayerIn")
  336.     up()
  337.     if curZ ~= 0 then
  338.         turnRight()
  339.         turnRight()
  340.     end
  341.     for x = w - 1, 0, -1 do
  342.         for y = d - 1, 0, -1 do
  343.             if cells[curX][curY][curZ].visited == false then
  344.                 blockDown()
  345.             end
  346.             if y > 0 then
  347.                 forward()
  348.             end
  349.         end
  350.         if x > 0 then
  351.             turnAroundIn()
  352.         end
  353.     end
  354. end
  355.  
  356. function placeWallLayer1In()
  357.     print("wallLayer1In")
  358.     up()
  359.     turnRight()
  360.     turnRight()
  361.     for x = w - 1, 0, -1 do
  362.         for y = d - 1, 0, -1 do
  363.             if cells[curX][curY][curZ].visited then
  364.                 placeLight()
  365.             else
  366.                 blockDown()
  367.             end
  368.             if y > 0 then
  369.                 forward()
  370.             end
  371.         end
  372.         if x > 0 then
  373.             turnAroundIn()
  374.         end
  375.     end
  376. end
  377.  
  378. function placeWallLayer2Out()
  379.     print("wallLayer2Out")
  380.     up()
  381.     turnRight()
  382.     turnRight()
  383.     for x = 0, w - 1 do
  384.         for y = 0, d - 1 do
  385.             if cells[curX][curY][curZ].visited == false then
  386.                 blockDown()
  387.             end
  388.             if y < d - 1 then
  389.                 forward()
  390.             end
  391.         end
  392.         if x < w - 1 then
  393.             turnAroundOut()
  394.         end
  395.     end
  396. end
  397.  
  398. --This could be made more efficient
  399. --Turtle could go directly to each vertical passage
  400. function placeLaddersOut()
  401.     print("placeLaddersOut")
  402.     if curZ == 0 then
  403.         return
  404.     end
  405.     turnRight()
  406.     turnRight()
  407.     for x = 0, w - 1 do
  408.         for y = 0, d - 1 do
  409.             if cells[curX][curY][curZ].visited then
  410.                 placeLadder()
  411.             end
  412.             if y < d - 1 then
  413.                 forward()
  414.             end
  415.         end
  416.         if x < w - 1 then
  417.             turnAroundOut()
  418.         end
  419.     end
  420. end
  421.  
  422. --checks if we are running low on blocks, torches, or ladders
  423. function checkInventory()
  424.     --check building blocks
  425.     totalBlocks = 0
  426.     for i = 3, 16 do
  427.         totalBlocks = totalBlocks + turtle.getItemCount(i)
  428.     end
  429.  
  430.     --check torches
  431.     torchCount = turtle.getItemCount(1)
  432.  
  433.     --check ladders
  434.     ladderCount = turtle.getItemCount(2)
  435.  
  436.     if totalBlocks < 5 or torchCount < 5 or ladderCount < 5 then
  437.         returnToOrigin()
  438.         getMoreBlocks()
  439.         resumeBuild()
  440.     end
  441. end
  442.  
  443. --resume coordinates
  444. resX = 0
  445. resY = 0
  446. resZ = 0
  447. resRotation = 0
  448.  
  449. --returns to starting chest
  450. function returnToOrigin()
  451.     resX = curX
  452.     resY = curY
  453.     resZ = worldZ
  454.     resRotation = curRotation
  455.  
  456.     --point south then go past the edge of the maze
  457.     orient(2)
  458.     for i = 0, resY do
  459.         forward()
  460.     end
  461.  
  462.     --point west then go to point above chest
  463.     orient(3)
  464.     for i = 0, resX - 1 do
  465.         forward()
  466.     end
  467.  
  468.     --drop down to above the chest
  469.     for i = 0, resZ - 1 do
  470.         down()
  471.     end
  472. end
  473.  
  474. --fill up on all 3 resources
  475. function getMoreBlocks()
  476.     --get building blocks from 1st chest
  477.     while turtle.suckDown(64) do
  478.     end
  479.  
  480.     --get torches from 2nd chest which is assumed to be 2 blocks east
  481.     --point east
  482.     orient(1)
  483.     forward()
  484.     forward()
  485.     turtle.select(1)
  486.     turtle.suckDown(64 - turtle.getItemCount()) --just enough to fill upt he stack
  487.  
  488.     --get ladders from 3rd chest assumed to be 2 more blocks east
  489.     forward()
  490.     forward()
  491.     turtle.select(2)
  492.     turtle.suckDown(64 - turtle.getItemCount()) --just enough
  493.  
  494.     --point west and go back to above the start chest
  495.     orient(3)
  496.     forward()
  497.     forward()
  498.     forward()
  499.     forward()
  500. end
  501.  
  502. --return to the position we left off
  503. function resumeBuild()
  504.     --back up
  505.     for i = 0, resZ - 1 do
  506.         up()
  507.     end
  508.  
  509.     --point east
  510.     orient(1)
  511.     for i = 0, resX - 1 do
  512.         forward()
  513.     end
  514.  
  515.     orient(0)
  516.     for i = 0, resY do
  517.         forward()
  518.     end
  519.     --resume original rotation
  520.     orient(resRotation)
  521. end
  522.  
  523. --prints ton of text representing maze state
  524. function fullDebug()
  525.     for z = 0, h - 1 do
  526.         for y = 0, d - 1 do
  527.             for x = 0, w - 1 do
  528.                 if cells[x][y][z].light == true and cells[x][y][z].visited == false then
  529.                     io.write("(" .. x .. "," .. y .. "," .. z .. "):FF") --if you see this something went wrong
  530.                 elseif cells[x][y][z].light then
  531.                     io.write("(" .. x .. "," .. y .. "," .. z .. "):**")
  532.                 elseif cells[x][y][z].visited == false then
  533.                     io.write("(" .. x .. "," .. y .. "," .. z .. "):XX")
  534.                 else
  535.                     io.write("(" .. x .. "," .. y .. "," .. z .. "):  ")
  536.                 end
  537.             end
  538.             io.write("\n")
  539.         end
  540.         io.write("\n")
  541.     end
  542. end
  543.  
  544. --quick text representation of each layer of the maze
  545. function debug()
  546.     for z = 0, h - 1 do
  547.         for y = 0, d - 1 do
  548.             for x = 0, w - 1 do
  549.                 if (cells[x][y][z].light == true) and (cells[x][y][z].visited == false) then
  550.                     io.write("FF") --if you see this something went wrong
  551.                 elseif cells[x][y][z].light == true then
  552.                     io.write("**")
  553.                 elseif cells[x][y][z].visited == false then
  554.                     io.write("XX")
  555.                 else
  556.                     io.write("  ")
  557.                 end
  558.             end
  559.             io.write("\n")
  560.         end
  561.         io.write("\n")
  562.     end
  563. end
  564.  
  565. hush = true --silences stub api prints, has no effect in game
  566.  
  567. turtle.refuel()
  568. turtle.forward() --move off the chest to starting position of maze
  569. placeFloorLayerOut()
  570. curZ = curZ + 1
  571. placeWallLayer1In()
  572. placeWallLayer2Out()
  573. while true do
  574.     print("loopstart")
  575.  
  576.     curZ = curZ + 1
  577.     placeFloorLayerIn()
  578.  
  579.     if curZ == h - 1 then
  580.         break
  581.     end
  582.  
  583.     placeLaddersOut()
  584.     curZ = curZ + 1
  585.  
  586.     placeWallLayer1In()
  587.     placeWallLayer2Out()
  588.  
  589.     if turtle.getFuelLevel() == 0 then
  590.         turtle.refuel()
  591.     end
  592. end
  593.  
  594. returnToOrigin()
  595.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement