Code formatting

This commit is contained in:
Simon Cambier 2023-10-07 19:12:53 +02:00
parent bc408aeeb3
commit cb74bdf740
16 changed files with 1066 additions and 1067 deletions

View File

@ -1,4 +1,4 @@
{ {
"editor.insertSpaces": false, "editor.insertSpaces": true,
"editor.detectIndentation": false "editor.detectIndentation": false,
} }

View File

@ -2,10 +2,9 @@ pico-8 cartridge // http://www.pico-8.com
version 38 version 38
__lua__ __lua__
-- Font M3X6 by daniel linssen -- Font M3X6 by daniel linssen
poke(0x5600, 4, 4, 7) 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 #include globals.lua
-- --

57
bg.lua
View File

@ -1,35 +1,36 @@
function draw_animated_bg(startx) function draw_animated_bg(startx)
if (amplitude <= 0) return if (amplitude <= 0) return
startx = startx or 0 startx = startx or 0
fillp(0b0101101001011010) fillp(0b0101101001011010)
local color = 1 local color = 1
-- vertical lines -- vertical lines
local t = t()+10 local t = t() + 10
for i=startx-1,127,9 do for i = startx - 1, 127, 9 do
local a=sin(i*t/512)*amplitude+64 local a = sin(i * t / 512) * amplitude + 64
local b=cos(i*t/256)*amplitude+64 local b = cos(i * t / 256) * amplitude + 64
line( line(
i, i,
a, a,
i, i,
b , b,
color) color
end )
end
-- horizontal lines -- horizontal lines
for i=startx-1,127,9 do for i = startx - 1, 127, 9 do
local a=sin(i*t/512)*amplitude+64 local a = sin(i * t / 512) * amplitude + 64
local b=cos(i*t/256)*amplitude+64 local b = cos(i * t / 256) * amplitude + 64
line( line(
a, a,
i, i,
b , b,
i, i,
color) color
end )
end
end end
function draw_bg_menu() function draw_bg_menu()
end end

794
board.lua
View File

