`,ÿÿÿ >â0ò0ÿ¶UÆ8®æ((i™…HeH0((A¦ösï÷ôôô”°ÂVl†3â0ò0ÿ¶UÆ8®æ((i™…HeH0((A¦ösï÷ôôô”°ÂVl†3>€€P €"Uw` "fP"pwP"pPp000Pp0000ˆpp000w0`p0"00`pP0w`p"0ˆ fpPp`  pP`  P `ww@``D"`fP"Pˆ P"P@0 "@"0"P"0p"D P0`€@  "@€w ""D€wP33"@DPpP€@w@Up€pP€"wU €ˆ"p€DP €p€p@@U`""ˆ@ """`w " `p33 `pwf`pP`ˆfpPpPP`UpU pD "@ "03w 0 P PP@0 fP UpP@0€p0€p€€ˆ`P€€f@PP€ˆP`@@U`f€U@p ˆPpp PpDpf" @p" Pf`DU w"@f@  "@` ˆ@w Dp  p0D `@"@0@` @"D0` 0@w€D"@`p@ "U fp`" P `f"ˆ ˆ`P@w @€ UD@€ €ˆ €p @0@ˆpwDD0@`f@@@f0`DU0DD00fUP0@0@P0Pw0@@0PpPw0@@pPppDwpP `€P03 "``"``wP`pDPp@PDPU@P03UUpP""`P" " @w@D"ww@0"`fPp0`Up€0fp€0`P @€DU @@""""1-- title: tetroid -- author: anescient -- desc: raining tetris pieces -- script: lua rand=math.random min=math.min max=math.max tick=0 stall=0 -- ticks without progress -- top (min) free y per x piletop={} -- current pile futuretop={} -- future pile falltop={} -- current falling -- bank 0 (bg) has pile, 1 (fg) has falling bdy={} -- vert. offset by bank -- translate from screen space function by(bank,y) return (y+bdy[bank])%136 end function randx() return rand(0,239) end function clear() vbank(1) cls() vbank(0) cls() for i=0,239 do piletop[i]=135 futuretop[i]=135 falltop[i]=135 end end function BOOT() clear() bdy[0]=0 bdy[1]=0 applybdy(0) applybdy(1) ticfn=ticrain end function TIC() tick=(tick+1)%0xffff if keyp(17) then exit() end ticfn() end function ticrain() stepfall() doodle() stall=stall+1 for i=1,4 do if tryinsert() then stall=0 end end --if stall>20 and allfallen() then if rowfilled(80) then ticfn=ticendrain end end function ticendrain() stepfall() if allfallen() then ticfn=ticevap end end function tryinsert() local d,h,c=randshape() local maxx=240-#d local basex=rand(0,maxx) --deepx()-4 for dx=0,maxx do local x=(basex+dx)%(maxx+1) local ok=true -- check cliffs local mc=rand(1,4) if x>0 and futuretop[x-1]>futuretop[x]-h[1]+mc then ok=false end if xfuturetop[right]-h[#h]+mc then ok=false end end -- check open space for x2=max(0,x-1),min(maxx,x+#d) do if not ok then break end if min(falltop[x2],futuretop[x2])<5 then ok=false end end -- check contour local gap=futuretop[x]-d[1]-h[1] for xi=1,#d do if not ok then break end if futuretop[x+xi-1]-d[xi]-h[xi]~=gap then ok=false end end if ok then putshape(x,0,d,h,c) return true end end return false end function allfallen() for x=0,239 do if piletop[x]~=futuretop[x] then return false end end return true end function ticevap() stepevap() stepevap() for i=1,40 do local x=highpilex() if x<0 then tick=0 ticfn=ticendevap return end if rand(0,1)==0 then mvpix(x,piletop[x]+1,0,1) else pset(0,x,piletop[x]+1) end piletop[x]=piletop[x]+1 futuretop[x]=futuretop[x]+1 end end function ticendevap() stepevap() stepevap() if tick>80 then clear() ticfn=ticrain end end function stepevap() hline(1,0,0) bdy[1]=(bdy[1]+1)%136 applybdy(1) end function highpilex() local x=randpilex() if x<0 then return x end for i=1,3 do local xx=randpilex() if piletop[xx]239 or y>135 then return end if x>0 and futuretop[x-1]>futuretop[x]+3 then return end if x<239 and futuretop[x+1]>futuretop[x]+3 then return end if left and piletop[x]>=y then pushpix(x,y,1) end end function stepfall() for x=0,239 do local floor=piletop[x] while floor>=0 and pget(1,x,floor)~=0 do mvpix(x,floor,1,0) floor=floor-1 end piletop[x]=floor falltop[x]=min(falltop[x]+1,135) end bdy[1]=(bdy[1]-1)%136 applybdy(1) end function sinkpile() for x=0,239 do piletop[x]=min(piletop[x]+1,135) futuretop[x]=min(futuretop[x]+1,135) end bdy[0]=(bdy[0]-1)%136 applybdy(0) hline(0,0,0) end function applybdy(bank) vbank(bank) local y=bdy[bank]%136 if y>127 then y=y+120 end poke(0x3FFA,y) end -- test if pile filled along screen row function rowfilled(y) vbank(0) local y=by(0,y) for x=0,239 do if pix(x,y)==0 then return false end end return true end -- add a falling pixel function pushpix(x,y,c) local new=pget(1,x,y)==0 pset(1,x,y,c) if not new then return end falltop[x]=min(falltop[x],y-1) futuretop[x]=futuretop[x]-1 end -- remove a falling pixel function poppix(x,y) if pget(1,x,y)==0 then return end pset(1,x,y,0) if falltop[x]==y-1 then findfalltop(x) end futuretop[x]=futuretop[x]+1 end -- search and update falltop[x] function findfalltop(x) falltop[x]=135 for y=-1,134 do if pget(1,x,y+1)~=0 then falltop[x]=y break end end end -- set pixel in screen space function pset(bank,x,y,c) vbank(bank) pix(x,by(bank,y),c) end -- get pixel in screen space function pget(bank,x,y) vbank(bank) return pix(x,by(bank,y)) end -- move pixel in screen space between pages function mvpix(x,y,src,dst) local c=pget(src,x,y) pset(src,x,y,0) pset(dst,x,y,c) end -- horiz. line in screen space function hline(bank,y,c) vbank(bank) y=by(bank,y) line(0,y,239,y,c) end function putshape(x,y,d,h,c) for xi=1,#d do for dy=1,h[xi] do pushpix(x+xi-1,y+dy-1+d[xi],c) end end end function randshape() local si=rand(1,#shapes) local rots=shapes[si] local dh=rots[rand(1,#rots)] return dh[1],dh[2],1+si end -- shapes[shape][rotation]=depth[],height[] shapes={ {{{0,0},{2,2}}}, -- square {{{0},{4}}, -- line {{0,0,0,0},{1,1,1,1}}}, {{{0,1},{2,2}}, -- S {{1,0,0},{1,2,1}}}, {{{1,0},{2,2}}, -- Z {{0,0,1},{1,2,1}}}, {{{0,0,0},{1,2,1}}, -- T {{1,0},{1,3}}, {{1,0,1},{1,2,1}}, {{0,1},{3,1}}}, {{{0,2},{3,1}}, -- L {{0,0,0},{2,1,1}}, {{0,0},{1,3}}, {{1,1,0},{1,1,2}}}, {{{2,0},{1,3}}, -- J {{0,1,1},{2,1,1}}, {{0,0},{3,1}}, {{0,0,0},{1,1,2}}} }