|
--pico puzzle league |
|
--by tobiasvl |
|
|
|
-- turn on 64x64 mode |
|
poke(0x5f2c,3) |
|
|
|
-- the block symbols and their colors. the index is the representation |
|
-- for the blocks in-game. the reason i chose the index and not the |
|
-- symbol itself is that i negate the index number while removing |
|
-- blocks, to be able to match longer chains than 3 blocks. |
|
w={10,11,8,2,12} |
|
o="★●♥◆✽" |
|
|
|
-- the playing area. this is a grid of symbols with 6 columns, |
|
-- stored as a one-dimensional table to save characters (zero-indexed, |
|
-- to make modulo shorter). the first row is all zeroes to make |
|
-- removal of blocks easier; it's implemented as gravity later on, |
|
-- which means that blocks need to have something on top of them to |
|
-- be removed from the board. |
|
b={[0]=0,0,0,0,0,0} |
|
|
|
-- how far up the board has scrolled |
|
z=56 |
|
|
|
-- the location of the player's marker (block number 6 is the first |
|
-- non-zero block on the board, remember) |
|
h=6 |
|
|
|
-- game loop |
|
::_:: |
|
cls() |
|
|
|
-- every frame, add a new random block. crude |
|
add(b,ceil(rnd(5))) |
|
|
|
-- print the player's marker |
|
?"██",8*(h%6),z+8*flr(h/6),5 |
|
|
|
-- in lieu of a scoring system, print the number of seconds you've survived |
|
?t(),49,58 |
|
|
|
-- update the visible board "limit"; any block with an index from 0 to j+6 |
|
-- is visible, but the last 6 blocks are "grayed out" and waiting to come |
|
-- into play. |
|
j=6*(8-flr(z/8))-6 |
|
|
|
-- for each visible blocks... |
|
for q=0,j+6 do |
|
-- take the absolute value of that block... |
|
u=abs(b[q]) |
|
-- then, both horizontally and vertically... |
|
for i in all{1,6}do |
|
-- if we are in the active playing area... |
|
if q<j |
|
-- and we're not wrapping left off the current row while checking... |
|
and (i>1 or q%6>1) |
|
-- then check if the current block is the same block as the two previous ones |
|
-- (by comparing absolute values) |
|
and u==abs(b[q-i])and u==abs(b[q-i*2]) |
|
-- oh also it should not be empty |
|
and u!=0 then |
|
-- if so, then mark all three blocks for removal by making them negative |
|
b[q-i]=-u b[q-i*2]=-u b[q]=-u |
|
end |
|
end |
|
-- print all blocks in a grid, in dark blue if it's off the playing area |
|
?sub(o,u,u),(q%6)*8,z+flr(q/6)*8,q<j and w[u]or 1 |
|
end |
|
|
|
-- one more pass for gravity and block removal. |
|
-- i spent a while refining this. originally i started at the end of the board, |
|
-- which means that stacks of blocks will fall together without leaving gaps |
|
-- between them (this was before i added the first row of zeroes). that seemed |
|
-- to create too many weird situations where falling blocks would match with blocks |
|
-- on either side though, so i went with this instead. it's not perfect either, |
|
-- of course, since stacks will now fall in a "staggered" manner. |
|
for q=0,j do |
|
-- (first check that we have enough blocks to check gravity, since we naively |
|
-- create one block per frame) |
|
if j>6 |
|
-- see if we're standing on empty air or a block marked for removal |
|
-- (note that we do this even for empty air, which means that all empty |
|
-- cells fall down through other empty cells... not efficient but works out |
|
-- with that first row of the board) |
|
and b[q+6]<1 then |
|
-- if so, it falls down and leaves empty air above it |
|
b[q+6]=b[q] |
|
b[q]=0 |
|
end |
|
end |
|
|
|
-- button input |
|
q=btnp() |
|
|
|
-- we move the player pre-emptively |
|
l=({-1,1,0,-6,[8]=6})[q] or 0 |
|
h=h+l |
|
|
|
-- if we moved outside the board, move back. |
|
-- i think doing it this way saved a character once but i'm not sure |
|
-- anymore. |
|
if (h%6>4 or h<6or h>=j) h-=l |
|
|
|
-- if the player pressed x or z |
|
if q>8 then |
|
-- swap the current block with the one to the right |
|
v=b[h+1] |
|
b[h+1]=b[h] |
|
b[h]=v |
|
end |
|
|
|
-- naive fail condition: |
|
-- pick a random pixel at the top of the screen. as long as that pixel |
|
-- isn't any of the colors used for the blocks, update the board's crawl, |
|
-- flip the display buffer and iterate the game loop. (otherwise, exit.) |
|
if pget(rnd(64),0)<6 then |
|
z-=.05 |
|
flip() |
|
goto _ |
|
end |