@ -1,447 +1,441 @@
local Board = {} local Board = {}
function Board.new() function Board.new()
local debug = false local debug = false
local width = board_size -- tiles local width = board_size
local tile_width = 8 -- pixels -- tiles
local padding = 1 local tile_width = 8
local tiles = {} -- pixels
local locked = {} -- list of indexes local padding = 1
local tiles = {}
local locked = {}
-- list of indexes
local reset = function() local reset = function()
tiles = {} tiles = {}
for i = 1, width * width do for i = 1, width * width do
tiles[i] = 0 tiles[i] = 0
end end
locked = {} locked = {}
end end
reset() reset()
return { return {
reset = reset, reset = reset,
get_tile = function(self, idx) get_tile = function(self, idx)
return tiles[idx] return tiles[idx]
end, end,
-- returns a COPY of the tiles array -- returns a COPY of the tiles array
get_tiles_copy = function(self) get_tiles_copy = function(self)
return copy(tiles) return copy(tiles)
end, end,
-- overwrites the whole tiles array -- overwrites the whole tiles array
set_tiles = function(self, newtiles) set_tiles = function(self, newtiles)
assert(#newtiles == #tiles, "New tiles array must have a length of " .. #tiles) assert(#newtiles == #tiles, "New tiles array must have a length of " .. #tiles)
tiles = copy(newtiles) tiles = copy(newtiles)
end, end,
idx_xy = function(self, idx) idx_xy = function(self, idx)
return idx_xy(idx, width) return idx_xy(idx, width)
end, end,
xy_idx = function(self, x, y) xy_idx = function(self, x, y)
return xy_idx(x, y, width) return xy_idx(x, y, width)
end, end,
draw_coords = function(self, x, y) draw_coords = function(self, x, y)
local margin = (128 - (tile_width + padding) * width) / 2- padding local margin = (128 - (tile_width + padding) * width) / 2 - padding
if not y then x, y = self:idx_xy(x) end if not y then x, y = self:idx_xy(x) end
return margin + (x-1)*tile_width + (x-1)*padding, return margin + (x - 1) * tile_width + (x - 1) * padding, margin + (y - 1) * tile_width + (y - 1) * padding
margin + (y-1)*tile_width + (y-1)*padding end,
end,
get_size = function(self) get_size = function(self)
return width return width
end, end,
get_tile_width = function(self) get_tile_width = function(self)
return tile_width + padding return tile_width + padding
end, end,
fill = function(self, idx, color, invert) fill = function(self, idx, color, invert)
if idx > width*width then return end if idx > width * width then return end
if invert then if invert then
color = color == YELLOW and BLUE or YELLOW color = color == YELLOW and BLUE or YELLOW
end end
tiles[idx] = color tiles[idx] = color
end, end,
try_flip_tile = function(self, id) try_flip_tile = function(self, id)
local to_color = nil local to_color = nil
if locked[id] then return end if locked[id] then return end
local from_color = tiles[id] local from_color = tiles[id]
if tiles[id] == 0 then if tiles[id] == 0 then
to_color = YELLOW to_color = YELLOW
elseif tiles[id] == YELLOW then elseif tiles[id] == YELLOW then
to_color = BLUE to_color = BLUE
else tiles[id] = 0 else
-- empty tile tiles[id] = 0
end -- empty tile
if to_color then end
tiles[id] = to_color if to_color then
end tiles[id] = to_color
local x,y = self:draw_coords(id) end
spawn_tile_transition(x, y, tile_width-1, tile_width-1, from_color, to_color) local x, y = self:draw_coords(id)
end, spawn_tile_transition(x, y, tile_width - 1, tile_width - 1, from_color, to_color)
end,
get_rows = function(self) get_rows = function(self)
local ret = {} local ret = {}
for i = 1, width do for i = 1, width do
add(ret, slice(tiles, ((i - 1) * width) + 1, i * width)) add(ret, slice(tiles, (i - 1) * width + 1, i * width))
end end
return ret return ret
end, end,
get_cols = function(self) get_cols = function(self)
local ret = {} local ret = {}
local rows = self.get_rows(self) local rows = self.get_rows(self)
for i = 1, width do for i = 1, width do
add(ret, map(rows, function(v) return v[i] end)) add(ret, map(rows, function(v) return v[i] end))
end end
return ret return ret
end, end,
is_complete = function(self) --- Returns true if all tiles are filled
return count(tiles, 0) == 0 is_complete = function(self)
end, return count(tiles, 0) == 0
end,
is_valid = function(self) --- Returns true if the board is valid (respects the rules)
return #self:get_issues() == 0 is_valid = function(self)
end, return #self:get_issues() == 0
end,
-- returns a list of issues of the board's current state -- returns a list of issues of the board's current state
get_issues = function(self, details) get_issues = function(self, details)
local rows = self:get_rows() local rows = self:get_rows()
local issues = {} local issues = {}
for y,row in ipairs(rows) do for y, row in ipairs(rows) do
local filled = count(row, 0) == 0 local filled = count(row, 0) == 0
-- check count -- check count
if filled and count(row, BLUE) ~= count(row, YELLOW) then if filled and count(row, BLUE) ~= count(row, YELLOW) then
add(issues, {"row", "count", row, y}) add(issues, { "row", "count", row, y })
if (debug) printh("uneven count on row "..y) if (debug) printh("uneven count on row " .. y) if (not details) return issues
if (not details) return issues end
end -- check identical lines
-- check identical lines for k, other in ipairs(rows) do
for k,other in ipairs(rows) do if filled and equal(other, row) and other ~= row then
if filled and equal(other, row) and other ~= row then add(issues, { "row", "identical", row, y, k })
add(issues, {"row", "identical", row, y, k}) if (debug) printh("equal rows " .. k) if (not details) return issues
if (debug) printh("equal rows "..k) end
if (not details) return issues end
end -- check triples
end if self:count_consecutives(row) > 2 then
-- check triples add(issues, { "row", "triples", row, y })
if self:count_consecutives(row) > 2 then if (debug) printh("triples") if (not details) return issues
add(issues, {"row", "triples", row, y}) end
if (debug) printh("triples") end
if (not details) return issues
end
end
local cols = self:get_cols() local cols = self:get_cols()
for x,col in ipairs(cols) do for x, col in ipairs(cols) do
local filled = count(col, 0) == 0 local filled = count(col, 0) == 0
-- check count -- check count
if filled and count(col, BLUE) ~= count(col, YELLOW) then if filled and count(col, BLUE) ~= count(col, YELLOW) then
add(issues, {"col", "count", col, x}) add(issues, { "col", "count", col, x })
if (debug) printh("uneven count") if (debug) printh("uneven count") if (not details) return issues
if (not details) return issues end
end -- check identical lines
-- check identical lines for k, other in ipairs(cols) do
for k,other in ipairs(cols) do if filled and equal(other, col) and other ~= col then
if filled and equal(other, col) and other ~= col then add(issues, { "col", "identical", col, x, k })
add(issues, {"col", "identical", col, x, k}) if (debug) printh("equal cols") if (not details) return issues
if (debug) printh("equal cols") end
if (not details) return issues end
end -- check triples
end if self:count_consecutives(col) > 2 then
-- check triples add(issues, { "col", "triples", col, x })
if self:count_consecutives(col) > 2 then if (debug) printh("triples") if (not details) return issues
add(issues, {"col", "triples", col, x}) end
if (debug) printh("triples") end
if (not details) return issues return issues
end end,
end
return issues
end,
count_consecutives = function(self, line) count_consecutives = function(self, line)
local top = 0 local top = 0
local current = 0 local current = 0
local last = 0 local last = 0
for v in all(line) do for v in all(line) do
if v ~= last then if v ~= last then
top = max(current, top) top = max(current, top)
current = 1 current = 1
last = v last = v
elseif v~= 0 then elseif v ~= 0 then
current += 1 current += 1
end end
end end
return max(current, top) return max(current, top)
end, end,
-- --
-- Returns the index of a random zero tile -- Returns the index of a random zero tile
-- --
get_random_zero = function(self) get_random_zero = function(self)
assert(count(tiles, 0) > 0, "No zero left") assert(count(tiles, 0) > 0, "No zero left")
local zeroes = filter(tiles, function(v) return v == 0 end, true) local zeroes = filter(tiles, function(v) return v == 0 end, true)
local z = {} local z = {}
for k,v in pairs(zeroes) do for k, v in pairs(zeroes) do
add(z, k) add(z, k)
end end
return rnd(z) return rnd(z)
end, end,
-- --
-- Returns the index of a random non-zero tile -- Returns the index of a random non-zero tile
-- --
get_random_non_zero = function(self) get_random_non_zero = function(self)
assert(count(tiles, 0) < #tiles, "All zeroes") assert(count(tiles, 0) < #tiles, "All zeroes")
local numbers = filter(tiles, function(v) return v ~= 0 end, true) local numbers = filter(tiles, function(v) return v ~= 0 end, true)
local z = {} local z = {}
for k,v in pairs(numbers) do for k, v in pairs(numbers) do
add(z, k) add(z, k)
end end
return rnd(z) return rnd(z)
end, end,
tostring = function(self) tostring = function(self)
local str = '' local str = ''
for v in all(tiles) do for v in all(tiles) do
str ..= ", " .. v str ..= ", " .. v
end end
return str return str
end, end,
-- Solves 1 step of the board -- Solves 1 step of the board
-- Returns "valid" if it solved it without guessing -- Returns "valid" if it solved it without guessing
-- Returns "invalid" if the board cannot be solved -- Returns "invalid" if the board cannot be solved
solve_step = function(self, random) solve_step = function(self, random)
local zeroes = count(tiles, 0) local zeroes = count(tiles, 0)
self:surround_doubles() self:surround_doubles()
self:split_triples() self:split_triples()
self:fill_lines() self:fill_lines()
self:no_identical_lines() self:no_identical_lines()
local changed = zeroes ~= count(tiles, 0) local changed = zeroes ~= count(tiles, 0)
if not changed and random and not self:is_complete() then if not changed and random and not self:is_complete() then
-- Set a random color -- Set a random color
local z = self:get_random_zero() local z = self:get_random_zero()
self:fill(z, rnd({BLUE, YELLOW})) self:fill(z, rnd({ BLUE, YELLOW }))
if (debug) printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z) if (debug) printh("!!!!!!!!!!!!!!!!! RANDOM FILL AT " .. z) return "invalid"
return "invalid" end
end return (changed or self:is_complete()) and "valid" or "invalid"
return (changed or self:is_complete()) and "valid" or "invalid" end,
end,
surround_doubles = function(self) surround_doubles = function(self)
for idx,v in ipairs(tiles) do for idx, v in ipairs(tiles) do
local x,y = self:idx_xy(idx) local x, y = self:idx_xy(idx)
if v == 0 then if v == 0 then
local neighbors = {} local neighbors = {}
-- 2 tiles on the left -- 2 tiles on the left
if x >= 3 then if x >= 3 then
add(neighbors, {idx, idx-1, idx-2}) add(neighbors, { idx, idx - 1, idx - 2 })
end end
-- 2 tiles on the right -- 2 tiles on the right
if x <= width-2 then if x <= width - 2 then
add(neighbors, {idx, idx+1, idx+2}) add(neighbors, { idx, idx + 1, idx + 2 })
end end
-- 2 tiles on top -- 2 tiles on top
if y >= 3 then if y >= 3 then
add(neighbors, {idx, idx-width, idx - width*2}) add(neighbors, { idx, idx - width, idx - width * 2 })
end end
-- 2 tiles under -- 2 tiles under
if y <= width-2 then if y <= width - 2 then
add(neighbors, {idx, idx+width, idx + width*2}) add(neighbors, { idx, idx + width, idx + width * 2 })
end end
-- only keep pairs that are identical (and not 0) -- 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) neighbors = filter(neighbors, function(o) return tiles[o[2]] == tiles[o[3]] and tiles[o[2]] ~= 0 end)
-- do the surrounding -- do the surrounding
for item in all(neighbors) do for item in all(neighbors) do
if item[1] then if item[1] then
if (debug) printh("Surrounding at " .. item[1]) if (debug) printh("Surrounding at " .. item[1]) self:fill(item[1], tiles[item[2]], true)
self:fill(item[1], tiles[item[2]], true) end
end end
end end
end end
end end,
end,
split_triples = function(self) split_triples = function(self)
for idx, col in ipairs(tiles) do for idx, col in ipairs(tiles) do
local x,y = self:idx_xy(idx) local x, y = self:idx_xy(idx)
if col == 0 then 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 if y > 1 and y < width then
-- check horizontal -- check vertical
local prev = tiles[idx-1] local prev = tiles[idx - width]
local next = tiles[idx+1] local next = tiles[idx + width]
if prev ~= 0 and prev == next then if prev ~= 0 and prev == next then
if (debug) printh("Splitting at " .. idx) if (debug) printh("Splitting at " .. idx) self:fill(idx, prev, true)
self:fill(idx, prev, true) end
end end
end end
end
end,
if y>1 and y < width then fill_lines = function(self)
-- check vertical local rows = self:get_rows()
local prev = tiles[idx-width] local cols = self:get_cols()
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) -- rows
local rows = self:get_rows() for y, row in ipairs(rows) do
local cols = self:get_cols() 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 -- columns
for y,row in ipairs(rows) do for x, col in ipairs(cols) do
local a = count(row, BLUE) local a = count(col, BLUE)
local b = count(row, YELLOW) local b = count(col, YELLOW)
if a ~= b then if a ~= b then
if a == width/2 then self:fill_row(y, YELLOW) end if a == width / 2 then self:fill_col(x, YELLOW) end
if b == width/2 then self:fill_row(y, BLUE) end if b == width / 2 then self:fill_col(x, BLUE) end
end end
end end
end,
-- columns fill_row = function(self, y, color)
for x,col in ipairs(cols) do if (debug) printh("Filling line " .. y .. " in " .. (color == BLUE and "blue" or "yellow"))
local a = count(col, BLUE) local idx = self:xy_idx(1, y)
local b = count(col, YELLOW) for i = idx, idx + width - 1 do
if a ~= b then if self:get_tile(i) == 0 then
if a == width/2 then self:fill_col(x, YELLOW) end self:fill(i, color)
if b == width/2 then self:fill_col(x, BLUE) end end
end end
end end,
end,
fill_row = function(self, y, color) fill_col = function(self, x, color)
if (debug) printh("Filling line " .. y .. " in " .. (color == BLUE and "blue" or "yellow")) if (debug) printh("Filling column " .. x .. " in " .. (color == BLUE and "blue" or "yellow"))
local idx = self:xy_idx(1, y) local idx = self:xy_idx(x, 1)
for i = idx, (idx+width-1) do for i = idx, #tiles, width do
if self:get_tile(i) == 0 then if self:get_tile(i) == 0 then
self:fill(i, color) self:fill(i, color)
end end
end end
end, end,
fill_col = function(self, x, color) -- Finds "identical" lines, and fill the 2 remaining tiles with inverted colors
if (debug) printh("Filling column " .. x .. " in " .. (color == BLUE and "blue" or "yellow")) no_identical_lines = function(self)
local idx = self:xy_idx(x, 1) -- columns
for i = idx, #tiles, width do local cols = self:get_cols()
if self:get_tile(i) == 0 then for x, col in ipairs(cols) do
self:fill(i, color) -- if the line has the corrent number of colors,
end -- but missing 2 tiles
end if count(col, 0) == 2 and count(col, BLUE) == count(col, YELLOW) then
end, 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 -- rows
no_identical_lines = function(self) local rows = self:get_rows()
-- columns for y, row in ipairs(rows) do
local cols = self:get_cols() if count(row, 0) == 2 and count(row, BLUE) == count(row, YELLOW) then
for x,col in ipairs(cols) do local x1, x2 = unpack(find(row, 0))
-- if the line has the corrent number of colors, local ab = copy(row) ab[x1] = BLUE ab[x2] = YELLOW
-- but missing 2 tiles local ba = copy(row) ba[x1] = YELLOW ba[x2] = BLUE
if count(col, 0) == 2 and count(col, BLUE) == count(col, YELLOW) then -- Check if a dupe exists
local y1, y2 = unpack(find(col, 0)) -- get the position of the 2 missing tiles for y2, row in ipairs(rows) do
-- create both both solutions if equal(row, ab) then
local ab = copy(col) ab[y1] = BLUE ab[y2] = YELLOW self:fill(self:xy_idx(x1, y), YELLOW)
local ba = copy(col) ba[y1] = YELLOW ba[y2] = BLUE self:fill(self:xy_idx(x2, y), BLUE)
-- Check if a dupe exists goto continue
for x2,col in ipairs(cols) do elseif equal(row, ba) then
if equal(col, ab) then self:fill(self:xy_idx(x1, y), BLUE)
self:fill(self:xy_idx(x,y1), YELLOW) self:fill(self:xy_idx(x2, y), YELLOW)
self:fill(self:xy_idx(x,y2), BLUE) goto continue
goto continue end
elseif equal(col, ba) then end
self:fill(self:xy_idx(x,y1), BLUE) end
self:fill(self:xy_idx(x,y2), YELLOW) ::continue::
goto continue end
end end,
end
end
::continue::
end
-- rows lock_tiles = function(self)
local rows = self:get_rows() locked = {}
for y,row in ipairs(rows) do for k, v in ipairs(tiles) do
if count(row, 0) == 2 and count(row, BLUE) == count(row, YELLOW) then if v > 0 then locked[k] = true end
local x1, x2 = unpack(find(row, 0)) end
local ab = copy(row) ab[x1] = BLUE ab[x2] = YELLOW end,
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) is_locked = function(self, idx)
locked = {} return locked[idx]
for k,v in ipairs(tiles) do end,
if v > 0 then locked[k] = true end
end
end,
is_locked = function(self, idx) draw_bg_tile = function(self, k)
return locked[idx] local w = tile_width
end, 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) draw = function(self)
local w = tile_width local w = tile_width
local x,y = self:draw_coords(k) for k, v in ipairs(tiles) do
rectfill2(x+1, y, w-2, w, 1) self:draw_tile(k)
rectfill2(x, y+1, w, w-2, 1) end
end, end,
draw = function(self) draw_tile = function(self, idx)
local w = tile_width local w = tile_width
for k,v in ipairs(tiles) do local v = tiles[idx]
self:draw_tile(k) if v > 0 then
end local x, y = self:draw_coords(idx)
end, local color = get_main_color(v)
local shade = get_shade_color(v)
draw_tile = function(self, idx) if color == 1 then fillp() else fillp() end
local w = tile_width if self:is_locked(idx) then
local v = tiles[idx] rectfill2(x, y, w, w, color)
if v > 0 then else
local x,y = self:draw_coords(idx) roundedrect(x, y, w, w, color)
local color = get_main_color(v) line(x + 1, y + w - 1, x + w - 2, y + w - 1, shade)
local shade = get_shade_color(v) line(x + w - 1, y + 1, x + w - 1, y + w - 2, shade)
if color == 1 then fillp() else fillp() end end
if self:is_locked(idx) then else
rectfill2(x, y, w, w, color) fillp()
else self:draw_bg_tile(idx)
roundedrect(x, y, w, w, color) end
line(x+1, y+w-1, x+w-2, y+w-1, shade) end
line(x+w-1, y+1, x+w-1, y+w-2, shade) }
end
else
fillp()
self:draw_bg_tile(idx)
end
end,
}
end end

