973 lines
20 KiB
Lua
973 lines
20 KiB
Lua
local board={}
|
|
local bw,bh=10,10
|
|
local g=love.graphics
|
|
local font=g.newFont(9,"mono")
|
|
font:setFilter("nearest")
|
|
g.setFont(font)
|
|
local colors={
|
|
function(a,b)
|
|
g.setColor(1,0,0,b*a)
|
|
g.polygon("fill",0.5,0, 1,0.5, 0.5,1, 0,0.5)
|
|
g.setColor(1,0,0,a)
|
|
g.polygon("line",0.5,0, 1,0.5, 0.5,1, 0,0.5)
|
|
end,
|
|
function(a,b)
|
|
local w=0.5^0.5
|
|
local p=(1-w)/2
|
|
g.setColor(1,1,0,b*a)
|
|
g.rectangle("fill",p,p,w,w)
|
|
g.setColor(1,1,0,a)
|
|
g.rectangle("line",p,p,w,w)
|
|
end,
|
|
function(a,b)
|
|
g.setColor(0,1,0,b*a)
|
|
g.circle("fill",0.5,0.5,0.45,8)
|
|
g.setColor(0,1,0,a)
|
|
g.circle("line",0.5,0.5,0.45,8)
|
|
end,
|
|
function(a,b)
|
|
g.translate(0,0.15)
|
|
g.translate(0.5,0.5)
|
|
g.rotate(math.pi/2*3)
|
|
g.translate(-0.5,-0.5)
|
|
g.setColor(0,1,1,b*a)
|
|
g.circle("fill",0.5,0.5,0.5,3)
|
|
g.setColor(0,1,1,a)
|
|
g.circle("line",0.5,0.5,0.5,3)
|
|
end,
|
|
function(a,b)
|
|
g.translate(0.5,0.5)
|
|
g.rotate(math.pi/2*3)
|
|
g.translate(-0.5,-0.5)
|
|
g.setColor(1,0,1,b*a)
|
|
g.circle("fill",0.5,0.5,0.45,6)
|
|
g.setColor(1,0,1,a)
|
|
g.circle("line",0.5,0.5,0.45,6)
|
|
end,
|
|
function(a,b)
|
|
g.setColor(0,0,1,b*a)
|
|
g.setColor(0,0,1,a)
|
|
g.line(0.1,0.4, 0.5,0, 0.9,0.4)
|
|
g.line(0.1,1-0.4, 0.5,1-0, 0.9,1-0.4)
|
|
g.line(0.3,0.5, 0.7,0.5)
|
|
end,
|
|
}
|
|
local gobjs={}
|
|
local cgobjs={}
|
|
local lgobjs={}
|
|
local mgobjs={}
|
|
for k,v in ipairs(colors) do
|
|
gobjs[k]={c=k}
|
|
cgobjs[k]={c=k,super="charge"}
|
|
lgobjs[k]={c=k,super="lines"}
|
|
mgobjs[k]={c=k,super="color"}
|
|
end
|
|
local ltest=os.time()
|
|
debug.sethook(function()
|
|
local lt=os.time()
|
|
if lt-ltest>4 then
|
|
print("!! we are in a freezer !!",debug.traceback())
|
|
ltest=lt
|
|
end
|
|
end,"",1000)
|
|
local cc=3
|
|
local tt=0
|
|
local bat=1
|
|
local batd=bat
|
|
local score=0
|
|
local tochar=0
|
|
local scored=score
|
|
local function znoise(...)
|
|
return love.math.noise(...)*2-1
|
|
end
|
|
local function eudist(x,y)
|
|
return (x*x+y*y)^0.5
|
|
end
|
|
local function norm(x1,y1)
|
|
local d=eudist(x,y)
|
|
if d==0 then return 0,0 end
|
|
return x/d,y/d
|
|
end
|
|
local function dlbolt(x,y,x1,y1)
|
|
|
|
end
|
|
local function drawfig(n,a)
|
|
g.push("all")
|
|
g.scale(2-(a or 1))
|
|
g.translate(-0.5,-0.5)
|
|
g.translate(0.1,0.1)
|
|
g.scale(0.8)
|
|
colors[n.c](a or 1,n.super=="charge" and ((math.sin(tt*math.pi*2)*0.5+0.5)*0.4+0.1) or 0)
|
|
if n.super=="lines" then
|
|
local hps,vps={},{}
|
|
local det=10
|
|
for n=0,det do
|
|
local dmul=(det-math.abs(n-det/2))/det*4
|
|
hps[n*2+1],hps[n*2+2]=n/det,0.5+znoise(tt,583,-775,n)*0.1*dmul
|
|
vps[n*2+1],vps[n*2+2]=0.5+znoise(tt,-492,444,n)*0.1*dmul,n/det
|
|
end
|
|
g.line(hps)
|
|
g.line(vps)
|
|
elseif n.super=="color" then
|
|
local l={}
|
|
local det=100
|
|
for n=0,det do
|
|
l[n*2+1],l[n*2+2]=0.5+znoise(tt,55,51,n*math.pi/det*2),0.5+znoise(tt,44,25,n*math.pi/det*2)
|
|
end
|
|
g.setLineJoin("none")
|
|
g.polygon("line",l)
|
|
end
|
|
g.scale(0.02)
|
|
g.pop()
|
|
end
|
|
|
|
local function pti(x,y)
|
|
return y+(x-1)*bh
|
|
end
|
|
|
|
local trans=love.math.newTransform()
|
|
local anims={}
|
|
local falling={}
|
|
local booms={}
|
|
|
|
local function smtar(x,y,tx,ty)
|
|
local i=pti(x,y)
|
|
local anim
|
|
if not anims[i] then
|
|
if x==tx and y==ty then return end
|
|
anims[i]={
|
|
cx=x,cy=y,
|
|
tx=tx,ty=ty,
|
|
x=x,y=y
|
|
}
|
|
end
|
|
anim=anims[i]
|
|
anim.tx,anim.ty=tx,ty
|
|
end
|
|
|
|
local function setbsize(x,y,w,h)
|
|
trans:reset()
|
|
trans:translate(x,y)
|
|
trans:scale(w/bw,h/bh)
|
|
end
|
|
|
|
local gemrng
|
|
local function randgem()
|
|
tochar=tochar-1
|
|
local objl=gobjs
|
|
if tochar<=0 then
|
|
tochar=gemrng:random((bw*bh)*0.5,(bw*bh)*1.5)
|
|
objl=cgobjs
|
|
end
|
|
return objl[gemrng:random(math.floor(cc))]
|
|
end
|
|
local function nextgem(o)
|
|
local c=o.c%math.floor(cc)+1
|
|
return (o.super and cgobjs or gobjs)[c]
|
|
end
|
|
local function isgem(o)
|
|
return type(o)=="table" and colors[o.c]
|
|
end
|
|
local function eqgem(a,b)
|
|
return isgem(a) and isgem(b) and a.c==b.c
|
|
end
|
|
|
|
local function badboigemcheck(c,am,ac,rm)
|
|
c=isgem(c) and c.c
|
|
if not c then return end
|
|
if ac~=5 and ac~=4 then return end
|
|
local aa={}
|
|
for k,v in pairs(am) do
|
|
local cc=board[v[1]][v[2]]
|
|
if isgem(cc) and (cc.super and cc.super~="charge") then
|
|
return
|
|
end
|
|
aa[#aa+1]=k
|
|
end
|
|
local e=aa[gemrng:random(#aa)]
|
|
local rc=ac==5 and mgobjs[c] or lgobjs[c]
|
|
rm[e][3]=rc
|
|
end
|
|
local function megascan(x,y,c,rm)
|
|
local ogc=c
|
|
rm=rm or {}
|
|
if not isgem(ogc) then return next(rm) and rm end
|
|
if ogc.super~="color" then return next(rm) and rm end
|
|
for x=1,bw do
|
|
for y=1,bh do
|
|
local i=pti(x,y)
|
|
local c=board[x][y]
|
|
if eqgem(c,ogc) then
|
|
rm[i]=rm[i] or {x,y}
|
|
end
|
|
end end
|
|
return next(rm) and rm
|
|
end
|
|
local function check(x,y,rm,oam,obm)
|
|
local c=board[x][y]
|
|
if not c then return rm,oam,obm end
|
|
local ac,bc=1,1
|
|
local am,bm={},{}
|
|
oam,obm=oam or {}, obm or {}
|
|
do
|
|
local i=pti(x,y)
|
|
local v={x,y}
|
|
am[i],bm[i]=v,v
|
|
end
|
|
rm=rm or {}
|
|
for d,v in ipairs{{-1,0},{1,0},{0,-1},{0,1}} do
|
|
local ox,oy=unpack(v)
|
|
local x,y=x+ox,y+oy
|
|
while x>=1 and x<=bw and y>=1 and y<=bh do
|
|
local i=pti(x,y)
|
|
if eqgem(board[x][y],c) then
|
|
if d>2 and not oam[i] then
|
|
ac=ac+1
|
|
am[i]={x,y}
|
|
oam[i]=true
|
|
elseif d<=2 and not obm[i] then
|
|
bc=bc+1
|
|
bm[i]={x,y}
|
|
obm[i]=true
|
|
end
|
|
else
|
|
break
|
|
end
|
|
x,y=x+ox,y+oy
|
|
end
|
|
end
|
|
if ac>=3 then
|
|
for k,v in pairs(am) do rm[k]=v end
|
|
badboigemcheck(c,am,ac,rm)
|
|
end
|
|
if bc>=3 then
|
|
for k,v in pairs(bm) do rm[k]=v end
|
|
badboigemcheck(c,bm,bc,rm)
|
|
end
|
|
return next(rm) and rm,oam,obm
|
|
end
|
|
|
|
local falltest=false
|
|
|
|
local function drawboard(x,y,w,h)
|
|
g.push("all")
|
|
g.applyTransform(trans)
|
|
g.setLineWidth(0.1)
|
|
g.stencil(function()
|
|
g.rectangle("fill",0,0,bw,bh)
|
|
end)
|
|
g.push("all")
|
|
g.translate(0.1,-1-0.05)
|
|
local bat=math.min(batd,1)
|
|
g.setColor((1-bat^2),bat^0.5,math.max(0,batd-1)^0.5)
|
|
g.rectangle("line",0,0,bw/2-0.1,0.8)
|
|
g.rectangle("fill",0.2,0.2,(bw/2-0.5)*bat,0.4)
|
|
g.rectangle("line",bw/2-0.09,0.2,0.2,0.4)
|
|
g.pop()
|
|
g.push("all")
|
|
local sctext=("%.1i"):format(math.floor(scored+.5))
|
|
local xx,yy=trans:transformPoint(0,0)
|
|
local tty=0.8/font:getHeight()
|
|
local ttx=font:getWidth(sctext)*tty
|
|
g.translate(bw-ttx,-1.1)
|
|
g.scale(tty)
|
|
g.setColor(1,1,1)
|
|
g.print(sctext)
|
|
g.pop()
|
|
if not falltest then
|
|
g.setStencilTest("greater",0)
|
|
end
|
|
for x=1,bw do
|
|
for y=1,bh do
|
|
g.push()
|
|
local tx,ty=x,y
|
|
local anim=anims[pti(x,y)]
|
|
if anim then
|
|
tx,ty=anim.cx or x, anim.cy or y
|
|
end
|
|
g.translate(tx-0.5,ty-0.5)
|
|
if isgem(board[x][y]) then
|
|
drawfig(board[x][y])
|
|
end
|
|
g.pop()
|
|
end
|
|
end
|
|
for x,falling in ipairs(falling) do
|
|
for fall,_ in pairs(falling) do
|
|
for i,c in ipairs(fall.figs) do
|
|
g.push("all")
|
|
local tx,ty=fall.x,fall.y-i+1
|
|
g.translate(tx-0.5,ty-0.5)
|
|
if isgem(c) then
|
|
drawfig(c)
|
|
end
|
|
g.pop()
|
|
end
|
|
end
|
|
end
|
|
for v,_ in pairs(booms) do
|
|
g.push("all")
|
|
local tx,ty=v.x,v.y
|
|
g.translate(tx-0.5,ty-0.5)
|
|
drawfig(v.c,v.a)
|
|
g.pop()
|
|
end
|
|
g.setStencilTest()
|
|
g.setColor(0.2,0.2,0.2)
|
|
g.rectangle("line",0,0,bw,bh)
|
|
g.pop()
|
|
end
|
|
local function fall(l)
|
|
local cols={}
|
|
for k,v in pairs(l) do
|
|
local x,y=unpack(v)
|
|
cols[x]=cols[x] or {l={},m={}}
|
|
cols.l[#cols+1]=y
|
|
cols.m[y]=true
|
|
end
|
|
end
|
|
local killall
|
|
|
|
local function kill(x,y,rc)
|
|
if not board[x][y] then print("Whar") return end
|
|
if board[x][y].super=="charge" then
|
|
bat=math.min(2,bat+0.1)
|
|
end
|
|
do
|
|
local tx,ty=x,y
|
|
local anim=anims[pti(x,y)]
|
|
if anim then
|
|
tx,ty=anim.cx,anim.cy
|
|
end
|
|
booms[{
|
|
x=tx,y=ty,
|
|
a=1,c=board[x][y] or mgobjs[4]
|
|
}]=true
|
|
end
|
|
if rc then
|
|
board[x][y]=rc
|
|
return true
|
|
end
|
|
board[x][y]=nil
|
|
local fall={}
|
|
for y=y-1,gem and 1 or (-bh+1),-1 do
|
|
if board[x][y] then
|
|
if not fall.figs then
|
|
fall.x,fall.y=x,y
|
|
fall.figs={}
|
|
fall.vel=0
|
|
falling[x][fall]=true
|
|
end
|
|
fall.figs[#fall.figs+1]=board[x][y]
|
|
board[x][y]=nil
|
|
elseif fall.figs then
|
|
fall={}
|
|
end
|
|
end
|
|
local my,mfall=math.huge
|
|
local unfell={}
|
|
local yls={}
|
|
local cx=x
|
|
for x=1,bw do
|
|
local yl
|
|
for y=bh,0,-1 do
|
|
if not board[x][y] then
|
|
yl=y
|
|
break
|
|
end
|
|
end
|
|
unfell[x]={}
|
|
local tt={}
|
|
for k,v in pairs(falling[x]) do
|
|
tt[#tt+1]=k
|
|
end
|
|
table.sort(tt,function(a,b)
|
|
return a.y>b.y
|
|
end)
|
|
for _,fall in ipairs(tt) do
|
|
if cx==x and fall.y<my then
|
|
my=fall.y
|
|
mfall=fall
|
|
end
|
|
for k,v in ipairs(fall.figs) do
|
|
unfell[x][yl]={board[x][yl]}
|
|
board[x][yl]=v
|
|
yl=yl-1
|
|
end
|
|
end
|
|
yls[x]=yl
|
|
end
|
|
local yl=yls[x]
|
|
if not mfall then
|
|
mfall={x=x,y=0,vel=0,figs={}}
|
|
falling[x][mfall]=true
|
|
end
|
|
local ll=#mfall.figs+1
|
|
mfall.figs[ll]=randgem()
|
|
local aa={}
|
|
unfell[x][yls[x]]=unfell[x][yls[x]] or {board[x][yls[x]]}
|
|
board[x][yls[x]]=mfall.figs[ll]
|
|
local ccc=0
|
|
if love.keyboard.isDown("f6") then
|
|
for x,falling in pairs(falling) do
|
|
for fall,_ in pairs(falling) do
|
|
falling[fall]=nil
|
|
end
|
|
end
|
|
return
|
|
end
|
|
local occ=mfall.figs[ll]
|
|
while check(x,yls[x]) do
|
|
mfall.figs[ll]=nextgem(mfall.figs[ll])
|
|
board[x][yls[x]]=mfall.figs[ll]
|
|
if eqgem(mfall.figs[ll],occ) then break end
|
|
end
|
|
for x,uf in pairs(unfell) do
|
|
for y,v in pairs(uf) do
|
|
board[x][y]=v[1]
|
|
end
|
|
end
|
|
cc=math.min(#colors,cc+((0.1/(bw*bh))/((cc/3)^2)))
|
|
end
|
|
killall=function(kills,b,...)
|
|
if not kills then return end
|
|
if b then
|
|
for k,v in pairs(b) do
|
|
kills[k]=v
|
|
end
|
|
return killall(kills,...)
|
|
end
|
|
local tt={}
|
|
local seen={}
|
|
local news=true
|
|
while news do
|
|
news=false
|
|
local ko
|
|
kills,ko={},kills
|
|
for k,v in pairs(ko) do
|
|
kills[k]=v
|
|
if not seen[k] then
|
|
local x,y=unpack(v)
|
|
local c=board[v[1]][v[2]]
|
|
seen[k]=true
|
|
if isgem(c) and c.super=="lines" then
|
|
for x=1,bw do
|
|
local i=pti(x,y)
|
|
if board[x][y] and not kills[i] then
|
|
news=true
|
|
kills[i]={x,y}
|
|
end
|
|
end
|
|
for y=1,bh do
|
|
local i=pti(x,y)
|
|
if board[x][y] and not kills[i] then
|
|
news=true
|
|
kills[i]={x,y}
|
|
end
|
|
end
|
|
end
|
|
if isgem(c) then
|
|
local mks={}
|
|
megascan(x,y,c,mks)
|
|
for k,v in pairs(mks) do
|
|
if not kills[k] then
|
|
kills[k]=v
|
|
news=true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for k,v in pairs(kills) do
|
|
tt[#tt+1]=v
|
|
end
|
|
table.sort(tt,function(a,b)
|
|
return b[2]>a[2] or b[1]>b[1]
|
|
end)
|
|
local checks={}
|
|
for k,v in ipairs(tt) do
|
|
local a=kill(unpack(v))
|
|
if a then
|
|
checks[k]=v
|
|
end
|
|
end
|
|
local rm,oam,obm={},{},{}
|
|
for k,v in pairs(checks) do
|
|
local x,y=unpack(v)
|
|
check(x,y,rm,oam,obm)
|
|
end
|
|
if next(rm) then
|
|
killall(rm)
|
|
end
|
|
score=score+#tt
|
|
end
|
|
|
|
local function dropall(off,die)
|
|
for x=1,bw do
|
|
falling[x]=falling[x] or {}
|
|
local fall={
|
|
x=x,y=bh+(off or 0),
|
|
vel=0,
|
|
figs={}
|
|
}
|
|
falling[x][fall]=true
|
|
for y=bh,1,-1 do
|
|
fall.figs[#fall.figs+1]=board[x][y]
|
|
board[x][y]=nil
|
|
end
|
|
end
|
|
if die then
|
|
for x,falling in pairs(falling) do
|
|
for fall,_ in pairs(falling) do
|
|
fall.die=true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function fillboard()
|
|
for x=1,bw do
|
|
board[x]={}
|
|
for y=1,bh do
|
|
local a=randgem()
|
|
board[x][y]=a
|
|
end
|
|
end
|
|
for n=1,math.huge do
|
|
local good=true
|
|
local rm={}
|
|
local kills
|
|
for x=1,bw do
|
|
for y=1,bh do
|
|
kills=check(x,y,rm) or kills
|
|
end
|
|
end
|
|
if not next(rm) then break end
|
|
for k,v in pairs(rm) do
|
|
local x,y=unpack(v)
|
|
board[x][y]=randgem()
|
|
end
|
|
end
|
|
dropall(-bh)
|
|
end
|
|
local function resboard()
|
|
cc=3
|
|
score=0
|
|
bat=1
|
|
gemrng=love.math.newRandomGenerator(991)
|
|
tochar=bw*bh+gemrng:random(bw)
|
|
fillboard()
|
|
end
|
|
local dbg=false
|
|
local playdbg=false
|
|
|
|
function love.load()
|
|
resboard()
|
|
end
|
|
|
|
local grabbed=nil
|
|
local dying=false
|
|
local running=false
|
|
|
|
function love.mousepressed(x,y,b)
|
|
x,y=trans:inverseTransformPoint(x,y)
|
|
x,y=x+1-0.5,y+1-0.5
|
|
local ix,iy=math.floor(x+.5),math.floor(y+.5)
|
|
if b==2 and dbg then
|
|
for ix=ix-50,iy+50 do
|
|
for iy=iy-50,iy+50 do
|
|
if board[ix] and board[ix][iy] and math.random()>0.1 then
|
|
kill(ix,iy)
|
|
end
|
|
end end
|
|
end
|
|
if b~=1 then return end
|
|
running=true
|
|
if ix<1 or ix>bw or
|
|
iy<1 or iy>bh
|
|
then
|
|
return
|
|
end
|
|
if grabbed then
|
|
return
|
|
end
|
|
grabbed={
|
|
ix,iy,
|
|
ix-x,iy-y,
|
|
}
|
|
end
|
|
|
|
function love.mousereleased(x,y,b)
|
|
if b~=1 then return end
|
|
if grabbed then
|
|
local ix,iy,ox,oy,px,py=unpack(grabbed)
|
|
if ix and px and (ix~=px or iy~=py) then
|
|
board[ix][iy],board[px][py]=
|
|
board[px][py],board[ix][iy]
|
|
local kills=check(ix,iy,check(px,py))
|
|
if kills and board[ix][iy] and board[px][py] then
|
|
megascan(ix,iy,board[ix][iy],megascan(px,py,board[px][py],kills))
|
|
local ii,pi=pti(ix,iy),pti(px,py)
|
|
local ania,anib=anims[ii],anims[pi]
|
|
anims[ii],anims[pi]=anib,ania
|
|
ania=ania or {x=ix,y=iy}
|
|
anib=anib or {x=px,y=py}
|
|
ania.x,anib.x=anib.x,ania.x
|
|
ania.y,anib.y=anib.y,ania.y
|
|
grabbed=nil
|
|
killall(kills)
|
|
return
|
|
else
|
|
board[ix][iy],board[px][py]=
|
|
board[px][py],board[ix][iy]
|
|
end
|
|
end
|
|
grabbed=nil
|
|
smtar(ix,iy,ix,iy)
|
|
if px then
|
|
smtar(px,py,px,py)
|
|
end
|
|
return
|
|
end
|
|
end
|
|
|
|
local gacc=50
|
|
|
|
-- i forgor how intersections work so here's a thingy to figure it out
|
|
-- A1-----A2
|
|
-- B1-----B2
|
|
--
|
|
-- B1-----B2
|
|
-- A1-----A2
|
|
|
|
local function inters(a1,a2,b1,b2)
|
|
return
|
|
(a1<=b1 and a2>=b1)
|
|
or (b1<=a1 and b2>=a1)
|
|
end
|
|
|
|
local function negdiff(a,b)
|
|
return math.abs(a-b)<0.01
|
|
end
|
|
|
|
local function sign(a)
|
|
return a>0 and 1 or (a<0 and -1 or 0)
|
|
end
|
|
|
|
local function interp(a,b,dt)
|
|
return a+sign(b-a)*math.min((b-a)*sign(b-a),math.max(dt,(b-a)*sign(b-a)*math.max(dt,0.01)*10))
|
|
end
|
|
|
|
local animc=0
|
|
local entc=0
|
|
local boomc=0
|
|
local slow=1
|
|
local accumdt=0
|
|
local tps=120
|
|
local speeds={1,0.05,10}
|
|
local plchint=1
|
|
local toplchi=plchint
|
|
|
|
function love.mousemoved()
|
|
if grabbed then
|
|
local x,y,ox,oy,px,py=unpack(grabbed)
|
|
local mx,my=love.mouse.getPosition()
|
|
mx,my=trans:inverseTransformPoint(mx,my)
|
|
mx,my=mx+1-0.5+ox,my+1-0.5+oy
|
|
mx,my=math.floor(mx+.5),math.floor(my+.5)
|
|
if math.abs(x-mx)>math.abs(y-my) then
|
|
mx,my=math.min(bw,math.max(1,x+sign(mx-x))),y
|
|
elseif math.abs(y-my)>0 then
|
|
my,mx=math.min(bh,math.max(1,y+sign(my-y))),x
|
|
end
|
|
if px then
|
|
smtar(px,py,px,py)
|
|
end
|
|
grabbed[5],grabbed[6]=mx,my
|
|
if not board[x][y] then
|
|
elseif board[mx][my] then
|
|
smtar(mx,my,x,y)
|
|
smtar(x,y,mx,my)
|
|
end
|
|
end
|
|
end
|
|
|
|
function love.update(dt)
|
|
ltest=os.time()
|
|
dt=math.min(dt,0.2)*(speeds[slow])
|
|
accumdt=math.min(1,accumdt+dt)
|
|
local fcc=0
|
|
while accumdt>1/tps do
|
|
fcc=fcc+1
|
|
local dt=1/tps
|
|
accumdt=accumdt-dt
|
|
if fcc>10 then return end
|
|
if running and playdbg then
|
|
local gc=0
|
|
local tc=0
|
|
for x=1,bw do
|
|
for y=1,bh do
|
|
gc=gc+(board[x][y] and 1 or 0)
|
|
tc=tc+1
|
|
end end
|
|
if gc/tc>0.8 then
|
|
local goods={}
|
|
for _=1,1000 do
|
|
local ix,iy=math.random(1,bw),math.random(1,bh)
|
|
local px,py=0,0
|
|
while px<1 or py<1 or px>bw or py>bh do
|
|
local ox,oy=unpack(({{1,0},{-1,0},{0,1},{0,-1}})[math.random(1,4)])
|
|
px,py=ix+ox,iy+oy
|
|
end
|
|
board[ix][iy],board[px][py]=
|
|
board[px][py],board[ix][iy]
|
|
local kills=check(ix,iy,check(px,py))
|
|
local kc=0
|
|
for k,v in pairs(kills or {}) do
|
|
if v[3] and v[3].super=="color" then
|
|
kc=kc+50
|
|
elseif v[3] then
|
|
kc=kc+20
|
|
end
|
|
kc=kc+1
|
|
end
|
|
if kills and board[ix][iy] and board[px][py] then
|
|
goods[#goods+1]={ix,iy,px,py,kills,kc}
|
|
end
|
|
board[ix][iy],board[px][py]=
|
|
board[px][py],board[ix][iy]
|
|
end
|
|
table.sort(goods,function(a,b)
|
|
return a[6]>b[6]
|
|
end)
|
|
if #goods>0 then
|
|
local ix,iy,px,py,kills=unpack(goods[1])
|
|
board[ix][iy],board[px][py]=
|
|
board[px][py],board[ix][iy]
|
|
megascan(ix,iy,board[ix][iy],megascan(px,py,board[px][py],kills))
|
|
killall(kills)
|
|
end
|
|
end
|
|
end
|
|
if running then
|
|
bat=math.max(0,bat-dt*0.015*(math.max(bat,0.0625)^0.5))
|
|
batd=interp(batd,bat,dt)
|
|
scored=interp(scored,score,dt)
|
|
end
|
|
if bat==0 and not dying then
|
|
dying=true
|
|
dropall(0,true)
|
|
end
|
|
animc=0
|
|
entc=0
|
|
boomc=0
|
|
for k,v in pairs(anims) do
|
|
animc=animc+1
|
|
v.cx=interp(v.cx,v.tx,dt*2)
|
|
v.cy=interp(v.cy,v.ty,dt*2)
|
|
if negdiff(v.cx,v.x) and negdiff(v.cy,v.y) then
|
|
anims[k]=nil
|
|
end
|
|
end
|
|
local tk={}
|
|
if running then
|
|
for x,falling in ipairs(falling) do
|
|
for fall,_ in pairs(falling) do
|
|
entc=entc+1
|
|
fall.vel=fall.vel+dt*gacc
|
|
fall.y=fall.y+fall.vel*dt
|
|
local iy=math.floor(fall.y)
|
|
for fallb,_ in pairs(falling) do
|
|
if fall~=fallb and inters(
|
|
fall.y-#fall.figs+1-0.5,fall.y+0.5,
|
|
fallb.y-#fallb.figs+1-0.5,fallb.y+0.5
|
|
) and fall.die==fallb.die then
|
|
local wa,wb=#fall.figs,#fallb.figs
|
|
fall.vel=(fall.vel*wa+fallb.vel*wb)/(wa+wb)
|
|
if fallb.y<fall.y then
|
|
local ff=#fall.figs
|
|
for i,fig in ipairs(fallb.figs) do
|
|
fall.figs[ff+i]=fig
|
|
end
|
|
else
|
|
local tt={}
|
|
for i,fig in ipairs(fall.figs) do
|
|
tt[i]=fig
|
|
end
|
|
for i,fig in ipairs(fallb.figs) do
|
|
fall.figs[i]=fig
|
|
end
|
|
local ff=#fallb.figs
|
|
for i,fig in ipairs(tt) do
|
|
fall.figs[ff+i]=fig
|
|
end
|
|
fall.y=fallb.y
|
|
end
|
|
falling[fallb]=nil
|
|
end
|
|
end
|
|
if board[x][iy+1] or (not fall.die and {iy>=bh} or {iy>=bh+#fall.figs})[1] then
|
|
falling[fall]=nil
|
|
if not fall.die then
|
|
local off=math.min(iy,bh)
|
|
for i,fig in ipairs(fall.figs) do
|
|
while board[x][off] do
|
|
off=off-1
|
|
end
|
|
if off<=bh and off>=1 then
|
|
board[x][off]=fig
|
|
end
|
|
off=off-1
|
|
end
|
|
for i=off+1,off+#fall.figs do
|
|
tk[#tk+1]={x,i}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if entc==0 and dying then
|
|
dying=false
|
|
running=false
|
|
resboard()
|
|
end
|
|
if entc==0 and running then
|
|
toplchi=toplchi-dt
|
|
if toplchi<0 then
|
|
toplchi=toplchi+plchint
|
|
local good=false
|
|
for ix=1,bw do
|
|
for iy=1,bh do
|
|
for _,a in pairs{{1,0},{-1,0},{0,1},{0,-1}} do
|
|
local px,py=ix+a[1],iy+a[2]
|
|
if px>=1 and py>=1 and px<=bw and py<=bh then
|
|
board[ix][iy],board[px][py]=
|
|
board[px][py],board[ix][iy]
|
|
good=good or check(ix,iy,check(px,py))
|
|
board[ix][iy],board[px][py]=
|
|
board[px][py],board[ix][iy]
|
|
end
|
|
end end end
|
|
if not good then dropall(0,true)fillboard() end
|
|
end
|
|
else
|
|
toplchi=plchint
|
|
end
|
|
local oam,obm,rm={},{},{}
|
|
local tt=os.clock()
|
|
local itc=0
|
|
for k,v in pairs(tk) do
|
|
itc=itc+1
|
|
if os.clock()-tt>2 then error("too long "..itc.."; #"..#tk) end
|
|
local x,y=unpack(v)
|
|
check(x,y,rm,oam,obm)
|
|
end
|
|
killall(rm)
|
|
for v,_ in pairs(booms) do
|
|
boomc=boomc+1
|
|
v.a=v.a-dt/math.abs(v.a)*4
|
|
if v.a<=0.01 then
|
|
booms[v]=nil
|
|
end
|
|
end
|
|
tt=tt+dt
|
|
end
|
|
end
|
|
|
|
local yes=true
|
|
|
|
function love.keypressed(k)
|
|
local x,y=love.mouse.getPosition()
|
|
x,y=trans:inverseTransformPoint(x,y)
|
|
x,y=math.floor(x)+1,math.floor(y)+1
|
|
x=math.max(1,math.min(bw,x))
|
|
y=math.max(1,math.min(bh,y))
|
|
if dbg and tonumber(k) then
|
|
print(gobjs[tonumber(k)],tonumber(k))
|
|
board[x][y]=gobjs[tonumber(k)] or board[x][y]
|
|
end
|
|
if dbg and isgem(board[x][y]) then
|
|
local c=board[x][y].c
|
|
if k=="h" then
|
|
board[x][y]=cgobjs[c]
|
|
elseif k=="j" then
|
|
board[x][y]=lgobjs[c]
|
|
elseif k=="k" then
|
|
board[x][y]=mgobjs[c]
|
|
end
|
|
end
|
|
if k=="f2" then
|
|
yes=not yes
|
|
elseif k=="f3" then
|
|
dbg=not dbg
|
|
elseif k=="f4" then
|
|
local unfell={}
|
|
local yls={}
|
|
local cx=x
|
|
for x=1,bw do
|
|
local yl
|
|
for y=bh,0,-1 do
|
|
if not board[x][y] then
|
|
yl=y
|
|
break
|
|
end
|
|
end
|
|
unfell[x]={}
|
|
local tt={}
|
|
for k,v in pairs(falling[x]) do
|
|
tt[#tt+1]=k
|
|
end
|
|
table.sort(tt,function(a,b)
|
|
return a.y>b.y
|
|
end)
|
|
for _,fall in ipairs(tt) do
|
|
falling[x][fall]=nil
|
|
for k,v in ipairs(fall.figs) do
|
|
unfell[x][yl]={board[x][yl]}
|
|
board[x][yl]=v
|
|
yl=yl-1
|
|
end
|
|
end
|
|
yls[x]=yl
|
|
end
|
|
elseif k=="f5" then
|
|
slow=slow%3+1
|
|
elseif k=="f7" then
|
|
falltest=not falltest
|
|
elseif k=="f8" then
|
|
bat=bat*0.25
|
|
elseif k=="f9" then
|
|
bat=bat*2
|
|
elseif k=="f10" then
|
|
playdbg=not playdbg
|
|
end
|
|
end
|
|
|
|
function love.draw()
|
|
if dbg then
|
|
g.push("all")
|
|
g.scale(2,2)
|
|
love.graphics.print(("FPS: %i; dt: %.2f; speed: %f; anims: %i; fallings: %i; booms: %i"):format(
|
|
love.timer.getFPS(),
|
|
math.floor(love.timer.getDelta()*100000)/100,
|
|
speeds[slow],
|
|
animc, entc, boomc
|
|
))
|
|
g.pop()
|
|
end
|
|
local sw,sh=g.getDimensions()
|
|
local ww=math.min(sw,sh)
|
|
local y
|
|
if falltest then
|
|
ww=math.min(sw,sh)*0.5
|
|
y=(sh)/2
|
|
end
|
|
local x,y=(sw-ww)/2,y or (sh-ww)/2
|
|
setbsize(x+ww*0.1,y+ww*0.1+ww/bh*0.2,ww*0.8,ww*0.8)
|
|
if yes then
|
|
drawboard()
|
|
end
|
|
end
|