--!name Life Counter
--!icon heart
--!category Games
local P,M,R,aq,ap,Q=-99,999,10,21,99,8 local aa={20,30,40}local t=26 local aG={B="D",D="B",C="E",E="C",G="I",I="G",H="J",J="H",["3"]="e",["4"]="h",["7"]="L",P="d",["6"]="9",["9"]="6",K="k"}local aH={["0"]=63,["2"]=91,["3"]=79,["4"]=102,["5"]=109,["6"]=125,["7"]=7,["8"]=127,["9"]=111,["-"]=64}local aF={{3,5,1},{4,7,1},{6,9,1},{7,10,2}}local h,C,m=4,40,1 local p,w,u={},{},{}local r,c,X,af="setup",1,nil,false local function v(D,K,av)if D<K then return K end if D>av then return av end return D end local function y(a,i)return(a-1)*Q+i end local function ai()for a=1,h do p[a],w[a]=C,0 for i=1,Q do u[y(a,i)]=0 end end m,X,af=1,nil,true end local function ag(a)if p[a]<=0 or w[a]>=R then return true end for i=1,h do if u[y(a,i)]>=aq then return true end end return false end local function L()local e={}for a=1,h do for i=1,h do if i~=a then e[#e+1]=u[y(a,i)]end end end snail.save(table.concat({"L2",h,C,m,table.concat(p,",",1,h),table.concat(w,",",1,h),table.concat(e,",")},";"))end local function aj(o)local k={}for D in(o or""):gmatch("%-?%d+")do k[#k+1]=tonumber(D)end return k end local function ax()local o=snail.load()if type(o)~="string"or o:sub(1,3)~="L2;"then return false end local f={}for D in(o..";"):gmatch("([^;]*);")do f[#f+1]=D end local j,aC=tonumber(f[2]),tonumber(f[3])if not j or j<2 or j>Q or not aC then return false end h,C=j,v(aC,1,M)ai()local W,aU,e=aj(f[5]),aj(f[6]),aj(f[7])local b=1 for a=1,h do p[a]=v(W[a]or C,P,M)w[a]=v(aU[a]or 0,0,R)for i=1,h do if i~=a then u[y(a,i)]=v(e[b]or 0,0,ap)b=b+1 end end end m=v(tonumber(f[4])or 1,1,h)return true end local function al()return(h+3)//4 end local function ak(q)local j=al()return q*(h//j)+math.min(q,h%j)end local function aT(a)local q=al()-1 while q>0 and a-1<ak(q)do q=q-1 end return q end local function ae(g,f)if g=="1"then return(f[3]>1 or f[1]<=4)and 3 or 4 end if g=="-"then return(f[1]*2+2)//3 end return f[1]end local function O(g,f,d,e)local E,U,k=ae(g,f),f[2],f[3]if d<0 or e<0 or d>=U or e>=E then return false end if g=="1"then if k>1 then return e>0 or d<2 end local o=E-2 return e==o or(d==0 and e==o-1)or(d==U-1 and e>=o-1)end local I,ay=aH[g],(U-k)//2 local ao,K=d<ay+k,d>=ay return(d<k and I&1>0)or(d>=U-k and I&8>0)or(ao and K and I&64>0 and(e>=k or g~="3"))or(e<k and(ao and I&32>0 or K and I&16>0))or(e>=E-k and(ao and I&2>0 or K and I&4>0))end local function aW(g,f,d,e)local aD,B,W,aB=O(g,f,d-1,e),O(g,f,d+1,e),O(g,f,d,e-1),O(g,f,d,e+1)local am,an,ad,ac=not(aD or W),not(aD or aB),not(B or aB),not(B or W)if am and an then return"G"end if an and ad then return"H"end if ad and ac then return"I"end if ac and am then return"J"end return am and"B"or an and"C"or ad and"D"or ac and"E"or"A"end local function az(x,o,G,aN,aS)local f,N,j for n=aN,1,-1 do f,j=aF[n],0 for b=1,#o do j=j+ae(o:sub(b,b),f)end N=f[3]if j+(#o-1)*N>G then N=1 end j=j+(#o-1)*N if j<=G then break end end local A,aZ=1+(G-j)//2,aS-f[2]//2 for b=1,#o do local g=o:sub(b,b)local as=ae(g,f)for d=0,f[2]-1 do for e=0,as-1 do if O(g,f,d,e)then x(aZ+d,A+e,aW(g,f,d,e))end end end A=A+as+N end end local function F(l,a_,a0,E,a,aV)local function x(d,e,g)if aV then d,e,g=14-d,E-1-e,aG[g]or g end l[(a0+d)*t+a_+e+1]=g end local G,ab=E-2,E>13 if a==m then for e=0,E-1 do x(1,e,"*");x(14,e,"*")end for d=2,13 do x(d,0,"*");x(d,E-1,"*")end end x(2,1,"P");x(2,2,tostring(a))if ag(a)then x(2,3,"K")end az(x,tostring(p[a]),G,ab and 4 or 2,7)local V,_={},{}if w[a]>0 then V[1]="p"..w[a]end for i=1,h do if i~=a and u[y(a,i)]>0 then _[#_+1]=i end end table.sort(_,function(s,S)local A,aE=u[y(a,s)],u[y(a,S)]if A~=aE then return A>aE end return s<S end)for aI,i in ipairs(_)do V[#V+1]="P"..i..":"..u[y(a,i)]end local J,H={},""for aI,ah in ipairs(V)do local k=H==""and ah or H.." "..ah if#k<=G then H=k else J[#J+1]=H;H=ah end end if H~=""then J[#J+1]=H end local Y=ab and 13 or 12 for n=1,math.min(#J,ab and 1 or 2)do local k=J[n]local A=1+(G-#k)//2 for b=1,#k do local g=k:sub(b,b)if g~=" "then x(Y+n-1,A+b-1,g)end end end end local function aY()local l={}for n=1,32*t do l[n]="."end local q,j=aT(m),al()local s=ak(q)local T=(q+1<j and ak(q+1)or h)-s local function au(Y,aw)if m~=aw and m~=aw+1 then for d=Y+1,Y+12 do l[d*t+13]="V"end end end if T==4 then F(l,0,0,13,s+1,true);F(l,13,0,13,s+2,true)F(l,0,17,13,s+3);F(l,13,17,13,s+4)au(0,s+1)else F(l,0,0,26,s+1,true)if T==2 then F(l,0,17,26,s+2)else F(l,0,17,13,s+2);F(l,13,17,13,s+3)end end if T>2 then au(18,s+T-1)end local z={}for d=0,31 do z[d+1]=table.concat(l,"",d*t+1,d*t+t)end return table.concat(z,"/"),q,j end local function at()return h+1 end local function aA(Z)local b=2 for i=1,h do if i~=m then b=b+1 if b==Z then return i end end end end local function aQ(b)if b=="up"then c=c>1 and c-1 or 3 elseif b=="down"then c=c<3 and c+1 or 1 elseif b=="left"or b=="right"then local B=b=="right"and 1 or-1 if c==1 then h=v(h+B,2,Q)elseif c==2 then local n=1 for A,D in ipairs(aa)do if D==C then n=A end end C=aa[(n-1+B)%#aa+1]end elseif b=="ok"then ai()r="table"L()elseif b=="top"and af then ax()r,c="options",1 end end local function aP(b)if b=="up"then c=c>1 and c-1 or 4 elseif b=="down"then c=c<4 and c+1 or 1 elseif b=="ok"then if c==2 then ai();L()elseif c==3 then r,c="setup",3;return elseif c==4 then m=math.random(h)X="P"..m.." goes first!"L()end r="table"end end local function aO(b)local a,z=m,at()if b=="up"then c=c>1 and c-1 or z elseif b=="down"then c=c<z and c+1 or 1 elseif b=="left"or b=="right"then local B=b=="right"and 1 or-1 if c==1 then p[a]=v(p[a]+5*B,P,M)elseif c==2 then w[a]=v(w[a]+B,0,R)else local n=y(a,aA(c))local ar=u[n]u[n]=v(ar+B,0,ap)p[a]=v(p[a]-(u[n]-ar),P,M)end L()elseif b=="ok"or b=="top"then r="table"end end local function aR(b)if b=="up"or b=="down"then m=(m-1+(b=="down"and 1 or h-1))%h+1 L()elseif b=="left"or b=="right"then p[m]=v(p[m]+(b=="right"and 1 or-1),P,M)L()elseif b=="ok"then r,c="detail",1 elseif b=="top"then r,c="options",1 end end function key(b)X=nil if r=="setup"then aQ(b)elseif r=="options"then aP(b)elseif r=="detail"then aO(b)else aR(b)end end local function aM()local aX,q,j=aY()local a=m local S=X or("P"..a..":  "..p[a].." life"..(w[a]>0 and",  "..w[a].." poison"or"")..(ag(a)and"  (out)"or"")..(j>1 and"   page "..(q+1).."/"..j or""))snail.title("Life Counter")snail.board(aX,nil,S)snail.hint("BACK options OK counters L-1 R+1 UP/DN player")end local function aJ()local a=m snail.title("P"..a..":  "..p[a].." life"..(ag(a)and"  -  out"or""))snail.row("Life  "..p[a].."    (5 per press)",c==1)snail.row("Poison  "..w[a].." of "..R,c==2)snail.gap()snail.small("Commander damage P"..a.." has taken:")for Z=3,at()do local i=aA(Z)snail.row("From P"..i.."'s commander  "..u[y(a,i)].." of "..aq,c==Z)end snail.gap()snail.small("Commander damage comes off life too. Out at 0 life, 10 poison or 21 from one commander.")local l={}for n=1,12*t do l[n]="."end az(function(d,e,g)l[d*t+e+1]=g end,tostring(p[a]),t-2,4,6)local z={}for d=0,11 do z[d+1]=table.concat(l,"",d*t+1,d*t+t)end snail.board(table.concat(z,"/"))snail.hint(c==1 and"BACK table OK table L-5 R+5 UP/DN choose"or"BACK table OK table L-1 R+1 UP/DN choose")end local function aK()snail.title("Life Counter")local z={"Back to the table","Rematch: "..h.." players, "..C.." life","New game: change players or life","Pick who goes first"}for n,k in ipairs(z)do snail.row(k,n==c)end snail.gap()snail.small("The game is kept when you leave. Open Life Counter again to carry on.")snail.hint("BACK leave OK choose UP/DN move")end local function aL()snail.title("New game")snail.row("Players  "..h,c==1)snail.row("Starting life  "..C,c==2)snail.row("Start the game",c==3)snail.gap()snail.small("20 life for most formats, 30 for Brawl or Two-Headed Giant, 40 for Commander.")snail.small("Lay the reader flat between the players: the top row faces the far side.")snail.small("Up to four players share a screen; five to eight go on two pages.")snail.hint((af and"BACK cancel"or"BACK leave").." OK start L/R change UP/DN move")end function draw()if r=="setup"then aL()elseif r=="options"then aK()elseif r=="detail"then aJ()else aM()end end function start()snail.ink("fast")if ax()then r="table"else h,C,r,c=4,40,"setup",3 end end
