From 9b66345e4ca06a5d6f63bfbc42b90edd9fce8272 Mon Sep 17 00:00:00 2001 From: Kistaro Windrider Date: Sat, 17 Dec 2022 20:09:17 +0000 Subject: [PATCH] Extreme Tetrom 7.4 Version 7.4 of Extreme Tetrom, the version I had written before the repository was created. Signed-off-by: Kistaro Windrider --- extreme-tetrom.p8 | 2454 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2454 insertions(+) create mode 100644 extreme-tetrom.p8 diff --git a/extreme-tetrom.p8 b/extreme-tetrom.p8 new file mode 100644 index 0000000..987781f --- /dev/null +++ b/extreme-tetrom.p8 @@ -0,0 +1,2454 @@ +pico-8 cartridge // http://www.pico-8.com +version 36 +__lua__ +--extreme tetrom +--by vanessa♥,kistaro,nyeogmi + +version={7,4} +cartdata("extreme_tetrom_v7_0") + +function usplit(str) + return unpack(split(str)) +end +function csv(s) + local ret=split(s,"\n") + for i,v in ipairs(ret) do + ret[i] = type(v) == "string" and split(v) or {v} end + return ret +end + +function _init() + for i=0,15 do + poke(0x5f60+i,i) + end + -- garbage color nybbles + garbage_bg=split"1,2,4,5,13" + garbage_fg=split"1536,1792,768,2584" + tetroms,start,do_update={all="ijlostz"},true,true + for i,t in ipairs(split"i,j,l,o,s,t,z") do + tetroms[t]=init_tetrom(15+i) + end + kick = split"0,0,-1,0,-1,-1,0,2,-1,2,0,0,-1,0,-1,1,0,-2,-1,-2,0,0,1,0,1,-1,0,2,1,2,0,0,1,0,1,1,0,-2,1,-2,0,0,1,0,1,-1,0,2,1,2,0,0,-1,0,-1,1,0,-2,-1,-2,0,0,-1,0,-1,-1,0,2,-1,2,0,0,1,0,1,1,0,-2,1,-2,0,0,-2,0,1,0,-2,1,1,-2,0,0,-2,0,1,0,1,2,-2,-1,0,0,-1,0,2,0,-1,2,2,-1,0,0,2,0,-1,0,2,1,-1,-1,0,0,2,0,-1,0,2,1,-1,-2,0,0,-2,0,1,0,-2,1,1,-1,0,0,1,0,-2,0,1,2,-2,-1,0,0,2,0,-1,0,-1,2,2,-1" + updaters={update_menu,update_options,update_scoremenu,update_game} + drawers={draw_menu,draw_options,draw_scoremenu,draw_game} + init_modes() + init_menu() +end + +function _update60() + anim.update() + updaters[gstate]() +end + +function _draw() + cls() + camera() + bg.draw() + drawers[gstate]() + anim.draw() +end + +--helper functions, data +function confirm() + return btnp()&0x0030~=0 +end + +function confirm_delay() + if (not confirm_deadline) confirm_deadline=time()+1 + if time()>=confirm_deadline and confirm() then + confirm_deadline=nil + return true + end + return false +end + +function get_num(d,m,n) + return d%m^(n+1) \ m^n +end + +function put_num(d,m,x) + return d*m+x +end + +function bitpack(t) + local ret=0 + for i=#t,1,-1 do + ret<<=1 + if(t[i])ret+=1 + end + return ret +end + +function get_bit(num,n) + return 0!=num&2^n +end + +function printc_multi(s,y,c,m) + local p,n = split(s," ") + for i,st in ipairs(p) do + st=tostr(st) + if not n then + n=st + elseif #st+#n+1 <= m then + n..=" "..st + else + printc(n,y,c) + y+=7 + n=st + end + end + printc(n,y,c) +end + +function print3(s,y,w) + for i=5,7 do + printc(s,y+7-i,i,w) + end +end + +function cyclenum(n,low,up) + low=low or 1 + up=up or low+1 + return(n-low)%(up-low+1)+low +end + +function fmttime(t) + return zpad(t\60,2)..":"..zpad(flr(t)%60,2) +end + +function printc(s,y,c,w) + local ww = print(s,0,256) + print(s,64-ww\2,y,c) +end + + +function btoi(b) + return b and 1 or 0 +end + +function cpt(from,to) + for k,v in pairs(from) do + if type(v)=="table" then + to[k]=to[k]or{} + cpt(v,to[k]) + else + to[k]=v +end end end + +function get_sprite(n) + local bytes,addr={},n\16*512+n%16*4 + + for i=0,31 do + bytes[i+1]=peek(addr+i%4+i\4*64) + end + + return bytes,fget(n) +end + +function zpad(str,len) + local res="" + str=tostr(str) + for i=1,(len or 2)-#str do + res..="0" + end + return res..str +end + +function irnd1(n) + return flr(rnd(n))+1 +end +-->8 +--globals, init + +--beginner curve - vaguely reminicent of classic tetris +classic_level_curve=csv[[1000,0.001 +999,0.2 +850,0.2 +849,0.25 +800,0.25 +799,0.33 +750,0.33 +749,0.5 +700,0.5 +699,0.75 +650,0.75 +649,1 +600,1 +599,2 +550,2 +549,3 +500,3 +499,4 +450,4 +449,5 +400,5 +399,6 +350,6 +349,8 +300,8 +299,10 +250,10 +249,12 +200,12 +199,16 +150,16 +149,22 +100,22 +99,30 +50,30 +49,60 +0,60]] + +-- section, are, line are, das delay, lock delay +classic_sections=csv[[50,4,0,3,10,10 +45,5,1,4,10,5 +44,6,1,5,10,5 +43,6,2,5,10,5 +42,8,4,6,10,5 +41,8,4,6,11,5 +40,8,4,6,12,5 +38,8,4,6,13,5 +35,8,4,6,14,5 +30,8,4,6,15,5 +29,8,4,6,17,4 +28,8,4,6,20,4 +27,8,4,6,24,4 +26,10,6,6,24,3 +25,10,6,8,30,3 +24,12,8,10,30,3 +23,12,10,10,30,2 +22,15,10,12,30,2 +21,15,15,12,30,2 +11,20,20,15,30,1 +6,25,20,15,30,1 +1,30,20,15,30,1]] + +function init_tetrom(num) + local t,bytes,flags={pattern={}},get_sprite(num) + + for a=1,4 do + add(t.pattern,{{},{},{},{}}) + end + + for i=1,32 do + local left,right,clm,tpat=bytes[i]%16,bytes[i]\16,(2*i-1)%4,t.pattern[ceil(((i-1)%4+1)/2)+2*btoi(16>4) + + return t +end + +function init_matrix(rows,clms) + local mtx={} + for r=1,rows do + mtx[r]={} + for c=1,clms do + mtx[r][c]=0 + end end + return mtx +end + +function initwnd(x,y,w,h,m) + local win={ + x=x,y=y,w=w,h=h,matrix=m} + return win +end + +-- block outline color flash +-- animates last-to-first! +-- first value is normal outline color +stdflash=split"135,138,11,12,13,141,2,14,142,15,7" +dkflash=split"13,141,133,130,129,1,131,134,6,6,7,7" +ltflash=split"0,128,129,1,3,139,138,135,10,7,135,7" + +function init_game(gamev) + gstate,messages,endgame,dirty=4,{},false,true + tetromsfx={i=8,o=9,t=7,j=6,l=5,s=3,z=4} + + --windows + field=initwnd(33,3,10,20,init_matrix(40,10)) + hold=initwnd(usplit"2,14,4,4") + preview=initwnd(usplit"100,14,4,4") + + bg.set"grid" + + bufmtx=init_matrix(40,10) + + --delay after locking + arecnt,arelen,areuse,clearing=0,10,false,false + + --delayed auto shift + --delay vars, not used for drop + das_len,das_cnt=14,0 + --done=false + das_bh=0 --last button held + + --the globals formerly known as game{} + + score=0 + lines=0 + linesneeded=150 + level=1 + drops=0 + gametime=0 + gm_glv=0 + gm_gtm=0 + gm_progress=0 + + --higher is better,this inverses that + invscr_ordering=false + + -- T-twist adds 2 tiers. + -- so "5 lines" is actually a T-twist triple + pts=split"10,30,50,80,150" + sprite={ + normal=1, + active=2, + hold=1, + ghost=1, + preview=1 + } + + gridspr=0 + progbar=true + bganim=true + + combo=0 + maxcombo=0 + streaking=false + invisible=false + outline_only=false + invrot=false + flash_idx=1 + flashies={} + flash_on_lock=true -- otherwise, swoosh only + + --game is over if true + topout=false + justended=false + + lv={ + tets=0, + progress=0, + goal=50, + --how much progess per + --line clear; affected by t-twists + vals=split"1,3,5,8,12" + } + bags=1 + level_curve={} + sections={} + clrspd=1 + + --stats shown on the left + --bottom-to-top + stats={} + + --how many pieces in preview + --prevlen=6 --inlined + + spawn={3,18} + + --frames spent per row + gravity=0 + gravcnt=0 + + --extra frames of are after + --line clear + lnclr_delay=10 + + --when on floor, how many + --frames before locking + lockdelay=30 + lockcnt=0 + locking_harddrop=true + + --tetromino sequence + seq={} + + ghost={ + y=0,draw=true, + color=0xd01 + } + --{name,orientation,x,y} + curtet={} + hldtet={"",1} + holdused=false + + qualify = yes + on_level = nil + on_drop = nil + + --load mode+options + cpt(gamev,_ENV) + + -- nonmerging defaults + if (#level_curve == 0) cpt(classic_level_curve, level_curve) + if (#sections == 0) cpt(classic_sections, sections) + if (#flashies == 0) cpt(stdflash, flashies) + + gm_values, gm_decay_cap=calc_gm_values(0) + gm_landmark=deli(level_curve) + next_gm_landmark=deli(level_curve) + + nextsec=deli(sections) + level_changes(level) + calc_grav() + hiscore=getscore(getscores(mode)[1],true) + randomize_bag() + last_hole = irnd1(10) + while not curtet[1] or not del(split"i,t,j,l",curtet[1]) do next_tetrom(true) end + + menuitem(1,"retry",function() + init_game(gamev) + end) + menuitem(2,"back to title",init_menu) + poke(0x5f5c,0xff) --disable btnp repeat +end +-->8 +--update routines, game logic + +function das_delay() + if das_done or das_cnt>=das_len then + das_done=true + else + das_cnt+=1 + end + if das_stuck then + das_stuck=false + return true + end + return das_done +end + +function do_das() + local x,y=0,0 + + local bh,bv= + btoi(btn"1")-btoi(btn"0"), + btn"3" + + --horizontal + if bh==0 or das_bh!=bh then + x,das_cnt,das_stuck,das_done=bh,0 + elseif das_delay() then + x=bh + end + + --vertical + if (bv) y-=1 + + das_bh=bh + return x,y +end + +function do_kick(iscw) + local ct=curtet + + --choosing the right tests + local ix= + ("i"==ct[1] and 80 or 0)+ + (iscw and 0 or 40)+ + (ct[2]-1)*10 + --kick string format: + --160 chars = [80 chars sztjl kicks][80 chars i kicks] + --80 chars = [40 chars clockwise][40 chars counterclockwise] + --40 chars = [10 chars orientation 1][...orientaiton 2][...3][...4] + --10 chars = [kick 1, x + 2][kick 1, y + 2] - repeat 5 times total for 5 + -- note: orientation is destination, not source + + --do tests + for i=ix+1,ix+9,2 do + local kx,ky=kick[i],kick[i+1] + if (move(kx,ky)) then + -- do not permit kicks to pop back up + if kx|ky~=0 then + while ct[4] > ct[5] and mv_vt(-1) do end + end + return true + end + end + return false +end + +function legal(t) + local m=field.matrix + for row=1,4 do + for clm=1,4 do + --current block + local b=tetroms[t[1]].pattern[t[2]][row][clm] + if(b)then + local x,y=clm+t[3],row+t[4] + if(1>x or #m[1]y or #m2 + end + + update_ghost() + sfx(btoi(iscw)+(ttwist and 30 or 1)) + return true +end + +function tryfall() + if (ghost.y==curtet[4]) return false + curtet[4]-=1 + update_floor() + sfx"12" + return true +end + +function update_floor() + local ct = curtet + if ct[4] < ct[5] then + ct[5] = ct[4] + lockcnt = 0 + end +end + +function update_ghost() + local t={} + cpt(curtet,t) + + --try moving down + while legal(t) do + t[4]-=1 + end + + --illegal, undo last move + t[4]+=1 + + --move ghost + ghost.y=t[4] +end + +function rnd_row(r,h) + local mr={} + field.matrix[r] = mr + for i=1,10 do + mr[i]=rnd(garbage_bg)+rnd(garbage_fg) + end + mr[h]=0 +end + +lockfade = split"7,6,134,5,133,128" +function counters() + gametime+=1/60 + if(gm_decay_cap)gm_progress=max(gm_progress-1/gm_decay_cap,0) + --are, spawning tetromino + if areuse then + if arecnt>=arelen then + next_tetrom() + sfx(tetromsfx[seq[1]]) + if (not clearing) areuse,arecnt=false,0 + else + arecnt+=1 + end + else + + --gravity + calc_grav() + if ghost.y=g do + if not tryfall() then + gravcnt=0 + break + end + gravcnt=max(0,gravcnt-g) + end + end + + --lock delay + if ghost.y>=curtet[4] then + if lockcnt>=lockdelay then + lockdn(false) + lockcnt=0 + else + lockcnt+=1 + end + end + + -- lock fade + if not(outline_only or invisible) and lockcnt > 0 then + pal(15, lockfade[lockcnt*6\lockdelay+1], 1) + end +end end + +function update_game() + pal(15,flashies[flash_idx],1) + if (flash_idx>1) flash_idx -= 1 + if(not do_update)return + update_msgs() --tab 9 + if not topout then + btn_handler() + counters() + if over() then + topout=true + justended=true + end end + if topout then + if justended then + rank = qualify() and addscore(mode,getscore()) or -1 + justended=false + end + --reset game + if (confirm_delay()) init_menu() + end +end + +function btn_handler() + local x,y=do_das() + if (areuse) return + mv_hz(x) + if(not mv_vt(y) and not locking_harddrop)lockdn() + + --hard drop,hold + if not held_since_harddrop and btn()&0x7==0x4 then + held_since_harddrop = true + hard_drop() + return + end + held_since_harddrop = held_since_harddrop and btn"2" + if btn()&0x30==0x30 then + swap_hold() + else + --rotation + local bp=btnp()&0x30 + if(bp~=0)rotate_curtet(bp==(invrot and 0x20 or 0x10)) + end +end + +function level_changes(n) +level_time=gametime + if (on_level and on_level(n)) return + if(0==n%4)bg.set("grid",{col=n\4}) + if (5<=n)ghost.draw=false + while nextsec and nextsec[1] <= n do + _, arelen, lnclr_delay, das_len, lockdelay, clrspd = unpack(nextsec) + nextsec=deli(sections) + end +end + +function gm_lv() + return lv.progress+(level-1)*lv.goal +end + +--gravity in frames per row +function calc_grav() +if (not next_gm_landmark) return + local lv=gm_lv() + while next_gm_landmark[1]<=lv do + gm_landmark = next_gm_landmark + next_gm_landmark=deli(level_curve) + if not next_gm_landmark then + gm_gtm=gametime + gravity=gm_landmark[2] + return + end + end + local lvbase,lvnext=gm_landmark[1],next_gm_landmark[1] + --interpolate for current level + gravity=((lv-lvbase)*next_gm_landmark[2]+(lvnext-lv)*gm_landmark[2])/(lvnext-lvbase) +end + +function randomize_bag() + local s=seq + local tet,from = tetroms.all,#s+1 + for i=2,bags do tet..=tetroms.all end + local cs=split(tet,"") + while #cs>0 do + local c=rnd(cs) + add(s,c) + del(cs,c) + end + for _=1,3 do + for i=from,#s do + local t=s[i] + if t==s[i-1] or t==s[i-2] or t==s[i-3] then + if i<#s then + s[i],s[i+1]=s[i+1],t + else + s[i],s[from]=s[from],t + end + end + end + end +end + +function next_tetrom(first) + ttwist=false + local ltr=deli(seq,1) + curtet= + --name,orientation,x,y,floor + {ltr,1,spawn[1], spawn[2], spawn[2]} + + if not first then + if btn()&0x30==0x30 then + swap_hold() + else + --rotation + local b,bp=invrot and 0x20 or 0x10,btn()&0x30 + if(bp!=0)rotate_curtet(bp==b) + end end + + --updating sequence + --prevlen inlined + if 6>=#seq then + randomize_bag() + end + + --block out + if not legal(curtet)then + topout=true + justended=true + return + end + + --move 1 line down if possible + mv_vt(-1) + update_ghost() +end + +function update_lines(morelines) + if(0==morelines)return + local glv=lv + + lines+=morelines + glv.progress+=glv.vals[morelines] + if(morelines>=4 or ttwist)glv.tets+=1 + + --update level + if glv.progress>=glv.goal then + sfx"21" + level+=1 + glv.progress-=glv.goal + gm_eligible=gm_eligible and glv.tets>=2 + glv.tets=0 + level_changes(level) + end +end + +function update_scores(morelines) + if 1>morelines then + combo=0 + return + end + + local streakmul=1 + if ttwist or morelines==4 then + if streaking then + streakmul=1.5 + push_flatmsg(split"12,6,7,6,12,1","streak",usplit"105,85,5,30,2.5") + end + streaking=true + else + streaking=false + end + if (ttwist) morelines+=2 + combo += 1 + local lcombo = combo + if lcombo > 1 then + local cols,msg = split"3,11,7,11","combo\n "..tostr(lcombo) + if (lcombo > max(4, maxcombo)) cols,msg=split"2,8,9,10,9,8",msg.."!" + push_flatmsg(cols,msg,usplit"105,82,2,30,3") + end + maxcombo=max(lcombo,maxcombo) + if (getscore == scr_gm) gm_progress += gm_values[morelines]*gm_combo_value[morelines][min(combo,15)]*ceil(level/2)*streakmul + if gm_progress >= 120 then + gm_progress=0 + local newlv,prev,_=gm_glv+1,parse_gm_ordinal(gm_ordinal()) + gm_glv=newlv + local ngm,_=parse_gm_ordinal(gm_ordinal()) + if(prev~=ngm) then + gm_gtm=gametime + if (newlv <= 25) sfx"24" + end + gm_values, gm_decay_cap=calc_gm_values(newlv) + end + score+=pts[morelines]*(1+(level-1)/10)*streakmul*(1.1^(combo-1))>>>16 + + --lines, process, level + update_lines(morelines) + + --sfx + if 0!=morelines then + if 1>=combo then + sfx(13+morelines) + else sfx(16+min(4,combo)) + end end +end + +function check_rows() + local counter=0 + local m=field.matrix + + local row,arr=1,{} + while row<=#m do + --find out if full + local full=true + for clm=1,10 do + if 0==m[row][clm] then + full=false + break + end end + + if full then + if(0==counter)cpt(m,bufmtx) + counter+=1 + + --anim + local x,y=34,124-6*(row+counter-1) + for i=0,9 do + local tmi=10-i + anim.new("crush",{x=x+6*i,y=y,c=m[row][i+1],lag=(100-tmi*tmi)/clrspd/10}) + end + anim.new("swoosh",{x=x,y=y,age=0}) + + --delete row + deli(field.matrix,row) + + --add empty row + local new={} + for i=1,10 do new[i]=0 end + add(field.matrix,new) + else--not full + row+=1 + end end + return counter +end + +function swap_hold() + if (holdused) return + + local h,gs=hldtet,spawn + h[1],h[2],curtet=curtet[1],1,{h[1],h[2],gs[1],gs[2],gs[2]} + + if ""==curtet[1] then + next_tetrom(true) + sfx(tetromsfx[curtet[1]]) + else + --move 1 line down if possible + mv_vt(-1) + end + + + update_ghost() + holdused = true + sfx"22" +end + +quadclr = split"7,10,4,5,1" +ttclrs=csv[[14,13,2,5,1 +7,14,8,2,5,1 +2,13,14,10,14,2,1 +14,13,12,13,14,13,2,1]] +ttlabels=split"tWISt,tWISt\n SolO,tWISt\n DuO,tWISt\n trio" + +function lockdn(hard) + dirty=true + gravcnt=0 + if (flash_on_lock) flash_idx=#flashies + local t=curtet + for row=1,4 do + for clm=1,4 do + local lockout = true + + --current block + local b=tetroms[t[1]].pattern[t[2]][row][clm] + if b then + --copying block to + --according pos in matrix + local x=clm+t[3] + local y=row+t[4] + field.matrix[y][x]=tetroms[t[1]].color + --at least one block + --locked in visible + --area, all ok! + if(20>y)lockout=false + end end end + + if lockout then + topout=true + justended=true + return + end + + drops+=1 + + --reset counters for next tetrom + gravcnt,lockcnt=0,0 + + --check rows, award points + local rcnt=check_rows() + update_scores(rcnt) + if (rcnt==4) push_flatmsg(quadclr,usplit"quad,105,85,6,30,2") + if ttwist then + local clrs=ttclrs[rcnt+1] + push_flatmsg(clrs,ttlabels[rcnt+1],102,80,5,5*#clrs,1.5) + end + + areuse=true + arecnt=0 + if(0!=rcnt)arecnt=-lnclr_delay + + sfx(hard and 11 or 10) + + holdused=false + if(lv.progress%lv.goal+1=n then + push_stack(1) + x = 0 + end + end +end + +function hard_drop() + --just to make sure + update_ghost() + + --drop and decay + curtet[4]=ghost.y + if locking_harddrop then + lockdn(true) +end end +-->8 +--drawing routines + +--draws an entire tetromino +function draw_tetrom(t,p,w,x,y,is_ghost) + local gg,gs=ghost,sprite + if(not gg.draw and is_ghost or not t)return + + local s,c=is_ghost and gs.ghost or gs.active,is_ghost and gg.color or t.color + if w==hold then + s=gs.hold + if (holdused) fillp(▒\1|0b.11) + elseif w==preview then + s=gs.preview + end + --iterate over all blocks + for row=1,4 do + for clm=1,4 do + + --any value means block exists + if t.pattern[p][row][clm] then + local xw,yw=clm+x,row+y + if(xw>0 and xw<=w.w and yw>0 and yw<=w.h) then + poke2(0x5f06,c) + spr(s,w.x-5+6*xw,w.y+1+6*(w.h-yw),0.75,0.75) + end + end + end end + poke2(0x5f06,0x706) + fillp() +end + +--3*3 px per block +function mini_tetrom(ltr,x,y,s) + local t=tetroms[ltr] + local c=t.color + + for row=1,4 do + for clm=1,4 do + if t.pattern[1][row][clm] then + local xpos,ypos=x+3*(clm-1),y+3*(4-(row-1)) + s=s or sprite.preview + poke2(0x5f06,c) + sspr(8*s,0,6,6,xpos,ypos,3,3) + end + end + end + poke2(0x5f06,0x706) +end + +--row-off,col-off;line-draw +borders=csv[[0,5,5,5,15,-11 +0,0,0,5,15,-1 +5,0,5,5,15,1 +0,0,5,0,15,11]] +corners=csv[[0,5,15,-12 +5,5,15,-10 +0,0,15,10 +5,0,15,12]] + +function draw_window(w,b,bgc) + local cornerx,cornery=w.x+1+6*w.w,w.y+1+6*w.h + + if bgc then + rectfill(w.x,w.y,cornerx,cornery,bgc) + if ghost.draw and not outline_only then + for clm=9,0,-1 do + for row=0,19 do + spr(23+gridspr,w.x+6*clm,w.y+6*row) + end end end end + + --borders + if b then + for i=0,2 do + rect(w.x-i,w.y-i,cornerx+i,cornery+i,7-i) + end + + if progbar then + local h=(6*w.h+6)*(lv.progress/lv.goal) + + clip(w.x-2,cornery+4-h,6*w.w+6,h) + for i=0,2 do + rect(w.x-i,w.y-i,cornerx+i,cornery+i, + progcols[ + min(4,level\5)*3+i+1 + ] + ) + end + clip() + end end + + --matrix + if(btn(6)) return --hide if pausing + if (not w.matrix or invisible and not topout) return + if not dirty then + palt(0,false) + sspr(0,64,60,62,w.x,w.y) + sspr(64,64,60,62,w.x,w.y+60) + palt(0,true) + return + end + local m=clearing and bufmtx or w.matrix + + -- use cart ram as temporary matrix storage + -- speeds up border drawing enough to be worth it + memset(0x8000,1,11) + memset(0x800c,0,250) + for row,rr in ipairs(m) do + local ix=0x8000+row*11 + poke(ix,1) + for clm,cc in ipairs(rr) do + if cc ~= 0 then + -- draw_block inlined + if not outline_only then + poke2(0x5f06,cc) + spr(sprite.normal,w.x-5+6*clm,w.y+1+6*(w.h-row),0.75,0.75) + end + poke(ix+clm,cc) + end end end + poke2(0x5f06,0x706) + + -- block outlines; suppress if + -- outline color is 0, so users + -- can't peek at the well + -- by pausing + if (flashies[flash_idx]==0) return + local cpos = $0x5f28 --camera offsets + for row,rr in ipairs(m) do + local ir=0x8000+row*11 + for clm,cc in ipairs(rr) do + local ix=ir+clm + if 0!=cc then + poke4(0x5f28, + cpos-w.y-6*(w.h-row) + -((w.x-5+6*clm)>>16)) + for packed in all(borders) do + if 0==@(ix+packed[6]) then + line(unpack(packed)) + end + end + for packed in all(corners) do + if 0==@(ix+packed[4]) then + pset(unpack(packed)) + end + end + end + end end + poke4(0x5f28, cpos) + + --save well to bottom half of sprite sheet + --draw mode: from screen to sprite sheet + poke2(0x5f54, 0x0060) + palt(0, false) + sspr(w.x,w.y,60,62,0,64) + sspr(w.x,w.y+60,60,62,64,64) + palt(0, true) + poke2(0x5f54,0x6000) + dirty = false +end + +function draw_stats() + for i,s in ipairs(stats) do + local c="" + print(s,3,127-17*i,6) + local cl = 7 + if s=="score" then c=scr(score,true) + elseif s=="time" then c=fmttime(gametime) + elseif s=="left" then + local rmn = linesneeded-lines + if (rmn <= linesneeded\4)cl=10 + c=max(0,linesneeded-lines) + elseif s=="combo" then c=maxcombo + elseif s=="grade" then c,cl=gm_grade() + elseif s=="level" then + local glv,ggl=gm_lv(),level*lv.goal + if(glv==ggl-1)cl=9 + if(ggl>999) ggl="⁘" + if(over==leveling_over and over()) ggl = "■" + c=tostr(glv).."/"..tostr(ggl) + elseif s =="section" then c=level + elseif s =="cpu" then + c=stat(1)*100\1 + if (c>85)cl=9 + if (c>100)cl=8 + elseif s =="remain" then + c=drop_target-drops + if (c<10)cl=9 + else c=_ENV[s] or "" end + + print(c,31-print(c,1,-50),134-17*i,cl) +end end + +function draw_game() + print("hold",3,5,6) + draw_window(hold) + draw_tetrom(tetroms[hldtet[1]],hldtet[2],hold,0,0) + print("❎+🅾️",5,30,5) + + print("next",101,5,6) + draw_window(preview) + local t=seq[1] + draw_tetrom(tetroms[t],1,preview,0,0) + for i=2,6 do --prevlen inlined + mini_tetrom(seq[i],101,27+8*(i-2)) + end + + print("best",101,110,6) + print(hiscore,101,117,7) + + draw_window(field,true,0) + local ct=curtet + if not areuse then + draw_tetrom(tetroms[ct[1]],ct[2],field,ct[3],ghost.y,true) + draw_tetrom(tetroms[ct[1]],ct[2],field,ct[3],ct[4]) + end + + draw_stats() + + if topout then + if rank>=0 then + rectfill(usplit"34,59,93,72,7") + if rank > 3 then + if over() then + printc("clear!",60,11) + else + printc("game over",60,8) + end + elseif rank > 1 then + printc("high score "..rank,60,12) + else + printc("new record!",60,9) + end + printc(getscore(nil,true,1),67,0) + else + rectfill(usplit"34,59,93,65,7") + print(usplit"game over,46,60,8") + end + else + draw_msgs() --tab 9 +end end +-->8 +--menu + +function init_menu() + poke(0x5f5c,0) --restore btnp repeat + menuitem(2) + menuitem(1) + + bg.set("falling") + gstate=1 + gamev,mode,slc={sprite={}},mode or 1,1 + + options=options or { + gamev={}, + sprv={} + } + + local spr_max=15 + + --titles between option items + opt_titles={[7]="tetromino sprites"} + + --items in option menu + opt_strs=opt_strs or { + {name="locking hard drop", + curr=true, + set=function(self) + options.gamev.locking_harddrop=self.curr + end}, + + {name="inverse rotation", + curr=false, + set=function(self) + options.gamev.invrot=self.curr + end}, + + {name="progress bar", + curr=true,set=function(self) + options.gamev.progbar=self.curr + end}, + + {name="animated bg", + curr=true,set=function(self) + options.gamev.bganim=self.curr + end}, + + {name="debris", + curr=1, + vals=split"lots,some,none", + set=function(self) + if(self.curr<1)self.curr=1 + options.gamev.debris=self.curr + end}, + + {name="well background", + curr=0,min=0,max=8,set=function(self) + options.gamev.gridspr=self.curr + end}, + + {name="normal", + curr=1,min=0,max=spr_max, + set=function(self) + options.sprv.normal=self.curr + end}, + + {name="active", + curr=2,min=0,max=spr_max, + set=function(self) + options.sprv.active=self.curr + end}, + + {name="ghost", + curr=1,min=0,max=spr_max, + set=function(self) + options.sprv.ghost=self.curr + end}, + + {name="hold", + curr=1,min=0,max=spr_max, + set=function(self) + options.sprv.hold=self.curr + end}, + + {name="preview", + curr=1,min=0,max=spr_max, + set=function(self) + options.sprv.preview=self.curr + end}} + + if(start)readdata() + start=false + + foreach(opt_strs, function(o) o:set() end) + + if options then + cpt(options.gamev,gamev) + cpt(options.sprv,gamev.sprite) + writedata() + end +end + +function update_menu() + if(not do_update)return + if btnp"2"then + slc=cyclenum(slc-1,1,4) + sfx"12" + end + if btnp"3"then + slc=cyclenum(slc+1,1,4) + sfx"12" + end + --start game + if 1==slc then + if confirm()then + cpt(modes[modes.list[mode]],gamev) + init_game(gamev) + end + --mode selection + elseif 2==slc then + if btnp"0"then + sfx"13" + mode-=1 + if(0==mode)mode=#modes.list + elseif btnp"1"then + sfx"13" + mode%=#modes.list + mode+=1 + end + --option menu + elseif 3==slc and confirm()then + init_options() + --highscore menu + elseif 4==slc and confirm()then + init_scoremenu() +end end + +function draw_menu() + --border + for i=0,2 do + rect(i,i,127-i,127-i,5+i) + end + + print3("extreme",18) + print(version[1].."."..version[2],4,119,5) + + --logo + map(0,0,21,27,11,3) + + printc("start!",65,btoi(1==slc)+6) + + local m=modes.list[mode] + local s="mode: "..m + if(2==slc)s="⬅️ "..s.." ➡️" + printc(s,72,btoi(2==slc)+6,2*btoi(2==slc)) + + printc("options",79,btoi(3==slc)+6) + + if (2==slc) then + printc_multi(modes[m].desc,100,5,27) + end + + printc("high scores",86,btoi(4==slc)+6) +end + +function init_options() + gstate,opt_slc=2,1 +end + +function update_options() + if(not do_update)return + if btnp"2"then + sfx"12" + opt_slc=cyclenum(opt_slc-1,1,#opt_strs+1) + end + if btnp"3"then + sfx"12" + opt_slc=cyclenum(opt_slc+1,1,#opt_strs+1) + end + + --an option is selected + if opt_slc<=#opt_strs then + local o=opt_strs[opt_slc] + + --what to do when + --⬅️ or ➡️ pressed + if(btnp"0"or btnp"1") then + sfx"13" + if "boolean"==type(o.curr)then + o.curr=not o.curr + else + local minv=o.min or 1 + local maxv=o.max or#o.vals + if(btnp"0")o.curr=cyclenum(o.curr-1,minv,maxv) + if(btnp"1")o.curr=cyclenum(o.curr+1,minv,maxv) + end end + + --back to title is selected + else + --❎/🅾️ confirm + if confirm() then + --set all options + foreach(opt_strs, function(o) o:set() end) + + --switch to title menu + init_menu() +end end end + +function draw_options() + cls() + for i=0,2 do + rect(i,i,127-i,127-i,5+i) + end + print3("options",4) + + --tetroms at the bottom + for i=1,3 do + local os = opt_strs[6+i] + drawt(os.curr,5,45+20*i,os.name) + end + for i=1,2 do + local os = opt_strs[9+i] + drawt(os.curr,105,65+20*i,os.name,true) + end + + mini_tetrom("t",100,100,opt_strs[11].curr) + + --options + local x=6 + for i=1,#opt_strs do + local o=opt_strs[i] + local s=o.name..": " + x+=6 + + if opt_titles[i] then + print3(opt_titles[i],x+2) + x+=10 + end + + if o.vals then + s=s..o.vals[o.curr] + elseif"boolean"==type(o.curr) then + s=s..(o.curr and"yes"or"no") + else + s=s..o.curr + end + + if(opt_slc==i)s="⬅️ "..s.." ➡️" + printc(s,x,btoi(opt_slc==i)+6,2*btoi(opt_slc==i)) + end + + x+=7 + printc("back to title",x,btoi(opt_slc==#opt_strs+1)+6) +end + +function drawt(s,x,y,name,r) + poke2(0x5f06,0xe08) + if (name=="ghost"and opt_strs[5].curr) poke2(0x5f06,0xd01) + + for i=0,12,6 do + spr(s,x+i,y+6) + end + spr(s,x+6,y) + poke2(0x5f06,0x706) + if name then + if(r)x-=max(0,4*#name-1)-18 + print(name,x,y+13,5) +end end + +function init_scoremenu() + opt_slc,gstate=1,3 + highscores=getscores(mode) +end + +function update_scoremenu() + if(not do_update)return + if btnp"2"then + sfx"12" + opt_slc=cyclenum(opt_slc-1,1,3) + end + if btnp"3"then + sfx"12" + opt_slc=cyclenum(opt_slc+1,1,3) + end + + local temp=mode + if 1==opt_slc then + bp = btnp()&0x3 + if bp~=0 then + sfx"13" + mode=cyclenum(mode+2*bp-3,1,#modes.list) + end + elseif 2==opt_slc then + if confirm()then + for i=10,63 do dset(i,0)end + sfx"23" + highscores=nil + end + else + if confirm()then + init_menu() + end + end + + if (not highscores or temp!=mode) highscores=getscores(mode) +end + +function draw_scoremenu() + cls() + rect(usplit"0,0, 127,127, 5") + rect(usplit"1,1, 126,126, 6") + rect(usplit"2,2, 125,125, 7") + print3("scores",6) + + s=modes.list[mode] + if(opt_slc==1)s="⬅️ "..s.." ➡️" + local b1 = btoi(opt_slc==1) + printc(s,20,b1+6,2*b1) + + printc("reset scores",27,btoi(opt_slc==2)+6) + printc("back to title",34,btoi(opt_slc==3)+6) + + for i,s in ipairs(highscores) do + spr(32+i,41,19+25*i,1,2) + local m=modes[modes.list[mode]].getscore + printc(m(s,true,2),32+25*i,7) +end end +-->8 +--modes +function scr(s,b,l) + s = s or score + if (l) return tostr(s,0x2) + if (not b) return s + local ret = tostr(s,0x2) + if (#ret > 5) return sub(ret,1,-4)..("K") + return zpad(ret,5) +end +function scr_t(s,b) + return b and fmttime(s or gametime) or s or gametime +end +function scr_l(s) + return s or lines +end +function scr_gm(s,disp,final) + s = s or 0x7ff0-gm_ordinal(not next_gm_landmark)+0x0.000a*min(0x1999, gm_gtm) + if(s==0) return disp and "---" or 0 + local rank=-(flr(s)-0x7ff0) + if(final==1)return parse_gm_ordinal(rank,true) + return disp and parse_gm_ordinal(rank,final).."\n"..fmttime(s%1/0x0.000a) or s +end +function gm_nz() + return gm_glv ~= 0 +end +function scr_lvltime(s, disp,final) + s = s or 0x7ff0-level+0x0.000a*min(0x1999,level_time) + if (not disp) return s + if (s == 0) return "---" + return tostr(-(flr(s)-0x7ff0))..(final and "@" or "\n")..fmttime(s%1/0x0.000a) or s +end +function sec_nz() + return level ~= 0 +end +function lines_over() return lines>=linesneeded end +function leveling_over() return not next_gm_landmark end + +function darken(flash) + outline_only=true + flashies=flash + flash_idx=#flash +end + +function drops_over() + return drops>=drop_target +end + +function yes() return true end +function no() end + +function init_modes() + modes={ + list=split"marathon,scoreathon,intermediate,grandmaster,gm plus,intense,intense plus,extreme,infinite,sprint,blitz,20g trainer,lightning,invisible", + + marathon={ + desc="a classic: clear 150 lines and you're done", + invscr_ordering=true, + stats=split"level,left,time", + qualify=lines_over, + over=lines_over, + getscore=scr_t + }, + + infinite={ + desc="let's see you overflow that score counter", + stats=split"score,level,lines,time", + getscore=scr, + over=no + }, + + blitz={ + desc="128 tetroms for a high score", + lv={goal=32}, + stats=split"score,level,remain", + qualify=drops_over, + over=drops_over, + drop_target=128, + getscore=scr, + level_curve=csv[[999,0.005 + 96,0.005 + 95,0.2 + 72,1 + 64,5 + 63,1 + 32,15 + 31,10 + 1,30]], + sections=csv[[999,8,3,4,25,10 + 6,7,3,4,25,10 + 5,8,3,5,25,10 + 3,12,8,8,30,5 + 1,20,15,10,30,2]] + }, + + grandmaster={ + desc="prove your skill", + over=leveling_over, + qualify=gm_nz, + lv={goal=128}, + gm_eligible=true, + level_curve = csv[[1024,0.005 + 512,0.005 + 511,10 + 502,1 + 501,0.2 + 440,1 + 400,1 + 384,3 + 383,1 + 256,5 + 255,2 + 162,6 + 128,10 + 127,5 + 64,15 + 14,40 + 1,40]], + bags=3, + invscr_ordering=true, + stats=split"grade,level,time", + getscore=scr_gm, + sections=csv[[8,8,4,6,20,10 + 7,10,8,6,20,5 + 6,12,8,6,30,4 + 5,15,10,10,30,3 + 4,20,20,10,30,2 + 3,20,20,15,30,1 + 1,25,20,15,30,1]] + } + } + local a={} + modes.sprint=a + cpt(modes.marathon,a) + a.desc="clear 40 lines as quickly as possible" + a.linesneeded=40 + + a={} + modes.scoreathon=a + cpt(modes.marathon,a) + a.desc="go for a high score in 150 lines" + a.getscore=scr + a.qualify=yes + a.invscr_ordering=false + a.stats=split"score,time,level,left" + + a={} + modes.intermediate=a + cpt(modes.grandmaster,a) + a.desc="walk the path towards mastery" + a.level_curve=csv[[768,0.005 + 640,0.005 + 639,1 + 600,1 + 512,5 + 511,2 + 416,5 + 400,8 + 384,10 + 383,5 + 338,10 + 274,20 + 256,20 + 255,12 + 192,15 + 144,20 + 128,40 + 127,20 + 14,60 + 1,60]] + a.sections=csv[[6,20,15,15,45,2 + 5,20,20,15,30,2 + 4,25,20,15,30,1 + 1,30,25,15,30,1]] + + a={} + modes.invisible=a + cpt(modes.sprint,a) + a.desc="there is no garbage... oh nononono not like that!" + a.invisible=true + a.on_drop=function() + if lines > 20 then + ghost.draw=false + on_drop=nil + end + end + + a={} + modes.lightning=a + cpt(modes.sprint,a) + a.desc="a lightning storm is your only light" + a.flashies=dkflash + a.outline_only=true + a.yikes=false + a.on_drop=function() + if not yikes and (lines>0 or drops >=5) then + darken(ltflash) + yikes = true + end + if (lines>=30) flash_on_lock=false + if (lines>=35) ghost.draw=false + end + + a={} + modes["gm plus"]=a + cpt(modes.grandmaster,a) + a.desc="increase the challenge with garbage." + a.on_level=function(newlv) + if (newlv<6) on_drop=garbage_every(14-newlv) + if (newlv==6) darken(dkflash) + if (newlv==7) darken(ltflash) + if (newlv==8) flash_on_lock=false + end + + a={} + modes["20g trainer"]=a + cpt(modes.grandmaster,a) + a.desc="get used to 20g play here. lockdown starts slow." + a.level_curve=csv[[768,0.001 + 1,0.001]] + a.sections=csv[[6,12,6,8,25,3 + 5,15,10,10,30,2 + 4,20,15,12,30,2 + 3,25,20,15,30,1 + 2,25,20,15,40,1 + 1,25,20,15,60,1]] + + a={} + modes.intense=a + cpt(modes.grandmaster,a) + a.desc="20g gets faster. can you survive?" + a.level_curve=csv[[1536,0.001 + 1,0.001]] + a.getscore=scr_lvltime + a.qualify=sec_nz + a.stats=split"section,level,time,drops" + a.sections=csv[[10,6,0,4,15,10 + 9,8,2,6,15,5 + 8,8,2,6,20,5 + 7,10,4,8,20,4 + 6,10,6,8,24,4 + 5,12,8,8,24,3 + 4,12,12,10,30,3 + 3,20,15,12,30,2 + 2,25,20,15,30,2 + 1,25,20,15,40,1]] + a.on_level=function(newlv) + if (newlv==11) darken(dkflash) + if (newlv==12) darken(ltflash) + end + + a={} + modes["intense plus"]=a + cpt(modes.intense, a) + a.desc="and now with a garbage flood." + a.on_level=function(newlv) + if (newlv<8) on_drop=garbage_every(8-newlv\2) + if (newlv==8) darken(dkflash) + if (newlv==9) darken(ltflash) + if (newlv==10) flash_on_lock=false + if newlv==12 then + on_drop=nil + invisible=true + end + end + + a={} + modes.extreme=a + cpt(modes.intense,a) + a.desc="good luck sucker" + a.sections=csv[[14,4,2,5,12,10 + 12,4,2,5,13,10 + 10,4,2,5,15,10 + 8,5,2,5,15,10 + 7,6,2,5,15,5 + 6,8,2,6,15,5 + 5,10,4,8,17,4 + 4,12,6,8,20,3 + 3,12,12,10,24,3 + 2,15,15,12,30,2 + 1,20,20,15,30,2]] + a.level_curve=csv[[2048,0.001 + 1,0.001]] + a.on_level=function(newlv) + if (newlv<9) on_drop=garbage_every(6-newlv\3) + if (newlv==9) darken(dkflash) + if (newlv == 11) darken(ltflash) + if (newlv == 13) flash_on_lock=false + if newlv == 15 then + invisible=true + on_drop=nil + end + end +end + +-->8 +--grandmaster grading + +gm_combo_value=csv[[1,1,1.1,1.2,1.3,1.4,1.5,1.75,2,2,2,2,2,2,2 +1,1.2,1.3,1.4,1.5,1.75,2,2.25,2.5,2.75,3,3,3,3,3 +1,1.3,1.5,1.75,2,2.25,2.5,2.75,3,3.33,3.66,4,4,4,4 +1,1.5,1.75,2,2.3,2.75,3.5,4,4.25,4.5,4.75,5,5,5,5 +1,1.5,1.75,2,2.5,3,3.5,4,4.5,5,5.5,6,6,6,6,6,6]] + +function gm_grade() --for in-game stats display + if(gm_glv>=17 and not topout)return "?????",8 + return parse_gm_ordinal(gm_ordinal(over())) +end + +function calc_gm_values(gm_lv) + if(gm_lv <= 0) return split"10,20,35,80,120",120 + if(gm_lv<=3) return split"8,16,30,60,120",split"100,75,60,50"[gm_lv] + if(gm_lv<=5)return split"5,10,22,50,80",split"40,35,30"[gm_lv-5] + if(gm_lv<=8)return split"4,8,20,40,75",25 + --s-ranks + if(gm_lv<=18)return split"3,8,16,35,65",split"23,22,20,20,18"[(gm_lv-8)\2] + if(gm_lv<=22)return split"2,7,14,30,60",split"20,20,15,15,10"[gm_lv-18] + return split"2,5,18,35,65",10 +end + +function gm_ordinal(won) + local gml=gm_glv + if (gml>8) gml=((gml-1)&0xfffe)+1 + return min(gml,0xff)+btoi(won)*0x100+btoi(won and gm_eligible and gml>26 and gametime<600)*0x1000 +end + +function fatboy(slim,phat) + return slim.."\^w"..phat.."\^-w" +end + +function parse_gm_ordinal(val, long) + if(val>0x1000)return long and "\^wg\^-wrand\^wm\^-waster" or "\^wgm\^-w",10 + if(val>0x11b)return long and "master-\^wm\^-w" or "m\^wm\^-w",14 + local base=val%0xff + if (base < 9) return fatboy(long and "grade " or "",9-base),7 + base=min((base-7)\2,9) + if(val>0x100)return fatboy(long and "master-" or "m",base),8 + return fatboy(long and "grade s" or "s",base),9 +end +-->8 +--cartdata + +function writedata() + local o=opt_strs + + --version + dset(0,1000*version[1]+version[2]) + + --booleans, up to 16 + dset(1, bitpack{gamev.locking_harddrop, gamev.invrot, gamev.bganim, gamev.progbar}) + + --sprite choices + dset(3,put_num(put_num(o[8].curr,16,o[7].curr),16,o[6].curr)) + dset(4,put_num(o[10].curr,16,o[9].curr)) + + --range options + dset(6,o[6].curr) + dset(7,o[5].curr) +end + +function readdata() + if(0==dget(0)\1000)return false + local o=opt_strs + + --bools + local d,index=dget(1),split"0,1,3,2" + for i,b in ipairs(index) do + o[i].curr=get_bit(d,b) + end + + --sprites + for i=0,4 do + o[6+i].curr=get_num(dget(3+i\3),16,i%3) + end + + --ranges + o[6].curr=dget(6) + o[5].curr=dget(7) +end + +function getscores(mode) + mode-=1 + local scores={} + for i=1,3 do + scores[i]=dget(15+3*mode+i) + end + return scores +end + +function addscore(mode,score) + if (score==0)return -1 + local s=getscores(mode) + s[4]=score + + if(invscr_ordering)inv_scores(s) + + local i=3 + while 0s[i]or 0==s[i]then + s[i+1],s[i]=s[i],s[i+1] + else break end + i-=1 + end + + if(invscr_ordering)inv_scores(s) + + mode-=1 + for n=1,3 do + dset(15+3*mode+n,s[n]) + end + + return i+1 +end + +function inv_scores(s) + for i=1,#s do + s[i]*=-1 + end +end +-->8 +--animations + +anim={ + --heads of linked lists. contains + --non-nil next exactly when the + --list is not empty. does not + --point straight to the first + --item so item removal has no + --special case + crushes={}, + swooshes={}, + + new=function(t,a) + local listname = t.."es" + a.type,a.new,a.next=t,true,anim[listname].next + anim[listname].next=a + _ENV["upd_"..t](a) + end, + + draw=function() + --drawing in correct order + for t in all({"swoosh","crush"})do + local lnm = t.."es" + local prev=anim[lnm] + local curr=prev.next + while curr do + if (not curr.wait and not anim[t](curr)) prev.next=curr.next + prev=curr + curr=curr.next + end + poke2(0x5f06,0x706) + end + end, + + update=function() + clearing=false + local curr=anim.swooshes.next + while curr do + upd_swoosh(curr) + curr=curr.next + end + curr = anim.crushes.next + while curr do + upd_crush(curr) + curr=curr.next + end + end, + + swoosh=function(a) + local baseframes = 10/clrspd --10 wide + local totalframes = baseframes+5 --5 swooshclrs + if a.age > totalframes then + dirty=true + return false + end + --outlines are bright during swoosh + flash_idx = #flashies + + local ax,ay,ctx_age=a.x,a.y,a.age+1 + for i,clr in ipairs(swooshclrs) do + ctx_age-=1 + if (ctx_age < 0) return true + local m = min(ctx_age/baseframes,1) + rectfill(ax,ay,ax+60*m*m,ay+5,clr) + end + return true + end, + + crush=function(a) + if (debris==3) return false + if (a.lag>0) return true + poke2(0x5f06,a.c) + local spr_base = 8*sprite.normal + local ret = false + for p in all(a.list) do + ret = ret or p.y<128 + sspr(spr_base+p.i%2*3,p.i\2*3,3,3,p.x,p.y) + end + return ret + end +} + +swooshclrs=split"10,11,12,12,7" + +function upd_swoosh(a) + a.age+=1 + clearing=clearing or a.age<10/clrspd+5 + --10 blocks wide, 5 swooshclrs. +end + +function upd_crush(a) + if a.list==nil then + a.list = { + {i=0,x=a.x,y=a.y,dx=-rnd(0.5),dy=rnd(1)-1.5}, + {i=1,x=a.x+3,y=a.y,dx=rnd(0.5),dy=rnd(1)-1.5}, + {i=3,x=a.x+3,y=a.y+3,dx=rnd(0.5),dy=rnd(1)-0.5}, + {i=2,x=a.x,y=a.y+3,dx=-rnd(0.5),dy=rnd(1)-0.5} + } + if debris==2 then + deli(a.list,irnd1(4)) + deli(a.list,irnd1(3)) + end + end + if a.lag>0 then + a.lag-=1 + return + end + for p in all(a.list) do + p.x+=p.dx + p.y+=p.dy + p.dy+=0.075 + end +end + +-- blue, green, yellow/orange, red/purple, grey with red +progcols=split"12,13,1,11,3,5,10,9,4,2,1,1,6,8,5" + +-- blue, green, brown/orange, purple, grey with red +bgcols=split"1,12,3,11,4,9,2,14,5,8" + +bg={data={},curr="",draw=function() + if(bg.curr)bg[bg.curr](bg.data) + end, + + set=function(s,d) + d=d or {} + bg.data,bg.curr=d,s + d.list=d.list or {} + end, + + grid=function(d) + if(not bganim)return + local dc=min(4,d.col or 0) + if(.928 +-- message queue + +-- message format: +-- text - text to print +-- tx, ty - text x, text y +-- cs - list of colors for text +-- ct - frames per color +-- dur - total frames to show +-- pri - message priority +-- ties replace existing msg + +function update_msgs() + local m = messages.next + while (m and m.t >= m.dur) m = m.next + if (m) m.t += 1 + messages.next = m +end + +function draw_msgs() + local m = messages.next + if (not m) return + print(m.text, m.tx, m.ty, + m.cs[m.t\m.ct%#m.cs+1]) +end + +function push_flatmsg( + cs, + text, tx, ty, + ct, dur, + pri + ) + push_msg{ + text=text, tx=tx, ty=ty, + cs=cs,ct=ct,dur=dur, + pri=pri} +end + +function push_msg(m) + --m.sprs = m.sprs or {} + m.cs = m.cs or {7} + m.ct = max(m.ct, 1) + -- offset count and limit + -- align color timing + m.t=-1 + m.dur-=1 + local p = messages + repeat + local n = p.next + if not n or m.pri < n.pri then + p.next = m + m.next = n + return + end + if m.pri == n.pri then + p.next=m + m.next=n.next + return + end + p = n + until false +end +__gfx__ +00000000777777006666660077777700766666007777770077777000777666006666660077777700777777007777770007777000077770000777700077777700 +07007000766667006777760077777700677666007676760076667600766776006776760076666700777767007666670077666700766667007766770077777700 +00770000767767006766760077667700676666007767660076777600767676006776760076667700777667007666760076667600767767007600770077777700 +00770000767767006766760077667700666666007676760076767600676767006666660076677700776667007667760076677600767767007600760077777700 +07007000766667006777760077777700666666007767660077777600677667006767760076777700766667007677760076777600766667007777760077777700 +00000000777777006666660077777700666666007666660006666600666777006666660077777700777777007766660007666000077770000776600077777700 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000070c0000cc0009009000aa00aa00bb00b000e000e0088000080000000000000000505050505550550555555555500000000000000000000000000055000 +77770070ccc00c00999009000aa00aa0bb000bb0eee00ee008800880000000000000000000000000000000050000000500000000000000000000000000055000 +0000007000000c000000099000000000000000b000000e0000000800000000000000000000000005000000000000000500000000000550000055550000055000 +00000070000000000000000000000000000000000000000000000000000000000000000000000000000000050000000500055000005005000050050055500555 +0000070000000c00000099000aa00aa00000b00000000e0000000800000000000000000000000005000000050000000500055000005005000050050055500555 +00000700ccc00c00999009000aa00aa00bb0bb00eee0ee0088008800000000000000000000000000000000000000000500000000000550000055550000055000 +7777070000c0cc009000090000000000bb000b000e000e0008808000000000000000000000000005000000050000000500000000000000000000000000055000 +00000700000000000000000000000000000000000000000000000000000000000000000000000000000000050000000500000000000000000000000000055000 +00000000000000000000000000000000000000000000000077707770777077707770000000000000000000000000000077777770770770000000000000000000 +10000000000000000000000000000000000000000000000070707070777070707070000000000000000000000000000070070707700707070000000000000000 +2100000000088880000cccc0000dddd0000000000000000070007070777077007070000077707070707707770000000070070707700707070000000000000000 +321000000080000800c0000c00d0000d000000000000000070007070707077007070000007007070707000700000000077070770770777070000000000000000 +421000000080000800c0000c00d0000d000000000000000070707070707070707070000007007770700700700000000077070770700707700000000000000000 +51000000080008800c000cc00d000dd0000000000000000077707770707077707770000007007770707700700000000007070707700707070000000000000000 +6d100000080080000c00c0000d00d000000000000000000000000000000000000000000000000000000000000000000007070707700707070000000000000000 +76d10000080800000c0c00000d0d0000000000000000000000000000000000000000000000000000000000000000000070070707777707070000000000000000 +82100000080800000c0c00000d0d0000000000000000000077700707007707700000000000000000000000000000000000000000000000000000000000000000 +94210000080800000c0c00000d0d0000000000000000000070700707070707070000000000000000000000000000000000000000000000000000000000000000 +a9421000088000000cc000000dd00000000000000000000070770707077707070000000000000000000000000000000000000000000000000000000000000000 +b3210000088000000cc000000dd00000000000000000000007770777070707700000000000000000000000000000000000000000000000000000000000000000 +cd100000aaaa00006666000099990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +d1000000a99a00006556000094490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +e2100000a9aa00006566000094990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +f6d51000aaaa00006666000099990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +8888888888888800999999999999900aaaaaaaaaaaaaa00bbbbbbbbbbbbbbbbb0cccccccccc0eeeeeeeeeee00000000000000000000000000000000000000000 +8777777777777800977777777779900a777777777777a00b7777777777777bb07777777777c07777777777e00000000000000000000000000000000000000000 +8788888888888800979999999999000a7aaaaaaaaaaaa00b7bbbbbbbbbbbbb0cccccccccccc0eeeeeeeeeee00000000000000000000000000000000000000000 +8888888888888800979999999999000aaaaaaaaaaaaaa00b7bbbbbbbbbbbb0ccccccccccccc0eeeeeeeeeee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb00000b7bb0cc00000000c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb0000b7bb07cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb000b7bb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb00b7bb00c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097999999990000000000a7aa0000000b7bb0b7bb000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097997777990000000000a7aa0000000b7bbb7bb0000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097999999900000000000a7aa0000000b7bbbbbb0000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097999999900000000000a7aa0000000b7bbbbbbb000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb0bbbbb00c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb00bbbbb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb000bbbb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb0000bbb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb00000bb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb000000b0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb00000000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097990000000000000000a7aa0000000b7bb00000000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097999999999999990000a7aa0000000b7bb00000000c7cccc0e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097997777777777790000a7aa0000000b7bb00000000c7cc770e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008788000000097999999999999999000a7aa0000000b7bb00000000c7cccc0e7ee0c7cc0e7ee000e7ee00000000000000000000000000000000000000000 +000008888000000099999999999999999000aaaa0000000bbbb00000000cccccc0eeee0cccc0eeee000eeee00000000000000000000000000000000000000000 +__label__ +55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 +56666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665 +56777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777765 +56700000000000000000000000000c00000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000ccc009990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000bb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +5670000bb0000000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000765 +5670000000000000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000999000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000765 +5670000000000000000000000000000000000000000000000000000000000000000000000880000000000000000000000aa00000000000000000000000000765 +5670000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000aa00000000000000000000000000765 +56700900000000000000000000000000000000000000000000000000000000008800000000000008800000000000000000000000000000000000000900000765 +56799900000000000000000000000000000000000000000000777070707770777077707770777000880000000000000000000000000000000000099900000765 +56700000000000000000000000000000000000000000000000766070706760767076607770766000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000775067605750776077507670775000000007777bb0000000000000000000000000000000000765 +5670000000000000000000000000000000000000000000000076007670070076707600757076000000000000bb00000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000777075700700757077707070777000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000666060600600606066606060666000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000555050500500505055505050555000000000000000000000000000000000000000000000000765 +5670000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000765 +567000000000000000000000000000000000000000000000000eee0000000000000000000000000000000000000000000000e000000000000000000000000765 +5670000000000000000008888888888888800999999999999900aaaaaaaaaaaaaa00bbbbbbbbbbbbbbbbb0cccccccccc0eeeeeeeeeee00000000000000000765 +5670000000000000000008777777777777800977777777779900a777777777777a00b7777777777777bb07777777777c07777777777e00000000000000000765 +5670000000000000000008788888888888800979999999999000a7aaaaaaaaaaaa00b7bbbbbbbbbbbbb0cccccccccccc0eeeeeeeeeee00000000000000000765 +5670000000000000000008888888888888800979999999999000aaaaaaaaaaaaaa00b7bbbbbbbbbbbb0ccccccccccccc0eeeeeeeeeee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb00000b7bb0cc00000000c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb0000b7bb07cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb000b7bb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb00b7bb00c7cc000e7ee0c7cc0e7ee000e7ee00000000000900000765 +567000000000000000000000008788000000097999999990000000000a7aa0000000b7bb0b7bb000c7cc000e7ee0c7cc0e7ee000e7ee00000000099900000765 +5670000000000000000000000087880000000979977779900000aa000a7aa0000000b7bbb7bb0000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +5670000000000000000000000087880000000979999999000000aa000a7aa0000000b7bbbbbb0000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000c00000008788000000097999999900000000000a7aa00e0000b7bbbbbbb000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000ccce00008788000000097990000000000000000a7aa0eee000b7bb0bbbbb00c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +56700000000000000000eee0008788000000097990000000000000000a7aa0000000b7bb00bbbbb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb000bbbb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000880000008788000000097990000000000000000a7aa0000000b7bb0000bbb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000088000008788000000097990000000000000000a7aa0000000b7bb00000bb0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb000000b0c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb00000000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097990000000000000000a7aa0000000b7bb00000000c7cc000e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097999999999999990000a7aa0000000b7bb00000000c7cccc0e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097997777777777790000a7aa0000000b7bb00000000c7cc770e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000008788000000097999999999999999000a7aa0000000b7bb00000000c7cccc0e7ee0c7cc0e7ee000e7ee00000000000000000765 +567000000000000000000000aa8888000000099999999999999999000aaaa0000000bbbb00000000cccccc0eeee0cccc0eeee000eeee00000000000000000765 +567000000000000000000000aa00000000000000000000000000000000000000000000ccc0000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000765 +56700000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000000000000000000000099900000000765 +56700000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +567000000000000000000000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000765 +567000000000000000000000000000000000000000000000000007707770777077707770070000000aa00000000000000000000000000000000000000000b765 +56700000000000000000000000000000000000000000000000007000070070707070070007000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000007770070077707700070007000000000000000000000000000000000000000000000000000765 +567000000000000000000000000000000000000000000000000000700700707070700700000000aa000000000000000000000000000000000000000000000765 +567000000000000000000000000000000000000000000000000077000700707070700700070000aa000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000066600660660066600000000066606660666066606660606006606600000000000000000000000000000000000765 +56700000000000000000000000000000000066606060606060000600000066606060606060600600606060606060000000000000000000000000000000000765 +56700000000000000000000000000000000060606060606066000000000060606660660066600600666060606060000000000000000000000000000000000765 +56700000000000000000000000000000000060606060606060000600000060606060606060600600606060606060000000000000000000000000000000000765 +56700000000000000000000000000000000060606600666066600000000060606060606060600600606066006060000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000066066606660666006606600066000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000606060600600060060606060600000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000606066600600060060606060666000000000000000000000000000000000000000000000000765 +56700000000000000000007777000000000000000000000000606060008600060060606069996000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000660060000680666066006060660000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000060606660066060600000066006600660666066600660000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000060600600600060600000600060006060606069006000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000066600600600066600000666060006060660966006660000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000060600600606060600000006060006060606060000060000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000060606660666060600000660006606600606066606600000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ccc000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000009990000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000007777000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000077770007777000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +567000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000765 +567000000000000000000088000000000000000000000000000000000000000000000000000000000000000000000000000000000000ccc00000000000000765 +56700000000000000000000880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56705550000050500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700050000050500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700050000055500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700050000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700050050000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765 +56777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777765 +56666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666665 +55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 + +__gff__ +00000000000000000000000000000000671c499a3b8e28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +__map__ +404142434445464748494a000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +505152535455565758595a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +606162636465666768696a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000002a2b2a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000002b2a2b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +__sfx__ +000100001403014030130301203011030100300f0300c00008000020000100028000270002700028000280002800028000280002800027000270002700027000270002800028000290002a0002a0002a0002b000 +000200001a0301e03022030260201b0001a000190001900018000180001800028000270002700028000280002800028000280002800027000270002700027000270002800028000290002a0002a0002a0002b000 +000200002a03026030220301e0201b0001a000190001900018000180001800028000270002700028000280002800028000280002800027000270002700027000270002800028000290002a0002a0002a0002b000 +00050000205502655020550265503050030500305003050030500335003350028500275002750028500285002850028500285002850027500275002750027500275002850028500295002a5002a5002a5002b500 +00050000205501a550205501a5503050030500305003050030500335003350028500275002750028500285002850028500285002850027500275002750027500275002850028500295002a5002a5002a5002b500 +00050000200402004026030260303000030000300003000030000330003300028000270002700028000280002800028000280002800027000270002700027000270002800028000290002a0002a0002a0002b000 +0105000020030200301a0401a0403000030000300003000030000330003300028000270002700028000280002800028000280002800027000270002700027000270002800028000290002a0002a0002a0002b000 +01050000257402075020750257403070030700307003070030700337003370028700277002770028700287002870028700287002870027700277002770027700277002870028700297002a7002a7002a7002b700 +010500002874028740287402e7203070030700307003070030700337003370028700277002770028700287002870028700287002870027700277002770027700277002870028700297002a7002a7002a7002b700 +00050000200301c040190401904000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000200000d05008040050300302002010010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00020000166100d050080400503003020020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000200002b0102d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000200002502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00040000130501305015040180301c02022000280002d0002f0003100032000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00040000130501305015050180401c03022020280002d0002f0003100032000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00040000130501305015050180501c04022030280202d0002f0003100032000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00040000130501305015050180501c05022040280302d0202f0103100032000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000400001705017050190401c0302002025010280002d0002f0003100032000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000400001b0501b0501d0501f04023030280202e0102d0002f0003100032000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000400001e0501e0502005022050260402b0303102033510345103100032000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000400001b0501e0502105024050240502105024050270502a0502d05030050300502d050300503305036040390303c0203e01000000000000000000000000000000000000000000000000000000000000000000 +000300002175023750277402a72027730227002170022700267002a70000700007000070000700007000070000700007000070000700007000070000700007000070000700007000070000700007000070000700 +000100002f6603c6602f6603c6602f6603c6602e6603b6602966034660236502b6501c65024650176401c64010640126400a6400a640046300263001620016001260001600116000460010600076000d6000b600 +35040000016000160001600046010660108601106013d600010600d06019060017500d75019750017400d74019740017300d73019730017200d72019720017100d71019710017150d71519715000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +650a00001955019550005000050019540145401454020500175501755000000195500000019550000000000019540145401454000500175501755000000205001750017500000000000000000000000000000000 +610800000d0500d0500000000000190500000019050000000d0500d0500000000000190500000019050000000d0500d0500000000000190500000019050000000d0500d050000000000019050000001905000000 +011000001025010250000000000000000000000000000000102501025000000000001025000000000000000000000000000000000000000000000000000000001025010250000000000000000000000000000000 +610800000d0500d05000000000001905000000190501025010050100500000000000190500000019050000000d0500d0500000000000190500000019050000000d0500d050000000000019050000001905000000 +05020000260302a0302e030320201b0001a000190001900018000180001800028000270002700028000280002800028000280002800027000270002700027000270002800028000290002a0002a0002a0002b000 +0502000036030320302e0302a0201b0001a000190001900018000180001800028000270002700028000280002800028000280002800027000270002700027000270002800028000290002a0002a0002a0002b000