Advertisement
CaptainSpaceCat

Maze2D

Jun 8th, 2015
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.48 KB | None | 0 0
  1. local termW, termH = term.getSize()
  2. local debug = false
  3.  
  4. function drawRelevantImage(img, xPos, yPos)   --update this!!!
  5.         for i, v in pairs(img) do
  6.                 for k, e in pairs(v) do
  7.                         if i + yPos - 1 >= 1 and i + yPos - 1 <= termH and k + xPos - 1 >= 1 and k + xPos - 1 <= termW then
  8.                                 term.setCursorPos(k + xPos - 1, i + yPos - 1)
  9.                                 term.setBackgroundColor(e)
  10.                                 term.write(" ")
  11.                         end
  12.                 end
  13.         end
  14. end
  15.  
  16. function gameGen(mapW, mapH)
  17.         pLocation = math.random(1, 4)
  18.         if pLocation == 1 then
  19.                 pLocation = {2, 2}
  20.                 gLocation = {mapW*2, mapH*2}
  21.         elseif pLocation == 2 then
  22.                 pLocation = {mapW*2, 2}
  23.                 gLocation = {2, mapH*2}
  24.         elseif pLocation == 3 then
  25.                 pLocation = {2, mapH*2}
  26.                 gLocation = {mapW*2, 2}
  27.         elseif pLocation == 4 then
  28.                 pLocation = {mapW*2, mapH*2}
  29.                 gLocation = {2, 2}
  30.         end
  31.         return pLocation, gLocation
  32. end
  33.  
  34. function mazeGenBranching(mapW, mapH)
  35.         local maze = {}
  36.         for y = 1, mapH do
  37.                 maze[y] = {}
  38.                 for x = 1, mapW do
  39.                         maze[y][x] = {}
  40.                         for i = 1, 4 do
  41.                                 maze[y][x][i] = true
  42.                         end
  43.                 end
  44.         end
  45.         local current = {1, 1}
  46.         local list = {}
  47.         list[1] = {math.random(1, mapH), math.random(1, mapW)}   --y, x
  48.         while #list > 0 do
  49.                 local choice = math.random(1, #list)
  50.                 current = {list[choice][1], list[choice][2]}
  51.                 local openWalls = {}
  52.                 if current[1] > 1 and 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
  53.                         openWalls[#openWalls + 1] = 1
  54.                 end
  55.                 if current[1] < mapH and 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
  56.                         openWalls[#openWalls + 1] = 3
  57.                 end
  58.                 if current[2] > 1 and 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
  59.                         openWalls[#openWalls + 1] = 4
  60.                 end
  61.                 if current[2] < mapW and 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
  62.                         openWalls[#openWalls + 1] = 2
  63.                 end
  64.                 if #openWalls > 0 then
  65.                         openWalls = openWalls[math.random(1, #openWalls)]
  66.                         maze[current[1]][current[2]][openWalls] = false
  67.                         if openWalls == 1 then
  68.                                 maze[current[1] - 1][current[2]][3] = false
  69.                                 list[#list + 1] = {current[1] - 1, current[2]}
  70.                         elseif openWalls == 2 then
  71.                                 maze[current[1]][current[2] + 1][4] = false
  72.                                 list[#list + 1] = {current[1], current[2] + 1}
  73.                         elseif openWalls == 3 then
  74.                                 maze[current[1] + 1][current[2]][1] = false
  75.                                 list[#list + 1] = {current[1] + 1, current[2]}
  76.                         elseif openWalls == 4 then
  77.                                 maze[current[1]][current[2] - 1][2] = false
  78.                                 list[#list + 1] = {current[1], current[2] - 1}
  79.                         end
  80.                 else
  81.                         table.remove(list, choice)
  82.                 end
  83.         end
  84.  
  85.         local gen = maze
  86.         maze = {}
  87.         for i = 1, mapH*2 + 1 do
  88.                 maze[i] = {}
  89.         end
  90.         for i = 1, mapW*2 + 1 do
  91.                 maze[1][i] = 1
  92.                 maze[mapH*2 + 1][i] = 1
  93.         end
  94.         for y = 2, mapH*2 do
  95.                 for x = 1, mapW*2 + 1 do
  96.                         if x == 1 or x == mapW*2 + 1 then
  97.                                 maze[y][x] = 1
  98.                         elseif y%2 == 0 and x%2 == 0 then
  99.                                 maze[y][x] = 2^15
  100.                         elseif y%2 == 1 and x%2 == 1 then
  101.                                 maze[y][x] = 1
  102.                         else
  103.                                 if y%2 == 0 then
  104.                                         if gen[y/2][(x - 1)/2][2] then
  105.                                                 maze[y][x] = 1
  106.                                         else
  107.                                                 maze[y][x] = 2^15
  108.                                         end
  109.                                 elseif y%2 == 1 then
  110.                                         if gen[(y - 1)/2][x/2][3] then
  111.                                                 maze[y][x] = 1
  112.                                         else
  113.                                                 maze[y][x] = 2^15
  114.                                         end
  115.                                 end
  116.                         end
  117.                 end
  118.         end
  119.         return maze
  120. end
  121.  
  122. function mazeGenRecursive(mapW, mapH)
  123.         local maze = {}
  124.         for y = 1, mapH do
  125.                 maze[y] = {}
  126.                 for x = 1, mapW do
  127.                         maze[y][x] = {}
  128.                         for i = 1, 4 do
  129.                                 maze[y][x][i] = true
  130.                         end
  131.                 end
  132.         end
  133.        
  134.         local current = {1, 1}   --y, x
  135.         local stack = {}
  136.         local cellsRemaining = mapW * mapH
  137.         while cellsRemaining > 1 do
  138.                 local fullCells = {}
  139.                 if current[1] > 1 and 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
  140.                         fullCells[#fullCells + 1] = 1
  141.                 end
  142.                 if current[1] < mapH and 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
  143.                         fullCells[#fullCells + 1] = 3
  144.                 end
  145.                 if current[2] > 1 and 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
  146.                         fullCells[#fullCells + 1] = 4
  147.                 end
  148.                 if current[2] < mapW and 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
  149.                         fullCells[#fullCells + 1] = 2
  150.                 end
  151.                 if #fullCells > 0 then
  152.                         cellsRemaining = cellsRemaining - 1
  153.                         stack[#stack + 1] = {current[1], current[2]}
  154.                         fullCells = fullCells[math.random(1, #fullCells)]
  155.                         maze[current[1]][current[2]][fullCells] = false
  156.                         if fullCells == 1 then
  157.                                 maze[current[1] - 1][current[2]][3] = false
  158.                                 current = {current[1] - 1, current[2]}
  159.                         elseif fullCells == 2 then
  160.                                 maze[current[1]][current[2] + 1][4] = false
  161.                                 current = {current[1], current[2] + 1}
  162.                         elseif fullCells == 3 then
  163.                                 maze[current[1] + 1][current[2]][1] = false
  164.                                 current = {current[1] + 1, current[2]}
  165.                         elseif fullCells == 4 then
  166.                                 maze[current[1]][current[2] - 1][2] = false
  167.                                 current = {current[1], current[2] - 1}
  168.                         end
  169.                 else
  170.                         current = table.remove(stack)
  171.                 end
  172.         end
  173.  
  174.         local gen = maze
  175.         maze = {}
  176.         for i = 1, mapH*2 + 1 do
  177.                 maze[i] = {}
  178.         end
  179.         for i = 1, mapW*2 + 1 do
  180.                 maze[1][i] = 1
  181.                 maze[mapH*2 + 1][i] = 1
  182.         end
  183.         for y = 2, mapH*2 do
  184.                 for x = 1, mapW*2 + 1 do
  185.                         if x == 1 or x == mapW*2 + 1 then
  186.                                 maze[y][x] = 1
  187.                         elseif y%2 == 0 and x%2 == 0 then
  188.                                 maze[y][x] = 2^15
  189.                         elseif y%2 == 1 and x%2 == 1 then
  190.                                 maze[y][x] = 1
  191.                         else
  192.                                 if y%2 == 0 then
  193.                                         if gen[y/2][(x - 1)/2][2] then
  194.                                                 maze[y][x] = 1
  195.                                         else
  196.                                                 maze[y][x] = 2^15
  197.                                         end
  198.                                 elseif y%2 == 1 then
  199.                                         if gen[(y - 1)/2][x/2][3] then
  200.                                                 maze[y][x] = 1
  201.                                         else
  202.                                                 maze[y][x] = 2^15
  203.                                         end
  204.                                 end
  205.                         end
  206.                 end
  207.         end
  208.         return maze
  209. end
  210.  
  211. function solveMaze(maze, pX, pY, gX, gY)
  212.         local stack = {}
  213.         visited = {}
  214.     local file = fs.open("debug", "w")
  215.     file.writeLine(tostring(pX) .. " " .. tostring(pY) .. " " .. tostring(gX) .. " " .. tostring(gY))
  216.         local mapW, mapH = #maze[1], #maze
  217.         for i, _ in pairs(maze) do
  218.                 visited[i] = {}
  219.         end
  220.     for y, v in pairs(maze) do
  221.         file.write(tostring(y) .. " ")
  222.         for x, e in pairs(v) do
  223.             file.write(tostring(e) .. ":")
  224.         end
  225.         file.writeLine("")
  226.     end
  227.         local sLocation = {pY, pX}   --y, x
  228.         visited[pY][pX] = true
  229.         while true do
  230.         file.flush()
  231.                 local adjCells = {}
  232.                 if sLocation[1] > 1 and maze[sLocation[1] - 1][sLocation[2]] ~= 1 and not visited[sLocation[1] - 1][sLocation[2]] then
  233.                         adjCells[#adjCells + 1] = 1
  234.  
  235.                 end
  236.                 if sLocation[2] < mapW and maze[sLocation[1]][sLocation[2] + 1] ~= 1 and not visited[sLocation[1]][sLocation[2] + 1] then
  237.                         adjCells[#adjCells + 1] = 2
  238.  
  239.                 end
  240.                 if sLocation[1] < mapH and maze[sLocation[1] + 1][sLocation[2]] ~= 1 and not visited[sLocation[1] + 1][sLocation[2]] then
  241.                         adjCells[#adjCells + 1] = 3
  242.  
  243.                 end
  244.                 if sLocation[2] > 1 and maze[sLocation[1]][sLocation[2] - 1] ~= 1 and not visited[sLocation[1]][sLocation[2] - 1] then
  245.                         adjCells[#adjCells + 1] = 4
  246.  
  247.                 end
  248.                 if #adjCells > 0 then
  249.                         stack[#stack + 1] = {sLocation[1], sLocation[2]}
  250.                         adjCells = adjCells[math.random(1, #adjCells)]
  251.                         if adjCells == 1 then
  252.                                 sLocation[1] = sLocation[1] - 1
  253.             file.writeLine("up")
  254.                         elseif adjCells == 2 then
  255.                                 sLocation[2] = sLocation[2] + 1
  256.             file.writeLine("right")
  257.                         elseif adjCells == 3 then
  258.                                 sLocation[1] = sLocation[1] + 1
  259.             file.writeLine("down")
  260.                         elseif adjCells == 4 then
  261.                                 sLocation[2] = sLocation[2] - 1
  262.             file.writeLine("right")
  263.                         end
  264.                         visited[sLocation[1]][sLocation[2]] = true
  265.                         if sLocation[1] == gY and sLocation[2] == gX then
  266.                                 --stack[#stack + 1] = {sLocation[1], sLocation[2]}
  267.                                 break
  268.                         end
  269.                 else
  270.             file.writeLine("back")
  271.                         sLocation = table.remove(stack)
  272.                 end
  273.         end
  274.         return stack
  275. end
  276.  
  277. function toggleSolution(maze, solution, state)
  278.     local color = nil
  279.     if state then
  280.         color = colors.yellow
  281.     else
  282.         color = 2^15
  283.     end
  284.     for i, v in pairs(solution) do
  285.         maze[v[1]][v[2]] = color
  286.     end
  287.     return maze
  288. end
  289.  
  290. local prevLocation = nil
  291. local solutionToggle = false
  292. local typeList = {"Recursive", "Branching"}
  293. term.setBackgroundColor(colors.black)
  294. term.clear()
  295. local logo = typeList[math.random(1, #typeList)]
  296. if logo == "Recursive" then
  297.     logo = mazeGenRecursive(5, 5)
  298. elseif logo == "Branching" then
  299.     logo = mazeGenBranching(5, 5)
  300. end
  301. term.setCursorPos(termW/2 - 4, 3)
  302. term.write("Maze Game")
  303. logo[2][2] = colors.lightBlue
  304. logo[10][10] = colors.orange
  305. drawRelevantImage(logo, termW/2 - 5, 6)
  306. term.setCursorPos(termW/2 - 7, termH - 2)
  307. term.setBackgroundColor(colors.black)
  308. term.setTextColor(colors.white)
  309. term.write("Press any key...")
  310. os.pullEvent("key")
  311. sleep(.05)
  312.  
  313. term.setBackgroundColor(colors.black)
  314. term.clear()
  315. term.setCursorPos(1, 1)
  316. term.write("Enter maze width: ")
  317. local mapW = read()
  318. while not tonumber(mapW) do
  319.         term.setCursorPos(1, 1)
  320.         term.clearLine()
  321.         term.write("Enter maze width: ")
  322.         mapW = read()
  323. end
  324. term.setCursorPos(1, 2)
  325. term.write("Enter maze height: ")
  326. local mapH = read()
  327. mapW, mapH = tonumber(mapW), tonumber(mapH)
  328. while not tonumber(mapH) do
  329.         term.setCursorPos(1, 2)
  330.         term.clearLine()
  331.         term.write("Enter maze height: ")
  332.         mapH = read()
  333. end
  334. term.setCursorPos(1, 3)
  335. term.write("Choose maze type: ")
  336. local begun = false
  337. local maze = {}
  338. while not begun do
  339.     for i, v in pairs(typeList) do
  340.         term.setCursorPos(termW/2 - #v/2 + 1, i + 3)
  341.         term.write(v)
  342.     end
  343.     local click = {os.pullEvent("mouse_click")}
  344.     for i, v in pairs(typeList) do
  345.         if click[4] == i + 3 then
  346.             term.setBackgroundColor(colors.blue)
  347.             term.setCursorPos(termW/2 - #v/2 + 1, i + 3)
  348.             term.write(v)
  349.             sleep(.2)
  350.             begun = true
  351.             if v == "Recursive" then
  352.                 maze = mazeGenRecursive(mapW, mapH)
  353.             elseif v == "Branching" then
  354.                 maze = mazeGenBranching(mapW, mapH)
  355.             end
  356.             break
  357.         end
  358.     end
  359. end
  360.  
  361.  
  362. local pLocation, gLocation = gameGen(mapW, mapH)
  363. local solDist = #(solveMaze(maze, pLocation[1], pLocation[2], gLocation[1], gLocation[2]))
  364. maze[gLocation[2]][gLocation[1]] = 2
  365. if debug then
  366.         paintutils.drawImage(maze, 1, 1)
  367.         term.setCursorPos(pLocation[1], pLocation[2])
  368.         term.setBackgroundColor(colors.lightBlue)
  369.         term.write(" ")
  370. end
  371.  
  372. term.setBackgroundColor(colors.black)
  373. term.setTextColor(colors.white)
  374. term.clear()
  375. term.setCursorPos(1, 1)
  376. print("You are the blue square...")
  377. term.setCursorPos(termW/2 + 1, termH/2 + 1)
  378. term.setBackgroundColor(colors.lightBlue)
  379. term.write(" ")
  380. term.setCursorPos(termW/2 - 7, termH - 1)
  381. term.setBackgroundColor(colors.black)
  382. term.setTextColor(colors.white)
  383. term.write("Press any key...")
  384. os.pullEvent("key")
  385.  
  386. term.setBackgroundColor(colors.black)
  387. term.setTextColor(colors.white)
  388. term.clear()
  389. term.setCursorPos(1, 1)
  390. print("Get to the orange square...")
  391. term.setCursorPos(termW/2 + 1, termH/2 + 1)
  392. term.setBackgroundColor(colors.orange)
  393. term.write(" ")
  394. term.setCursorPos(termW/2 - 7, termH - 1)
  395. term.setBackgroundColor(colors.black)
  396. term.setTextColor(colors.white)
  397. term.write("Press any key...")
  398. os.pullEvent("key")
  399.  
  400. term.setBackgroundColor(colors.black)
  401. term.setTextColor(colors.white)
  402. term.clear()
  403. term.setCursorPos(termW/2 - 4, 1)
  404. print([[Controls:
  405.  
  406. ARROW KEYS to move
  407.  
  408. TAB to show/hide solution
  409.  
  410. Q to quit]])
  411. term.setCursorPos(termW/2 - 7, termH - 1)
  412. term.write("Press any key...")
  413. os.pullEvent("key")
  414. local startTime = os.clock()
  415. local pressedtab = false
  416. local distance = 0
  417. while true do
  418.     term.setBackgroundColor(colors.black)
  419.     term.clear()
  420.     if solutionToggle and prevLocation and (prevLocation[1] ~= pLocation[1] or prevLocation[2] ~= pLocation[2]) then
  421.         if maze[pLocation[2]][pLocation[1]] == 2^15 then
  422.             maze[pLocation[2]][pLocation[1]] = colors.yellow
  423.         else
  424.             maze[prevLocation[2]][prevLocation[1]] = 2^15
  425.         end
  426.     end
  427.     --term.setCursorPos(10, 1)
  428.     --write(tostring(pLocation[1]) .. " " .. tostring(pLocation[2]))
  429.     drawRelevantImage(maze, termW/2 - pLocation[1] + 2, termH/2 - pLocation[2] + 2)
  430.     term.setBackgroundColor(colors.lightBlue)
  431.     term.setCursorPos(termW/2 + 1, termH/2 + 1)
  432.     term.write(" ")
  433.     if pLocation[1] == gLocation[1] and pLocation[2] == gLocation[2] then
  434.         local endTime = os.clock()
  435.         local score = (mapW*mapH)*(solDist*.5)/(distance*.5) - (endTime - startTime)*.2
  436.         if pressedtab then
  437.             score = score*.1
  438.         end
  439.             for i = 1, 7 do
  440.                     term.setCursorPos(termW/2 - 11, 1)
  441.                     term.setBackgroundColor(colors.black)
  442.                     term.setTextColor(colors.yellow)
  443.                     term.clearLine()
  444.                     term.write("You won! Congratulations!")
  445.                     sleep(.1)
  446.                     term.setCursorPos(termW/2 - 11, 1)
  447.                     term.setBackgroundColor(colors.black)
  448.                     term.setTextColor(colors.blue)
  449.                     term.clearLine()
  450.                     term.write("You won! Congratulations!")
  451.                     sleep(.1)
  452.             end
  453.             term.setBackgroundColor(colors.black)
  454.             term.clear()
  455.             term.setCursorPos(1, 1)
  456.         for i = 1, termW do
  457.             write("-")
  458.         end
  459.         term.setCursorPos(termW/2 - 2, 1)
  460.         term.write("STATS")
  461.         term.setCursorPos(1, 2)
  462.         print("Time spent: " .. tostring(math.floor((endTime - startTime)/60)) .. ":" .. tostring(math.ceil((endTime - startTime)%60)))
  463.         print("Distance travelled: " .. tostring(distance))
  464.         print("Minimum distance possible: " .. tostring(solDist))
  465.         print("Pressed tab: " .. tostring(pressedtab))
  466.         print("FINAL SCORE: " .. tostring(score))
  467.         os.pullEvent()
  468.         break
  469.     end
  470.     local events = {os.pullEvent()}
  471.     if solutionToggle then
  472.         prevLocation = {pLocation[1], pLocation[2]}
  473.     end
  474.     if events[1] == "key" then
  475.             if events[2] == 200 then
  476.                 if maze[pLocation[2] - 1][pLocation[1]] ~= 1 then
  477.                     pLocation[2] = pLocation[2] - 1
  478.                 distance = distance + 1
  479.                 end
  480.             elseif events[2] == 203 then
  481.                 if maze[pLocation[2]][pLocation[1] - 1] ~= 1 then
  482.                     pLocation[1] = pLocation[1] - 1
  483.                 distance = distance + 1
  484.                 end
  485.             elseif events[2] == 208 then
  486.                 if maze[pLocation[2] + 1][pLocation[1]] ~= 1 then
  487.                     pLocation[2] = pLocation[2] + 1
  488.                 distance = distance + 1
  489.                 end
  490.             elseif events[2] == 205 then
  491.                 if maze[pLocation[2]][pLocation[1] + 1] ~= 1 then
  492.                     pLocation[1] = pLocation[1] + 1
  493.                 distance = distance + 1
  494.                 end
  495.             end
  496.         if events[2] == keys.tab then
  497.             pressedtab = true
  498.             if solutionToggle then
  499.                 solutionToggle = false
  500.             else
  501.                 solutionToggle = true
  502.             end
  503.             maze = toggleSolution(maze, solveMaze(maze, pLocation[1], pLocation[2], gLocation[1], gLocation[2]), solutionToggle)
  504.         end
  505.         if events[2] == keys.q then
  506.             sleep(.05)
  507.             term.setBackgroundColor(colors.black)
  508.             term.clear()
  509.             term.setCursorPos(1, 1)
  510.             break
  511.         end
  512.     end
  513. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement