From 2c7e47fc121014c1218d58248cd7c49cf2f38f0a Mon Sep 17 00:00:00 2001 From: Nathan Korth Date: Sat, 25 Feb 2012 10:34:26 -0500 Subject: New plugin: Picross Picross is a puzzle game also known as Picture Crossword, Nonograms, or Paint By Numbers. See http://en.wikipedia.org/wiki/Nonogram for information on how to play. Update 1: nicer graphics with less images, fixed directory listing, changed how the board works to make a lot of math more sane Update 2: added missing rb.yield to viewPicture loop Update 3: you can now save a game in progress Update 4: fixed a file pointer leak, improved the numbers font Update 5: no images, use vector num draw library add zoom, freedraw -- Bilgus Change-Id: Idc476b46b6eaa10818400fa789701d5bac83467f --- apps/plugins/CATEGORIES | 1 + apps/plugins/SOURCES | 1 + apps/plugins/SUBDIRS | 1 + apps/plugins/picross.lua | 820 +++++++++++++++++++++++++++ apps/plugins/picross/picross.make | 24 + apps/plugins/picross/picross_default.picross | 7 + apps/plugins/picross/rb.picross | 7 + 7 files changed, 861 insertions(+) create mode 100644 apps/plugins/picross.lua create mode 100644 apps/plugins/picross/picross.make create mode 100755 apps/plugins/picross/picross_default.picross create mode 100644 apps/plugins/picross/rb.picross (limited to 'apps/plugins') diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 28b8b67c68..db0eb70fc4 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -82,6 +82,7 @@ pacbox,games pdbox,viewers pegbox,games periodic_table,apps +picross,games pictureflow,demos pitch_detector,apps pitch_screen,viewers diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index edc801362f..ff08074f82 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -116,6 +116,7 @@ metronome.c /* Lua needs at least 160 KB to work in */ #if PLUGIN_BUFFER_SIZE >= 0x80000 boomshine.lua +picross.lua lua_scripts.lua #ifdef HAVE_LCD_COLOR pixel-painter.lua diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index b9c18b5fd9..7884989d1c 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS @@ -87,4 +87,5 @@ mpegplayer #if PLUGIN_BUFFER_SIZE >= 0x80000 lua lua_scripts +picross #endif diff --git a/apps/plugins/picross.lua b/apps/plugins/picross.lua new file mode 100644 index 0000000000..26ad57ee74 --- /dev/null +++ b/apps/plugins/picross.lua @@ -0,0 +1,820 @@ +--[[ + __________ __ ___. + Open \______ \ ____ ____ | | _\_ |__ _______ ___ + Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + \/ \/ \/ \/ \/ + +Port of Picross (aka. Picture Crossword, Nonograms, Paint By Numbers) +Copyright (c) 2012 by Nathan Korth + +See http://en.wikipedia.org/wiki/Nonogram for details on how to play, and +http://nkorth.com/picross for more puzzles. + +]]-- + +require "actions" +require "luadir" +require("rbsettings") +require("settings") + +local _nums = require("draw_num") +local _clr = require("color") -- clrset, clrinc provides device independent colors +local _lcd = require("lcd") -- lcd helper functions + +local plugindir = rb.PLUGIN_GAMES_DATA_DIR +local userdir = plugindir .. "/picross" + +local wrap = rb.settings.read('global_settings', rb.system.global_settings.list_wraparound) +wrap = (wrap or 1) == 1 + +do -- free up some ram by removing items we don't need + local function strip_functions(t, ...) + local t_keep = {...} + local keep + for key, val in pairs(t) do + keep = false + for _, v in ipairs(t_keep) do + if string.find (key, v) then + keep = true; break + end + end + if keep ~= true then + t[key] = nil + end + end + end + + strip_functions(rb.actions, "PLA_", "TOUCHSCREEN", "_NONE") + rb.contexts = nil + + _clr.inc = nil + rb.metadata = nil -- remove metadata settings + rb.system = nil -- remove system settings + rb.settings = nil --remove setting read/write fns +end + +--colors for fg/bg ------------------------ +local WHITE = _clr.set(-1, 255, 255, 255) +local BLACK = _clr.set(0, 0, 0, 0) +------------------------------------------- + +-- set colors on color targets +if rb.lcd_rgbpack ~= nil then + rb.lcd_set_background(rb.lcd_rgbpack(255, 255, 255)) + rb.lcd_set_foreground(rb.lcd_rgbpack(0, 0, 0)) +end + +local TEXT_COLOR = BLACK + +if rb.LCD_DEPTH == 2 then TEXT_COLOR = bit.bnot(TEXT_COLOR) end + +--[[ +-- load images +local img_numbers = rb.read_bmp_file(rb.current_path().."picross_numbers.bmp") + +-- image helper function +function draw_image(img, x, y, w, h, tilenum) + + local func = rb.lcd_bitmap_transparent_part + or rb.lcd_bitmap_part -- Fallback version for grayscale targets + or rb.lcd_mono_bitmap_part -- Fallback version for mono targets + + func(img, 0, (tilenum * h), w, x, y, w, h) +end +]] + +function draw_number(x, y, w, tilenum, scale) + scale = scale or 1 + _nums.print(_LCD, tilenum, x, y, w, TEXT_COLOR, nil, nil, true, scale, scale) +end + +function showComplete(self) + if self:isComplete() then + rb.splash(rb.HZ * 2, "Puzzle complete!") + self:saveGame() + self.puzzleh = 50 + self.puzzlew = 50 + local old_boardh, old_boardw = self.boardh, self.boardw + local old_numbersw, old_numbersh = self.numbersw, self.numbersh + while self.numbersh > 0 do -- remove the number rows + table.remove (self.board, 1) + self.numbersh = self.numbersh - 1 + end + self.numbersh = 0 + self.numbersw = 0 + self.solution = nil + self.boardh = self.puzzleh + self.boardw = self.puzzlew + self.freedraw = 0 + -- find a free number + while rb.file_exists(string.format("%s/user_freedraw_%d.picross", + userdir, self.freedraw)) do + self.freedraw = self.freedraw + 1 + end + + for r = 1, self.boardh do + local old_row = self.board[r] or {} + + self.board[r] = {} + -- copy over the last drawing + for c = 1, self.boardw do + local ch = old_row[c + old_numbersw] + if not ch or ch ~= '*' then + self.board[r][c] = '.' + else + self.board[r][c] = '*' + end + end + end + rb.splash(rb.HZ * 3, "Free Draw!") + self.cursor.x = 1 + self.cursor.y = 1 + self.showComplete = function() end --show once, then remove the reference + end +end + +local State = { + puzzlew = 0, + puzzleh = 0, + numbersw = 0, + numbersh = 0, + boardw = 0, + boardh = 0, + board = {}, + solution = {}, + filename = '', + cursor = {x = 0, y = 0}, + scale = 1, + freedraw = false +} + +--[[ + +Notes on how puzzles work in the code: + +The "board" array is bigger than the actual puzzle, so the numbers +above and to the left of it can be stored and do not need to be recalculated +for every draw. (The "solution" array is the same size as the puzzle, however.) +The various width/height variables help keep track of where everything is. +(they should be fairly self-explanatory) + +The width/height of the numbers section is always half the width/height of the +puzzle. For odd-number-sized puzzles, the value must be rounded up. This is +because strings of squares must have at least one blank space in between. For +example, on a board 5 wide, the maximum set of row numbers is "1 1 1". + +Here are the values used in the "board" array: + ' ': empty space + '.': unfilled square + '*': filled square + [number]: number (not a string) + +The .picross puzzle files are text files which look pretty much the same as the +"board" array, with two differences: + + - puzzle files should not contain numbers, because they will be generated + based on the puzzle at runtime + - blank lines and lines starting with '#' are ignored + +]]-- + +function State:initBoard() + if self.freedraw then + -- clear board (set the puzzle area to '.' and everything else to ' ') + self.board = {} + for r = 1,self.boardh do + self.board[r] = {} + for c = 1,self.boardw do + if r > self.numbersh and c > self.numbersw then + self.board[r][c] = '.' + else + self.board[r][c] = ' ' + end + end + end + + -- reset cursor + self.cursor.x = 1 + self.cursor.y = 1 + return + end --freedraw + + -- metrics + self.puzzleh = #self.solution + self.puzzlew = #self.solution[1] + self.numbersh = math.floor(self.puzzleh / 2) + 1 + self.numbersw = math.floor(self.puzzlew / 2) + 1 + self.boardh = self.puzzleh + self.numbersh + self.boardw = self.puzzlew + self.numbersw + self.showComplete = showComplete + + -- clear board (set the puzzle area to '.' and everything else to ' ') + self.board = {} + for r = 1,self.boardh do + self.board[r] = {} + for c = 1,self.boardw do + if r > self.numbersh and c > self.numbersw then + self.board[r][c] = '.' + else + self.board[r][c] = ' ' + end + end + end + + -- reset cursor + self.cursor.x = self.numbersw + 1 + self.cursor.y = self.numbersh + 1 + + -- calculate row numbers + local rownums = {} + for r = 1,self.puzzleh do + rownums[r] = {} + local count = 0 + for c = 1,self.puzzlew do + if self.solution[r][c] == '*' then + -- filled square + count = count + 1 + else + -- empty square + if count > 0 then + table.insert(rownums[r], count) + count = 0 + end + end + end + -- if there were no empty squares + if count > 0 then + table.insert(rownums[r], count) + count = 0 + end + end + + -- calculate column numbers + local columnnums = {} + for c = 1,self.puzzlew do + columnnums[c] = {} + local count = 0 + for r = 1,self.puzzleh do + if self.solution[r][c] == '*' then + -- filled square + count = count + 1 + else + -- empty square + if count > 0 then + table.insert(columnnums[c], count) + count = 0 + end + end + end + -- if there were no empty squares + if count > 0 then + table.insert(columnnums[c], count) + count = 0 + end + end + + -- add row numbers to board + for r = 1,self.puzzleh do + for i,num in ipairs(rownums[r]) do + self.board[self.numbersh + r][self.numbersw - #rownums[r] + i] = num + end + end + + -- add column numbers to board + for c = 1,self.puzzlew do + for i,num in ipairs(columnnums[c]) do + self.board[self.numbersh - #columnnums[c] + i][self.numbersw + c] = num + end + end +end + +function State:saveGame() + local file + local boardw, boardh = self.boardw, self.boardh + + if self.freedraw then + self.filename = string.format("%s/user_freedraw_%d.picross", userdir, self.freedraw) + + + --remove blank lines from the end + while boardh > 1 and not string.find(table.concat(self.board[boardh]), "\*") do + boardh = boardh - 1 + end + --remove blank lines from right + local max_w = 0 + for r = self.numbersh + 1, boardh do + for c = max_w + 1, boardw do + if self.board[r][c] == '*' then + max_w = c + end + end + end + boardw = max_w + if max_w == 0 then return end--nothing to save + + file = io.open(self.filename, 'w') + else + file = io.open(plugindir .. '/picross.sav', 'w') + end + + if file then + file:write("#"..self.filename.."\n") + for r = self.numbersh + 1, boardh do + for c = self.numbersw + 1, boardw do + file:write(self.board[r][c]) + end + file:write("\n") + end + file:close() + if self.freedraw then + rb.splash(rb.HZ, "Freedraw saved.") + else + rb.splash(rb.HZ, "Game saved.") + end + return true + else + rb.splash(rb.HZ * 2, "Failed to open save file") + return false + end +end + +function State:loadSave() + local file = io.open(plugindir .. '/picross.sav') + if file then + -- first line is commented path of original puzzle + path = file:read('*l') + path = path:sub(2,-1) + -- prepare original puzzle + if self:loadFile(path) then + -- load saved board + contents = file:read('*all') + file:close() + local r = 1 + for line in contents:gmatch("[^\r\n]+") do + local c = 1 + for char in line:gmatch('.') do + self.board[self.numbersh + r][self.numbersw + c] = char + c = c + 1 + end + r = r + 1 + end + + return true + else + return false + end + else + return false + end +end + +function State:loadDefault() + self:loadFile(userdir .. '/picross_default.picross') +end + +function State:loadFile(path) + local file = io.open(path) + if file then + self.freedraw = false + local board = {} + local boardwidth = 0 + local count = 0 + contents = file:read('*all') + + for line in contents:gmatch("[^\r\n]+") do + count = count + 1 + -- ignore blank lines and comments + if line ~= '' and line:sub(1, 1) ~= '#' then + table.insert(board, {}) -- add a new row + + -- ensure all lines are the same width + if boardwidth == 0 then + boardwidth = #line + elseif #line ~= boardwidth then + -- a line was the wrong width + local err = "Invalid puzzle file!" + local msg = + string.format("%s (wrong line width ln: %d w: %d)", err, count, #line) + rb.splash(rb.HZ * 2, msg) + return false + end + local pos = 0 + for char in line:gmatch('.') do + pos = pos + 1 + if char == '*' or char == '.' then + table.insert(board[#board], char) + else + local err = "Invalid puzzle file!" + local msg = string.format("%s (invalid character ln: %d '%s' @ %d)", + err, count, char, pos) + -- invalid character in puzzle area + rb.splash(rb.HZ * 2, msg) + return false + end + end + else + -- display puzzle comments + --rb.splash(rb.HZ, line:sub(2,#line)) + end + end + + if #board == 0 then + -- empty file + rb.splash(rb.HZ * 2, "Invalid puzzle file! (empty)") + return false + end + + file:close() + + self.solution = board + self.filename = path + if self.puzzleh < 100 and self.puzzlew < 100 then + self:initBoard() + return true + else + -- puzzle too big + rb.splash(rb.HZ * 2, "Invalid puzzle file! (too big)") + return false + end + else + -- file open failed + rb.splash(rb.HZ * 2, "Failed to open file!") + return false + end +end + +function State:drawBoard() + local tw, th = 10 * self.scale, 10 * self.scale -- tile width and height (including bottom+right padding) + + local ofsx = rb.LCD_WIDTH/2 - 4 - (self.cursor.x * tw) + local ofsy = rb.LCD_HEIGHT/2 - 4 - (self.cursor.y * th) + + rb.lcd_clear_display() + + -- guide lines + for r = 0, self.puzzleh do + local x1, x2, y = + ofsx + tw - 1, + ofsx + ((self.boardw + 1) * tw) - 1, + ofsy + ((self.numbersh + 1 + r) * th) - 1 + if r % 5 == 0 or r == self.puzzleh then + rb.lcd_hline(x1, x2, y) + else + for x = x1, x2, 2 do + rb.lcd_drawpixel(x, y) + end + end + end + for c = 0, self.puzzlew do + local x, y1, y2 = + ofsx + ((self.numbersw + 1 + c) * tw) - 1, + ofsy + th - 1, + ofsy + ((self.boardh + 1) * th) - 1 + if c % 5 == 0 or c == self.puzzlew then + rb.lcd_vline(x, y1, y2) + else + for y = y1,y2, 2 do + rb.lcd_drawpixel(x, y) + end + end + end + + -- cursor + local cx, cy = ofsx + (self.cursor.x * tw) - 1, ofsy + (self.cursor.y * th) - 1 + rb.lcd_drawrect(cx, cy, tw + 1, th + 1) + local n_width = tw / self.scale / 2 - 1 + local xc = (tw - 5 * self.scale) / 2 + -- tiles + for r = 1, self.boardh do + for c = 1, self.boardw do + local x, y = ofsx + (c * tw) + 1, ofsy + (r * th) + 1 + + if self.board[r][c] == '.' then + -- unfilled square + elseif self.board[r][c] == '*' then + -- filled square + rb.lcd_fillrect(x, y, tw - 3, th - 3) + elseif self.board[r][c] == 'x' then + -- eliminated square + rb.lcd_drawline(x + 1, y + 1, x + tw - 5, y + th - 5) + rb.lcd_drawline(x + tw - 5, y + 1, x + 1, y + th - 5) + elseif self.board[r][c] == ' ' then + -- empty space + elseif self.board[r][c] > 0 and self.board[r][c] < 100 then + -- number + local num = self.board[r][c] + if num < 10 then + draw_number(x + xc, y, n_width, num, self.scale) + draw_number(x + xc + 1, y, n_width, num, self.scale) + else + draw_number(x, y, n_width, num, self.scale) + draw_number(x + 1, y, n_width, num, self.scale) + end + end + end + end + + rb.lcd_update() +end + +function State:isComplete() + for r = 1,self.puzzleh do + for c = 1,self.puzzlew do + if self.solution[r][c] == '*' and + self.board[self.numbersh + r][self.numbersw + c] ~= '*' then + return false + end + end + end + + return true +end + +function State:moveCursor(dir) + -- The cursor isn't allowed to move in the top-left quadrant of the board. + -- This has to be checked in up and left moves. + local in_board_area = (self.cursor.y > (self.numbersh + 1) + and self.cursor.x > self.numbersw + 1) + + if dir == 'left' then + if (self.cursor.x > (self.numbersw + 1) or self.cursor.y > self.numbersh) + and self.cursor.x > 1 then + self.cursor.x = self.cursor.x - 1 + elseif wrap == true then + if in_board_area then + self.cursor.x = 1 + else + self.cursor.x = self.boardw + end + dir = 'up' + end + elseif dir == 'right' then + if self.cursor.x < self.boardw then + self.cursor.x = self.cursor.x + 1 + elseif wrap == true then + if in_board_area then + self.cursor.x = 1 + else + self.cursor.x = self.numbersw + 1 + end + dir = 'down' + end + end + + if dir == 'up' then + if (self.cursor.y > (self.numbersh + 1) or self.cursor.x > self.numbersw) + and self.cursor.y > 1 then + self.cursor.y = self.cursor.y - 1 + elseif wrap == true then + if in_board_area then + self.cursor.y = 1 + else + self.cursor.y = self.boardh + end + end + elseif dir == 'down' then + if self.cursor.y < self.boardh then + self.cursor.y = self.cursor.y + 1 + elseif wrap == true then + if in_board_area then + self.cursor.y = 1 + else + self.cursor.y = self.numbersh + 1 + end + end + end +end + +function State:fillSquare(mode) + mode = mode or 0 + if self.cursor.x > self.numbersw and self.cursor.y > self.numbersh then + if self.board[self.cursor.y][self.cursor.x] == '*' and mode ~= 2 then + -- clear square + self.board[self.cursor.y][self.cursor.x] = '.' + elseif mode ~= 1 then -- '.' or 'x' + -- fill square + local x, y = self.cursor.x - self.numbersw, self.cursor.y - self.numbersh + if not self.solution or self.solution[y][x] == '*' then + self.board[self.cursor.y][self.cursor.x] = '*' + else + rb.splash(rb.HZ * 2, "Invalid move!") + -- "x" square for convenience + self.board[self.cursor.y][self.cursor.x] = 'x' + end + end + end + + self:showComplete() +end + +function State:eliminateSquare() + if not self.freedraw + and self.cursor.x > self.numbersw + and self.cursor.y > self.numbersh then + if self.board[self.cursor.y][self.cursor.x] == 'x' then + -- clear square + self.board[self.cursor.y][self.cursor.x] = '.' + else-- '.' or '*' + -- "x" square + self.board[self.cursor.y][self.cursor.x] = 'x' + end + else + self.board[self.cursor.y][self.cursor.x] = '.' + end +end + +-- main code ------------------------------------------------------------------ + +local function mainMenu() + local menu = { + "Resume", + "View picture", + "Restart puzzle", + "Load puzzle", + "Zoom " .. State.scale - 1, + "Save progress", + "Save and quit", + "Quit without saving" + } + local start + + if State.freedraw then + menu[6] = "Save freedraw " .. State.freedraw --Save Progress + end + while true do + local s = rb.do_menu("Picross", menu, start, false) + start = s + if s == 0 then + -- resume + return + elseif s == 1 then + -- view picture + viewPicture() + start = 0 --resume + elseif s == 2 then + -- restart + State:initBoard() + return + elseif s == 3 then + -- choose puzzle + if puzzleList() then + return + end + elseif s == 4 then + -- zoom + State.scale = State.scale + 1 + if State.scale > 4 then + State.scale = 1 + end + menu[5] = "Zoom " .. State.scale - 1 + elseif s == 5 then + -- save + if State:saveGame() then + return + end + elseif s == 6 then + -- save and quit + if State:saveGame() then + os.exit() + end + elseif s == 7 then + -- quit + os.exit() + elseif s == -2 then + -- back button pressed + return + else + -- something strange happened + rb.splash(rb.HZ * 2, "Invalid menu index: "..s) + end + end +end + +function puzzleList() + if rb.dir_exists(userdir) then + local files = {} + for file in luadir.dir(userdir) do + if file ~= '.' and file ~= '..' then + table.insert(files, file) + end + end + + table.sort(files) + local udir = userdir .. "/" + if #files > 0 then + local s = rb.do_menu("Puzzles", files, nil, false) + if s >= 0 and s < #files then + if State:loadFile(udir..files[s+1]) then + return true -- return to puzzle screen + else + -- puzzle failed to load, return to main menu + return false + end + elseif s == -2 then + -- back button pressed, return to main menu + return false + else + -- something strange happened + rb.splash(rb.HZ * 2, "Invalid menu index: "..s) + return false + end + else + rb.splash(rb.HZ * 2, "No puzzles found! Put .picross files in " .. userdir) + return false + end + else + rb.splash(rb.HZ * 2, "Put .picross files in " .. userdir) + return false + end +end + +function viewPicture() + rb.lcd_clear_display() + + -- draw filled squares as pixels (scaled 2x) + for r = State.numbersh + 1, State.boardh do + for c = State.numbersw + 1, State.boardw do + if State.board[r][c] == '*' then + --rb.lcd_drawpixel(c - State.numbersw, r - State.numbersh) + local px = (c - State.numbersw) * State.scale - State.scale + 1 + local py = (r - State.numbersh) * State.scale - State.scale + 1 + + rb.lcd_fillrect(px, py, State.scale, State.scale) + end + end + end + + rb.lcd_update() + + -- exit on button press + while true do + local action = rb.get_plugin_action(0) + + if action == rb.actions.PLA_EXIT + or action == rb.actions.PLA_CANCEL + or action == rb.actions.PLA_SELECT then + return + end + + rb.yield() + end +end + +if not State:loadSave() then + State:loadDefault() +end + +local act = rb.actions +local action = act.ACTION_NONE +local lockdraw = false + +while true do + action = rb.get_plugin_action(0) + if action == rb.actions.PLA_EXIT then + lockdraw = false + mainMenu() + elseif action == act.PLA_UP or action == act.PLA_UP_REPEAT then + State:moveCursor('up') + elseif action == act.PLA_DOWN or action == act.PLA_DOWN_REPEAT then + State:moveCursor('down') + elseif action == act.PLA_LEFT or action == act.PLA_LEFT_REPEAT then + State:moveCursor('left') + elseif action == act.PLA_RIGHT or action == act.PLA_RIGHT_REPEAT then + State:moveCursor('right') + elseif action == act.PLA_SELECT then + if lockdraw then + lockdraw = lockdraw - 1 + if lockdraw < 0 then + lockdraw = false + elseif lockdraw == 1 then + rb.splash(50, "clear") + else + rb.splash(50, "invert") + end + else + State:fillSquare() + end + action = act.ACTION_NONE + elseif action == act.PLA_SELECT_REPEAT then + if State.freedraw and not lockdraw then + lockdraw = 2 + rb.splash(50, "draw") + action = act.ACTION_NONE + end + elseif action == act.PLA_CANCEL then + State:eliminateSquare() + action = act.ACTION_NONE + else + action = act.ACTION_NONE + end + + if lockdraw and action ~= act.ACTION_NONE then + State:fillSquare(lockdraw) + end + + State:drawBoard() + + rb.yield() +end diff --git a/apps/plugins/picross/picross.make b/apps/plugins/picross/picross.make new file mode 100644 index 0000000000..7e78c0fb1c --- /dev/null +++ b/apps/plugins/picross/picross.make @@ -0,0 +1,24 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +LUASCR_SRCDIR := $(APPSDIR)/plugins/picross +LUASCR_BUILDDIR := $(BUILDDIR)/apps/plugins/picross +LUASCRS := $(wildcard $(LUASCR_SRCDIR)/*.picross) + +#DUMMY := $(info [${LUASCRS}]) + +DUMMY : all + +all: $(subst $(LUASCR_SRCDIR)/,$(LUASCR_BUILDDIR)/,$(LUASCRS)) + +$(LUASCR_BUILDDIR)/%.picross: $(LUASCR_SRCDIR)/%.picross | $(LUASCR_BUILDDIR) + $(call PRINTS,CP $(subst $(LUASCR_SRCDIR)/,,$<))cp $< $@ + +$(LUASCR_BUILDDIR): + $(call PRINTS,MKDIR $@)mkdir -p $(LUASCR_BUILDDIR)/ diff --git a/apps/plugins/picross/picross_default.picross b/apps/plugins/picross/picross_default.picross new file mode 100755 index 0000000000..ad7643b79e --- /dev/null +++ b/apps/plugins/picross/picross_default.picross @@ -0,0 +1,7 @@ +# simple default puzzle + +****..*...*.. +*...*.*...*.. +****..*.***** +*.....*...*.. +*.....*...*.. diff --git a/apps/plugins/picross/rb.picross b/apps/plugins/picross/rb.picross new file mode 100644 index 0000000000..bb63b506f5 --- /dev/null +++ b/apps/plugins/picross/rb.picross @@ -0,0 +1,7 @@ +#open source jukebox firmware + +****...**...***.*..*.............. +*...*.*..*.*....*.*.*............. +****..*..*.*....**..***...**..*..* +*..**.*..*.*....*.*.*..*.*..*..**. +*...*..**...***.*..****...**..*..* -- cgit v1.2.3