Skip to content

Instantly share code, notes, and snippets.

@Ivoah
Last active July 13, 2020 17:50
Show Gist options
  • Save Ivoah/f1c3c87c76e40f4cc6ade679cd79f9bc to your computer and use it in GitHub Desktop.
Save Ivoah/f1c3c87c76e40f4cc6ade679cd79f9bc to your computer and use it in GitHub Desktop.
all_cards = {
{0, 3},
{0, 0}, {0, 0}, {0, 0}, {0, 0},
{0, 1}, {0, 1}, {0, 1}, {0, 1},
{0, 2}, {0, 2}, {0, 2}, {0, 2},
{1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0},
{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {8, 1}, {9, 1},
{1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {8, 2}, {9, 2},
}
function draw_card(x, y, card)
spr(14, x, y, 2, 4) -- draw card base
spr(card[1] + card[2]*32, x, y, 1, 2) -- draw top left corner
spr(card[1] + card[2]*32, x + 8, y + 16, 1, 2, true, true) -- draw bottom right corner (flipping on the vertical and horizontal)
end
function draw_stack(x, y, stack)
for i, card in pairs(stack) do
draw_card(x, y + (i - 1)*6, card)
end
end
function lerp(a, b, r) return a + (b - a)*r end
function move(x1, y1, x2, y2, stack)
local speed = 5
sfx(1)
for i = 1, speed do
_draw()
draw_stack(lerp(x1, x2, i/speed), lerp(y1, y2, i/speed), stack)
flip()
end
end
function split(table, n)
local t1 = {}
local t2 = {}
for i = 1, #table do
if i < n then
add(t1, table[i])
else
add(t2, table[i])
end
end
return t1, t2
end
function slice(table, n)
local t = {}
for i = n, #table do
add(t, table[i])
end
return t
end
function top(table)
return table[#table]
end
function equals(t1, t2)
if type(t1) ~= type(t2) or #t1 ~= #t2 then return false end
for i = 1, #t1 do
if t1[i] ~= t2[i] then
return false
end
end
return true
end
function valid_pair(card1, card2)
return btn(4, 1) or btn(5, 1) or card1 == nil or card2[1] != 0 and card1[1] == card2[1] + 1 and card1[2] != card2[2]
end
function valid_stack(stack)
for i = #stack, 2, -1 do
if not valid_pair(stack[i - 1], stack[i]) then
return false
end
end
return true
end
function auto_move()
local min_safe = 9
for i = 1, #safe do
min_safe = min(min_safe, safe[i] and safe[i][1] or 0)
end
for i = 1, #free do
local card = free[i]
if type(card) == "table" then
for j = 1, #safe do
if (safe[j] == false and card[1] == 1) or (safe[j] and card[1] == safe[j][1] + 1 and card[1] - 1 <= min_safe and card[2] == safe[j][2]) then
free[i] = false
move((i - 1)*16, 0, 80 + (j - 1)*16, 0, {card})
safe[j] = card
return
end
end
end
end
for i = 1, #cards do
local card = top(cards[i])
if card then
if card[2] == 3 then
del(cards[i], card)
move((i - 1)*16, 33 + #cards[i]*6, 61, 0, {card})
flower = card
else
for j = 1, #safe do
if (safe[j] == false and card[1] == 1) or (safe[j] and card[1] == safe[j][1] + 1 and card[1] - 1 <= min_safe and card[2] == safe[j][2]) then
del(cards[i], card)
move((i - 1)*16, 33 + #cards[i]*6, 80 + (j - 1)*16, 0, {card})
safe[j] = card
return
end
end
end
end
end
end
function check_win()
for i = 1, #cards do
if #cards[i] > 0 then
return false
end
end
return true
end
function rrect(x1, y1, x2, y2, col)
color(col)
line(x1 + 1, y1, x2 - 1, y1)
line(x2, y1 + 1, x2, y2 - 1)
line(x2 - 1, y2, x1 + 1, y2)
line(x1, y2 - 1, x1, y1 + 1)
end
function dragons_out(suite)
local n = 0
for i = 1, #free do
if type(free[i]) == "table" and equals(free[i], {0, suite}) then
n += 1
end
end
for i = 1, #cards do
if type(top(cards[i])) == "table" and equals(top(cards[i]), {0, suite}) then
n += 1
end
end
return n == 4
end
function available_free(suite)
for i = 1, #free do
if not free[i] or equals(free[i], {0, suite}) then
return true
end
end
return false
end
function deal()
free = {false, false, false}
flower = false
safe = {false, false, false}
cards = {{}, {}, {}, {}, {}, {}, {}, {}}
sel = nil
cur = {x=1, h=1}
local pick = {}
for i = 1, #all_cards do
add(pick, i)
end
dealing = true
for c = 1, 5 do
for s = 1, 8 do
n = flr(rnd(#pick)) + 1
move(
64, 0,
(s - 1)*16, 33 + (c - 1)*6,
{all_cards[pick[n]]}
)
cards[s][c] = all_cards[pick[n]]
del(pick, pick[n])
end
end
dealing = false
playing = true
end
function _init()
cartdata("ivoah_shenzhen")
wins = dget(0)
loaded = 0
palt(0, false)
palt(12, true)
end
function _update60()
if loaded <= 111 then
loaded += 1
if loaded > 111 then
menuitem(1, "re-deal", deal)
sfx(0)
deal()
end
elseif playing then
if cur.h > 0 then
if btnp(0) then
cur.x -= 1
cur.h = 1
if cur.x < 1 then cur.x = 8 end
elseif btnp(1) then
cur.x += 1
cur.h = 1
if cur.x > 8 then cur.x = 1 end
elseif btnp(2) and cur.h < #cards[cur.x] and valid_stack(slice(cards[cur.x], #cards[cur.x] - cur.h)) then
cur.h += 1
elseif btnp(3) and cur.h > 1 then
cur.h -= 1
elseif btnp(4) then
if sel then
if sel.h == 0 then
if valid_pair(top(cards[cur.x]), free[sel.x]) then
local card = free[sel.x]
free[sel.x] = false
local x = sel.x
sel = nil
move((x - 1)*16, 0, (cur.x - 1)*16, 33 + #cards[cur.x]*6, {card})
add(cards[cur.x], card)
end
else
if sel.x == cur.x then
sel = nil
elseif valid_pair(top(cards[cur.x]), cards[sel.x][#cards[sel.x] - sel.h + 1]) then
local stack
cards[sel.x], stack = split(cards[sel.x], #cards[sel.x] - sel.h + 1)
local x = sel.x
sel = nil
move((x - 1)*16, 33 + #cards[x]*6, (cur.x - 1)*16, 33 + #cards[cur.x]*6, stack)
for i = 1, #stack do
add(cards[cur.x], stack[i])
end
end
end
elseif #cards[cur.x] != 0 then
sel = {x=cur.x, h=cur.h}
end
elseif btnp(5) then
cur.h = 0
if cur.x > 4 then
cur.x -= 1
end
end
else
if btnp(0) then
cur.x -= 1
if cur.x < 1 then cur.x = 7 end
elseif btnp(1) then
cur.x += 1
if cur.x > 7 then cur.x = 1 end
elseif btnp(2) and cur.x == 4 and cur.h > -2 then
cur.h -= 1
elseif btnp(3) and cur.x == 4 and cur.h < 0 then
cur.h += 1
elseif btnp(4) then
if cur.x < 4 then
if sel then
if sel.h == 0 then
if sel.x == cur.x then
sel = nil
elseif not free[cur.x] then
local card = free[sel.x]
local x = sel.x
free[sel.x] = false
sel = nil
move((x - 1)*16, 0, (cur.x - 1)*16, 0, {card})
free[cur.x] = card
end
elseif sel.h == 1 then
if not free[cur.x] then
local card
cards[sel.x], card = split(cards[sel.x], #cards[sel.x])
local x = sel.x
sel = nil
move((x - 1)*16, 33 + #cards[x]*6, (cur.x - 1)*16, 0, card)
free[cur.x] = card[1]
end
end
elseif type(free[cur.x]) == "table" then
sel = {x=cur.x, h=0}
end
elseif cur.x == 4 then
if dragons_out(-cur.h) then
local dragon = {0, -cur.h}
for i = 1, #free do
if not free[i] or equals(free[i], dragon) then
for j = 1, #free do
if equals(free[j], dragon) then
free[j] = false
move((j - 1)*16, 0, (i - 1)*16, 0, {dragon})
free[i] = dragon
end
end
for j = 1, #cards do
if equals(top(cards[j]), dragon) then
cards[j], _ = split(cards[j], #cards[j])
move((j - 1)*16, 33 + #cards[j]*6, (i - 1)*16, 0, {dragon})
free[i] = dragon
end
end
free[i] = true
return
end
end
end
elseif cur.x > 4 then
if sel then
if sel.h == 0 then
local card = free[sel.x]
if equals({card[1] - 1, card[2]}, safe[cur.x - 4]) then
local x = sel.x
free[sel.x] = false
sel = nil
move((x - 1)*16, 0, (cur.x - 5)*16 + 80, 0, {card})
safe[cur.x - 4] = card
end
elseif sel.h == 1 then
local card = top(cards[sel.x])
if equals({card[1] - 1, card[2]}, safe[cur.x - 4]) then
local x = sel.x
cards[x], _ = split(cards[x], #cards[x])
sel = nil
move((x - 1)*16, 33 + #cards[x]*6, (cur.x - 5)*16 + 80, 0, {card})
safe[cur.x - 4] = card
end
end
end
end
elseif btnp(5) then
cur.h = 1
if cur.x > 4 then
cur.x += 1
end
end
end
auto_move()
if check_win() and playing then
wins += 1
dset(0, wins)
playing = false
end
else
if btnp() ~= 0 then
deal()
end
end
end
function _draw()
if loaded <= 111 then
cls()
spr(128, 3, 40, 16, 5)
rectfill(3, 40 + 41, 3 + 111, 40 + 45, 5)
rectfill(3, 40 + 41, 3 + loaded, 40 + 45, 7)
else
rectfill(0, 0, 127, 127, 3) -- felt
for i = 0, 2 do -- free slots
if type(free[i + 1]) == "table" then
draw_card(i*16, 0, free[i + 1])
elseif free[i + 1] then
spr(10, i*16, 0, 2, 4)
else
spr(78, i*16, 0, 2, 4)
end
end
for i = 0, 2 do
spr(99 + i*2, 49, i*11, 2, 2)
if dragons_out(2 - i) and available_free(2 - i) then
rrect(49, i*11, 49 + 8, i*11 + 9, 12)
end
end
if dealing then
spr(10, 61, 0, 2, 4) -- card backs
else
if flower then
draw_card(61, 0, flower)
else
spr(76, 61, 0, 2, 4) -- flower card slot
end
end
for i = 0, 2 do
if safe[i + 1] then
draw_card(80 + i*16, 0, safe[i + 1])
else
spr(78, 80 + i*16, 0, 2, 4) -- finished slots
end
end
for i = 0, 7 do
spr(78, i*16, 33, 2, 4) -- active slots
end
for i, stack in pairs(cards) do
draw_stack((i - 1)*16, 33, stack)
end
if cur.h <= 0 then
if cur.x < 4 then
spr(12, (cur.x - 1)*16, 0, 2, 4) -- highlight for dragon slots
elseif cur.x == 4 then
spr(97, 3*16, (cur.h + 2)*11, 2, 2) -- highlight for dragon buttons
else
spr(12, cur.x*16, 0, 2, 4)
end
else
if #cards[cur.x] != 0 then
rrect((cur.x - 1)*16, 33 + (#cards[cur.x] - cur.h)*6, (cur.x - 1)*16 + 15, 33 + #cards[cur.x]*6 + 25, 10)
else
rrect((cur.x - 1)*16, 33, (cur.x - 1)*16 + 15, 64, 10)
end
end
if sel then
if sel.h == 0 then
rrect((sel.x - 1)*16, 0, (sel.x - 1)*16 + 15, 31, 12)
else
rrect((sel.x - 1)*16, 33 + (#cards[sel.x] - sel.h)*6, (sel.x - 1)*16 + 15, 33 + #cards[sel.x]*6 + 25, 12)
end
end
rectfill(0, 121, 127, 127, 5)
print("wins: " .. wins, 1, 122, 7)
-- print("cur = {x=" .. cur.x .. ", h=" .. cur.h .. "}", 1, 122 - 7, 7)
-- if sel then
-- print("sel = {x=" .. sel.x .. ", h=" .. sel.h .. "}", 1, 122 - 2*7, 7)
-- else
-- print("sel = nil", 1, 122 - 2*7, 7)
-- end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment