diff --git a/.vscode/settings.json b/.vscode/settings.json index 99e9c3f..f3b270a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { - "editor.insertSpaces": false, - "editor.detectIndentation": false + "editor.insertSpaces": true, + "editor.detectIndentation": false, } \ No newline at end of file diff --git a/0hh1.p8 b/0hh1.p8 index b84a9b9..38da7c0 100644 --- a/0hh1.p8 +++ b/0hh1.p8 @@ -2,10 +2,9 @@ pico-8 cartridge // http://www.pico-8.com version 38 __lua__ - -- Font M3X6 by daniel linssen poke(0x5600, 4, 4, 7) -poke4(0x5700,unpack(split"0x0000.0000,0x0000.0000,0x0202.0202,0x0000.0200,0x0000.0505,0x0000.0000,0x0505.0705,0x0000.0507,0x0407.0106,0x0000.0203,0x0204.0100,0x0000.0401,0x0102.0502,0x0000.0305,0x0000.0102,0x0000.0000,0x0101.0102,0x0000.0201,0x0202.0201,0x0000.0102,0x0205.0000,0x0000.0005,0x0702.0000,0x0000.0002,0x0000.0000,0x0000.0102,0x0700.0000,0x0000.0000,0x0000.0000,0x0000.0200,0x0202.0404,0x0000.0101,0x0505.0506,0x0000.0305,0x0202.0302,0x0000.0702,0x0204.0403,0x0000.0701,0x0403.0403,0x0000.0304,0x0406.0505,0x0000.0404,0x0403.0107,0x0000.0304,0x0503.0106,0x0000.0605,0x0204.0407,0x0000.0202,0x0502.0506,0x0000.0305,0x0605.0503,0x0000.0304,0x0002.0000,0x0000.0002,0x0002.0000,0x0000.0102,0x0102.0400,0x0000.0402,0x0007.0000,0x0000.0007,0x0402.0100,0x0000.0102,0x0204.0403,0x0000.0200,0x0505.0506,0x0000.0601,0x0604.0300,0x0000.0705,0x0505.0301,0x0000.0705,0x0101.0600,0x0000.0701,0x0505.0604,0x0000.0705,0x0705.0600,0x0000.0601,0x0702.0204,0x0000.0202,0x0705.0600,0x0000.0304,0x0505.0301,0x0000.0505,0x0202.0002,0x0000.0202,0x0202.0002,0x0000.0102,0x0305.0101,0x0000.0505,0x0202.0202,0x0000.0402,0x0707.0300,0x0000.0507,0x0505.0300,0x0000.0505,0x0505.0600,0x0000.0305,0x0305.0700,0x0000.0101,0x0705.0600,0x0000.0404,0x0101.0600,0x0000.0101,0x0701.0600,0x0000.0304,0x0207.0202,0x0000.0202,0x0505.0500,0x0000.0705,0x0505.0500,0x0000.0205,0x0705.0500,0x0000.0507,0x0205.0500,0x0000.0505,0x0605.0500,0x0000.0304,0x0204.0700,0x0000.0701,0x0101.0103,0x0000.0301,0x0202.0101,0x0000.0404,0x0202.0203,0x0000.0302,0x0000.0502,0x0000.0000,0x0000.0000,0x0000.0403,0x0000.0201,0x0000.0000,0x0507.0506,0x0000.0505,0x0507.0503,0x0000.0705,0x0101.0106,0x0000.0701,0x0505.0503,0x0000.0305,0x0103.0107,0x0000.0701,0x0301.0106,0x0000.0101,0x0501.0106,0x0000.0705,0x0507.0505,0x0000.0505,0x0202.0207,0x0000.0702,0x0404.0407,0x0000.0304,0x0503.0505,0x0000.0505,0x0101.0101,0x0000.0701,0x0507.0705,0x0000.0505,0x0505.0503,0x0000.0505,0x0505.0506,0x0000.0305,0x0103.0507,0x0000.0101,0x0505.0506,0x0000.0403,0x0503.0507,0x0000.0505,0x0407.0106,0x0000.0304,0x0202.0207,0x0000.0202,0x0505.0505,0x0000.0705,0x0505.0505,0x0000.0205,0x0705.0505,0x0000.0507,0x0202.0505,0x0000.0505,0x0205.0505,0x0000.0202,0x0202.0407,0x0000.0701,0x0302.0204,0x0000.0402,0x0202.0202,0x0000.0202,0x0602.0201,0x0000.0102,0x0704.0000,0x0000.0001,0x0205.0200,0x0000.0000")) +poke4(0x5700, unpack(split "0x0000.0000,0x0000.0000,0x0202.0202,0x0000.0200,0x0000.0505,0x0000.0000,0x0505.0705,0x0000.0507,0x0407.0106,0x0000.0203,0x0204.0100,0x0000.0401,0x0102.0502,0x0000.0305,0x0000.0102,0x0000.0000,0x0101.0102,0x0000.0201,0x0202.0201,0x0000.0102,0x0205.0000,0x0000.0005,0x0702.0000,0x0000.0002,0x0000.0000,0x0000.0102,0x0700.0000,0x0000.0000,0x0000.0000,0x0000.0200,0x0202.0404,0x0000.0101,0x0505.0506,0x0000.0305,0x0202.0302,0x0000.0702,0x0204.0403,0x0000.0701,0x0403.0403,0x0000.0304,0x0406.0505,0x0000.0404,0x0403.0107,0x0000.0304,0x0503.0106,0x0000.0605,0x0204.0407,0x0000.0202,0x0502.0506,0x0000.0305,0x0605.0503,0x0000.0304,0x0002.0000,0x0000.0002,0x0002.0000,0x0000.0102,0x0102.0400,0x0000.0402,0x0007.0000,0x0000.0007,0x0402.0100,0x0000.0102,0x0204.0403,0x0000.0200,0x0505.0506,0x0000.0601,0x0604.0300,0x0000.0705,0x0505.0301,0x0000.0705,0x0101.0600,0x0000.0701,0x0505.0604,0x0000.0705,0x0705.0600,0x0000.0601,0x0702.0204,0x0000.0202,0x0705.0600,0x0000.0304,0x0505.0301,0x0000.0505,0x0202.0002,0x0000.0202,0x0202.0002,0x0000.0102,0x0305.0101,0x0000.0505,0x0202.0202,0x0000.0402,0x0707.0300,0x0000.0507,0x0505.0300,0x0000.0505,0x0505.0600,0x0000.0305,0x0305.0700,0x0000.0101,0x0705.0600,0x0000.0404,0x0101.0600,0x0000.0101,0x0701.0600,0x0000.0304,0x0207.0202,0x0000.0202,0x0505.0500,0x0000.0705,0x0505.0500,0x0000.0205,0x0705.0500,0x0000.0507,0x0205.0500,0x0000.0505,0x0605.0500,0x0000.0304,0x0204.0700,0x0000.0701,0x0101.0103,0x0000.0301,0x0202.0101,0x0000.0404,0x0202.0203,0x0000.0302,0x0000.0502,0x0000.0000,0x0000.0000,0x0000.0403,0x0000.0201,0x0000.0000,0x0507.0506,0x0000.0505,0x0507.0503,0x0000.0705,0x0101.0106,0x0000.0701,0x0505.0503,0x0000.0305,0x0103.0107,0x0000.0701,0x0301.0106,0x0000.0101,0x0501.0106,0x0000.0705,0x0507.0505,0x0000.0505,0x0202.0207,0x0000.0702,0x0404.0407,0x0000.0304,0x0503.0505,0x0000.0505,0x0101.0101,0x0000.0701,0x0507.0705,0x0000.0505,0x0505.0503,0x0000.0505,0x0505.0506,0x0000.0305,0x0103.0507,0x0000.0101,0x0505.0506,0x0000.0403,0x0503.0507,0x0000.0505,0x0407.0106,0x0000.0304,0x0202.0207,0x0000.0202,0x0505.0505,0x0000.0705,0x0505.0505,0x0000.0205,0x0705.0505,0x0000.0507,0x0202.0505,0x0000.0505,0x0205.0505,0x0000.0202,0x0202.0407,0x0000.0701,0x0302.0204,0x0000.0402,0x0202.0202,0x0000.0202,0x0602.0201,0x0000.0102,0x0704.0000,0x0000.0001,0x0205.0200,0x0000.0000")) #include globals.lua -- diff --git a/bg.lua b/bg.lua index 3fe3ba1..a72abb1 100644 --- a/bg.lua +++ b/bg.lua @@ -1,35 +1,36 @@ function draw_animated_bg(startx) - if (amplitude <= 0) return - startx = startx or 0 - fillp(0b0101101001011010) + if (amplitude <= 0) return + startx = startx or 0 + fillp(0b0101101001011010) - local color = 1 - -- vertical lines - local t = t()+10 - for i=startx-1,127,9 do - local a=sin(i*t/512)*amplitude+64 - local b=cos(i*t/256)*amplitude+64 - line( - i, - a, - i, - b , - color) - end + local color = 1 + -- vertical lines + local t = t() + 10 + for i = startx - 1, 127, 9 do + local a = sin(i * t / 512) * amplitude + 64 + local b = cos(i * t / 256) * amplitude + 64 + line( + i, + a, + i, + b, + color + ) + end - -- horizontal lines - for i=startx-1,127,9 do - local a=sin(i*t/512)*amplitude+64 - local b=cos(i*t/256)*amplitude+64 - line( - a, - i, - b , - i, - color) - end + -- horizontal lines + for i = startx - 1, 127, 9 do + local a = sin(i * t / 512) * amplitude + 64 + local b = cos(i * t / 256) * amplitude + 64 + line( + a, + i, + b, + i, + color + ) + end end function draw_bg_menu() - end \ No newline at end of file diff --git a/board.lua b/board.lua index d1e72a1..5197889 100644 --- a/board.lua +++ b/board.lua @@ -1,447 +1,441 @@ local Board = {} function Board.new() - local debug = false + local debug = false - local width = board_size -- tiles - local tile_width = 8 -- pixels - local padding = 1 - local tiles = {} - local locked = {} -- list of indexes + local width = board_size + -- tiles + local tile_width = 8 + -- pixels + local padding = 1 + local tiles = {} + local locked = {} + -- list of indexes - local reset = function() - tiles = {} - for i = 1, width * width do - tiles[i] = 0 - end - locked = {} - end + local reset = function() + tiles = {} + for i = 1, width * width do + tiles[i] = 0 + end + locked = {} + end - reset() + reset() - return { - reset = reset, + return { + reset = reset, - get_tile = function(self, idx) - return tiles[idx] - end, + get_tile = function(self, idx) + return tiles[idx] + end, - -- returns a COPY of the tiles array - get_tiles_copy = function(self) - return copy(tiles) - end, + -- returns a COPY of the tiles array + get_tiles_copy = function(self) + return copy(tiles) + end, - -- overwrites the whole tiles array - set_tiles = function(self, newtiles) - assert(#newtiles == #tiles, "New tiles array must have a length of " .. #tiles) - tiles = copy(newtiles) - end, + -- overwrites the whole tiles array + set_tiles = function(self, newtiles) + assert(#newtiles == #tiles, "New tiles array must have a length of " .. #tiles) + tiles = copy(newtiles) + end, - idx_xy = function(self, idx) - return idx_xy(idx, width) - end, + idx_xy = function(self, idx) + return idx_xy(idx, width) + end, - xy_idx = function(self, x, y) - return xy_idx(x, y, width) - end, + xy_idx = function(self, x, y) + return xy_idx(x, y, width) + end, - draw_coords = function(self, x, y) - local margin = (128 - (tile_width + padding) * width) / 2- padding - if not y then x, y = self:idx_xy(x) end - return margin + (x-1)*tile_width + (x-1)*padding, - margin + (y-1)*tile_width + (y-1)*padding - end, + draw_coords = function(self, x, y) + local margin = (128 - (tile_width + padding) * width) / 2 - padding + if not y then x, y = self:idx_xy(x) end + return margin + (x - 1) * tile_width + (x - 1) * padding, margin + (y - 1) * tile_width + (y - 1) * padding + end, - get_size = function(self) - return width - end, + get_size = function(self) + return width + end, - get_tile_width = function(self) - return tile_width + padding - end, + get_tile_width = function(self) + return tile_width + padding + end, - fill = function(self, idx, color, invert) - if idx > width*width then return end - if invert then - color = color == YELLOW and BLUE or YELLOW - end - tiles[idx] = color - end, + fill = function(self, idx, color, invert) + if idx > width * width then return end + if invert then + color = color == YELLOW and BLUE or YELLOW + end + tiles[idx] = color + end, - try_flip_tile = function(self, id) - local to_color = nil - if locked[id] then return end - local from_color = tiles[id] - if tiles[id] == 0 then - to_color = YELLOW - elseif tiles[id] == YELLOW then - to_color = BLUE - else tiles[id] = 0 - -- empty tile - end - if to_color then - tiles[id] = to_color - end - local x,y = self:draw_coords(id) - spawn_tile_transition(x, y, tile_width-1, tile_width-1, from_color, to_color) - end, + try_flip_tile = function(self, id) + local to_color = nil + if locked[id] then return end + local from_color = tiles[id] + if tiles[id] == 0 then + to_color = YELLOW + elseif tiles[id] == YELLOW then + to_color = BLUE + else + tiles[id] = 0 + -- empty tile + end + if to_color then + tiles[id] = to_color + end + local x, y = self:draw_coords(id) + spawn_tile_transition(x, y, tile_width - 1, tile_width - 1, from_color, to_color) + end, - get_rows = function(self) - local ret = {} - for i = 1, width do - add(ret, slice(tiles, ((i - 1) * width) + 1, i * width)) - end - return ret - end, + get_rows = function(self) + local ret = {} + for i = 1, width do + add(ret, slice(tiles, (i - 1) * width + 1, i * width)) + end + return ret + end, - get_cols = function(self) - local ret = {} - local rows = self.get_rows(self) - for i = 1, width do - add(ret, map(rows, function(v) return v[i] end)) - end - return ret - end, + get_cols = function(self) + local ret = {} + local rows = self.get_rows(self) + for i = 1, width do + add(ret, map(rows, function(v) return v[i] end)) + end + return ret + end, - is_complete = function(self) - return count(tiles, 0) == 0 - end, + --- Returns true if all tiles are filled + is_complete = function(self) + return count(tiles, 0) == 0 + end, - is_valid = function(self) - return #self:get_issues() == 0 - end, + --- Returns true if the board is valid (respects the rules) + is_valid = function(self) + return #self:get_issues() == 0 + end, - -- returns a list of issues of the board's current state - get_issues = function(self, details) - local rows = self:get_rows() - local issues = {} - for y,row in ipairs(rows) do - local filled = count(row, 0) == 0 - -- check count - if filled and count(row, BLUE) ~= count(row, YELLOW) then - add(issues, {"row", "count", row, y}) - if (debug) printh("uneven count on row "..y) - if (not details) return issues - end - -- check identical lines - for k,other in ipairs(rows) do - if filled and equal(other, row) and other ~= row then - add(issues, {"row", "identical", row, y, k}) - if (debug) printh("equal rows "..k) - if (not details) return issues - end - end - -- check triples - if self:count_consecutives(row) > 2 then - add(issues, {"row", "triples", row, y}) - if (debug) printh("triples") - if (not details) return issues - end - end + -- returns a list of issues of the board's current state + get_issues = function(self, details) + local rows = self:get_rows() + local issues = {} + for y, row in ipairs(rows) do + local filled = count(row, 0) == 0 + -- check count + if filled and count(row, BLUE) ~= count(row, YELLOW) then + add(issues, { "row", "count", row, y }) + if (debug) printh("uneven count on row " .. y) if (not details) return issues + end + -- check identical lines + for k, other in ipairs(rows) do + if filled and equal(other, row) and other ~= row then + add(issues, { "row", "identical", row, y, k }) + if (debug) printh("equal rows " .. k) if (not details) return issues + end + end + -- check triples + if self:count_consecutives(row) > 2 then + add(issues, { "row", "triples", row, y }) + if (debug) printh("triples") if (not details) return issues + end + end - local cols = self:get_cols() - for x,col in ipairs(cols) do - local filled = count(col, 0) == 0 + local cols = self:get_cols() + for x, col in ipairs(cols) do + local filled = count(col, 0) == 0 - -- check count - if filled and count(col, BLUE) ~= count(col, YELLOW) then - add(issues, {"col", "count", col, x}) - if (debug) printh("uneven count") - if (not details) return issues - end - -- check identical lines - for k,other in ipairs(cols) do - if filled and equal(other, col) and other ~= col then - add(issues, {"col", "identical", col, x, k}) - if (debug) printh("equal cols") - if (not details) return issues - end - end - -- check triples - if self:count_consecutives(col) > 2 then - add(issues, {"col", "triples", col, x}) - if (debug) printh("triples") - if (not details) return issues - end - end - return issues - end, + -- check count + if filled and count(col, BLUE) ~= count(col, YELLOW) then + add(issues, { "col", "count", col, x }) + if (debug) printh("uneven count") if (not details) return issues + end + -- check identical lines + for k, other in ipairs(cols) do + if filled and equal(other, col) and other ~= col then + add(issues, { "col", "identical", col, x, k }) + if (debug) printh("equal cols") if (not details) return issues + end + end + -- check triples + if self:count_consecutives(col) > 2 then + add(issues, { "col", "triples", col, x }) + if (debug) printh("triples") if (not details) return issues + end + end + return issues + end, - count_consecutives = function(self, line) - local top = 0 - local current = 0 - local last = 0 - for v in all(line) do - if v ~= last then - top = max(current, top) - current = 1 - last = v - elseif v~= 0 then - current += 1 - end - end - return max(current, top) - end, + count_consecutives = function(self, line) + local top = 0 + local current = 0 + local last = 0 + for v in all(line) do + if v ~= last then + top = max(current, top) + current = 1 + last = v + elseif v ~= 0 then + current += 1 + end + end + return max(current, top) + end, - -- - -- Returns the index of a random zero tile - -- - get_random_zero = function(self) - assert(count(tiles, 0) > 0, "No zero left") - local zeroes = filter(tiles, function(v) return v == 0 end, true) - local z = {} - for k,v in pairs(zeroes) do - add(z, k) - end - return rnd(z) - end, + -- + -- Returns the index of a random zero tile + -- + get_random_zero = function(self) + assert(count(tiles, 0) > 0, "No zero left") + local zeroes = filter(tiles, function(v) return v == 0 end, true) + local z = {} + for k, v in pairs(zeroes) do + add(z, k) + end + return rnd(z) + end, - -- - -- Returns the index of a random non-zero tile - -- - get_random_non_zero = function(self) - assert(count(tiles, 0) < #tiles, "All zeroes") - local numbers = filter(tiles, function(v) return v ~= 0 end, true) - local z = {} - for k,v in pairs(numbers) do - add(z, k) - end - return rnd(z) - end, + -- + -- Returns the index of a random non-zero tile + -- + get_random_non_zero = function(self) + assert(count(tiles, 0) < #tiles, "All zeroes") + local numbers = filter(tiles, function(v) return v ~= 0 end, true) + local z = {} + for k, v in pairs(numbers) do + add(z, k) + end + return rnd(z) + end, - tostring = function(self) - local str = '' - for v in all(tiles) do - str ..= ", " .. v - end - return str - end, + tostring = function(self) + local str = '' + for v in all(tiles) do + str ..= ", " .. v + end + return str + end, - -- Solves 1 step of the board - -- Returns "valid" if it solved it without guessing - -- Returns "invalid" if the board cannot be solved - solve_step = function(self, random) - local zeroes = count(tiles, 0) - self:surround_doubles() - self:split_triples() - self:fill_lines() - self:no_identical_lines() - local changed = zeroes ~= count(tiles, 0) + -- Solves 1 step of the board + -- Returns "valid" if it solved it without guessing + -- Returns "invalid" if the board cannot be solved + solve_step = function(self, random) + local zeroes = count(tiles, 0) + self:surround_doubles() + self:split_triples() + self:fill_lines() + self:no_identical_lines() + local changed = zeroes ~= count(tiles, 0) - if not changed and random and not self:is_complete() then - -- Set a random color - local z = self:get_random_zero() - self:fill(z, rnd({BLUE, YELLOW})) - if (debug) printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z) - return "invalid" - end - return (changed or self:is_complete()) and "valid" or "invalid" - end, + if not changed and random and not self:is_complete() then + -- Set a random color + local z = self:get_random_zero() + self:fill(z, rnd({ BLUE, YELLOW })) + if (debug) printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z) return "invalid" + end + return (changed or self:is_complete()) and "valid" or "invalid" + end, - surround_doubles = function(self) - for idx,v in ipairs(tiles) do - local x,y = self:idx_xy(idx) - if v == 0 then - local neighbors = {} - -- 2 tiles on the left - if x >= 3 then - add(neighbors, {idx, idx-1, idx-2}) - end - -- 2 tiles on the right - if x <= width-2 then - add(neighbors, {idx, idx+1, idx+2}) - end - -- 2 tiles on top - if y >= 3 then - add(neighbors, {idx, idx-width, idx - width*2}) - end - -- 2 tiles under - if y <= width-2 then - add(neighbors, {idx, idx+width, idx + width*2}) - end + surround_doubles = function(self) + for idx, v in ipairs(tiles) do + local x, y = self:idx_xy(idx) + if v == 0 then + local neighbors = {} + -- 2 tiles on the left + if x >= 3 then + add(neighbors, { idx, idx - 1, idx - 2 }) + end + -- 2 tiles on the right + if x <= width - 2 then + add(neighbors, { idx, idx + 1, idx + 2 }) + end + -- 2 tiles on top + if y >= 3 then + add(neighbors, { idx, idx - width, idx - width * 2 }) + end + -- 2 tiles under + if y <= width - 2 then + add(neighbors, { idx, idx + width, idx + width * 2 }) + end - -- only keep pairs that are identical (and not 0) - neighbors = filter(neighbors, function (o) return tiles[o[2]] == tiles[o[3]] and tiles[o[2]] ~= 0 end) + -- only keep pairs that are identical (and not 0) + neighbors = filter(neighbors, function(o) return tiles[o[2]] == tiles[o[3]] and tiles[o[2]] ~= 0 end) - -- do the surrounding - for item in all(neighbors) do - if item[1] then - if (debug) printh("Surrounding at " .. item[1]) - self:fill(item[1], tiles[item[2]], true) - end - end - end - end - end, + -- do the surrounding + for item in all(neighbors) do + if item[1] then + if (debug) printh("Surrounding at " .. item[1]) self:fill(item[1], tiles[item[2]], true) + end + end + end + end + end, - split_triples = function(self) - for idx, col in ipairs(tiles) do - local x,y = self:idx_xy(idx) - if col == 0 then + split_triples = function(self) + for idx, col in ipairs(tiles) do + local x, y = self:idx_xy(idx) + if col == 0 then + if x > 1 and x < width then + -- check horizontal + local prev = tiles[idx - 1] + local next = tiles[idx + 1] + if prev ~= 0 and prev == next then + if (debug) printh("Splitting at " .. idx) self:fill(idx, prev, true) + end + end - if x > 1 and x < width then - -- check horizontal - local prev = tiles[idx-1] - local next = tiles[idx+1] - if prev ~= 0 and prev == next then - if (debug) printh("Splitting at " .. idx) - self:fill(idx, prev, true) - end - end + if y > 1 and y < width then + -- check vertical + local prev = tiles[idx - width] + local next = tiles[idx + width] + if prev ~= 0 and prev == next then + if (debug) printh("Splitting at " .. idx) self:fill(idx, prev, true) + end + end + end + end + end, - if y>1 and y < width then - -- check vertical - local prev = tiles[idx-width] - local next = tiles[idx+width] - if prev ~= 0 and prev == next then - if (debug) printh("Splitting at " .. idx) - self:fill(idx, prev, true) - end - end - end - end - end, + fill_lines = function(self) + local rows = self:get_rows() + local cols = self:get_cols() - fill_lines = function(self) - local rows = self:get_rows() - local cols = self:get_cols() + -- rows + for y, row in ipairs(rows) do + local a = count(row, BLUE) + local b = count(row, YELLOW) + if a ~= b then + if a == width / 2 then self:fill_row(y, YELLOW) end + if b == width / 2 then self:fill_row(y, BLUE) end + end + end - -- rows - for y,row in ipairs(rows) do - local a = count(row, BLUE) - local b = count(row, YELLOW) - if a ~= b then - if a == width/2 then self:fill_row(y, YELLOW) end - if b == width/2 then self:fill_row(y, BLUE) end - end - end + -- columns + for x, col in ipairs(cols) do + local a = count(col, BLUE) + local b = count(col, YELLOW) + if a ~= b then + if a == width / 2 then self:fill_col(x, YELLOW) end + if b == width / 2 then self:fill_col(x, BLUE) end + end + end + end, - -- columns - for x,col in ipairs(cols) do - local a = count(col, BLUE) - local b = count(col, YELLOW) - if a ~= b then - if a == width/2 then self:fill_col(x, YELLOW) end - if b == width/2 then self:fill_col(x, BLUE) end - end - end - end, + fill_row = function(self, y, color) + if (debug) printh("Filling line " .. y .. " in " .. (color == BLUE and "blue" or "yellow")) + local idx = self:xy_idx(1, y) + for i = idx, idx + width - 1 do + if self:get_tile(i) == 0 then + self:fill(i, color) + end + end + end, - fill_row = function(self, y, color) - if (debug) printh("Filling line " .. y .. " in " .. (color == BLUE and "blue" or "yellow")) - local idx = self:xy_idx(1, y) - for i = idx, (idx+width-1) do - if self:get_tile(i) == 0 then - self:fill(i, color) - end - end - end, + fill_col = function(self, x, color) + if (debug) printh("Filling column " .. x .. " in " .. (color == BLUE and "blue" or "yellow")) + local idx = self:xy_idx(x, 1) + for i = idx, #tiles, width do + if self:get_tile(i) == 0 then + self:fill(i, color) + end + end + end, - fill_col = function(self, x, color) - if (debug) printh("Filling column " .. x .. " in " .. (color == BLUE and "blue" or "yellow")) - local idx = self:xy_idx(x, 1) - for i = idx, #tiles, width do - if self:get_tile(i) == 0 then - self:fill(i, color) - end - end - end, + -- Finds "identical" lines, and fill the 2 remaining tiles with inverted colors + no_identical_lines = function(self) + -- columns + local cols = self:get_cols() + for x, col in ipairs(cols) do + -- if the line has the corrent number of colors, + -- but missing 2 tiles + if count(col, 0) == 2 and count(col, BLUE) == count(col, YELLOW) then + local y1, y2 = unpack(find(col, 0)) -- get the position of the 2 missing tiles + -- create both both solutions + local ab = copy(col) ab[y1] = BLUE ab[y2] = YELLOW + local ba = copy(col) ba[y1] = YELLOW ba[y2] = BLUE + -- Check if a dupe exists + for x2, col in ipairs(cols) do + if equal(col, ab) then + self:fill(self:xy_idx(x, y1), YELLOW) + self:fill(self:xy_idx(x, y2), BLUE) + goto continue + elseif equal(col, ba) then + self:fill(self:xy_idx(x, y1), BLUE) + self:fill(self:xy_idx(x, y2), YELLOW) + goto continue + end + end + end + ::continue:: + end - -- Finds "identical" lines, and fill the 2 remaining tiles with inverted colors - no_identical_lines = function(self) - -- columns - local cols = self:get_cols() - for x,col in ipairs(cols) do - -- if the line has the corrent number of colors, - -- but missing 2 tiles - if count(col, 0) == 2 and count(col, BLUE) == count(col, YELLOW) then - local y1, y2 = unpack(find(col, 0)) -- get the position of the 2 missing tiles - -- create both both solutions - local ab = copy(col) ab[y1] = BLUE ab[y2] = YELLOW - local ba = copy(col) ba[y1] = YELLOW ba[y2] = BLUE - -- Check if a dupe exists - for x2,col in ipairs(cols) do - if equal(col, ab) then - self:fill(self:xy_idx(x,y1), YELLOW) - self:fill(self:xy_idx(x,y2), BLUE) - goto continue - elseif equal(col, ba) then - self:fill(self:xy_idx(x,y1), BLUE) - self:fill(self:xy_idx(x,y2), YELLOW) - goto continue - end - end - end - ::continue:: - end + -- rows + local rows = self:get_rows() + for y, row in ipairs(rows) do + if count(row, 0) == 2 and count(row, BLUE) == count(row, YELLOW) then + local x1, x2 = unpack(find(row, 0)) + local ab = copy(row) ab[x1] = BLUE ab[x2] = YELLOW + local ba = copy(row) ba[x1] = YELLOW ba[x2] = BLUE + -- Check if a dupe exists + for y2, row in ipairs(rows) do + if equal(row, ab) then + self:fill(self:xy_idx(x1, y), YELLOW) + self:fill(self:xy_idx(x2, y), BLUE) + goto continue + elseif equal(row, ba) then + self:fill(self:xy_idx(x1, y), BLUE) + self:fill(self:xy_idx(x2, y), YELLOW) + goto continue + end + end + end + ::continue:: + end + end, - -- rows - local rows = self:get_rows() - for y,row in ipairs(rows) do - if count(row, 0) == 2 and count(row, BLUE) == count(row, YELLOW) then - local x1, x2 = unpack(find(row, 0)) - local ab = copy(row) ab[x1] = BLUE ab[x2] = YELLOW - local ba = copy(row) ba[x1] = YELLOW ba[x2] = BLUE - -- Check if a dupe exists - for y2,row in ipairs(rows) do - if equal(row, ab) then - self:fill(self:xy_idx(x1,y), YELLOW) - self:fill(self:xy_idx(x2,y), BLUE) - goto continue - elseif equal(row, ba) then - self:fill(self:xy_idx(x1,y), BLUE) - self:fill(self:xy_idx(x2,y), YELLOW) - goto continue - end - end - end - ::continue:: - end - end, + lock_tiles = function(self) + locked = {} + for k, v in ipairs(tiles) do + if v > 0 then locked[k] = true end + end + end, - lock_tiles = function(self) - locked = {} - for k,v in ipairs(tiles) do - if v > 0 then locked[k] = true end - end - end, + is_locked = function(self, idx) + return locked[idx] + end, - is_locked = function(self, idx) - return locked[idx] - end, + draw_bg_tile = function(self, k) + local w = tile_width + local x, y = self:draw_coords(k) + rectfill2(x + 1, y, w - 2, w, 1) + rectfill2(x, y + 1, w, w - 2, 1) + end, - draw_bg_tile = function(self, k) - local w = tile_width - local x,y = self:draw_coords(k) - rectfill2(x+1, y, w-2, w, 1) - rectfill2(x, y+1, w, w-2, 1) - end, + draw = function(self) + local w = tile_width + for k, v in ipairs(tiles) do + self:draw_tile(k) + end + end, - draw = function(self) - local w = tile_width - for k,v in ipairs(tiles) do - self:draw_tile(k) - end - end, - - draw_tile = function(self, idx) - local w = tile_width - local v = tiles[idx] - if v > 0 then - local x,y = self:draw_coords(idx) - local color = get_main_color(v) - local shade = get_shade_color(v) - if color == 1 then fillp(▒) else fillp(█) end - if self:is_locked(idx) then - rectfill2(x, y, w, w, color) - else - roundedrect(x, y, w, w, color) - line(x+1, y+w-1, x+w-2, y+w-1, shade) - line(x+w-1, y+1, x+w-1, y+w-2, shade) - end - else - fillp(█) - self:draw_bg_tile(idx) - end - end, - } + draw_tile = function(self, idx) + local w = tile_width + local v = tiles[idx] + if v > 0 then + local x, y = self:draw_coords(idx) + local color = get_main_color(v) + local shade = get_shade_color(v) + if color == 1 then fillp(▒) else fillp(█) end + if self:is_locked(idx) then + rectfill2(x, y, w, w, color) + else + roundedrect(x, y, w, w, color) + line(x + 1, y + w - 1, x + w - 2, y + w - 1, shade) + line(x + w - 1, y + 1, x + w - 1, y + w - 2, shade) + end + else + fillp(█) + self:draw_bg_tile(idx) + end + end + } end \ No newline at end of file diff --git a/coroutines.lua b/coroutines.lua index a0e41d7..ce6f76b 100644 --- a/coroutines.lua +++ b/coroutines.lua @@ -1,34 +1,35 @@ -local coroutines={} +local coroutines = {} -- starts a coroutine and saves it for future reference function startcoroutine(co) - assert(tostr(co) == "[thread]") -- make sure that co is a coroutine, the return value of cocreate() - add(coroutines, co) + assert(tostr(co) == "[thread]") + -- make sure that co is a coroutine, the return value of cocreate() + add(coroutines, co) end -- stops the the coroutine function stopcoroutine(co) - del(coroutines, co) + del(coroutines, co) end function _coresolve() - for co in all(coroutines) do - if costatus(co) != 'dead' then - assert(coresume(co)) - else - stopcoroutine(co) - end - end + for co in all(coroutines) do + if costatus(co) != 'dead' then + assert(coresume(co)) + else + stopcoroutine(co) + end + end end -- to be used inside a coroutine function wait(seconds) - wait_frames(seconds*30) + wait_frames(seconds * 30) end -- to be used inside a coroutine function wait_frames(frames) - for i=1,frames do - yield() - end + for i = 1, frames do + yield() + end end \ No newline at end of file diff --git a/globals.lua b/globals.lua index 29e8838..a5a0b40 100644 --- a/globals.lua +++ b/globals.lua @@ -12,24 +12,24 @@ local YELLOW = 1 -- 🅾️ Z[C]N ❎ [X]VM -- X and C have the same position on QWERTY and AZERTY -local LEFT,RIGHT,UP,DOWN,BTN_O,BTN_X = 0,1,2,3,4,5 +local LEFT, RIGHT, UP, DOWN, BTN_O, BTN_X = 0, 1, 2, 3, 4, 5 local patterns = { - 0b0000000000000000, - 0b1000000000000000, - 0b1000000000100000, - 0b1010000000100000, - 0b1010000010100000, - 0b1010010010100000, - 0b1010010010100001, - 0b1010010110100001, - 0b1010010110100101, - 0b1110010110100101, - 0b1110010110110101, - 0b1111010110110101, - 0b1111010111110101, - 0b1111110111110101, - 0b1111110111110111, - 0b1111111111110111, - 0b1111111111111111, + 0b0000000000000000, + 0b1000000000000000, + 0b1000000000100000, + 0b1010000000100000, + 0b1010000010100000, + 0b1010010010100000, + 0b1010010010100001, + 0b1010010110100001, + 0b1010010110100101, + 0b1110010110100101, + 0b1110010110110101, + 0b1111010110110101, + 0b1111010111110101, + 0b1111110111110101, + 0b1111110111110111, + 0b1111111111110111, + 0b1111111111111111 } \ No newline at end of file diff --git a/main.lua b/main.lua index 39dc1cd..1d6088d 100644 --- a/main.lua +++ b/main.lua @@ -3,62 +3,63 @@ -- function custom_font() - poke(0x5f58,0x81) + poke(0x5f58, 0x81) end function standard_font(font) - poke(0x5f58,0x80) + poke(0x5f58, 0x80) end function idx_xy(idx, width) - return (idx - 1) % width + 1, (idx - 1) \ width + 1 + return (idx - 1) % width + 1, (idx - 1) \ width + 1 end function xy_idx(x, y, width) - return ((y - 1) * width) + x + return (y - 1) * width + x end function map(tbl, f) - local t = {} - for k, v in pairs(tbl) do - t[k] = f(v) - end - return t + local t = {} + for k, v in pairs(tbl) do + t[k] = f(v) + end + return t end function filter(tbl, f, keepindex) - local ret = {} - for k, v in pairs(tbl) do - if f(v) then - if keepindex - then ret[k] = v - else add(ret, v) - end - end - end - return ret + local ret = {} + for k, v in pairs(tbl) do + if f(v) then + if keepindex then + ret[k] = v + else + add(ret, v) + end + end + end + return ret end function slice(tbl, first, last, step) - local sliced = {} - for i = (first or 1), (last or #tbl), (step or 1) do - sliced[#sliced + 1] = tbl[i] - end - return sliced + local sliced = {} + for i = first or 1, last or #tbl, step or 1 do + sliced[#sliced + 1] = tbl[i] + end + return sliced end function rectfill2(x, y, w, h, col) - rectfill(x, y, x+w-1, y+h-1, col) + rectfill(x, y, x + w - 1, y + h - 1, col) end function roundedrect(x, y, w, h, col) - rectfill2(x,y,w,h,0) - rectfill2(x+1, y, w-2, h, col) - rectfill2(x, y+1, w, h-2, col) + rectfill2(x, y, w, h, 0) + rectfill2(x + 1, y, w - 2, h, col) + rectfill2(x, y + 1, w, h - 2, col) end function rect2(x, y, w, h, col) - rect(x, y, x+w, y+h, col) + rect(x, y, x + w, y + h, col) end -- @@ -74,7 +75,6 @@ end -- return c -- end - -- function tostring(any) -- if (type(any)~="table") return tostr(any) -- local str = "{" @@ -85,53 +85,50 @@ end -- return str.."}" -- end - -- -- main loop -- function _init() - -- pal({[0]=0,128,132,7,136,8,14,137,9,10,131,3,11,1,140,12},1) - -- poke(0x5f2e,1) --to keep colors + -- pal({[0]=0,128,132,7,136,8,14,137,9,10,131,3,11,1,140,12},1) + -- poke(0x5f2e,1) --to keep colors - printh(" ") - printh("*************") - printh(" ") - local date = stat(80)..stat(81)..stat(82)..stat(84)..stat(85) - srand(date) - printh("seed " .. date) + printh(" ") + printh("*************") + printh(" ") + local date = stat(80) .. stat(81) .. stat(82) .. stat(84) .. stat(85) + srand(date) + printh("seed " .. date) + frame_count = 0 - frame_count = 0 - - states = { - rules = state_rules(), - menu = state_menu(), - loading = state_loading(), - game = state_game(), - endgame = state_endgame(), - } - - set_state(states.menu) + states = { + rules = state_rules(), + menu = state_menu(), + loading = state_loading(), + game = state_game(), + endgame = state_endgame() + } + set_state(states.menu) end function _update60() - frame_count += 1 + frame_count += 1 - -- update mouse coords - mouse_x = stat(32) - mouse_y = stat(33) + -- update mouse coords + mouse_x = stat(32) + mouse_y = stat(33) - _coresolve() - gs._update() + _coresolve() + gs._update() end function _draw() - gs._draw() - for overlay in all(overlays) do - overlay:_draw() - end - -- mouse cursor - spr(1, mouse_x, mouse_y) -end + gs._draw() + for overlay in all(overlays) do + overlay:_draw() + end + -- mouse cursor + spr(1, mouse_x, mouse_y) +end \ No newline at end of file diff --git a/states/endgame.lua b/states/endgame.lua index 55c8956..898a9b7 100644 --- a/states/endgame.lua +++ b/states/endgame.lua @@ -1,51 +1,54 @@ function state_endgame() - local board - local message = "웃웃 yay! 웃웃" - local message_x = 0 + local board + local message = "웃웃 yay! 웃웃" + local message_x = 0 - local function go_to_menu() - set_state(states.menu) - end + local function go_to_menu() + set_state(states.menu) + end - local btn_back = make_button({x=1, y=118, h=7, text="🅾️/C bACK TO mENU", color=8, - on_click=function() go_to_menu() end, - on_hover=function(btn) btn.color = 7 end}) + local btn_back = make_button({ + x = 1, y = 118, h = 7, text = "🅾️/C bACK TO mENU", color = 8, + on_click = function() go_to_menu() end, + on_hover = function(btn) btn.color = 7 end + }) - local function _enter(_board) - board = _board - message_x = (128 - print(message,0,-100))/2 - end + local function _enter(_board) + board = _board + message_x = (128 - print(message, 0, -100)) / 2 + end - local function _update() - btn_back:update() - if btnp(BTN_O) then - go_to_menu() - end - end + local function _update() + btn_back:update() + if btnp(BTN_O) then + go_to_menu() + end + end - local function _draw() - cls() - board:draw() + local function _draw() + cls() + board:draw() - -- wavy message - local offset=0 - for i = 1, #message, 1 do -- loop through every letter - letter = sub(message, i, i) -- grab this letter - local st = t() + 0.125 * i -- create a modified time for this letter - print(letter, message_x + offset, 20 + sin(st*0.5)*10, 7) -- draw this letter - offset += print(letter,0,-100) - end + -- wavy message + local offset = 0 + for i = 1, #message, 1 do + -- loop through every letter + letter = sub(message, i, i) -- grab this letter + local st = t() + 0.125 * i -- create a modified time for this letter + print(letter, message_x + offset, 20 + sin(st * 0.5) * 10, 7) -- draw this letter + offset += print(letter, 0, -100) + end - btn_back:draw() - end + btn_back:draw() + end - local function _leave() - end + local function _leave() + end - return { - _enter = _enter, - _update = _update, - _draw = _draw, - _leave = _leave - } + return { + _enter = _enter, + _update = _update, + _draw = _draw, + _leave = _leave + } end \ No newline at end of file diff --git a/states/game.lua b/states/game.lua index 649888a..cc6f4a8 100644 --- a/states/game.lua +++ b/states/game.lua @@ -1,134 +1,133 @@ function state_game() + local board + local selected_id = 1 + local timer_clue = 0 + local mx, mx = 0, 0 - local board - local selected_id = 1 - local timer_clue = 0 - local mx,mx = 0,0 + local clues = {} + local function show_clues() + local issues = board:get_issues(true) + clues = {} + for issue in all(issues) do + local type, err, row, pos, other = unpack(issue) + printh(type .. " " .. err .. " " .. pos) + add(clues, { type = type, pos = pos, t = 0 }) + if err == "identical" then + add(clues, { type = type, pos = other, t = 0 }) + end + end + end - local clues = {} - local function show_clues() - local issues = board:get_issues(true) - clues = {} - for issue in all(issues) do - local type, err, row, pos, other = unpack(issue) - printh(type .. " " .. err .. " " .. pos) - add(clues, {type=type, pos=pos, t=0}) - if err == "identical" then - add(clues, {type=type, pos=other, t=0}) - end - end - end + local function draw_selected_tile() + local x, y = board:draw_coords(selected_id) + local w = board:get_tile_width() + -- fillp(▒) + rect2(x - 1, y - 1, w, w, 6) + line() + fillp(█) + end - local function draw_selected_tile() - local x, y = board:draw_coords(selected_id) - local w = board:get_tile_width() - -- fillp(▒) - rect2(x-1, y-1, w, w, 6) - line() - fillp(█) - end + local function update_mouse() + -- update mouse position + if mx == mouse_x and my == mouse_y then return end + mx, my = mouse_x, mouse_y + local board_x, board_y = board:draw_coords(1) + local tw = board:get_tile_width() + local bw = board:get_size() + -- pixels coords to grid coords + local x = mid(1, (mouse_x - board_x) \ tw + 1, bw) + local y = mid(1, (mouse_y - board_y) \ tw + 1, bw) + selected_id = board:xy_idx(x, y) + end - local function update_mouse() - -- update mouse position - if mx == mouse_x and my == mouse_y then return end - mx,my = mouse_x, mouse_y - local board_x, board_y = board:draw_coords(1) - local tw = board:get_tile_width() - local bw = board:get_size() - -- pixels coords to grid coords - local x = mid(1, (mouse_x - board_x) \ tw + 1, bw) - local y = mid(1, (mouse_y - board_y) \ tw + 1, bw) - selected_id = board:xy_idx(x,y) - end + local function check_endgame() + if board:is_complete() and board:is_valid() then + set_state(states.endgame, board) + end + end - local function check_endgame() - if board:is_complete() and board:is_valid() then - set_state(states.endgame, board) - end - end + local function _enter(_board) + -- mouse bound to buttons + poke(0x5F2D, 3) - local function _enter(_board) - -- mouse bound to buttons - poke(0x5F2D, 3) + board = _board + -- lock the initial tiles + board:lock_tiles() + end - board = _board - -- lock the initial tiles - board:lock_tiles() - end + local function _leave() + -- stopcoroutine(show_clues) + end - local function _leave() - -- stopcoroutine(show_clues) - end + local function _update() + update_mouse() - local function _update() - update_mouse() + local size = board:get_size() + local x, y = board:idx_xy(selected_id) + local moved = false - local size = board:get_size() - local x, y = board:idx_xy(selected_id) - local moved = false + if btnp(UP) then + moved = true + y -= 1 + elseif btnp(DOWN) then + moved = true + y += 1 + elseif btnp(LEFT) then + moved = true + x -= 1 + elseif btnp(RIGHT) then + moved = true + x += 1 + end + if moved then + selected_id = board:xy_idx(x, y) + end - if btnp(UP) then - moved = true - y -= 1 - elseif btnp(DOWN) then - moved = true - y += 1 - elseif btnp(LEFT) then - moved = true - x -= 1 - elseif btnp(RIGHT) then - moved = true - x += 1 - end - if moved then - selected_id = board:xy_idx(x, y) - end + if btnp(BTN_X) then + board:try_flip_tile(selected_id) + show_clues() + end - if btnp(BTN_X) then - board:try_flip_tile(selected_id) - show_clues() - end + if (x < 1) x = size + if (x > size) x = 1 + if (y < 1) y = size + if (y > size) y = 1 + check_endgame() + end - if (x<1) x=size - if (x>size) x=1 - if (y<1) y=size - if (y>size) y=1 + local function _draw() + cls() + local x, y = board:draw_coords(1) + draw_animated_bg(x) - check_endgame() - end + board:draw() + draw_selected_tile() - local function _draw() - cls() - local x,y = board:draw_coords(1) - draw_animated_bg(x) + -- draw clues + for clue in all(clues) do + palt(0, false) + palt(5, true) + local x, y + if clue.type == "row" then + x, y = board:draw_coords((clue.pos - 1) * board:get_size() + 1) + x = -32 + spr(19, x + clue.t % 144, y + 1 + sin(t()) * 2) + else + -- col + x, y = board:draw_coords(clue.pos) + y = -32 + spr(19, x + 2 + sin(t()) * 2, y + clue.t % 144) + end + pset(x, y, 5) + clue.t += 1 + end + palt() + end - board:draw() - draw_selected_tile() - - -- draw clues - for clue in all(clues) do - palt(0,false) - palt(5,true) - local x,y - if clue.type == "row" then - x,y = board:draw_coords((clue.pos-1) * board:get_size()+1) - x=-32 - spr(19, x+clue.t%144, y+1+sin(t())*2) - else -- col - x,y = board:draw_coords(clue.pos) - y=-32 - spr(19, x+2+sin(t())*2, y+clue.t%144) - end - pset(x, y, 5) - clue.t += 1 - end - palt() - end - - return { - _enter = _enter, - _update = _update, - _draw = _draw, - _leave = _leave - } + return { + _enter = _enter, + _update = _update, + _draw = _draw, + _leave = _leave + } end \ No newline at end of file diff --git a/states/loading.lua b/states/loading.lua index d796eff..ba2899e 100644 --- a/states/loading.lua +++ b/states/loading.lua @@ -1,158 +1,160 @@ function state_loading() - local board - local size - local og_rt - local removing_tile + local board + local size + local og_rt + local removing_tile - local spinner = split"-,\\,|,/" - local loading_messages = { - "rETICULATING SPLINES", - "aLLOCATING RESSOURCES", - "eMULATING HARDWARE", - "uNCLOGGING MEMORY BUS", - "sPINNING UP ai AGENT", - "sIDE-STEPPING VIRTUAL MACHINE", - "iNSTALLING BACKTRACKING WIZARD", - "eXFOLIATING PIXELS", - "sCAFFOLDING RAY-TRACING ALGORITHM", - "sWEEPING PARTICLES", - "pRESSURIZING USER INTERFACE", - "sHAKING RED AND BLUE PAINT BUCKETS", - "gATHERING GRAVITY", - "sERIALIZING BOARD MATRIX", - "bACKPORTING e2e ENCRYPTION", - } + local spinner = split "-,\\,|,/" + local loading_messages = { + "rETICULATING SPLINES", + "aLLOCATING RESSOURCES", + "eMULATING HARDWARE", + "uNCLOGGING MEMORY BUS", + "sPINNING UP ai AGENT", + "sIDE-STEPPING VIRTUAL MACHINE", + "iNSTALLING BACKTRACKING WIZARD", + "eXFOLIATING PIXELS", + "sCAFFOLDING RAY-TRACING ALGORITHM", + "sWEEPING PARTICLES", + "pRESSURIZING USER INTERFACE", + "sHAKING RED AND BLUE PAINT BUCKETS", + "gATHERING GRAVITY", + "sERIALIZING BOARD MATRIX", + "bACKPORTING e2e ENCRYPTION" + } - local message = "" - local messages_str = "" - local messages_x = 128 - local loaded = false - local done = {} + local message = "" + local messages_str = "" + local messages_x = 128 + local loaded = false + local done = {} - local create_board = function() - printh("creating") - local start = time() - repeat - board:reset() - repeat - board:solve_step(true) - yield() - until board:is_complete() - until board:is_valid() + local create_board = function() + printh("creating") + local start = time() + repeat + board:reset() + repeat + board:solve_step(true) + yield() + until board:is_complete() + until board:is_valid() - -- Remove tiles that can be removed - local previous = {board:get_tiles_copy()} -- initial state - done = {} - while true do + -- Remove tiles that can be removed + local previous = { board:get_tiles_copy() } + -- initial state + done = {} + while true do + board:set_tiles(previous[#previous]) + -- remove a random tile + repeat + removing_tile += 1 + if removing_tile > size then + removing_tile = 1 + end + until removing_tile == size or board:get_tiles_copy()[removing_tile] ~= 0 + if removing_tile == og_rt then + break + end - board:set_tiles(previous[#previous]) - -- remove a random tile - repeat - removing_tile += 1 - if removing_tile > size then - removing_tile = 1 - end - until removing_tile == size or board:get_tiles_copy()[removing_tile] ~= 0 - if removing_tile == og_rt then - break - end + board:fill(removing_tile, 0) + add(done, removing_tile) + add(previous, board:get_tiles_copy()) - board:fill(removing_tile, 0) - add(done, removing_tile) - add(previous, board:get_tiles_copy()) + -- try to solve the board + local solved = "" + yield() + repeat + solved = board:solve_step() + if solved == "valid" then + amplitude -= .125 + end + until board:is_complete() or solved == "invalid" - -- try to solve the board - local solved = "" - yield() - repeat - solved = board:solve_step() - if solved == "valid" then - amplitude -= .125 - end - until board:is_complete() or solved == "invalid" + if solved == "invalid" then + deli(previous) + end + end + -- end while + printh("board generated in " .. time() - start .. " seconds") + startcoroutine(cocreate(function() + repeat + amplitude -= .5 + yield() + until amplitude <= 0 + end)) - if solved == "invalid" then - deli(previous) - end - end -- end while - printh("board generated in "..time()-start.." seconds") - startcoroutine(cocreate(function() - repeat - amplitude -= .5 - yield() - until amplitude <= 0 - end)) + board:set_tiles(previous[#previous]) + printh(board:tostring()) + printh(count(board:get_tiles_copy(), 0) .. " zeroes") - board:set_tiles(previous[#previous]) - printh(board:tostring()) - printh(count(board:get_tiles_copy(), 0).." zeroes") + loaded = true + end - loaded = true - end + local function draw_tiles(board) + local w = board:get_size() + local tiles = board:get_tiles_copy() + for k, v in ipairs(tiles) do + if v == 0 or contains(done, k) then + board:draw_tile(k) + end + end + end - local function draw_tiles(board) - local w = board:get_size() - local tiles = board:get_tiles_copy() - for k,v in ipairs(tiles) do - if v==0 or contains(done, k) then - board:draw_tile(k) - end - end - end + local function _enter() + printh("enter loading") + board = Board:new() + size = board:get_size() * board:get_size() + og_rt = rnd(size) \ 1 + 1 + -- original removing tile + removing_tile = og_rt - local function _enter() - printh("enter loading") - board = Board:new() - size = board:get_size()*board:get_size() - og_rt = rnd(size)\1+1 -- original removing tile - removing_tile = og_rt - - amplitude = 64 - loaded = false - done = {} + amplitude = 64 + loaded = false + done = {} - local copy_messages = copy(loading_messages) - messages_str = "" - messages_x = 128 - while #copy_messages > 0 do - local m = rnd(copy_messages) - messages_str ..= m .. " " - del(copy_messages, m) - end - messages_str ..= "tHANK YOU FOR YOUR PATIENCE" + local copy_messages = copy(loading_messages) + messages_str = "" + messages_x = 128 + while #copy_messages > 0 do + local m = rnd(copy_messages) + messages_str ..= m .. " " + del(copy_messages, m) + end + messages_str ..= "tHANK YOU FOR YOUR PATIENCE" - startcoroutine(cocreate(create_board)) - end + startcoroutine(cocreate(create_board)) + end - local function _update() - board:lock_tiles() + local function _update() + board:lock_tiles() - messages_x -= 4 - if loaded then - set_state(states.game, board) - end - end + messages_x -= 4 + if loaded then + set_state(states.game, board) + end + end - local function _draw() - cls() - local x,y = board:draw_coords(1) - draw_animated_bg(x) - -- board:draw_bg() - draw_tiles(board) - local s = board:get_size()*board:get_size() - local l = print(message, 0, -100) - local y = 118+(removing_tile/s)*100/8 - local ci = removing_tile\20+1 - -- if not loaded then - -- rectfill2(0,y-2,127,10,0) - -- print(messages_str, messages_x, y, 3, 0) - -- -- print(spinner[t()\.25%4+1], 120, 120) - -- end - end + local function _draw() + cls() + local x, y = board:draw_coords(1) + draw_animated_bg(x) + -- board:draw_bg() + draw_tiles(board) + local s = board:get_size() * board:get_size() + local l = print(message, 0, -100) + local y = 118 + removing_tile / s * 100 / 8 + local ci = removing_tile \ 20 + 1 + -- if not loaded then + -- rectfill2(0,y-2,127,10,0) + -- print(messages_str, messages_x, y, 3, 0) + -- -- print(spinner[t()\.25%4+1], 120, 120) + -- end + end - return { - _enter = _enter, - _update = _update, - _draw = _draw, - } + return { + _enter = _enter, + _update = _update, + _draw = _draw + } end \ No newline at end of file diff --git a/states/menu.lua b/states/menu.lua index c2b8d47..91cc13c 100644 --- a/states/menu.lua +++ b/states/menu.lua @@ -1,78 +1,79 @@ function state_menu() - local selected = 1 + local selected = 1 - local buttons = {} - -- local buttons = { - -- make_button({x=10, y=10, w=30, text="pLAY", data={i=1}, - -- on_click=function() set_state(states.loading) end, - -- on_hover=function(btn) selected=1 end, - -- }), - -- } + local buttons = {} + -- local buttons = { + -- make_button({x=10, y=10, w=30, text="pLAY", data={i=1}, + -- on_click=function() set_state(states.loading) end, + -- on_hover=function(btn) selected=1 end, + -- }), + -- } - local game_sizes = { - {"mINI bOARD - 4X4", 4}, - {"sMALL bOARD - 6X6", 6}, - {"mEDIUM bOARD - 8X8", 8}, - {"lARGE bOARD - 10X10", 10} - } - for k, item in ipairs(game_sizes) do - add(buttons, - make_button({ - x=10, y=10+k*10, - selected_color=7, - text=item[1], - on_click=function() board_size=item[2] set_state(states.loading) end, - on_hover=function() selected=k end, - }) - ) - end + local game_sizes = { + { "mINI bOARD - 4X4", 4 }, + { "sMALL bOARD - 6X6", 6 }, + { "mEDIUM bOARD - 8X8", 8 }, + { "lARGE bOARD - 10X10", 10 } + } + for k, item in ipairs(game_sizes) do + add( + buttons, + make_button({ + x = 10, y = 10 + k * 10, + selected_color = 7, + text = item[1], + on_click = function() board_size = item[2] set_state(states.loading) end, + on_hover = function() selected = k end + }) + ) + end + local rulesId = #buttons + 1 + add( + buttons, + make_button({ + x = 10, y = 20 + (#game_sizes + 1) * 10, w = 30, text = "rULES", + color = 13, selected_color = 12, + on_click = function() set_state(states.rules) end, + on_hover = function() selected = rulesId end + }) + ) - local rulesId = #buttons+1 - add(buttons, - make_button({x=10, y=20+(#game_sizes+1)*10, w=30, text="rULES", - color=13, selected_color=12, - on_click=function() set_state(states.rules) end, - on_hover=function() selected=rulesId end, - }) - ) + local function _enter() + -- mouse not bound to buttons + poke(0x5F2D, 1) + end - local function _enter() - -- mouse not bound to buttons - poke(0x5F2D, 1) - end + local function _draw() + cls() + draw_bg_menu() - local function _draw() - cls() - draw_bg_menu() - - print("pLAY", 10, 8, 8) + print("pLAY", 10, 8, 8) - for k,button in ipairs(buttons) do - button:draw(selected == k) - end - print("pRESS ❎/X TO CONTINUE", 8, 120, 7) - end + for k, button in ipairs(buttons) do + button:draw(selected == k) + end + print("pRESS ❎/X TO CONTINUE", 8, 120, 7) + end - return { - _enter = _enter, + return { + _enter = _enter, - _update = function() - for button in all(buttons) do - button:update() - end + _update = function() + for button in all(buttons) do + button:update() + end - if btnp(UP) then - selected -= 1 - elseif btnp(DOWN) then - selected += 1 - elseif btnp(BTN_X) then - buttons[selected]:on_click() - end - selected = mid(1, selected, #buttons) + if btnp(UP) then + selected -= 1 + elseif btnp(DOWN) then + selected += 1 + elseif btnp(BTN_X) then + buttons[selected]:on_click() + end + selected = mid(1, selected, #buttons) + end, - end, - - _draw = _draw - } + _draw = _draw + } end \ No newline at end of file diff --git a/states/rules.lua b/states/rules.lua index e56d523..a0ed156 100644 --- a/states/rules.lua +++ b/states/rules.lua @@ -1,94 +1,94 @@ function state_rules() + local fade = split "0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,4,9,10,9,4,2,1" + local color = 1 - local fade = split"0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,4,9,10,9,4,2,1" - local color = 1 + local function blink(x, y, w, h) + rect2(x, y, w, h, fade[color]) + end - local function blink(x,y,w,h) - rect2(x,y,w,h,fade[color]) - end + local function go_back() + set_state(states.menu) + end - local function go_back() - set_state(states.menu) - end + local btn_back = make_button({ + x = 1, y = 118, w = 30, h = 7, text = "🅾️/C mENU", color = 8, + on_click = function() go_back() end, + on_hover = function(btn) btn.color = 7 end + }) - local btn_back = make_button({x=1, y=118, w=30, h=7, text="🅾️/C mENU", color=8, - on_click=function() go_back() end, - on_hover=function(btn) btn.color = 7 end}) + return { + _enter = function() + end, - return { - _enter = function() - end, - - _exit = function() - -- standard_font() - end, - - _update=function() - -- custom_font() - if frame_count%8==0 then - color += 1 - end - if color>#fade then - color = 1 - end + _exit = function() + -- standard_font() + end, - -- Back to the menu - if btnp(BTN_O) then - go_back() - end + _update = function() + -- custom_font() + if frame_count % 8 == 0 then + color += 1 + end + if color > #fade then + color = 1 + end - btn_back:update() - end, + -- Back to the menu + if btnp(BTN_O) then + go_back() + end - _draw=function() - cls() + btn_back:update() + end, - print("1) yOU CAN'T HAVE MORE THAN\n TWO (2) CONSECUTIVE TILES\n OF THE SAME COLOR", 2,2, 7) - local x = 14 - local y = 28 - sspr(0,32, 12,12, x,y) - spr(2, x+14, y+1) - sspr(13,32, 12,12, x+26,y) - blink(x-1, y-1, 9, 3) - blink(x+25, y-1, 9, 3) - blink(x-1, y+8, 12, 3) - blink(x+25, y+8, 12, 3) + _draw = function() + cls() - x = 75 - sspr(26,32, 12,12, x,y) - spr(2, x+14, y+1) - sspr(39,32, 12,12, x+26,y) - blink(x+5, y+2, 3, 9) - blink(x+31, y+2, 3, 9) + print("1) yOU CAN'T HAVE MORE THAN\n TWO (2) CONSECUTIVE TILES\n OF THE SAME COLOR", 2, 2, 7) + local x = 14 + local y = 28 + sspr(0, 32, 12, 12, x, y) + spr(2, x + 14, y + 1) + sspr(13, 32, 12, 12, x + 26, y) + blink(x - 1, y - 1, 9, 3) + blink(x + 25, y - 1, 9, 3) + blink(x - 1, y + 8, 12, 3) + blink(x + 25, y + 8, 12, 3) + x = 75 + sspr(26, 32, 12, 12, x, y) + spr(2, x + 14, y + 1) + sspr(39, 32, 12, 12, x + 26, y) + blink(x + 5, y + 2, 3, 9) + blink(x + 31, y + 2, 3, 9) - -------------- + -------------- - x = 44 - y = 50 - print("2) eACH LINE CONTAINS AN EQUAL\n NUMBER OF EACH COLOR", 2, y, 7) - sspr(52,32, 12,12, x,y+20) - spr(2, x+14, y+21) - sspr(65,32, 12,12, x+26,y+20) - blink(x+5, y+22, 6, 3) - blink(x+31, y+22, 6, 3) - blink(x-1, y+19, 3, 6) - blink(x+25, y+19, 3, 6) + x = 44 + y = 50 + print("2) eACH LINE CONTAINS AN EQUAL\n NUMBER OF EACH COLOR", 2, y, 7) + sspr(52, 32, 12, 12, x, y + 20) + spr(2, x + 14, y + 21) + sspr(65, 32, 12, 12, x + 26, y + 20) + blink(x + 5, y + 22, 6, 3) + blink(x + 31, y + 22, 6, 3) + blink(x - 1, y + 19, 3, 6) + blink(x + 25, y + 19, 3, 6) - -------------- + -------------- - x = 44 - y = 90 - print("3) aLL ROWS AND COLUMNS\n ARE DIFFERENT", 2, y, 7) - sspr(78,32, 12,12, x,y+20) - spr(2, x+14, y+21) - sspr(91,32, 12,12, x+26,y+20) - blink(x-1, y+25, 12, 6) - blink(x+25, y+25, 12, 6) + x = 44 + y = 90 + print("3) aLL ROWS AND COLUMNS\n ARE DIFFERENT", 2, y, 7) + sspr(78, 32, 12, 12, x, y + 20) + spr(2, x + 14, y + 21) + sspr(91, 32, 12, 12, x + 26, y + 20) + blink(x - 1, y + 25, 12, 6) + blink(x + 25, y + 25, 12, 6) - -------------- + -------------- - btn_back:draw() - end, - } + btn_back:draw() + end + } end \ No newline at end of file diff --git a/tile.lua b/tile.lua index fa9594a..83af776 100644 --- a/tile.lua +++ b/tile.lua @@ -1,7 +1,7 @@ local Tile = {} function Tile.new(color) - return { - color=color - } -end + return { + color = color + } +end \ No newline at end of file diff --git a/ui.lua b/ui.lua index e718ebc..7bd2443 100644 --- a/ui.lua +++ b/ui.lua @@ -1,42 +1,43 @@ function make_button(options) - local state = 0 -- 0 = normal, 1 = hovered, 2 = pressed - local w = print(options.text, 0, -100) - return { - x = options.x, - y = options.y, - w = options.w or w, - h = options.h or 6, - data = options.data, - text = options.text, - on_click = options.on_click, - on_hover = options.on_hover, - ogColor = options.color or 5, - selected_color = options.selected_color or 5, - color = options.color or 5, + local state = 0 + -- 0 = normal, 1 = hovered, 2 = pressed + local w = print(options.text, 0, -100) + return { + x = options.x, + y = options.y, + w = options.w or w, + h = options.h or 6, + data = options.data, + text = options.text, + on_click = options.on_click, + on_hover = options.on_hover, + ogColor = options.color or 5, + selected_color = options.selected_color or 5, + color = options.color or 5, - draw=function(self, selected) - standard_font() - local color = selected and self.selected_color or self.color - print(self.text, self.x, self.y, color) - -- rect(self.x, self.y, self.x+self.w, self.y+self.h, color) - end, + draw = function(self, selected) + standard_font() + local color = selected and self.selected_color or self.color + print(self.text, self.x, self.y, color) + -- rect(self.x, self.y, self.x+self.w, self.y+self.h, color) + end, - update=function(self) - self.color = self.ogColor - if mouse_x >= self.x and mouse_x <= self.x + self.w and - mouse_y >= self.y and mouse_y <= self.y + self.h then - if stat(34)&1 == 0 and state == 2 and self.on_click then - self.on_click(self) - end - if stat(34)&1 == 1 then - state = 2 - else - if self.on_hover then self:on_hover() end - state = 1 - end - else - state = 0 - end - end - } + update = function(self) + self.color = self.ogColor + if mouse_x >= self.x and mouse_x <= self.x + self.w + and mouse_y >= self.y and mouse_y <= self.y + self.h then + if stat(34) & 1 == 0 and state == 2 and self.on_click then + self.on_click(self) + end + if stat(34) & 1 == 1 then + state = 2 + else + if self.on_hover then self:on_hover() end + state = 1 + end + else + state = 0 + end + end + } end \ No newline at end of file diff --git a/utils.lua b/utils.lua index 7c4ab07..a9ab174 100644 --- a/utils.lua +++ b/utils.lua @@ -1,63 +1,62 @@ local oldprint = print -function print(t,x,y,col1,col2) - if col2 then - for i=-1,1 do - for j=-1,1 do - oldprint(t, x+i, y+j, col2) - end - end - end - return oldprint(t, x, y, col1) +function print(t, x, y, col1, col2) + if col2 then + for i = -1, 1 do + for j = -1, 1 do + oldprint(t, x + i, y + j, col2) + end + end + end + return oldprint(t, x, y, col1) end function str_width(str) - return print(str,0,-8) + return print(str, 0, -8) end -function print_shade(t,x,y,col1,col2) - print(t,x,y+1,col2) - print(t,x+1,y+1,col2) - print(t,x,y,col1) +function print_shade(t, x, y, col1, col2) + print(t, x, y + 1, col2) + print(t, x + 1, y + 1, col2) + print(t, x, y, col1) end function set_state(state, ...) - local args = {...} - if gs and gs._leave then gs._leave() end - gs = state - if gs and gs._enter then gs._enter(unpack(args)) end + local args = { ... } + if gs and gs._leave then gs._leave() end + gs = state + if gs and gs._enter then gs._enter(unpack(args)) end end - -- -- Returns the indices of found occurences of `o` within `tbl` -- function find(tbl, o) - local indices = {} - for k,v in ipairs(tbl) do - if v == o then add(indices, k) end - end - return indices + local indices = {} + for k, v in ipairs(tbl) do + if v == o then add(indices, k) end + end + return indices end function contains(tbl, o) - for v in all(tbl) do - if v == o then return true end - end - return false + for v in all(tbl) do + if v == o then return true end + end + return false end -- -- Makes a shallow table copy -- function copy(tbl) - return map(tbl, function (o) return o end) + return map(tbl, function(o) return o end) end -- -- Table equality - shallow comparison -- function equal(tbl1, tbl2) - for k, _ in ipairs(tbl1) do - if tbl1[k] ~= tbl2[k] then return false end - end - return true + for k, _ in ipairs(tbl1) do + if tbl1[k] ~= tbl2[k] then return false end + end + return true end \ No newline at end of file diff --git a/visuals.lua b/visuals.lua index 333b883..76e8c37 100644 --- a/visuals.lua +++ b/visuals.lua @@ -1,39 +1,41 @@ local overlays = {} function get_main_color(tint) - if tint == BLUE then - return 12 - elseif tint == YELLOW then - return 9 - else - return 1 - end + if tint == BLUE then + return 12 + elseif tint == YELLOW then + return 9 + else + return 1 + end end function get_shade_color(tint) - if tint == BLUE then - return 13 - elseif tint == YELLOW then - return 4 - else - return 1 - end + if tint == BLUE then + return 13 + elseif tint == YELLOW then + return 4 + else + return 1 + end end function spawn_tile_transition(x, y, w, h, from_tint, to_tint) - local p = #patterns - local from_color = get_main_color(from_tint) - local to_color = get_main_color(to_tint) - add(overlays, { - _draw = function(self) - fillp() - rectfill(x, y, x + w, y + h, from_color) - fillp(patterns[p\1]+0b0.1) - rectfill(x, y, x + w, y + h, to_color) - p -= 1 - if p < 1 then - del(overlays, self) - end - end - }) -end + local p = #patterns + local from_color = get_main_color(from_tint) + local to_color = get_main_color(to_tint) + add( + overlays, { + _draw = function(self) + fillp() + rectfill(x, y, x + w, y + h, from_color) + fillp(patterns[p \ 1] + 0b0.1) + rectfill(x, y, x + w, y + h, to_color) + p -= 1 + if p < 1 then + del(overlays, self) + end + end + } + ) +end \ No newline at end of file