Advertisement
faubiguy

Hello World Maze

Aug 13th, 2013
332
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.90 KB | None | 0 0
  1. local debug = (select(2,...))=='debug';
  2. local termW, termH = term.getSize();
  3. local w, h = math.floor(termW/2), math.floor(termH/2-1)
  4. --w, h = tonumber(w) or 9, tonumber(h) or 9;
  5. --[[local]] text = ((...) or 'Hello_World!'):gsub('%s', '_'):sub(1,16);
  6.  
  7. local movePos = function(pos, dir)
  8.     local newpos = {pos[1], pos[2]}
  9.     newpos[2-dir%2] = newpos[2-dir%2] + dir-dir%2-1;
  10.     return newpos;
  11. end
  12.  
  13. local getWallPos = function(pos, wall)
  14.     pos = {2*pos[2],2*pos[1]};
  15.     --[
  16.     local dir = wall%2+1;
  17.     wall = wall-dir
  18.     pos[dir]=pos[dir]+wall
  19.     --]]
  20.     --pos = movePos(pos, wall);
  21.     return pos[2], pos[1];
  22. end
  23.  
  24. checkWalls = function(pos, count, _maze)
  25.     if debug then term.setCursorPos(21,9); term.clearLine(); term.write('checkWalls called'); end
  26.     if pos[1] < 1 or pos[2] < 1 or pos[1] > w or pos[2] > h then return false end
  27.     local walls = 4;
  28.     for i = 0,3 do
  29.         local charX, charY = getWallPos(pos, i);
  30.         if _maze[charX][charY]==' ' then
  31.             if debug then term.setCursorPos(21,10); term.clearLine(); term.write('Missing walls at {'..table.concat(pos,', ')..', '..i..'}'); end
  32.             if count then walls = walls - 1 else return false; end
  33.         end
  34.     end
  35.     if debug then term.setCursorPos(21,10); term.clearLine(); term.write('All walls at {'..table.concat(pos, ', ')..'}'); end
  36.     return count and walls or true;
  37. end
  38.  
  39. local removeWall = function(pos, wall, _maze)
  40.     local charX, charY = getWallPos(pos, wall);
  41.     _maze[charX][charY] = ' '
  42. end
  43.  
  44.  
  45. local centerText = function(y, text)
  46.     term.setCursorPos((termW-#text)/2,y)
  47.     term.write(text);
  48. end
  49.  
  50. local MAZECHARS = {'+', '-', '|', ' '};
  51.  
  52. function generateMaze(--[[w,h]])
  53.     local maze = {};
  54.     for x = 0, 2*w do
  55.         local col = {};
  56.         for y = 0, 2*h do  
  57.             col[y+1] = MAZECHARS[x%2 + (y%2)*2 + 1];
  58.         end
  59.         maze[x+1]=col;
  60.     end
  61.  
  62.  
  63.            
  64.     local cells = {}; --LIFO stack containing visited cells
  65.     local total = w*h; --Total number of cells to visit
  66.     local visited = 1;
  67.     local currentCell = {math.random(1,w), math.random(1,h)};
  68.     while visited < total do
  69.         if debug and currentCell then term.setCursorPos(24, 2); term.clearLine(); term.write('{'..table.concat(currentCell, ', ')..'}') end
  70.         local adjacentCells = {};
  71.         for j = 0, 3 do
  72.             --[
  73.             cell = {currentCell[1], currentCell[2]};
  74.             cell[2-j%2] = cell[2-j%2] + j-j%2-1;
  75.             --]]
  76.             --local cell = movePos(currentCell, j)
  77.             if debug then term.clear(); term.setCursorPos(1,1); term.write(tostring(visited)..'/{'..table.concat(cell, ', ')..'}'); end
  78.             if checkWalls(cell, false, maze) then
  79.                 cell[3] = j;
  80.                 adjacentCells[#adjacentCells+1] = cell;
  81.                 if debug then term.setCursorPos(24+j, 19); term.clearLine(); term.write(tostring(j+1)); end
  82.             end
  83.            
  84.             if debug then term.setCursorPos(24, 13+j); term.clearLine(); term.write('{'..table.concat(cell, ', ')..'}') end
  85.         end
  86.         if #adjacentCells >= 1 then
  87.             local cell = adjacentCells[math.random(1,#adjacentCells)];
  88.             removeWall(currentCell, cell[3], maze);
  89.             cells[#cells+1]=currentCell;
  90.             currentCell = cell;
  91.             visited = visited + 1;
  92.         else
  93.             currentCell = cells[#cells];
  94.             cells[#cells]=nil;
  95.         end
  96.         if debug then --[[draw(true);]] term.write(visited..' '); for k=1,4 do local zcf = adjacentCells[k]; term.setCursorPos(24,2+k); term.clearLine(); term.write(not zcf and '---' or '{'..table.concat(zcf, ', ')..'}') end term.setCursorPos(24,7); term.clearLine(); term.write(#adjacentCells); term.setCursorPos(1,1) end
  97.     end
  98.     return maze
  99. end
  100.  
  101. local maze;
  102. local deadEnds = {};
  103. local letters = {};
  104. local playerPos;
  105. local collectedText = '';
  106. local completed = false;
  107. local easterEgg = false;
  108.  
  109. local attempts = 0;
  110. repeat
  111.     deadEnds = {};
  112.     maze = generateMaze(--[[w,h]])
  113.     for x = 1, w do
  114.         for y = 1, h do
  115.             if checkWalls({x,y}, true, maze) == 3 then
  116.                 deadEnds[#deadEnds+1] = {x, y};
  117.             end
  118.         end
  119.     end
  120.     attempts = attempts+1;
  121. until #deadEnds >= #text+1 or attempts>=16;
  122.  
  123. if attempts>=16 then
  124.     term.clear()
  125.     term.setCursorPos(1,1)
  126.     print('Failed to generate a maze with at least ',#text+1,' dead ends within 16 attempts. Try again with a larger screen size.')
  127.     return
  128. end
  129.  
  130. --[[repeat]] playerPos = {math.random(1,w), math.random(1,h)}
  131. --until not letters[playerPos[1]*w+playerPos[2]];
  132.  
  133. local assignToDeadEnd = function(letter)
  134.     local num = math.random(1,#deadEnds)
  135.     if (playerPos[1] == deadEnds[num][1] and playerPos[2] == deadEnds[num][2]) then
  136.         num = num % #deadEnds + 1
  137.     end
  138.     local deadEnd = table.remove(deadEnds, num);
  139.     letters[deadEnd[1]-1+(deadEnd[2]-1)*w]=letter;
  140. end
  141.  
  142. for i = 1, #text do
  143.     assignToDeadEnd(text:sub(i,i));
  144. end
  145.  
  146.  
  147. local checkForLetter = function()
  148.     --if playerPos[1]%2 ==1 or playerPos[2]%2 ==1 then return end
  149.     local pos = playerPos[1]-1+(playerPos[2]-1)*w;
  150.     local letter = letters[pos];
  151.     if letter then
  152.         collectedText = collectedText .. letter;
  153.         letters[pos] = nil;
  154.         deadEnds[#deadEnds+1]={playerPos[1],playerPos[2]};
  155.         if collectedText == text then completed = true; return end
  156.         if collectedText == text:reverse() then completed = true; easterEgg = true; return end
  157.     end
  158. end
  159.  
  160. local returnLetter = function()
  161.     if #collectedText < 1 then return end
  162.     assignToDeadEnd(collectedText:sub(-1,-1));
  163.     collectedText=collectedText:sub(1,-2);
  164. end
  165.  
  166. local movePlayer = function(dir)
  167.     local wallX, wallY = getWallPos(playerPos, dir)
  168.     if maze[wallX][wallY] ~= ' ' then return end
  169.     playerPos = movePos(playerPos, dir)
  170.     checkForLetter();
  171. end
  172.    
  173. local draw = function()
  174.     term.clear();
  175.     local w1, h1 = math.min(2*w+1,(term.getSize())), math.min(2*h+1, (select(2,term.getSize())));
  176.     for x = 1, w1 do
  177.         for y = 1, h1 do
  178.             term.setCursorPos(x, y);
  179.             term.write(maze[x][y]);
  180.         end
  181.     end
  182.     for i, v in pairs(letters) do
  183.         local x = i%w+1;
  184.         local y = (i-x+1)/w+1;
  185.         term.setCursorPos(2*x, 2*y);
  186.         term.write(v)
  187.     end
  188.     term.setCursorPos(playerPos[1]*2, playerPos[2]*2);
  189.     term.write('#');
  190.     term.setCursorPos(1,termH);
  191.     centerText(termH,collectedText);
  192.     term.setCursorPos(1,1);
  193. end
  194.  
  195. local controls = {
  196.     [keys.up] = function() movePlayer(0) end,
  197.     [keys.left] = function() movePlayer(1) end,
  198.     [keys.down] = function() movePlayer(2) end,
  199.     [keys.right] = function() movePlayer(3) end,
  200.     [keys.space] = returnLetter
  201. }
  202.  
  203. term.clear()
  204. centerText(3, 'Instructions')
  205. centerText(math.floor(termH/2)-2, 'Arrow keys to move')
  206. centerText(math.floor(termH/2)-1, 'SPACE to return letter to maze')
  207. centerText(math.floor(termH/2), '_ is a space')
  208. centerText(math.floor(termH/2)+1, 'You control the #')
  209. centerText(termH-2, 'Press ENTER to continue')
  210. for evt, key in os.pullEvent do if evt=='key' and key==keys.enter then break end end
  211.  
  212. draw();
  213. while not completed do
  214.     local evt, key = os.pullEvent('key');
  215.     if controls[key] then
  216.         controls[key]();
  217.         draw()
  218.     end
  219. end
  220.  
  221. for i = 1, termH-1 do
  222.     term.setCursorPos(1,i);
  223.     term.clearLine();
  224.     sleep(0.1);
  225. end
  226. for i = 1,5 do
  227.     centerText(math.floor(termH/2), not easterEgg and text or ({'!oot', 'sdrawkcab', 'etirw', 'nac', 'I'})[i])
  228.     sleep(0.6)
  229.     term.clearLine()
  230.     sleep(0.4)
  231. end
  232. term.setCursorPos(1,1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement