Advertisement
CaptainSpaceCat

2D Procedural Maze Generator

Jun 25th, 2015
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.82 KB | None | 0 0
  1. local w, h = term.getSize()
  2. local events
  3. local midW, midH = math.floor(w/2), math.floor(h/2)
  4. local rooms = {
  5.     [1] = {false, true, true, true},
  6.     [2] = {true, false, true, true},
  7.     [3] = {true, true, false, true},
  8.     [4] = {true, true, true, false},
  9.     [5] = {false, false, true, true},
  10.     [6] = {true, false, false, true},
  11.     [7] = {true, true, false, false},
  12.     [8] = {false, true, true, false},
  13.     [9] = {false, true, false, true},
  14.     [10] = {true, false, true, false},
  15.     [11] = {false, false, false, true},
  16.     [12] = {true, false, false, false},
  17.     [13] = {false, true, false, false},
  18.     [14] = {false, false, true, false},
  19.     [15] = {false, false, false, false}
  20. }
  21.  
  22. --[[local available = {
  23.     ["1"] = {1},
  24.     ["2"] = {2},
  25.     ["3"] = {3},
  26.     ["4"] = {4},
  27.     ["12"] = {1, 2, 5},
  28.     ["23"] = {2, 3, 6},
  29.     ["34"] = {3, 4, 7},
  30.     ["14"] = {1, 4, 8},
  31.     ["13"] = {1, 3, 9},
  32.     ["24"] = {2, 4, 10},
  33.     ["123"] = {1, 2, 3, 5, 6, 11},
  34.     ["234"] = {2, 3, 4, 6, 7, 12},
  35.     ["134"] = {1, 3, 4, 7, 8, 13},
  36.     ["124"] = {1, 2, 4, 5, 8, 14},
  37.     ["1234"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
  38. }]]
  39.  
  40. local available = {
  41.     ["1"] = {1},
  42.     ["2"] = {2},
  43.     ["3"] = {3},
  44.     ["4"] = {4},
  45.     ["12"] = {1, 2},
  46.     ["23"] = {2, 3},
  47.     ["34"] = {3, 4},
  48.     ["14"] = {1, 4},
  49.     ["13"] = {1, 3},
  50.     ["24"] = {2, 4},
  51.     ["123"] = {1, 2, 3},
  52.     ["234"] = {2, 3, 4},
  53.     ["134"] = {1, 3, 4},
  54.     ["124"] = {1, 2, 4},
  55.     ["1234"] = {1, 2, 3, 4}
  56. }
  57.  
  58. function draw(words,x,y,txtcol,backcol)
  59.         local w,h = term.getSize()
  60.         words = tostring(words)
  61.         words = words or ""
  62.         txtcol = txtcol or colors.white
  63.         backcol = backcol or colors.black
  64.         term.setCursorPos(x, y)
  65.         term.setTextColor(txtcol)
  66.         term.setBackgroundColor(backcol)
  67.         write(words)
  68. end
  69.  
  70. function mazeGenProcedural(mapW, mapH)
  71.         local maze = {}
  72.     local list = {}
  73.         for x = 1, mapW do
  74.                 maze[x] = {}
  75.                 for y = 1, mapH do
  76.                         maze[x][y] = {}
  77.             list[#list + 1] = {x, y}
  78.                         for i = 1, 4 do
  79.                                 maze[x][y][i] = true
  80.                         end
  81.                 end
  82.         end
  83.     while #list > 0 do
  84.         local current = table.remove(list, math.random(1, #list))
  85.         local usableCells = ""
  86.         if current[2] > 1 and not (maze[current[1]][current[2] - 1][1] and maze[current[1]][current[2] - 1][2] and maze[current[1]][current[2] - 1][3] and maze[current[1]][current[2] - 1][4]) then
  87.             usableCells = usableCells .. "1"
  88.         end
  89.         if current[1] < mapW and not (maze[current[1] + 1][current[2]][1] and maze[current[1] + 1][current[2]][2] and maze[current[1] + 1][current[2]][3] and maze[current[1] + 1][current[2]][4]) then
  90.             usableCells = usableCells .. "2"
  91.         end
  92.         if current[2] < mapH and not (maze[current[1]][current[2] + 1][1] and maze[current[1]][current[2] + 1][2] and maze[current[1]][current[2] + 1][3] and maze[current[1]][current[2] + 1][4]) then
  93.             usableCells = usableCells .. "3"
  94.         end
  95.         if current[1] > 1 and not (maze[current[1] - 1][current[2]][1] and maze[current[1] - 1][current[2]][2] and maze[current[1] - 1][current[2]][3] and maze[current[1] - 1][current[2]][4]) then
  96.             usableCells = usableCells .. "4"
  97.         end
  98.         if usableCells == "" then
  99.             if current[2] > 1 then
  100.                 usableCells = usableCells .. "1"
  101.             elseif current[1] < mapW then
  102.                 usableCells = usableCells .. "2"
  103.             elseif current[2] < mapH then
  104.                 usableCells = usableCells .. "3"
  105.             elseif current[1] > 1 then
  106.                 usableCells = usableCells .. "4"
  107.             end
  108.         end
  109.         usableCells = rooms[available[usableCells][math.random(1, #available[usableCells])]]
  110.         for i = 1, 4 do
  111.             if maze[current[1]][current[2]][i] then
  112.                 maze[current[1]][current[2]][i] = usableCells[i]   
  113.             end
  114.             if not usableCells[i] then
  115.                 if current[2] > 1 and i == 1 then
  116.                     maze[current[1]][current[2] - 1][3] = false
  117.                 elseif current[1] < mapW and i == 2 then
  118.                     maze[current[1] + 1][current[2]][4] = false
  119.                 elseif current[2] < mapH and i == 3 then
  120.                     maze[current[1]][current[2] + 1][1] = false
  121.                 elseif current[1] > 1 and i == 4 then
  122.                     maze[current[1] - 1][current[2]][2] = false
  123.                 end
  124.             end
  125.         end
  126.     end
  127.     for x, v in pairs(maze) do
  128.         for y, e in pairs(v) do
  129.             if e[1] and e[2] and e[3] and e[4] then
  130.                 maze[x][y] = {false, false, false, false}
  131.             end
  132.         end
  133.     end
  134.     local gen = maze
  135.         maze = {}
  136.         for i = 1, mapW*2 + 1 do
  137.                 maze[i] = {}
  138.         end
  139.         for i = 1, mapH*2 + 1 do
  140.                 maze[1][i] = 2^15
  141.                 maze[mapW*2 + 1][i] = 2^15
  142.         end
  143.         for x = 2, mapW*2 do
  144.                 for y = 1, mapH*2 + 1 do
  145.                         if y == 1 or y == mapH*2 + 1 then
  146.                                 maze[x][y] = 2^15
  147.                         elseif x%2 == 0 and y%2 == 0 then
  148.                                 maze[x][y] = 128
  149.                         elseif x%2 == 1 and y%2 == 1 then
  150.                                 maze[x][y] = 2^15
  151.                         else
  152.                 if x%2 == 0 then
  153.                                         if gen[x/2][(y - 1)/2][2] and gen[x/2][(y + 1)/2][4] then
  154.                                                 maze[x][y] = 2^15
  155.                                         else
  156.                                                 maze[x][y] = 128
  157.                                         end
  158.                                 elseif x%2 == 1 then
  159.                                         if gen[(x - 1)/2][y/2][3] and gen[(x + 1)/2][y/2][1] then
  160.                                                 maze[x][y] = 2^15
  161.                                         else
  162.                                                 maze[x][y] = 128
  163.                                         end
  164.                                 end
  165.                         end
  166.                 end
  167.         end
  168.  
  169.     local map = {}
  170.     for x, v in pairs(maze) do
  171.         for i = 0, 9 do
  172.             map[x*10 - i] = {}
  173.         end
  174.         for y, e in pairs(v) do
  175.             for i = 0, 9 do
  176.                 for n = 0, 9 do
  177.                     map[x*10 - i][y*10 - n] = e
  178.                 end
  179.             end
  180.         end
  181.     end
  182.  
  183.     return maze, map
  184. end
  185.  
  186. function drawRelevantImage(xPos, yPos, img, col)
  187.     for x = xPos < midW and 1 or xPos - midW + 1, xPos + midW < #img and xPos + midW + 1 or #img do
  188.         for y = yPos < midH and 1 or yPos - midH + 1, yPos + midH < #img[x] and yPos + midH + 1 or #img[x] do
  189.             if img[x][y] == 128 then
  190.                 term.setCursorPos(x + midW - xPos, y + midH - yPos)
  191.                 term.setBackgroundColor(col)
  192.                 term.write(" ")
  193.             end
  194.         end
  195.     end
  196. end
  197.  
  198. local maze, map = mazeGenProcedural(24, 8)
  199.  
  200. local pLocation = {11, 11}
  201. local feet = {2, 1}
  202. local mapColor = colors.gray
  203. local backColor = colors.red
  204. local changeFeet, changeMap = true, true
  205.  
  206. function backFlash()
  207.     while true do
  208.         term.setBackgroundColor(backColor)
  209.         term.clear()
  210.         sleep(1)
  211.         if backColor == colors.black then
  212.             backColor = colors.red
  213.         else
  214.             backcolor = colors.black
  215.         end
  216.     end
  217. end
  218.  
  219. function pullTimedEvent(type, time)
  220.     local timer, events
  221.     if time then
  222.         timer = os.startTimer(time)
  223.     end
  224.     if type then
  225.         events = {os.pullEvent(type)}
  226.     else
  227.         events = {os.pullEvent()}
  228.     end
  229.     if events[1] ~= "timer" then
  230.         os.cancelTimer(timer)
  231.         return events
  232.     end
  233.     return nil
  234. end
  235.  
  236. function main(events)
  237.    
  238. end
  239.  
  240.  
  241.  
  242. local coMain = coroutine.create(function()
  243.     while true do
  244.         if events[1] == "key" then
  245.                 if events[2] == keys.up and map[pLocation[1]][pLocation[2] - 1] ~= 2^15 and map[pLocation[1] + 1][pLocation[2] - 1] ~= 2^15 then
  246.                     pLocation[2] = pLocation[2] - 1
  247.                     changeMap, changeFeet = true, true
  248.                 elseif events[2] == keys.down and map[pLocation[1]][pLocation[2] + 2] ~= 2^15 and map[pLocation[1] + 1][pLocation[2] + 2] ~= 2^15 then
  249.                     pLocation[2] = pLocation[2] + 1
  250.                     changeMap, changeFeet = true, true
  251.                 elseif events[2] == keys.left and map[pLocation[1] - 1][pLocation[2]] ~= 2^15 and map[pLocation[1] - 1][pLocation[2] + 1] ~= 2^15 then
  252.                     pLocation[1] = pLocation[1] - 1
  253.                     changeMap, changeFeet = true, true
  254.                 elseif events[2] == keys.right and map[pLocation[1] + 2][pLocation[2]] ~= 2^15 and map[pLocation[1] + 2][pLocation[2] + 1] ~= 2^15 then
  255.                     pLocation[1] = pLocation[1] + 1
  256.                     changeMap, changeFeet = true, true
  257.                 end
  258.             end
  259.             if changeFeet then
  260.                 if feet[1] == 1 then
  261.                     feet = {2, 1}
  262.                 else
  263.                     feet = {1, 2}
  264.                 end
  265.                 changeFeet = false
  266.             end
  267.         end
  268.         coroutine.yield()
  269.     end
  270. end)
  271.  
  272. local coFlash = coroutine.create(function()
  273.     while true do
  274.         if backColor == colors.black then
  275.             backColor = colors.red
  276.         else
  277.             backColor = colors.black
  278.         end
  279.         term.setBackgroundColor(backColor)
  280.         term.clear()
  281.         drawRelevantImage(pLocation[1], pLocation[2], map, mapColor)
  282.         draw(" ", midW + feet[1] - 1, midH, _, colors.lightBlue)
  283.         draw(" ", midW + feet[2] - 1, midH + 1, _, colors.lightBlue)
  284.         coroutine.yield()
  285.     end
  286. end
  287. )
  288.  
  289. while true do
  290.     events = pullTimedEvent(_, 1)
  291.     coroutine.resume(coMain)
  292.     coroutine.resume(coFlash)
  293.     sleep(.05)
  294. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement