Last active
July 13, 2020 17:50
-
-
Save Ivoah/f1c3c87c76e40f4cc6ade679cd79f9bc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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