--!name Light Up
--!icon puzzle
--!category Puzzles
local aG="!$%&()+,-0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnpqrstuvwxyz|~"local function ai(b)return aG:sub(b+1,b+1)end local aJ,aM,aO,aN,aE,aF,aH,aD,aQ,aK=0,1,2,3,4,5,6,12,13,18 local J={7,10,12}local aR={0,23,0}local F={"Easy","Medium","Hard"}local ak={"010W8fHA80bDTCW0A1HW1f0000C13032GX2AA2AA8OID038480f0010G82AE8LEG32A01G0001W10X3WC158S0D484O4131a1W08GL81282W0O81001m8Q12883GG3480103800OJKGO0840088358Z101f0X0WD5DTDE8O8O8O00CO80040O30E82082840D8WD0100OGOC82G5GC080058J1I131fHWD84C21Y0804D430082X2DC158G83ID1H221f000n229GDAK80GX000aAA805D1H4D012ADf008WR00C1Z080X4OOh0O10CX3803O10X1e8Z4080CU800EBW8W1W1000101Yn3010JRG1041gW80100Iff0100858208285080801WQGO010C3e4010X0W0159h48100OXf40408DD08bDO16C00D048XWHHG8148DY0O8X0WAi94100HHG8044LD84820O0X20C0C5JD080YO09210141WYAWWE8102110QWA1001v0O1m88n08f0O1m8012821312f0YA0A5EA12AO1g8C12880L88O868QK804IX490n03H0028GPWX02G1eH0HW1I10nWfH200122fhGf0012A1008WJOQ2008131XeG4200B005012C8GOOD80OX30800QASA0823QAP00048XWCR0C3Xe1411e8e0D10WR413S8O014X3080000100008D8a001WK8020ECf681IAH158Z30A014G08H12CfW8Q08002O1fh211G80848OR080O0B3Z401W013OX308O800083CW10XHe01jC008800OG1028W8WE81G8H041e0O2100G0C08805D00CW8T104C010831012833W3010010080050SD8208f0GPGA00D0B00E030921GfG1W2Af1W1n4X0080008R0W0O1YA0O104D1008W9i3W1e10143008OO0D8D0OE80O008X058WC0C01W1f010GQ2X20OHf21o2fH010f0AW8If58H0022A2008H40QG8Q8800LAW10X3001030f10Q3G800001008W4E30O8XC440O080080CS8400D1W08W8W80f40140Ca88XeC01408010W101030031WX0G2HG1nK01488G0D014GO0HI0GXe13fa100C1WWO4100CeZ01fW2J200104CW90001iC010023I014100803OC0R4XC0S00080D80140808OC44000834D0f00131084ED85E0158010E806E0DEC081G09mH410WO1G8On041Hn80H01HW800WDD1408315D0W088XG808OXL01G8fG8H0GO0H03HWX000011h1v1e1G100G0O1WDX0080A0DK158He09m1e10fG584K8282C08A4KAG8508480IDJ2884A0OAX080W4O0801008Z0O808Q8O","001W88G03GG00018G014W0D82G8W0Df0021800022f0210E80080Xe301W80ODO13XmO4058O580W31v8f36DW83X400C01X348008O80He32X210IK0D0I83Z08G208ZO8I0O1gI01GDHf5A105801aHG341If2000823W0084AfG082EGO0013fG0008H3I1mO2AT8C301358O0C10O8Z0X00334008001WnO0858R1310O848OX00WOD133W1030800800WC13O80O80003013X0OD0080008f003WO8X0000808OCn0W1581HG10F8GK2Hg28f802280X0303OC00000101300C200108GH4148GQOGfY1010KFA4LA1e8X2211000GO01f0C4Hf00100KO80GfH0OG8830QW4K8O01241242103Q00080C2Of800000D10331W4DZ433f8WD8W48W484fneaXeE8XW80f08000048048Da80nn0W08D0100WSF8010fi40001n0130EE80Zf1e08O2A00C8e1034DA02I00013XZ1WC0SDO0800IG0HfeX0068O08HHG0D8QDC01200144O143100R0800S108OX04WO001H00OWL8O0A33103008f0840E1Z10n408OE88e301eD80a8W1W813010O80OXC00D840C2GH021GO804G000480O0012f00428G122Gf0X8O80O01f00D803G4W80fHWW0820W0WC0C1G0835A300CW2W10O08401X480O000A10A1n00Y2GC8000KY0001OAGK8148G08G080301n31e008F8S80f000044C03C3003W00OOX0Xnf0008501h0f0084801ZJ080031G2C0EH00Xv42G08012GWC4102e8OGA8f0001YS80010a8D8O82eZ3108280J0OH301WA31Q01G801WS4G841f1h100A80J01g1G8Y0ECG80000W84GX32X04000102fe8K0A8J18Y08G0800R1n00000C1e0CW080Z0Ce3W8b8083f030O8080031Z1000A0010e130Y8O0EA0001v14A0DW8HW0D0001HW840L1e141000H008O80831e83001f04CWWS3488XWS33OO13001W058O01130801WD8220008483X08042ffGX2AGH423DGO8013O1W0010GG8O31OZ00808401G01J401000158OHA40X001000fY00A80W80008Z310XWXA0015f030100C0W8030De1W01E8X0010W84W080HC330880OD8080WHGY0100000Df02ZHASG84e1000800KA2C1001eE8001W01X5084S1e08W083f8Wf00085483e1030840ZX00OC00C10100045010X1WD108030O000C00f00058O1010X685001eX0000C3O8OWC10OO08OXX000040R0801a8W0001334103C10OD30COf1W8034448OC1000400f01308W680e81308f0010O31WWWO00D8HW00AD1000eG0C28O0WHH000000012AD841GW12E1000nG00DA8I0AGG8OI8f3X0f8G010K80680W01g10021F83O41ID122G1I8W0014DO10Xf48O00000Da8O318n48SW8000131eDE00Cff0004D805C3W01e000011WX5800014O00010ODC001000E804Ofe01Wf00008XaC100008OO1fh0080008000R30C3000088XZ3110004100314O1WSC100000001O4D0DX0ff4000018000OiD83O8W080C141fG8H00HmL84A8OI1G012DfG8028I31HW8QFA01212C0X0XG0CG8G8004f00O1D001WWH0W0140ADD001v0D00DW100282X02SOC3Off301DW08O4Cf000W84DXW041013XWE804W10ODC4OX3Zfn310FEO081nW8f5O04O131f00D8O83e03e484E8014fm10X5COO3121GD218G124J0410080000000880f0YnG8218GW20G1WDC10O080f0R40DH41800HGWOA8001H342A0018WAX0fa1580158004D011410S41000C4080080eO34080010nW0008fZ00W880OO00D8000Z3W88048W1f0004400G200Xn1005851W8014Xi0080X0W1W088O14ff30X0008S001eO4OD3010Z080848f34O168104131f0X2EGH0H1058Y0GG08Y0J0180Q0K08228J0W01A0A2WH3148D8RW83h0C048R0030010001WW340080100W00T8X1e1iO0CS1WO348O08000O4831XWW0840f0000D1W083430f0OC10000E8Xf3848001YW08WH0Xn840IK408Q81J10fYI0f0DD0A3014K8001W180IKAW0H4308O108eO0108024OG8000833180480ff203GQI10C30W8e0080800eX5C08414003O10O8O01Wf4301010004848OXXWSO8001WW8O80OW14X00OfW804D4103W14300D0EC00113R34010HI8KHLA1YA8I4001n08XL81g5804080WI8HK8HoAY0IA080DG1281040G03280008WXW1n008040C5C08010Gf021n001G82X01W8XO8O141e30O203O0C30G8028Of13W0G68X48f0584D0C0104C0D80031W80S400010WOX418f43408000OZ0131W080O1fe1K80Xf03100008QA0Y01e08R401eS80E10J0HL008010O1DD10Q0D8008W1e81308f4OOn4W00E88f003WD43W301W884841100X0","12GD82DX0000G5AX0X08n0008W8210e1IAO084HI0D10G0D1000C10483GO200014XG1f2H08G08IIeH3W128O8041001fW0WGTG0382148008O8H0O12aA316C0108f0041G83O2EII012101YH4D000001KC2O1eI080G88X0000WOO8001005C400013102100ID84GOY000008XWAJ101iAAY8080G8002J144C0001H01W4001WW10000845808eC1020800OOO1YG01020808JHHi800D8481G0f00OXW08RI00800OA1eH0104GL3WQ2O1082C0GC00080IZ105DD8041211W1W10I2W100O080SDLC0001124D8G8W0300080003W0001080X04121WfG80008OYXb80030103HIG00CWOGC0W80C08Xe1020Q0OO0100O1G0010080028300083D1K8H014308f00D1eA33f002ADD8G1G4320S010580850102G10G10WG1J0180Q02D082012G008W110O080T0HWW2128XWH015D80JK100080Q14C10O000M80J1f1G100000802848Y01o800308WX0K010001YY10XW081fH0HI00W1bDDAE8GH0W10000000121420F80X0Gn0G00080000831AA0WGOfp1310IA0AE810X0H08X04E8008000O3W20000010f30840801e01eC0010008G4OD0000010OO0D0120C103010X4C0D1510OI0100f3008W800W38285A01He1G1OE0805010W31800I300W8O8OOC001WC084J10OW10001041408X341000080Ga8Q0808J1Z20000018ff310W8O080000C401YO01W2000080140821512f4510He1102G802A8YK01gK8HG00AG0883208eWCG1m8G01e8000080GGE8OOC3H0O10083O8I80W1GD3W8401080002G0000180O84Of21310I14O0800C0AeX331eA100310E80W8O0W080G01e158G08SHe0GfG011025A0FAS1021m141028005830D80W01e0018f2D800AA0I4O2WX210010X08W8000G800581e00120000E10D00108H4CG3WI0GG008XH31I80R1f1n0O4040008228HGW88b8000G1002IIG000A0001h083228GG0010f1n3048E8S80I8058003ff0022D521f001g8Y1WA8W8G1G1WnD4120A148H30K0J001D8GOXGG1034O001W800013101f285AD08gO10CW8000010J2328LAG2Hg1GfGQ0008000DX00CJ10WGW8GE810W0100R0008800OGY00800QX3g0800080n3II1e800858IIO30100100KX4K00001K248001000S808000HDf00XW1000IOO0C3220C08000015C18Xe1000080X0GGWW0C3I080034803XA800008W80280D1WOWJ1WG0000008012D8G0512008100G1v021nG800080080248Y4330W81G0131D210G814800WIA08O1A20e1KKX2CG8HL1G800121o282fGCQY0D0GH1308HIF800O81210GfH34800a0803182010010Q42I40144808410n408O081WW08eIGXK080001H01n000Z080OOA1230GAE0001i1041W14310G80828021e803G2X0030H00G088208Xe030e01R0080WGA1eG8O1e0X2G08028H0e10fGW8430080000Oe00100800430000808OX042400D121G0102GD840C01310X0E85O0G001008O128201Y1n040082CfG001e848J01G8G0D800010203O8f0C01e80IAA0138eHG00080041OeAG1008YW420008318O0100GWCK10082GED8W0001012A40X00HHIG080G1X00YDA0A58W1O01e1i0J01580O0K0101Y8308W10Q0b84103158OH0GXK0838210020OG1W81f0000D00DAOG0800013041n68W1281G840W58n0X00080023He10O0000C18482481G0C1YO08201O0WR08000080010XhOO01000080003CaC01000080001a48308H003J0O12812A010L01f4X1000008W3240082D13000123OG0000W8OG108WHWD10000083OC01o010GG88O100RH00000830100e4AF8082W1e4001e01015800O583G008WGOC0010X0800002Z00131Ha831Y824G01G01028C1W80ZW000C008O30180W3081e8004U8030X1G0012082fG8J0O8R2WXHW0180O0CK100O08OD8O2W40010010000O41000080000X3G30O4085800QW13101042ECAG1ff0WCO0081000008G848Oi800218302GDf2G0X00G010SE8O0A11000000103OD05D82H12OD8020104831g10n82804A0D130f210G15f0200HE0O1W0He08G8F80L8W1m010G08X4G810I001O13315O8O08f200Ce80GO08I8000G3f20100I086A884W10H410414X0XW0D080I0180HG82W1gGb80ECHf010000J8O0DO801e10KY0840183W0C0Y80000032Xf08SAK0CH02A80GHG0C1X221G4008580ED3010fH31L1022010080GG00g1WAC080Ofe80W001e28GGD8O0AA200C10J41iDR01000008O308000C0Z1O001480O10030S0O10010O400800008hOR1fY80O801W148GE103G81580Oe5G0008100WX001480G280W8013300800012e4308O812X00W21W0C11W1310AG80G1HeKD840800ICO0CGX02128O1041G0G832X03fI1000W1WQDA82012G01W831080G0C3n00000D1WO0008f003W48O0080G10012800041e3O8040800358W100104OX0201080H030KD85A18W3144G100X0OD4A68100G12G120800OHWe3830082eO8O418He1fY0O0A01O313G812001nW30O0W830008080G032aD080001eZHX028000100O8C030O35800H012O1W3K1W8O1100308800OHeZ000820001m84D00D08f00ff141000G0800R32480080O0080C148Y1048H4400YG10085D801m1030080S000G0100802018a8000e00D808ff0000AL10WX21W080100JH4EAI088000023f3X20GAJ08X1nG8H00212F8E80QH21GCf4OG0080008IGXWAY000110O1HG010408EDf02ff28O100O00E00128n00D1G800W01308030GC3H03Xe08O001220C08X028OS010W01O4O3G808000Z33100080000O4000011000OWa0000882O3O3104800S48G13010O8fXe8O082C1GX08WG8GW00Cf4AW00080800003Hn4O105A12518328XG10315C413080O1I2Af0001j88280H0J1e4E002O8HJ1300808000W8YA83G10fe48Q1210G10T8000CHGI0C8O0800100W1ebAC0E882000101G1WK40He10105A8OQ582010100G81e1nGZE86800001048008301f0330DA00010W1048008O30f8Z000EW010S148OD1000O10480000Hf0OO8401W0088208X01W1n044GDG01a80K2880I10G1nW40808OC40201I100GQ10S082WAfO0E8581310H00082AD3102G10D0CHW80028Ge1n300858I02H0I1e801WF83A0G10042X0W112G08WOHG00830012X3X0L0G4001041J008H4GX0f08H02G012G1280D86Ae2001g8W0001eA1Y85O3G001WX201000X48WA0QYW8H0080f0DI100J1J0WGIIA58Q8Q010Ie140008A14KJ1H41n400008H3"}local aC="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-"local al={}for b=1,64 do al[aC:byte(b)]=b-1 end local function az(h)return(J[h]*J[h]+1)//2 end local function aU(h)return#ak[h]//az(h)end local function aZ(e)local h=os.date("*t",e)return os.time({year=h.year,month=h.month,day=h.day,hour=12})//86400 end local function P()local e=os.time()if not e or e<1700000000 then return nil end return aZ(e)end local aS={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}local aP={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}local aI={3,1,1,2,2,2,3}local function aq(K)return os.date("*t",K*86400+43200)end local function ar(K)local h=aq(K)return aS[h.wday].." "..aP[h.month].." "..h.day end local function ap(K)return aI[aq(K).wday]end local c=7 local t,E,n={},{},{}local a local z={}local g={}for b=1,13 do g[b]=0 end local M={1,1,1}local A={}local o,L=1,false local k,q,an="menu",1,"menu"local x,S,Z=nil,nil,nil local function G(i)i=math.floor(i or 0)if i>=3600 then return string.format("%d:%02d:%02d",i//3600,i//60%60,i%60)end return string.format("%d:%02d",i//60,i%60)end local function Y(V)if V.kind=="d"then return"Daily, "..ar(V.num)end return F[V.diff].." #"..V.num end local function a6(X,p,u)local f=aU(p)if X=="d"then return(u*37+11)%f,u%8 end return(u-1)%f,(u*5+(u-1)//f)%8 end local function _(X,p,u)local ao,e=a6(X,p,u)local Q=az(p)local a9=ak[p]:sub(ao*Q+1,ao*Q+Q)local af={}for d=1,Q do local r=al[a9:byte(d)]or 0 af[2*d-1],af[2*d]=r>>3,r&7 end c=J[p]t,E,n={},{},{}o=nil for v=0,c-1 do for m=0,c-1 do local O,N=v,m if e&4~=0 then O,N=N,O end if e&1~=0 then O=c-1-O end if e&2~=0 then N=c-1-N end local r,b=af[O*c+N+1],v*c+m+1 t[b]=r>=2 and r-3 or nil E[b],n[b]=r==1,0 if not o and not t[b]then o=b end end end a={kind=X,diff=p,num=u,el=0,hints=0,done=false}A,L,x={},false,nil end local function bc()local r={}for b=1,c*c do r[b]=n[b]end return table.concat({a.kind,a.diff,a.num,a.el,a.hints,a.done and 1 or 0,o,table.concat(r)},",")end local function aA(i)local j={}for w in(i..","):gmatch("([^,]*),")do j[#j+1]=w end local p,u=tonumber(j[2]),tonumber(j[3])if(j[1]~="d"and j[1]~="b")or not p or p<1 or p>3 or not u then return end _(j[1],p,u)a.el,a.hints,a.done=tonumber(j[4])or 0,tonumber(j[5])or 0,j[6]=="1"local m=tonumber(j[7])or 0 if m>=1 and m<=c*c and not t[m]then o=m end local r=j[8]or""for b=1,c*c do local w=(r:byte(b)or 48)-48 if not t[b]and w>=0 and w<=2 then n[b]=w end end return true end local function y()if a then z[a.kind]=bc()end snail.save(table.concat({"LU1",table.concat(g,","),table.concat(M,","),a and a.kind or"",z.d or"",z.b or""},";"))end local function a3()local i=snail.load()if type(i)~="string"or i:sub(1,4)~="LU1;"then return end local j={}for w in(i..";"):gmatch("([^;]*);")do j[#j+1]=w end local d=0 for w in(j[2]or""):gmatch("[^,]+")do d=d+1 if d<=13 then g[d]=tonumber(w)or 0 end end d=0 for w in(j[3]or""):gmatch("[^,]+")do d=d+1 if d<=3 then M[d]=math.max(1,tonumber(w)or 1)end end if j[5]and j[5]~=""then z.d=j[5]end if j[6]and j[6]~=""then z.b=j[6]end local ad=j[4]if ad and z[ad]then local ae,ag=pcall(aA,z[ad])if not(ae and ag)then a=nil end end end local function ba(b)local e={}local v,m=(b-1)//c,(b-1)%c for h=1,4 do local U,T=(h==1 and-1)or(h==2 and 1)or 0,(h==3 and-1)or(h==4 and 1)or 0 local I,H=v+U,m+T while I>=0 and I<c and H>=0 and H<c and not t[I*c+H+1]do e[#e+1]=I*c+H+1 I,H=I+U,H+T end end return e end local function au()local C,R={},{}for b=1,c*c do if n[b]==1 then C[b]=true for am,W in ipairs(ba(b))do C[W]=true if n[W]==1 then R[b]=true end end end end return C,R end local function aT(b)local v,m,e=(b-1)//c,(b-1)%c,{}if v>0 then e[#e+1]=b-c end if v<c-1 then e[#e+1]=b+c end if m>0 then e[#e+1]=b-1 end if m<c-1 then e[#e+1]=b+1 end return e end local function aW(b)local f=0 for am,W in ipairs(aT(b))do if n[W]==1 then f=f+1 end end return f end local function aj(b)return not t[b]and((n[b]==1 and not E[b])or(n[b]==2 and E[b]))end local function a4()local f=0 for b=1,c*c do if aj(b)then f=f+1 end end return f end local function be()local C,f=au(),0 for b=1,c*c do if not t[b]and not C[b]then f=f+1 end end return f end local function ay(b)A[#A+1]=b*4+n[b]if#A>150 then table.remove(A,1)end end local function at()for b=1,c*c do if not t[b]and(n[b]==1)~=E[b]then return end end a.done,L=true,false local l=(a.diff-1)*3 g[l+1]=g[l+1]+1 if g[l+2]==0 or a.el<g[l+2]then g[l+2]=math.max(1,a.el)end g[l+3]=g[l+3]+a.el if a.kind=="d"and g[13]~=a.num then g[10]=g[10]+1 g[11]=g[13]==a.num-1 and g[11]+1 or 1 if g[11]>g[12]then g[12]=g[11]end g[13]=a.num end end local function a1()for d=0,c*c-1 do local b=(o-1+d)%(c*c)+1 if aj(b)or(E[b]and n[b]~=1)then ay(b)n[b]=E[b]and 1 or 0 o=b a.hints=a.hints+1 x=E[b]and"Hint: a bulb goes here"or"Hint: no bulb here"at()return end end end local function aa()local h=P()if h and g[13]<h-1 then return 0 end return g[11]end local function D()k,Z,q="play",os.time(),1 end local function aB(p)if a then y()end local f=M[p]M[p]=f+1 _("b",p,f)D()y()end local function bd(h)if a then y()end a=nil if z.d then local ae,ag=pcall(aA,z.d)if not(ae and ag)or a.num~=h then a=nil end end if not a then _("d",ap(h),h)end D()y()end local function aY()local aw=os.time()if a and k=="play"and Z and not a.done then local as=aw-Z if as>0 then a.el=a.el+math.min(as,600)end end Z=aw end local function bb(h)return J[h].."x"..J[h]end local function av()local e={}if a and not a.done then e[#e+1]={"Continue: "..Y(a).." ("..G(a.el)..")","cont"}end local h=P()if h then local i="Daily puzzle: "..ar(h)..", "..F[ap(h)]if g[13]==h then i=i.." (solved)"end e[#e+1]={i,"daily"}else e[#e+1]={"Daily puzzle: needs the clock","noclock"}end for d=1,3 do e[#e+1]={"New "..F[d].." "..bb(d).." puzzle (#"..M[d]..")",d}end e[#e+1]={"Statistics","stats"}e[#e+1]={"How to play","help"}return e end local function ax()return{{"Back to the puzzle","cont"},{#A>0 and("Undo ("..#A..(#A==1 and" move)"or" moves)"))or"Undo (nothing to undo)","undo"},{"Check for mistakes","check"},{"Hint: fix a square","hint"},{"Restart this puzzle","restart"},{"Main menu","menu"},{"How to play","help"},}end local function aX(s)if s=="cont"then D()elseif s=="undo"then local ab=table.remove(A)if ab then n[ab//4],o=ab%4,ab//4 D()y()else x="Nothing to undo"end elseif s=="check"then D()local f=a4()L=f>0 x=f==0 and"No mistakes so far"or(f==1 and"1 mistake, marked"or f.." mistakes, marked")elseif s=="hint"then D()if not a.done then a1();y()end elseif s=="restart"then _(a.kind,a.diff,a.num)D()y()elseif s=="menu"then k,q="menu",1 elseif s=="daily"then bd(P())elseif type(s)=="number"then if a and a.kind=="b"and not a.done and S~=s then S,x=s,"Press OK again to leave "..Y(a)else S=nil aB(s)end else an,k=k,s end end local function a5(d)local v,m=(o-1)//c,(o-1)%c local U=(d=="up"and-1)or(d=="down"and 1)or 0 local T=(d=="left"and-1)or(d=="right"and 1)or 0 for i=1,c-1 do local b=(v+U*i)%c*c+(m+T*i)%c+1 if not t[b]then o=b return end end end local function a7(d)if a.done then if d=="top"then k,q="menu",1 elseif d=="ok"then if a.kind=="b"then aB(a.diff)else k,q="menu",1 end end return end if d=="top"then k,q="opts",1 y()elseif d=="ok"then ay(o)n[o]=(n[o]+1)%3 at()y()else a5(d)end end function key(d)aY()x,L=nil,false if k=="play"and a then a7(d)return end if k=="menu"or k=="opts"then local B=k=="menu"and av()or ax()if d~="ok"then S=nil end if d=="up"then q=(q-2)%#B+1 elseif d=="down"then q=q%#B+1 elseif d=="ok"then aX(B[math.min(q,#B)][2])elseif d=="top"and k=="opts"then k,q="menu",1 end return end if d=="top"or d=="ok"then k=an end end local function aV()local ac=aR[a.diff]local C,R=au()local a8=a.done local ah={}for v=0,c-1 do local e={}for m=1,c do local b=v*c+m local l=t[b]if L and aj(b)then e[m]="@"elseif l then if l<0 then e[m]=ai(ac+aD)else e[m]=ai(ac+(aW(b)==l and aK or aQ)+l)end else local i=n[b]local r=(i==1 and(R[b]and aF or aE))or(i==2 and(C[b]and aN or aO))or(C[b]and aM or aJ)if b==o and not a8 then r=r+aH end e[m]=ai(ac+r)end end ah[#ah+1]=table.concat(e)end return table.concat(ah,"/")end local function a_()snail.title("Light Up - "..Y(a))local i if a.done then local l=(a.diff-1)*3 i="Solved! Best "..F[a.diff].." time "..G(g[l+2])if a.hints>0 then i=i..", "..a.hints..(a.hints==1 and" hint"or" hints")end elseif x then i=x else local f=be()i=G(a.el).."  "..(f==0 and"All lit"or(f.." dark "..(f==1 and"square"or"squares")))end snail.status(i:sub(1,47))snail.board(aV(),nil,a.done and("Solved in "..G(a.el))or nil)if a.done then local l=(a.diff-1)*3 snail.text(F[a.diff].." puzzles solved: "..g[l+1])if a.kind=="d"then snail.text("Daily streak: "..aa()..(aa()==1 and" day"or" days"))end snail.hint(a.kind=="b"and"BACK puzzles OK next puzzle"or"BACK puzzles OK puzzles")else local bf=({"bulb","dot","clear"})[n[o]+1]snail.hint("BACK options OK "..bf.." L/R move UP/DN move")end end local function a0()snail.title("Light Up statistics")for d=1,3 do local l=(d-1)*3 local f=g[l+1]if f>0 then snail.text(F[d]..": "..f.." solved, best "..G(g[l+2])..", average "..G(g[l+3]/f))else snail.text(F[d]..": none solved yet")end end snail.gap()snail.text("Daily puzzles solved: "..g[10])snail.text("Daily streak "..aa()..", best "..g[12])snail.hint("BACK back OK back")end local aL={"Put bulbs in white squares until every white square is lit.","A bulb lights its row and column up to a black square. Bulbs may never light each other.","A number on a black square says how many bulbs touch it, above, below and to the sides.","Arrows move, skipping black squares. OK cycles: bulb, dot (no bulb here), empty.","Lit squares are shaded. A number gets a white ring once it has all its bulbs.","BACK opens options: undo, check, a hint and a restart.",}function draw()if k=="play"and a then a_()return end if k=="stats"then a0()return end if k=="help"then snail.title("How to play")for am,i in ipairs(aL)do snail.text(i)end snail.hint("BACK back OK back")return end if k=="noclock"then snail.title("Daily puzzle")snail.text("The daily puzzle needs the date. Connect to Wi-Fi once so the clock gets set, then come back.")snail.text("The Easy, Medium and Hard puzzles work any time.")snail.hint("BACK back OK back")return end local B=k=="menu"and av()or ax()if q>#B then q=#B end snail.title(k=="menu"and"Light Up"or("Light Up - "..Y(a)))if x then snail.status(x)end for b,a2 in ipairs(B)do snail.row(a2[1],b==q)end snail.gap()if k=="menu"then local f=g[1]+g[4]+g[7]snail.small("Daily streak "..aa()..", "..f..(f==1 and" puzzle"or" puzzles").." solved.")snail.hint("BACK leave OK choose UP/DN move")else snail.small("Time "..G(a.el)..(a.hints>0 and(", hints "..a.hints)or""))snail.hint("BACK puzzles OK choose UP/DN move")end end function start()snail.ink("fast")a3()if a and not a.done and not(a.kind=="d"and P()and a.num~=P())then D()else k,q="menu",1 end end
