JustDoesGames

Minesweeper

Jun 3rd, 2020
1,520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.63 KB | None | 0 0
  1. -- Minesweeper --
  2.  
  3. local dir = fs.getDir(shell.getRunningProgram())
  4. local w,h = term.getSize() h = h-1
  5. assert(term.isColor(), "Advanced Computer Required.")
  6. local run,result = true,"Lost"
  7. local cols = {"white", "orange", "magenta", "lightBlue", "yellow", "lime", "pink", "gray", "lightGray", "cyan", "purple", "blue", "brown", "green", "red", "black"}
  8.  
  9. --[[
  10. local writ = function(t) write(tostring(t)) end
  11. local write = function(t) writ(t) end
  12. --]]
  13. local number_colors = {
  14.     colors.green,
  15.     colors.green,
  16.     colors.yellow,
  17.     colors.orange,
  18.     colors.magenta,
  19.     colors.purple,
  20.     colors.lightGray,
  21.     colors.red,
  22. }
  23. local data = {
  24.     display = {
  25.         text = {
  26.             flag = "orange",
  27.             masked = "gray",
  28.             foreground = "black",
  29.             bomb = "red",
  30.             highlight = "lightGray",
  31.             invalidflag = "red",
  32.             validflag = "cyan",
  33.         },
  34.         sprites = {
  35.             numbs = {"1","2","3","4","5","6","7","8"},
  36.             flag = "^",
  37.             bomb = "!",
  38.             masked = "#",
  39.             foreground = " ",
  40.             highlight = "-",
  41.             invalidflag = "^",
  42.             validflag = "^",
  43.         },
  44.         background = {
  45.             foreground = "black",
  46.             masked = "black",
  47.             flag = "lightGray",
  48.             bomb = "black",
  49.             highlight = "black",
  50.             invalidflag = "black",
  51.             validflag = "black",
  52.         },
  53.     },
  54.     settings = {
  55.         enableHighlight = false,
  56.     },
  57.     number_colors = {
  58.         "lime",
  59.         "green",
  60.         "yellow",
  61.         "orange",
  62.         "magenta",
  63.         "purple",
  64.         "lightGray",
  65.         "red",
  66.     }
  67. }
  68.  
  69. local user_data = nil
  70. if fs.exists(dir.."/theme.lua") then local file = fs.open(dir.."/theme.lua", "r") user_data = textutils.unserialize(file.readAll()) file.close() end
  71.  
  72. if user_data then
  73.     if user_data.display then
  74.         if user_data.text then data.text = user_data.text end
  75.         if user_data.sprites then data.sprites = user_data.sprites end
  76.         if user_data.background then data.background = user_data.background end
  77.     end
  78.     if user_data.settings then data.settings = user_data.settings end
  79.     if user_data.number_colors then data.number_colors = user_data.number_colors end
  80. end
  81.  
  82.  
  83. local map,time,tbombs = {}, {true, 0},math.ceil(((w*h)/math.random(70,100)))*10
  84.  
  85. local lookup = {
  86.     {-1, 0},
  87.     {1, 0},
  88.     {0, -1},
  89.     {0, 1},
  90.     {-1, -1},
  91.     {1, 1},
  92.     {1, -1},
  93.     {-1, 1},
  94. }
  95.  
  96. local function getBombs(locationx,locationy)
  97.     local tmp = 0
  98.     for i=1, #lookup do
  99.         if map[locationy+lookup[i][1]] then
  100.             if map[locationy+lookup[i][1]][locationx+lookup[i][2]] then
  101.                 if map[locationy+lookup[i][1]][locationx+lookup[i][2]][1] == 10 then
  102.                     tmp = tmp + 1
  103.                 end
  104.             end
  105.         end
  106.     end
  107.    
  108.     return tmp
  109. end
  110.  
  111. local function generateMap()
  112.     map = {}
  113.     map.x,map.y = w,h
  114.     map.totalBombs = tbombs
  115.     map.flags = 0
  116.     map.correctFlags = 0
  117.     result = "Lost"
  118.     for i=1, map.y do
  119.         map[i] = {}
  120.         for ii=1, map.x do
  121.             map[i][ii] = {9, 0}
  122.         end
  123.     end
  124.    
  125.     local tmpx,tmpy
  126.     for i=1, map.totalBombs do
  127.         local l = true
  128.         while l do
  129.             tmpy = math.random(1,map.y)
  130.             for ii=1, #map[tmpy] do
  131.                 if map[tmpy][ii][1] == 9 then l = false end
  132.             end
  133.         end
  134.         repeat tmpx = math.random(1,map.x) until map[tmpy][tmpx][1] == 9
  135.         map[tmpy][tmpx][1] = 10
  136.     end
  137.     for i=1, #map do
  138.         for ii=1, #map[i] do
  139.             if map[i][ii][1] == 9 then
  140.                 map[i][ii][1] = getBombs(ii,i)
  141.             end
  142.         end
  143.     end
  144. end
  145.  
  146. local function drawMapPixel(x,y)
  147.     term.setCursorPos(x,y)
  148.     if map[y][x][2] == 0 then
  149.         term.setBackgroundColor(colors[data.display.background.masked] or colors.black)
  150.         term.setTextColor(colors[data.display.text.masked] or colors.gray)
  151.         write(data.display.sprites.masked or "#")
  152.     elseif map[y][x][2] == 1 then
  153.         if map[y][x][1] == 10 then
  154.             term.setBackgroundColor(colors[data.display.background.bomb] or colors.black)
  155.             term.setTextColor(colors[data.display.text.bomb] or colors.red)
  156.             write(data.display.sprites.bomb or "!")
  157.         elseif map[y][x][1] == 0 then
  158.             term.setBackgroundColor(colors[data.display.background.foreground] or colors.black)
  159.             term.setTextColor(colors[data.display.text.foreground] or colors.black)
  160.             write(data.display.sprites.foreground or " ")
  161.         else
  162.             term.setBackgroundColor(colors[data.display.background.foreground] or colors.black)
  163.             term.setTextColor(colors[data.number_colors[map[y][x][1]] or 1] or number_colors[map[y][x][1] or 1])
  164.             write(data.display.sprites.numbs[map[y][x][1]] or "0")
  165.         end
  166.     elseif map[y][x][2] == 2 then
  167.         term.setBackgroundColor(colors[data.display.background.masked] or colors.black)
  168.         term.setTextColor(colors[data.display.text.flag] or colors.orange)
  169.         write(data.display.sprites.flag or "^")
  170.     elseif map[y][x][2] == 3 then
  171.         term.setBackgroundColor(colors[data.display.background.validflag] or colors.black)
  172.         term.setTextColor(colors[data.display.text.validflag] or colors.cyan)
  173.         write(data.display.sprites.validflag or "^")
  174.     elseif map[y][x][2] == 4 then
  175.         term.setBackgroundColor(colors[data.display.background.invalidflag] or colors.black)
  176.         term.setTextColor(colors[data.display.text.invalidflag] or colors.red)
  177.         write(data.display.sprites.invalidflag or "^")
  178.     else
  179.         write(map[y][x][1])
  180.     end
  181. end
  182.  
  183. local function drawMap()
  184.     term.setCursorPos(1,1)
  185.     for i=1, #map do
  186.         term.setCursorPos(1,i)
  187.         for ii=1, #map[i] do
  188.             drawMapPixel(ii,i)
  189.         end
  190.     end
  191. end
  192.  
  193. local function runSettings()
  194.     local loop, sel = true, 1
  195.     term.setBackgroundColor(colors.black)
  196.     term.setTextColor(colors.white)
  197.     term.clear()
  198.     local menu = {
  199.         --
  200.     }
  201.     while loop do
  202.         for i=1, #menu do
  203.             term.setCursorPos(1,i)
  204.             if i == sel then
  205.                 term.setBackgroundColor(colors.black)
  206.                 term.setTextColor(colors.white)
  207.                 write("< ")
  208.                 write(menu[i][1])
  209.                 write(" >")
  210.             else
  211.                 term.setBackgroundColor(colors.black)
  212.                 term.setTextColor(colors.gray)
  213.                 write("  ")
  214.                 write(menu[i][1])
  215.                 write("  ")
  216.             end
  217.            
  218.         end
  219.         local a,i = os.pullEvent("key")
  220.         if i == keys.w or i == keys.up then
  221.             if sel ~= 1 then sel = sel - 1 end
  222.         elseif i == keys.s or i == keys.down then
  223.             if sel ~= #menu then sel = sel + 1 end
  224.         elseif i == keys.enter or i == keys.e then
  225.             if type(menu[sel][2]) ~= "table" then
  226.                 menu[sel][2]()
  227.             end
  228.         elseif i == keys.q then
  229.             loop = false
  230.         end
  231.     end
  232.     term.clear()
  233. end
  234.  
  235. local function drawDisplay()
  236.     if data.display.sprites.flag then
  237.         term.setCursorPos(w-string.len(" "..data.display.sprites.flag..map.totalBombs-map.flags.."  Time: "..time[2]), h+1)
  238.     else
  239.         term.setCursorPos(w-string.len(" ^"..map.totalBombs-map.flags.."  Time: "..time[2]), h+1)
  240.     end
  241.     term.setBackgroundColor(colors[data.display.background.masked] or colors.black)
  242.     term.setTextColor(colors[data.display.text.flag] or colors.orange)
  243.     write(" "..data.display.sprites.flag or "^")
  244.     term.setTextColor(colors.white)
  245.     term.setBackgroundColor(colors.black)
  246.     write(map.totalBombs-map.flags.." ")
  247. end
  248.  
  249. local function runMenu()
  250.     local menu = {
  251.         {"Reset", function() generateMap() time[2] = 0 drawMap() drawDisplay() end},
  252.         {"Clr Flags", function() for i=1, #map do for ii=1, #map[i] do if map[i][ii][2] == 2 then map[i][ii][2] = 0 end end end drawMap() end},
  253.         --{"Settings", function() runSettings() drawMap() drawDisplay() end},
  254.         {"Exit", function() result = "Exit" run = false end},
  255.     }
  256.     term.setTextColor(colors.gray)
  257.     term.setBackgroundColor(colors.black)
  258.     term.setCursorPos(1,h+1)
  259.     write("[Menu]")
  260.     while run do
  261.         sleep(.001)
  262.         a,i = os.pullEvent("key")
  263.         if i == keys.leftCtrl or i == keys.rightCtrl then
  264.             local active,sel = true,1
  265.             time[1] = false
  266.             while active do
  267.                 term.setCursorPos(1,h+1)
  268.                 for i=1, #menu do
  269.                     if sel == i then term.setTextColor(colors.yellow) write("["..menu[i][1].."]") else term.setTextColor(colors.gray) write(" "..menu[i][1].." ") end
  270.                 end
  271.                 a,i = os.pullEvent("key")
  272.                 if i == keys.d or i == keys.right then
  273.                     if sel ~= #menu then sel = sel + 1 end
  274.                 elseif i == keys.a or i == keys.left then
  275.                     if sel ~= 1 then sel = sel - 1 end
  276.                 elseif i == keys.enter or i == keys.e then
  277.                     menu[sel][2]()
  278.                     active = false
  279.                 elseif i == keys.q or i == keys.leftCtrl or i == keys.rightCtrl then
  280.                     active = false
  281.                 end
  282.             end
  283.             term.setTextColor(colors.black)
  284.             term.setBackgroundColor(colors.black)
  285.             term.setCursorPos(1,h+1)
  286.             for i=1, #menu do
  287.                 write(" "..menu[i][1].." ")
  288.             end
  289.             term.setTextColor(colors.gray)
  290.             term.setBackgroundColor(colors.black)
  291.             term.setCursorPos(1,h+1)
  292.             write("[Menu]")
  293.             time[1] = true
  294.         end
  295.     end
  296. end
  297.  
  298. local function runGame()
  299.     local discover_chart = {}
  300.     local function discover(x,y)
  301.         --discover_chart = {}
  302.         for i=1, #lookup do
  303.             if map[y+lookup[i][1]] then
  304.                 if map[y+lookup[i][1]][x+lookup[i][2]] then
  305.                     if map[y+lookup[i][1]][x+lookup[i][2]][2] == 0 and map[y+lookup[i][1]][x+lookup[i][2]][1] ~= 9 and map[y+lookup[i][1]][x+lookup[i][2]][2] ~= 10 then
  306.                         map[y+lookup[i][1]][x+lookup[i][2]][2] = 1
  307.                         if map[y+lookup[i][1]][x+lookup[i][2]][1] == 0 then
  308.                             discover_chart[#discover_chart+1] = {x+lookup[i][2], y+lookup[i][1]}
  309.                         end
  310.                         drawMapPixel(x+lookup[i][2],y+lookup[i][1])
  311.                     end
  312.                 end
  313.             end
  314.         end
  315.     end
  316.     local function highlight(x,y,status)
  317.         for i=1, #lookup do
  318.             if map[y+lookup[i][1]] then
  319.                 if map[y+lookup[i][1]][x+lookup[i][2]] then
  320.                     if status then
  321.                         term.setCursorPos(x+lookup[i][2],y+lookup[i][1])
  322.                         term.setTextColor(colors[data.display.text.highlight] or colors.lightGray)
  323.                         term.setBackgroundColor(colors[data.display.background.highlight] or colors.black)
  324.                         write(data.display.sprites.highlight or "-")
  325.                     else
  326.                         drawMapPixel(x+lookup[i][2],y+lookup[i][1])
  327.                     end
  328.                 end
  329.             end
  330.         end
  331.     end
  332.     while run do
  333.         a,i,x,y = os.pullEvent("mouse_click")
  334.         if i == 1 then
  335.             if map[y][x][2] ~= 2 then
  336.                 if data.settings.enableHighlight then
  337.                     highlight(x,y,true)
  338.                     os.pullEvent("mouse_up")
  339.                     highlight(x,y,false)
  340.                 end
  341.                 map[y][x][2] = 1
  342.                 if map[y][x][1] == 10 then
  343.                     run = false
  344.                 elseif map[y][x][1] == 0 then
  345.                     discover(x,y)
  346.                     repeat
  347.                         local tmp = #discover_chart
  348.                         for i=1, #discover_chart do
  349.                             discover(discover_chart[i][1],discover_chart[i][2])
  350.                         end
  351.                     until #discover_chart == tmp
  352.                 end
  353.                 drawMapPixel(x,y)
  354.             end
  355.         elseif i == 2 or i == 3 then
  356.             if map[y][x][2] ~= 2 and map[y][x][2] ~= 1 and map.flags ~= map.totalBombs then
  357.                 map[y][x][2] = 2 map.flags = map.flags+1
  358.                 if map[y][x][1] == 10 then map.correctFlags = map.correctFlags+1 end
  359.                 drawDisplay()
  360.             elseif map[y][x][2] == 2 then
  361.                 map[y][x][2] = 0 map.flags = map.flags-1
  362.                 if map[y][x][1] == 10 then map.correctFlags = map.correctFlags-1 end
  363.                 drawDisplay()
  364.             end
  365.             if map.correctFlags == map.totalBombs then result = "Win" run = false end
  366.             drawMapPixel(x,y)
  367.         end
  368.         --drawMap()
  369.     end
  370. end
  371.  
  372.  
  373.  
  374.  
  375.  
  376. local function runTime()
  377.     while true do
  378.         if time[2] > 0 then time[2] = 0 end
  379.         while run do
  380.             if time[1] then
  381.                 term.setTextColor(colors.white)
  382.                 term.setBackgroundColor(colors.black)
  383.                 term.setCursorPos((w-string.len("Time: "..time[2])),h+1)
  384.                 write("Time: "..time[2])
  385.                 sleep(1)
  386.                 time[2] = time[2] + 1
  387.             else
  388.                 sleep(.00001)
  389.             end
  390.         end
  391.         sleep(.00001)
  392.     end
  393. end
  394.  
  395. local function runMinesweeper()
  396.     generateMap()
  397.     term.clear()
  398.     drawMap()
  399.     drawDisplay() run = true
  400.     parallel.waitForAny(runGame, runMenu, runTime)
  401.     if result ~= "Exit" then
  402.         for i=1, #map do
  403.             for ii=1, #map[i] do
  404.                 if map[i][ii][1] == 10 and map[i][ii][2] == 2 then
  405.                     map[i][ii][2] = 3
  406.                 elseif map[i][ii][1] ~= 10 and map[i][ii][2] == 2 then
  407.                     map[i][ii][2] = 4
  408.                 else
  409.                     map[i][ii][2] = 1
  410.                 end
  411.             end
  412.         end
  413.         drawMap()
  414.         term.setCursorPos(1,h+1)
  415.         term.setTextColor(colors.white)
  416.         term.setBackgroundColor(colors.black) sleep(1)
  417.         write(result..". Press any key to exit...") sleep(.2) os.pullEvent()
  418.     end
  419.  
  420.  
  421.     term.clear() term.setCursorPos(1,1)
  422. end
  423.  
  424. local function main()
  425.     local r, m_sel, sel = true, 1,1
  426.     local m = {
  427.         {
  428.             {"Play Game", function() runMinesweeper() end},
  429.             {"Set Bombs", function() term.clear() term.setCursorPos(1,1) term.setTextColor(colors.white) write("Bombs: ") local tmp = tonumber(read()) if type(tmp) == "number" then tbombs = math.min(math.max(tmp,1),(w*h)-1) end end},
  430.             {"Create a Theme file", function() term.setTextColor(colors.white) if not fs.exists(dir.."/theme.lua") then local file = fs.open(dir.."/theme.lua", "w") if file then file.write(textutils.serialize(data)) file.close() term.clear() term.setCursorPos(1,1) write("Theme file created at '"..dir.."/theme.lua'.") else term.clear() term.setCursorPos(1,1) write("Failed to create File at '"..dir.."/theme.lua'.") end else term.clear() term.setCursorPos(1,1) write("Theme file Already exists at '"..dir.."/theme.lua'.") sleep(.5) end sleep(1) loop = false end},
  431.             {"Exit", function() r = false end},
  432.         },
  433.     }
  434.     term.clear()
  435.     while r do
  436.         term.setCursorPos(1,1)
  437.         term.setBackgroundColor(colors.black)
  438.         term.setTextColor(colors.lime)
  439.         print("Minesweeper")
  440.         term.setCursorPos(1,3)
  441.         for i=1, #m[m_sel] do
  442.             if i == sel then
  443.                 term.setTextColor(colors.white)
  444.                 print("> "..m[m_sel][i][1].." ")
  445.             else
  446.                 term.setTextColor(colors.gray)
  447.                 print(" "..m[m_sel][i][1].." ")
  448.             end
  449.         end
  450.         term.setCursorPos(1,h+1)
  451.         term.setTextColor(colors.gray)
  452.         write("Bombs: "..tbombs)
  453.         a,i = os.pullEvent("key")
  454.         if i == keys.w or i == keys.up then
  455.             if sel ~= 1 then sel = sel - 1 end
  456.         elseif i == keys.s or i == keys.down then
  457.             if sel ~= #m[m_sel] then sel = sel + 1 end
  458.         elseif i == keys.enter or i == keys.e then
  459.             m[m_sel][sel][2]() term.clear()
  460.         end
  461.     end
  462. end
  463.  
  464. main()
  465. term.setBackgroundColor(colors.black) term.setTextColor(colors.white) term.clear() term.setCursorPos(1,1) sleep(.1)
Advertisement
Add Comment
Please, Sign In to add comment