View File

@ -1,34 +1,35 @@
local coroutines={} local coroutines = {}
-- starts a coroutine and saves it for future reference -- starts a coroutine and saves it for future reference
function startcoroutine(co) function startcoroutine(co)
assert(tostr(co) == "[thread]") -- make sure that co is a coroutine, the return value of cocreate() assert(tostr(co) == "[thread]")
add(coroutines, co) -- make sure that co is a coroutine, the return value of cocreate()
add(coroutines, co)
end end
-- stops the the coroutine -- stops the the coroutine
function stopcoroutine(co) function stopcoroutine(co)
del(coroutines, co) del(coroutines, co)
end end
function _coresolve() function _coresolve()
for co in all(coroutines) do for co in all(coroutines) do
if costatus(co) != 'dead' then if costatus(co) != 'dead' then
assert(coresume(co)) assert(coresume(co))
else else
stopcoroutine(co) stopcoroutine(co)
end end
end end
end end
-- to be used inside a coroutine -- to be used inside a coroutine
function wait(seconds) function wait(seconds)
wait_frames(seconds*30) wait_frames(seconds * 30)
end end
-- to be used inside a coroutine -- to be used inside a coroutine
function wait_frames(frames) function wait_frames(frames)
for i=1,frames do for i = 1, frames do
yield() yield()
end end
end end

