Kingdaro

Picross

Mar 10th, 2013
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.67 KB | None | 0 0
  1. -- variables
  2. local args = {...}
  3.  
  4. local picross = {}
  5. local size = 6
  6. local decodedRows = {}
  7. local decodedCols = {}
  8.  
  9. local config = {}
  10. local configPath = shell.resolve('.picross-config')
  11.  
  12. local running = true
  13.  
  14. local drawGrid, clear, chooseDrawStyle
  15.  
  16. -- logic functions
  17. local function loadConfig()
  18.     local file = fs.open(configPath, 'r')
  19.     if file then
  20.         config = textutils.unserialize(file.readAll())
  21.         return true, file.close()
  22.     end
  23.     return false
  24. end
  25.  
  26. local function saveConfig()
  27.     local file = fs.open(configPath, 'w')
  28.     file.write(textutils.serialize(config))
  29.     file.close()
  30. end
  31.  
  32. local function genPicross()
  33.     local x1, y1, x2, y2
  34.     local image
  35.    
  36.     if args[1] then
  37.         if tonumber(args[1]) then
  38.             size = tonumber(args[1])
  39.         else
  40.             image = paintutils.loadImage(shell.resolve(args[1]))
  41.             if image then
  42.                 local looping = true
  43.                 for y=1, #image do
  44.                     for x=1, #image[y] do
  45.                         if image[y][x] == 64 then
  46.                             if not (x1 and y1) then
  47.                                 x1, y1 = x, y
  48.                             else
  49.                                 x2, y2 = x, y
  50.                                 looping = false
  51.                                 break
  52.                             end
  53.                         end
  54.                     end
  55.                     if not looping then break end
  56.                 end
  57.             end
  58.         end
  59.     end
  60.    
  61.     if x1 and y1 and x2 and y2 then
  62.         x1, y1 = x1 + 1, y1 + 1
  63.         x2, y2 = x2 - 1, y2 - 1
  64.         size = math.max(x2 - x1 + 1, y2 - y1 + 1)
  65.     end
  66.    
  67.     for y=1, size do
  68.         picross[y] = {}
  69.         for x=1, size do
  70.             if image then
  71.                 picross[y][x] = {
  72.                     value = image[y + y1 - 1] and image[y + y1 - 1][x + x1 - 1] == 32768 and 1 or 0;
  73.                     marked = 1;
  74.                 }
  75.             else
  76.                 picross[y][x] = {
  77.                     value = math.random() > 0.5 and 0 or 1;
  78.                     marked = 1;
  79.                 }
  80.             end
  81.         end
  82.     end
  83. end
  84.  
  85. local function decode(str)
  86.     local decoded = {}
  87.     for bunch in str:gmatch('1+') do
  88.         table.insert(decoded, #bunch)
  89.     end
  90.     return decoded
  91. end
  92.  
  93. local function decodePicross()
  94.     for y=1, size do
  95.         local rowstr = ''
  96.         local decoded = ' '
  97.        
  98.         for i=1, #picross[y] do
  99.             rowstr = rowstr .. picross[y][i].value
  100.         end
  101.         table.insert(decodedRows, decode(rowstr))
  102.     end
  103.    
  104.     for x=1, size do
  105.         local colstr = ''
  106.         local decoded = ' '
  107.        
  108.         for i=1, size do
  109.             colstr = colstr .. picross[i][x].value
  110.         end
  111.         table.insert(decodedCols, decode(colstr))
  112.     end
  113. end
  114.  
  115. local function checkCorrect()
  116.     for y=1, size do
  117.         for x=1, size do
  118.             local cell = picross[y][x]
  119.             if (cell.value == 0 and cell.marked == 2)
  120.             or (cell.value == 1 and cell.marked ~= 2) then
  121.                 return false
  122.             end
  123.         end
  124.     end
  125.     return true
  126. end
  127.  
  128. local function showSolution()
  129.     for y=1, size do
  130.         for x=1, size do
  131.             local cell = picross[y][x]
  132.             cell.marked = cell.value == 0 and 3 or 2
  133.         end
  134.     end
  135. end
  136.  
  137. local function pause()
  138.     repeat
  139.         local ev = os.pullEvent()
  140.     until ev == 'key' or ev == 'mouse_click'
  141. end
  142.  
  143. local function getInput(ev, p1, p2, p3)
  144.     if ev == 'mouse_click' or ev == 'mouse_drag' then
  145.         local b, x, y = p1, p2, p3
  146.         local cx, cy = config.drawStyle == 'ascii' and (x + 1)/2 or x, y
  147.         if picross[cy] and picross[cy][cx] then
  148.             local cell = picross[cy][cx]
  149.            
  150.             if b == 1 then
  151.                 cell.marked = cell.marked ~= 2 and 2 or 1
  152.             elseif b == 2 then
  153.                 cell.marked = cell.marked ~= 3 and 3 or 1
  154.             end
  155.            
  156.             if checkCorrect() then
  157.                 drawGrid(true)
  158.                 running = false
  159.             end
  160.         end
  161.     end
  162.    
  163.     if ev == 'key' and p1 == keys.backspace then
  164.         showSolution()
  165.         drawGrid(true, true)
  166.         running = false
  167.     end
  168. end
  169.  
  170.  
  171. -- drawing functions
  172. function clear()
  173.     term.setBackgroundColor(colors.black)
  174.     term.setCursorPos(1,1)
  175.     term.clear()
  176. end
  177.  
  178. function chooseDrawStyle()
  179.     local options = {
  180.         {4,4,'Ascii', 'ascii'},
  181.         {4,5,'Black and White', 'baw'},
  182.         {4,6,'Color', 'color'}
  183.     }
  184.     local sel = 1
  185.     local writeText = function(str, x, y, color)
  186.         term.setTextColor(color or colors.white)
  187.         term.setCursorPos(x, y)
  188.         term.write(str)
  189.     end
  190.     local looping = true
  191.    
  192.     while looping do
  193.         clear()
  194.         writeText('Select Draw Style (Click twice)', 4, 2, colors.yellow)
  195.         for i=1, #options do
  196.             local opt = options[i]
  197.             if sel == i then
  198.                 writeText('> '..opt[3], opt[1] - 2, opt[2], colors.lime)
  199.             else
  200.                 writeText(opt[3], opt[1], opt[2], colors.white)
  201.             end
  202.         end
  203.        
  204.         local _, b, x, y = os.pullEvent('mouse_click')
  205.         for i=1, #options do
  206.             local opt = options[i]
  207.             if y == opt[2] then
  208.                 if sel == i then
  209.                     config.drawStyle = opt[4]
  210.                     looping = false
  211.                     break
  212.                 else
  213.                     sel = i
  214.                     break
  215.                 end
  216.             end
  217.         end
  218.     end
  219.    
  220.     clear()
  221.     writeText('Type "picross --drawmode" to go', 4, 2, colors.yellow)
  222.     writeText('back to this screen.', 4, 3, colors.yellow)
  223.     writeText('Press any key to continue.', 4, 4, colors.yellow)
  224.     pause()
  225. end
  226.  
  227. function drawGrid(winning, solution)
  228.     local t = term
  229.     local offset = solution and (
  230.         config.drawStyle == 'ascii' and size*2 + 7 or
  231.         size + math.floor(size/2) + 5
  232.     ) or 0
  233.    
  234.     if config.drawStyle == 'ascii' then
  235.         local chars = {'.','#','X'}
  236.         local color = {colors.white, winning and colors.lime or colors.yellow, colors.gray}
  237.        
  238.         for y=1, size do
  239.             for x=1, size do
  240.                 local marked = picross[y][x].marked
  241.                
  242.                 t.setCursorPos(x*2 - 1 + offset, y)
  243.                 t.setTextColor(color[marked])
  244.                 t.write(chars[marked])
  245.             end
  246.         end
  247.     else
  248.         -- useless table definitions but i'm too lazy to make it all shorter
  249.         local color = config.drawStyle == 'baw' and {
  250.             colors.black,
  251.             winning and colors.white or colors.lightGray,
  252.             colors.black
  253.         }
  254.         or config.drawStyle == 'color' and {
  255.             colors.black,
  256.             winning and colors.lime or colors.yellow,
  257.             colors.black
  258.         }
  259.        
  260.         for y=1, size do
  261.             for x=1, size do
  262.                 local marked = picross[y][x].marked
  263.                
  264.                 t.setCursorPos(x + offset, y)
  265.                 t.setBackgroundColor(color[marked])
  266.                 t.setTextColor(
  267.                     marked == 3 and colors.gray or
  268.                     colors.white
  269.                 )
  270.                 t.write(
  271.                     marked == 1 and '.' or
  272.                     marked == 3 and 'X' or
  273.                     ' '
  274.                 )
  275.             end
  276.         end
  277.     end
  278.    
  279.     local t = term
  280.     t.setTextColor(colors.lightBlue)
  281.     t.setBackgroundColor(colors.black)
  282.    
  283.     for i=1, #decodedRows do
  284.         local row = decodedRows[i]
  285.        
  286.         t.setCursorPos((config.drawStyle == 'ascii' and size*2 + 2 or size + 2) + offset, i)
  287.         t.write(table.concat(row, ' '))
  288.     end
  289.    
  290.     for i=1, #decodedCols do
  291.         local col = decodedCols[i]
  292.         for y=1, #col do
  293.             t.setCursorPos((config.drawStyle == 'ascii' and i*2 - 1 or i) + offset, size + y + 1)
  294.             t.write(tostring(col[y]):gsub('%..+$'))
  295.         end
  296.     end
  297. end
  298.  
  299. -- main running function
  300. local function run()
  301.     if args[1] == '--drawmode' or args[2] == '--drawmode' then
  302.         chooseDrawStyle()
  303.     end
  304.    
  305.     loadConfig()
  306.    
  307.     if not config.drawStyle then
  308.         chooseDrawStyle()
  309.     end
  310.    
  311.     genPicross()
  312.     decodePicross()
  313.    
  314.     while running do
  315.         clear()
  316.         drawGrid()
  317.         getInput(os.pullEvent())
  318.     end
  319.    
  320.     saveConfig()
  321.     pause()
  322.     clear()
  323. end
  324.  
  325. run()
Advertisement
Add Comment
Please, Sign In to add comment