--!name Sky Defender
--!icon game
--!category Games
local w=snail.touchscreen==true local ae,L=14,17 local F,K,E=7,5,3 local G,ao,U=2,12,13 local aD,aB=14,15 local ap={[1]=true,[3]=true,[5]=true}local an=1 local am={{10,2,"up",true}}local aC={"..^!..","..++..","<++++>","=++++?","..++..","..~|.."}local l,R="menu",1 local M,ad,o={},{},{}local I,z,H,S,Y=0,0,1,0,0 local j,e,s,m,al=3,0,0,nil,1 local D,O,n,v=0,3,1,0 local h,B,x=0,0,nil local A,k,Z,J,ak=false,1,nil,0,false local q={0,0}local ac=1 local function aa(P)ac=(ac*1664525+1013904223)&0xFFFFFFFF return(ac>>16)%P end local function ah()if k==1 then return math.max(500,700-(n-1)*50)end return math.max(450,550-(n-1)*50)end local function aV()local P=v>=10 and 4 or v>=5 and 3 or v>=2 and 2 or 1 return math.max(1,P-(n-1)//2-(k-1))end local function aS()snail.save(q[1]..","..q[2])end local function aA(c,d)if d<G or(d-G)%2~=0 then return nil end local a,b=(d-G)//2-z+1,c-I+1 if a>=1 and a<=E and b>=1 and b<=K and M[a][b]then return a,b end end local function W(c,d)for f,g in ipairs(o)do if g[1]==c and g[2]==d then return f end end end local function az()for a=1,E do M[a]={true,true,true,true,true}end for c in pairs(ap)do ad[c]=true end v,I,z,H,S=E*K,0,math.min(2,(n-1)//2),1,0 o,e,m={},0,nil end local function aQ()if os and os.time then ac=os.time()%100000+11 end D,O,n,j=0,3,1,3 az()h,B,x,Y=0,1,nil,0 A,Z,J=false,nil,0 l="play"snail.tick(ah())end local function aR()l="over"snail.tick(0)ak=D>q[k]if ak then q[k]=D aS()end end local function ay()O=O-1 h,e,o=3,0,{}end local function aq(P)D=math.min(9999,D+P)end local function aO()if e==0 then return end local a,b=aA(s,e-1)if a then M[a][b]=false v=v-1 aq((E+1-a)*10)x,e={s,e-1},0 return end e=e-2 if e<3 then if m==s then aq(100)x,m={s,1},nil end e=0 return end local f=W(s,e)if f then table.remove(o,f)e=0 end end local function aN()local ai={}for af,g in ipairs(o)do local c,d=g[1],g[2]+2 if d>U then if ad[c]then ad[c]=false elseif c==j and h==0 then ay()end elseif e==d and s==c then e=0 else ai[#ai+1]={c,d}end end if h==0 then o=ai end end local function aM()Y=1-Y local aj,ag,au=K,1,1 for a=1,E do for b=1,K do if M[a][b]then aj,ag,au=math.min(aj,b),math.max(ag,b),a end end end local c=I+(H>0 and ag or aj)-1+H if c>=0 and c<F then I=I+H return end H,z=-H,z+1 if G+2*(z+au-1)>ao then z=0 ay()end end local function aI()if#o>=math.min(4,k+1+(n-1)//2)or aa(100)>=30+n*5 then return end local b=aa(K)+1 for a=E,1,-1 do if M[a][b]then local c,d=I+b-1,G+2*(z+a-1)+1 if e==d and s==c then e=0 elseif not W(c,d)then o[#o+1]={c,d}end return end end end local function aP()if m then m=m+al if m<0 or m>=F then m=nil end elseif aa(100)<6 then al=aa(2)==0 and 1 or-1 m=al>0 and 0 or F-1 end end function tick()if l~="play"or A then snail.tick(0)return end x=nil if B>0 then B=B-1 return end if J>0 then J=J-1 if J==0 then Z=nil end end if h>0 then h=h-1 if h==0 and O==0 then aR()end return end if v==0 then n=n+1 az()Z,J="WAVE "..n,2 snail.tick(ah())return end aO()aN()if h>0 or v==0 then return end S=S+1 if S>=aV()then S=0 aM()if h>0 then return end end aI()aP()end local function av()return l=="play"and not A and B==0 and h==0 end local function ax()if e~=0 then return end local f=W(j,U)if f then table.remove(o,f)return end e,s=U,j end function key(i)if l=="menu"then if i=="up"or i=="down"then R=3-R elseif i=="ok"then k=R aQ()end return end if l=="over"then if i=="ok"then l="menu"end return end if i=="ok"then A=not A snail.tick(A and 0 or ah())return end if not av()then return end if i=="left"then j=math.max(0,j-1)return true elseif i=="right"then j=math.min(F-1,j+1)return true elseif i=="up"or i=="down"then ax()end end local function aG(t,g)local a,b=g-L-1,t-1 if a<0 then return nil end local X,aw=2*(b-an)-5,2*a-5 if X>=-7 and X<=7 then local ar,as=math.abs(X),math.abs(aw)if ar>as then return X<0 and"left"or"right"end if as>ar then return aw<0 and"up"or"down"end return nil end for af,y in ipairs(am)do if b>=y[1]and b<=y[1]+1 then return y[3]end end end function touch(aL,t,g)if aL~="board"then return end if w then local i=aG(t,g)if i then return key(i)end else t=t-1 end if g<=L and av()then local c=math.min(F-1,(t-1)//2)if c==j then ax()else j=c end end end local function aH()local p={}for a=1,6 do p[a]={}for b=1,ae do p[a][b]="."end for f=1,6 do p[a][an+f]=aC[a]:sub(f,f)end end for af,y in ipairs(am)do local _,a,b=y[4]and"()[]"or"$&;:",y[2]+1,y[1]+1 p[a][b],p[a][b+1]=_:sub(1,1),_:sub(2,2)p[a+1][b],p[a+1][b+1]=_:sub(3,3),_:sub(4,4)end for a=1,6 do p[a]=table.concat(p[a])end return p end local function aU(N)local Q={}for a=0,L-1 do local C=table.concat(N[a])Q[#Q+1]=w and C or"."..C.."."end if w then for af,ab in ipairs(aH())do Q[#Q+1]=ab end end return table.concat(Q,"/")end local function aE()local u=B>0 local N={}for a=0,L-1 do local ab={}for b=1,ae do ab[b]="."end N[a]=ab end local function r(b,a,aF)N[a][b+1]=aF end local C=u and"8888"or string.format("%4d",D):gsub(" ","_")for f=1,4 do r(f-1,0,C:sub(f,f))end for f=1,3 do r(10+f,0,(u or O>=f)and"c"or"C")end for c=0,F-1 do local T=2*c r(T,1,(u or m==c)and"u"or"U")for d=G,ao,2 do r(T,d,(u or aA(c,d))and(Y==0 and"a"or"b")or"A")end for d=3,U,2 do local aT,at=u or(e==d and s==c),u or W(c,d)r(T,d,aT and(at and"z"or"s")or(at and"d"or"m"))end if ap[c]then r(T,aD,(u or ad[c])and"h"or"H")end local aJ=u or j==c r(T,aB,aJ and(h>0 and"w"or"c")or"C")end if x then r(2*x[1],x[2],"x")end for b=0,ae-1 do r(b,L-1,"g")end return aU(N)end function draw()local aK=string.format("GAME %s  BEST %d",k==1 and"A"or"B",q[k])snail.title((w and l~="menu")and"Sky Defender  "..aK or"Sky Defender")if l=="menu"then snail.row("Game A",R==1)snail.row("Game B (faster)",R==2)snail.gap()snail.text(string.format("Best: A %d   B %d",q[1],q[2]))snail.gap()snail.small("Shoot down the invaders before they reach your shields.")snail.small("Each wave comes faster. The saucer is worth 100.")if w then snail.small("Move with the d-pad or tap a lane; the round button,")snail.small("or a tap on your own lane, fires.")else snail.small("LEFT and RIGHT move the cannon, UP or DOWN fires.")end snail.small("One shot at a time. Shields stop one bomb each.")snail.small("Three cannons.")snail.hint("OK start BACK leave")return end if not w then snail.small(string.format("GAME %s   WAVE %d   BEST %d",k==1 and"A"or"B",n,q[k]))end local V=Z if B>0 then V="GAME "..(k==1 and"A"or"B")end if A then V="PAUSED"end if l=="over"then V=string.format("GAME OVER  %d%s",D,ak and"  BEST!"or"")end snail.board(aE(),nil,V)if l=="over"then snail.hint("OK menu BACK leave")elseif w then snail.hint("OK pause BACK leave")else snail.hint("L left R right OK pause BACK leave")end end function start()snail.ink("fast")local C=snail.load()if C then local t,g=C:match("(%d+),(%d+)")q={tonumber(t)or 0,tonumber(g)or 0}end end