View File

@ -12,24 +12,24 @@ local YELLOW = 1
-- 🅾️ Z[C]N ❎ [X]VM -- 🅾️ Z[C]N ❎ [X]VM
-- X and C have the same position on QWERTY and AZERTY -- 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 = { local patterns = {
0b0000000000000000, 0b0000000000000000,
0b1000000000000000, 0b1000000000000000,
0b1000000000100000, 0b1000000000100000,
0b1010000000100000, 0b1010000000100000,
0b1010000010100000, 0b1010000010100000,
0b1010010010100000, 0b1010010010100000,
0b1010010010100001, 0b1010010010100001,
0b1010010110100001, 0b1010010110100001,
0b1010010110100101, 0b1010010110100101,
0b1110010110100101, 0b1110010110100101,
0b1110010110110101, 0b1110010110110101,
0b1111010110110101, 0b1111010110110101,
0b1111010111110101, 0b1111010111110101,
0b1111110111110101, 0b1111110111110101,
0b1111110111110111, 0b1111110111110111,
0b1111111111110111, 0b1111111111110111,
0b1111111111111111, 0b1111111111111111
} }

123
main.lua
View File

@ -3,62 +3,63 @@
-- --
function custom_font() function custom_font()
poke(0x5f58,0x81) poke(0x5f58, 0x81)
end end
function standard_font(font) function standard_font(font)
poke(0x5f58,0x80) poke(0x5f58, 0x80)
end end
function idx_xy(idx, width) function idx_xy(idx, width)
return (idx - 1) % width + 1, (idx - 1) \ width + 1 return (idx - 1) % width + 1, (idx - 1) \ width + 1
end end
function xy_idx(x, y, width) function xy_idx(x, y, width)
return ((y - 1) * width) + x return (y - 1) * width + x
end end
function map(tbl, f) function map(tbl, f)
local t = {} local t = {}
for k, v in pairs(tbl) do for k, v in pairs(tbl) do
t[k] = f(v) t[k] = f(v)
end end
return t return t
end end
function filter(tbl, f, keepindex) function filter(tbl, f, keepindex)
local ret = {} local ret = {}
for k, v in pairs(tbl) do for k, v in pairs(tbl) do
if f(v) then if f(v) then
if keepindex if keepindex then
then ret[k] = v ret[k] = v
else add(ret, v) else
end add(ret, v)
end end
end end
return ret end
return ret
end end
function slice(tbl, first, last, step) function slice(tbl, first, last, step)
local sliced = {} local sliced = {}
for i = (first or 1), (last or #tbl), (step or 1) do for i = first or 1, last or #tbl, step or 1 do
sliced[#sliced + 1] = tbl[i] sliced[#sliced + 1] = tbl[i]
end end
return sliced return sliced
end end
function rectfill2(x, y, w, h, col) 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 end
function roundedrect(x, y, w, h, col) function roundedrect(x, y, w, h, col)
rectfill2(x,y,w,h,0) rectfill2(x, y, w, h, 0)
rectfill2(x+1, y, w-2, h, col) rectfill2(x + 1, y, w - 2, h, col)
rectfill2(x, y+1, w, h-2, col) rectfill2(x, y + 1, w, h - 2, col)
end end
function rect2(x, y, w, h, col) function rect2(x, y, w, h, col)
rect(x, y, x+w, y+h, col) rect(x, y, x + w, y + h, col)
end end
-- --
@ -74,7 +75,6 @@ end
-- return c -- return c
-- end -- end
-- function tostring(any) -- function tostring(any)
-- if (type(any)~="table") return tostr(any) -- if (type(any)~="table") return tostr(any)
-- local str = "{" -- local str = "{"
@ -85,53 +85,50 @@ end
-- return str.."}" -- return str.."}"
-- end -- end
-- --
-- main loop -- main loop
-- --
function _init() function _init()
-- pal({[0]=0,128,132,7,136,8,14,137,9,10,131,3,11,1,140,12},1) -- 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 -- poke(0x5f2e,1) --to keep colors
printh(" ") printh(" ")
printh("*************") printh("*************")
printh(" ") printh(" ")
local date = stat(80)..stat(81)..stat(82)..stat(84)..stat(85) local date = stat(80) .. stat(81) .. stat(82) .. stat(84) .. stat(85)
srand(date) srand(date)
printh("seed " .. date) printh("seed " .. date)
frame_count = 0
frame_count = 0 states = {
rules = state_rules(),
states = { menu = state_menu(),
rules = state_rules(), loading = state_loading(),
menu = state_menu(), game = state_game(),
loading = state_loading(), endgame = state_endgame()
game = state_game(), }
endgame = state_endgame(),
}
set_state(states.menu)
set_state(states.menu)
end end
function _update60() function _update60()
frame_count += 1 frame_count += 1
-- update mouse coords -- update mouse coords
mouse_x = stat(32) mouse_x = stat(32)
mouse_y = stat(33) mouse_y = stat(33)
_coresolve() _coresolve()
gs._update() gs._update()
end end
function _draw() function _draw()
gs._draw() gs._draw()
for overlay in all(overlays) do for overlay in all(overlays) do
overlay:_draw() overlay:_draw()
end end
-- mouse cursor -- mouse cursor
spr(1, mouse_x, mouse_y) spr(1, mouse_x, mouse_y)
end end

View File

@ -1,51 +1,54 @@
function state_endgame() function state_endgame()
local board local board
local message = "웃웃 yay! 웃웃" local message = "웃웃 yay! 웃웃"
local message_x = 0 local message_x = 0
local function go_to_menu() local function go_to_menu()
set_state(states.menu) set_state(states.menu)
end end
local btn_back = make_button({x=1, y=118, h=7, text="🅾️/C bACK TO mENU", color=8, local btn_back = make_button({
on_click=function() go_to_menu() end, x = 1, y = 118, h = 7, text = "🅾️/C bACK TO mENU", color = 8,
on_hover=function(btn) btn.color = 7 end}) on_click = function() go_to_menu() end,
on_hover = function(btn) btn.color = 7 end
})
local function _enter(_board) local function _enter(_board)
board = _board board = _board
message_x = (128 - print(message,0,-100))/2 message_x = (128 - print(message, 0, -100)) / 2
end end
local function _update() local function _update()
btn_back:update() btn_back:update()
if btnp(BTN_O) then if btnp(BTN_O) then
go_to_menu() go_to_menu()
end end
end end
local function _draw() local function _draw()
cls() cls()
board:draw() board:draw()
-- wavy message -- wavy message
local offset=0 local offset = 0
for i = 1, #message, 1 do -- loop through every letter for i = 1, #message, 1 do
letter = sub(message, i, i) -- grab this letter -- loop through every letter
local st = t() + 0.125 * i -- create a modified time for this letter letter = sub(message, i, i) -- grab this letter
print(letter, message_x + offset, 20 + sin(st*0.5)*10, 7) -- draw this letter local st = t() + 0.125 * i -- create a modified time for this letter
offset += print(letter,0,-100) print(letter, message_x + offset, 20 + sin(st * 0.5) * 10, 7) -- draw this letter
end offset += print(letter, 0, -100)
end
btn_back:draw() btn_back:draw()
end end
local function _leave() local function _leave()
end end
return { return {
_enter = _enter, _enter = _enter,
_update = _update, _update = _update,
_draw = _draw, _draw = _draw,
_leave = _leave _leave = _leave
} }
end end

View File

@ -1,134 +1,133 @@
function state_game() function state_game()
local board
local selected_id = 1
local timer_clue = 0
local mx, mx = 0, 0
local board local clues = {}
local selected_id = 1 local function show_clues()
local timer_clue = 0 local issues = board:get_issues(true)
local mx,mx = 0,0 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 draw_selected_tile()
local function show_clues() local x, y = board:draw_coords(selected_id)
local issues = board:get_issues(true) local w = board:get_tile_width()
clues = {} -- fillp(▒)
for issue in all(issues) do rect2(x - 1, y - 1, w, w, 6)
local type, err, row, pos, other = unpack(issue) line()
printh(type .. " " .. err .. " " .. pos) fillp()
add(clues, {type=type, pos=pos, t=0}) end
if err == "identical" then
add(clues, {type=type, pos=other, t=0})
end
end
end
local function draw_selected_tile() local function update_mouse()
local x, y = board:draw_coords(selected_id) -- update mouse position
local w = board:get_tile_width() if mx == mouse_x and my == mouse_y then return end
-- fillp(▒) mx, my = mouse_x, mouse_y
rect2(x-1, y-1, w, w, 6) local board_x, board_y = board:draw_coords(1)
line() local tw = board:get_tile_width()
fillp() local bw = board:get_size()
end -- 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() local function check_endgame()
-- update mouse position if board:is_complete() and board:is_valid() then
if mx == mouse_x and my == mouse_y then return end set_state(states.endgame, board)
mx,my = mouse_x, mouse_y end
local board_x, board_y = board:draw_coords(1) end
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() local function _enter(_board)
if board:is_complete() and board:is_valid() then -- mouse bound to buttons
set_state(states.endgame, board) poke(0x5F2D, 3)
end
end
local function _enter(_board) board = _board
-- mouse bound to buttons -- lock the initial tiles
poke(0x5F2D, 3) board:lock_tiles()
end
board = _board local function _leave()
-- lock the initial tiles -- stopcoroutine(show_clues)
board:lock_tiles() end
end
local function _leave() local function _update()
-- stopcoroutine(show_clues) update_mouse()
end
local function _update() local size = board:get_size()
update_mouse() local x, y = board:idx_xy(selected_id)
local moved = false
local size = board:get_size() if btnp(UP) then
local x, y = board:idx_xy(selected_id) moved = true
local moved = false 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 if btnp(BTN_X) then
moved = true board:try_flip_tile(selected_id)
y -= 1 show_clues()
elseif btnp(DOWN) then end
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 if (x < 1) x = size
board:try_flip_tile(selected_id) if (x > size) x = 1
show_clues() if (y < 1) y = size
end if (y > size) y = 1
check_endgame()
end
if (x<1) x=size local function _draw()
if (x>size) x=1 cls()
if (y<1) y=size local x, y = board:draw_coords(1)
if (y>size) y=1 draw_animated_bg(x)
check_endgame() board:draw()
end draw_selected_tile()
local function _draw() -- draw clues
cls() for clue in all(clues) do
local x,y = board:draw_coords(1) palt(0, false)
draw_animated_bg(x) 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() return {
draw_selected_tile() _enter = _enter,
_update = _update,
-- draw clues _draw = _draw,
for clue in all(clues) do _leave = _leave
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
}
end end

View File

@ -1,158 +1,160 @@
function state_loading() function state_loading()
local board local board
local size local size
local og_rt local og_rt
local removing_tile local removing_tile
local spinner = split"-,\\,|,/" local spinner = split "-,\\,|,/"
local loading_messages = { local loading_messages = {
"rETICULATING SPLINES", "rETICULATING SPLINES",
"aLLOCATING RESSOURCES", "aLLOCATING RESSOURCES",
"eMULATING HARDWARE", "eMULATING HARDWARE",
"uNCLOGGING MEMORY BUS", "uNCLOGGING MEMORY BUS",
"sPINNING UP ai AGENT", "sPINNING UP ai AGENT",
"sIDE-STEPPING VIRTUAL MACHINE", "sIDE-STEPPING VIRTUAL MACHINE",
"iNSTALLING BACKTRACKING WIZARD", "iNSTALLING BACKTRACKING WIZARD",
"eXFOLIATING PIXELS", "eXFOLIATING PIXELS",
"sCAFFOLDING RAY-TRACING ALGORITHM", "sCAFFOLDING RAY-TRACING ALGORITHM",
"sWEEPING PARTICLES", "sWEEPING PARTICLES",
"pRESSURIZING USER INTERFACE", "pRESSURIZING USER INTERFACE",
"sHAKING RED AND BLUE PAINT BUCKETS", "sHAKING RED AND BLUE PAINT BUCKETS",
"gATHERING GRAVITY", "gATHERING GRAVITY",
"sERIALIZING BOARD MATRIX", "sERIALIZING BOARD MATRIX",
"bACKPORTING e2e ENCRYPTION", "bACKPORTING e2e ENCRYPTION"
} }
local message = "" local message = ""
local messages_str = "" local messages_str = ""
local messages_x = 128 local messages_x = 128
local loaded = false local loaded = false
local done = {} local done = {}
local create_board = function() local create_board = function()
printh("creating") printh("creating")
local start = time() local start = time()
repeat repeat
board:reset() board:reset()
repeat repeat
board:solve_step(true) board:solve_step(true)
yield() yield()
until board:is_complete() until board:is_complete()
until board:is_valid() until board:is_valid()
-- Remove tiles that can be removed -- Remove tiles that can be removed
local previous = {board:get_tiles_copy()} -- initial state local previous = { board:get_tiles_copy() }
done = {} -- initial state
while true do 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]) board:fill(removing_tile, 0)
-- remove a random tile add(done, removing_tile)
repeat add(previous, board:get_tiles_copy())
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) -- try to solve the board
add(done, removing_tile) local solved = ""
add(previous, board:get_tiles_copy()) 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 if solved == "invalid" then
local solved = "" deli(previous)
yield() end
repeat end
solved = board:solve_step() -- end while
if solved == "valid" then printh("board generated in " .. time() - start .. " seconds")
amplitude -= .125 startcoroutine(cocreate(function()
end repeat
until board:is_complete() or solved == "invalid" amplitude -= .5
yield()
until amplitude <= 0
end))
if solved == "invalid" then board:set_tiles(previous[#previous])
deli(previous) printh(board:tostring())
end printh(count(board:get_tiles_copy(), 0) .. " zeroes")
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]) loaded = true
printh(board:tostring()) end
printh(count(board:get_tiles_copy(), 0).." zeroes")
loaded = true local function draw_tiles(board)
end 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 function _enter()
local w = board:get_size() printh("enter loading")
local tiles = board:get_tiles_copy() board = Board:new()
for k,v in ipairs(tiles) do size = board:get_size() * board:get_size()
if v==0 or contains(done, k) then og_rt = rnd(size) \ 1 + 1
board:draw_tile(k) -- original removing tile
end removing_tile = og_rt
end
end
local function _enter() amplitude = 64
printh("enter loading") loaded = false
board = Board:new() done = {}
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 = {}
local copy_messages = copy(loading_messages) local copy_messages = copy(loading_messages)
messages_str = "" messages_str = ""
messages_x = 128 messages_x = 128
while #copy_messages > 0 do while #copy_messages > 0 do
local m = rnd(copy_messages) local m = rnd(copy_messages)
messages_str ..= m .. " " messages_str ..= m .. " "
del(copy_messages, m) del(copy_messages, m)
end end
messages_str ..= "tHANK YOU FOR YOUR PATIENCE" messages_str ..= "tHANK YOU FOR YOUR PATIENCE"
startcoroutine(cocreate(create_board)) startcoroutine(cocreate(create_board))
end end
local function _update() local function _update()
board:lock_tiles() board:lock_tiles()
messages_x -= 4 messages_x -= 4
if loaded then if loaded then
set_state(states.game, board) set_state(states.game, board)
end end
end end
local function _draw() local function _draw()
cls() cls()
local x,y = board:draw_coords(1) local x, y = board:draw_coords(1)
draw_animated_bg(x) draw_animated_bg(x)
-- board:draw_bg() -- board:draw_bg()
draw_tiles(board) draw_tiles(board)
local s = board:get_size()*board:get_size() local s = board:get_size() * board:get_size()
local l = print(message, 0, -100) local l = print(message, 0, -100)
local y = 118+(removing_tile/s)*100/8 local y = 118 + removing_tile / s * 100 / 8
local ci = removing_tile\20+1 local ci = removing_tile \ 20 + 1
-- if not loaded then -- if not loaded then
-- rectfill2(0,y-2,127,10,0) -- rectfill2(0,y-2,127,10,0)
-- print(messages_str, messages_x, y, 3, 0) -- print(messages_str, messages_x, y, 3, 0)
-- -- print(spinner[t()\.25%4+1], 120, 120) -- -- print(spinner[t()\.25%4+1], 120, 120)
-- end -- end
end end
return { return {
_enter = _enter, _enter = _enter,
_update = _update, _update = _update,
_draw = _draw, _draw = _draw
} }
end end

View File

@ -1,78 +1,79 @@
function state_menu() function state_menu()
local selected = 1 local selected = 1
local buttons = {} local buttons = {}
-- local buttons = { -- local buttons = {
-- make_button({x=10, y=10, w=30, text="pLAY", data={i=1}, -- make_button({x=10, y=10, w=30, text="pLAY", data={i=1},
-- on_click=function() set_state(states.loading) end, -- on_click=function() set_state(states.loading) end,
-- on_hover=function(btn) selected=1 end, -- on_hover=function(btn) selected=1 end,
-- }), -- }),
-- } -- }
local game_sizes = { local game_sizes = {
{"mINI bOARD - 4X4", 4}, { "mINI bOARD - 4X4", 4 },
{"sMALL bOARD - 6X6", 6}, { "sMALL bOARD - 6X6", 6 },
{"mEDIUM bOARD - 8X8", 8}, { "mEDIUM bOARD - 8X8", 8 },
{"lARGE bOARD - 10X10", 10} { "lARGE bOARD - 10X10", 10 }
} }
for k, item in ipairs(game_sizes) do for k, item in ipairs(game_sizes) do
add(buttons, add(
make_button({ buttons,
x=10, y=10+k*10, make_button({
selected_color=7, x = 10, y = 10 + k * 10,
text=item[1], selected_color = 7,
on_click=function() board_size=item[2] set_state(states.loading) end, text = item[1],
on_hover=function() selected=k end, on_click = function() board_size = item[2] set_state(states.loading) end,
}) on_hover = function() selected = k end
) })
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 local function _enter()
add(buttons, -- mouse not bound to buttons
make_button({x=10, y=20+(#game_sizes+1)*10, w=30, text="rULES", poke(0x5F2D, 1)
color=13, selected_color=12, end
on_click=function() set_state(states.rules) end,
on_hover=function() selected=rulesId end,
})
)
local function _enter() local function _draw()
-- mouse not bound to buttons cls()
poke(0x5F2D, 1) draw_bg_menu()
end
local function _draw() print("pLAY", 10, 8, 8)
cls()
draw_bg_menu()
print("pLAY", 10, 8, 8)
for k,button in ipairs(buttons) do for k, button in ipairs(buttons) do
button:draw(selected == k) button:draw(selected == k)
end end
print("pRESS ❎/X TO CONTINUE", 8, 120, 7) print("pRESS ❎/X TO CONTINUE", 8, 120, 7)
end end
return { return {
_enter = _enter, _enter = _enter,
_update = function() _update = function()
for button in all(buttons) do for button in all(buttons) do
button:update() button:update()
end end
if btnp(UP) then if btnp(UP) then
selected -= 1 selected -= 1
elseif btnp(DOWN) then elseif btnp(DOWN) then
selected += 1 selected += 1
elseif btnp(BTN_X) then elseif btnp(BTN_X) then
buttons[selected]:on_click() buttons[selected]:on_click()
end end
selected = mid(1, selected, #buttons) selected = mid(1, selected, #buttons)
end,
end, _draw = _draw
}
_draw = _draw
}
end end

View File

@ -1,94 +1,94 @@
function state_rules() 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 function blink(x, y, w, h)
local color = 1 rect2(x, y, w, h, fade[color])
end
local function blink(x,y,w,h) local function go_back()
rect2(x,y,w,h,fade[color]) set_state(states.menu)
end end
local function go_back() local btn_back = make_button({
set_state(states.menu) x = 1, y = 118, w = 30, h = 7, text = "🅾️/C mENU", color = 8,
end 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, return {
on_click=function() go_back() end, _enter = function()
on_hover=function(btn) btn.color = 7 end}) end,
return { _exit = function()
_enter = function() -- standard_font()
end, 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
-- Back to the menu _update = function()
if btnp(BTN_O) then -- custom_font()
go_back() if frame_count % 8 == 0 then
end color += 1
end
if color > #fade then
color = 1
end
btn_back:update() -- Back to the menu
end, if btnp(BTN_O) then
go_back()
end
_draw=function() btn_back:update()
cls() end,
print("1) yOU CAN'T HAVE MORE THAN\n TWO (2) CONSECUTIVE TILES\n OF THE SAME COLOR", 2,2, 7) _draw = function()
local x = 14 cls()
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 print("1) yOU CAN'T HAVE MORE THAN\n TWO (2) CONSECUTIVE TILES\n OF THE SAME COLOR", 2, 2, 7)
sspr(26,32, 12,12, x,y) local x = 14
spr(2, x+14, y+1) local y = 28
sspr(39,32, 12,12, x+26,y) sspr(0, 32, 12, 12, x, y)
blink(x+5, y+2, 3, 9) spr(2, x + 14, y + 1)
blink(x+31, y+2, 3, 9) 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 x = 44
y = 50 y = 50
print("2) eACH LINE CONTAINS AN EQUAL\n NUMBER OF EACH COLOR", 2, y, 7) print("2) eACH LINE CONTAINS AN EQUAL\n NUMBER OF EACH COLOR", 2, y, 7)
sspr(52,32, 12,12, x,y+20) sspr(52, 32, 12, 12, x, y + 20)
spr(2, x+14, y+21) spr(2, x + 14, y + 21)
sspr(65,32, 12,12, x+26,y+20) sspr(65, 32, 12, 12, x + 26, y + 20)
blink(x+5, y+22, 6, 3) blink(x + 5, y + 22, 6, 3)
blink(x+31, y+22, 6, 3) blink(x + 31, y + 22, 6, 3)
blink(x-1, y+19, 3, 6) blink(x - 1, y + 19, 3, 6)
blink(x+25, y+19, 3, 6) blink(x + 25, y + 19, 3, 6)
-------------- --------------
x = 44 x = 44
y = 90 y = 90
print("3) aLL ROWS AND COLUMNS\n ARE DIFFERENT", 2, y, 7) print("3) aLL ROWS AND COLUMNS\n ARE DIFFERENT", 2, y, 7)
sspr(78,32, 12,12, x,y+20) sspr(78, 32, 12, 12, x, y + 20)
spr(2, x+14, y+21) spr(2, x + 14, y + 21)
sspr(91,32, 12,12, x+26,y+20) sspr(91, 32, 12, 12, x + 26, y + 20)
blink(x-1, y+25, 12, 6) blink(x - 1, y + 25, 12, 6)
blink(x+25, y+25, 12, 6) blink(x + 25, y + 25, 12, 6)
-------------- --------------
btn_back:draw() btn_back:draw()
end, end
} }
end end

View File

@ -1,7 +1,7 @@
local Tile = {} local Tile = {}
function Tile.new(color) function Tile.new(color)
return { return {
color=color color = color
} }
end end

77
ui.lua
View File

@ -1,42 +1,43 @@
function make_button(options) function make_button(options)
local state = 0 -- 0 = normal, 1 = hovered, 2 = pressed local state = 0
local w = print(options.text, 0, -100) -- 0 = normal, 1 = hovered, 2 = pressed
return { local w = print(options.text, 0, -100)
x = options.x, return {
y = options.y, x = options.x,
w = options.w or w, y = options.y,
h = options.h or 6, w = options.w or w,
data = options.data, h = options.h or 6,
text = options.text, data = options.data,
on_click = options.on_click, text = options.text,
on_hover = options.on_hover, on_click = options.on_click,
ogColor = options.color or 5, on_hover = options.on_hover,
selected_color = options.selected_color or 5, ogColor = options.color or 5,
color = options.color or 5, selected_color = options.selected_color or 5,
color = options.color or 5,
draw=function(self, selected) draw = function(self, selected)
standard_font() standard_font()
local color = selected and self.selected_color or self.color local color = selected and self.selected_color or self.color
print(self.text, self.x, self.y, color) print(self.text, self.x, self.y, color)
-- rect(self.x, self.y, self.x+self.w, self.y+self.h, color) -- rect(self.x, self.y, self.x+self.w, self.y+self.h, color)
end, end,
update=function(self) update = function(self)
self.color = self.ogColor self.color = self.ogColor
if mouse_x >= self.x and mouse_x <= self.x + self.w and if mouse_x >= self.x and mouse_x <= self.x + self.w
mouse_y >= self.y and mouse_y <= self.y + self.h then 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 if stat(34) & 1 == 0 and state == 2 and self.on_click then
self.on_click(self) self.on_click(self)
end end
if stat(34)&1 == 1 then if stat(34) & 1 == 1 then
state = 2 state = 2
else else
if self.on_hover then self:on_hover() end if self.on_hover then self:on_hover() end
state = 1 state = 1
end end
else else
state = 0 state = 0
end end
end end
} }
end end

View File

@ -1,63 +1,62 @@
local oldprint = print local oldprint = print
function print(t,x,y,col1,col2) function print(t, x, y, col1, col2)
if col2 then if col2 then
for i=-1,1 do for i = -1, 1 do
for j=-1,1 do for j = -1, 1 do
oldprint(t, x+i, y+j, col2) oldprint(t, x + i, y + j, col2)
end end
end end
end end
return oldprint(t, x, y, col1) return oldprint(t, x, y, col1)
end end
function str_width(str) function str_width(str)
return print(str,0,-8) return print(str, 0, -8)
end end
function print_shade(t,x,y,col1,col2) function print_shade(t, x, y, col1, col2)
print(t,x,y+1,col2) print(t, x, y + 1, col2)
print(t,x+1,y+1,col2) print(t, x + 1, y + 1, col2)
print(t,x,y,col1) print(t, x, y, col1)
end end
function set_state(state, ...) function set_state(state, ...)
local args = {...} local args = { ... }
if gs and gs._leave then gs._leave() end if gs and gs._leave then gs._leave() end
gs = state gs = state
if gs and gs._enter then gs._enter(unpack(args)) end if gs and gs._enter then gs._enter(unpack(args)) end
end end
-- --
-- Returns the indices of found occurences of `o` within `tbl` -- Returns the indices of found occurences of `o` within `tbl`
-- --
function find(tbl, o) function find(tbl, o)
local indices = {} local indices = {}
for k,v in ipairs(tbl) do for k, v in ipairs(tbl) do
if v == o then add(indices, k) end if v == o then add(indices, k) end
end end
return indices return indices
end end
function contains(tbl, o) function contains(tbl, o)
for v in all(tbl) do for v in all(tbl) do
if v == o then return true end if v == o then return true end
end end
return false return false
end end
-- --
-- Makes a shallow table copy -- Makes a shallow table copy
-- --
function copy(tbl) function copy(tbl)
return map(tbl, function (o) return o end) return map(tbl, function(o) return o end)
end end
-- --
-- Table equality - shallow comparison -- Table equality - shallow comparison
-- --
function equal(tbl1, tbl2) function equal(tbl1, tbl2)
for k, _ in ipairs(tbl1) do for k, _ in ipairs(tbl1) do
if tbl1[k] ~= tbl2[k] then return false end if tbl1[k] ~= tbl2[k] then return false end
end end
return true return true
end end

View File

@ -1,39 +1,41 @@
local overlays = {} local overlays = {}
function get_main_color(tint) function get_main_color(tint)
if tint == BLUE then if tint == BLUE then
return 12 return 12
elseif tint == YELLOW then elseif tint == YELLOW then
return 9 return 9
else else
return 1 return 1
end end
end end
function get_shade_color(tint) function get_shade_color(tint)
if tint == BLUE then if tint == BLUE then
return 13 return 13
elseif tint == YELLOW then elseif tint == YELLOW then
return 4 return 4
else else
return 1 return 1
end end
end end
function spawn_tile_transition(x, y, w, h, from_tint, to_tint) function spawn_tile_transition(x, y, w, h, from_tint, to_tint)
local p = #patterns local p = #patterns
local from_color = get_main_color(from_tint) local from_color = get_main_color(from_tint)
local to_color = get_main_color(to_tint) local to_color = get_main_color(to_tint)
add(overlays, { add(
_draw = function(self) overlays, {
fillp() _draw = function(self)
rectfill(x, y, x + w, y + h, from_color) fillp()
fillp(patterns[p\1]+0b0.1) rectfill(x, y, x + w, y + h, from_color)
rectfill(x, y, x + w, y + h, to_color) fillp(patterns[p \ 1] + 0b0.1)
p -= 1 rectfill(x, y, x + w, y + h, to_color)
if p < 1 then p -= 1
del(overlays, self) if p < 1 then
end del(overlays, self)
end end
}) end
end }
)
end