Simplify pinch detector

This commit is contained in:
Pyrex 2023-01-02 20:43:59 -08:00
parent 3911ae6eee
commit 9960aafd71

View File

@ -129,11 +129,12 @@ end
function _rast(
xs,ys,x0,y0,x1,y1
xys,x0,y0,x1,y1
)
local function _add()
local n=#xs
if (n==0 or xs[n]!=x0 or ys[n]!=y0) add(xs,x0) add(ys,y0)
local n=#xys
local xy0={x0,y0}
if (n==0 or not _anch_eq(xys[n],xy0)) add(xys,xy0)
end
local dx,dy=abs(x1-x0),abs(y1-y0)
@ -432,10 +433,10 @@ function level:recollide_reanchor()
local mx1,my1=mx0+dx,my0+dy
if (
self:mcoll(mx0,my0) and not self:get_crate(mx0,my0) and
not self:mcoll(mx0,my1) and
not self:mcoll(mx1,my0) and
not self:mcoll(mx1,my1)
self:mcoll{mx0,my0} and not self:get_crate(mx0,my0) and
not self:mcoll{mx0,my1} and
not self:mcoll{mx1,my0} and
not self:mcoll{mx1,my1}
) then
local key=_mix{"GEOM",mx0,my0,dx,dy}
anch_new[key]= {
@ -543,7 +544,8 @@ function level:spawn_exit()
assert(spawned)
end
function level:mcoll(mx,my)
function level:mcoll(mxy)
local mx,my=unpack(mxy)
if ((mx | my) & 0xFFF0!=0) return true
return self._coll[_mix{mx,my}]
end
@ -628,7 +630,7 @@ function level:can_move(
if (is_player and self:win_at(mx1,my1)) return true
if (is_player and self:get_open_pit(mx1,my1)) return wrongbleep:adequately_warned()
if (self:mcoll(mx1,my1) or player.x==mx1 and player.y==my1) return
if (self:mcoll{mx1,my1} or player.x==mx1 and player.y==my1) return
if player.rope then
local w,h=1.2,0.2
@ -748,7 +750,7 @@ function player:update()
local dx,dy=self.orientx,self.orienty
if (dy!=0) dx=0
while not level:mcoll(x,y) do x+=dx y+=dy end
while not level:mcoll{x,y} do x+=dx y+=dy end
self.rope=rope:new(
{x+0.5-dx*0.5,y+0.5-dy*0.5},
@ -1131,60 +1133,43 @@ function rope:_check_pinch()
local n0=self.src
local qxs,qys={},{}
local qxys={}
while true do
local n1=n0.next
if (not n1) break
local n0ax,n0ay=_anch_unpack(n0)
local n1ax,n1ay=_anch_unpack(n1)
_rast(qxs,qys,flr(n0ax*2),flr(n0ay*2),flr(n1ax*2),flr(n1ay*2))
_rast(qxys,n0ax\0.5,n0ay\0.5,n1ax\0.5,n1ay\0.5)
n0=n1
end
local function _possible_tiles(qx,qy)
local mx0=(qx-1)\2
local mx1=qx\2
local my0=(qy-1)\2
local my1=qy\2
local function _possible_tiles(t)
local qx,qy=unpack(qxys[t])
local poss={}
for mx=mx0,mx1 do
for my=my0,my1 do
add(poss,{mx=mx,my=my})
for mx=(qx-1)\2,qx\2 do
for my=(qy-1)\2,qy\2 do
if (not level:mcoll{mx,my}) add(poss,{mx,my})
end
end
return poss
end
local function _blocked(qx,qy)
for i in all(_possible_tiles(qx,qy)) do
if (not level:mcoll(i.mx,i.my)) return
end
return true
return all(poss)
end
-- find cases where i move through an impassable zone
for i=1,#qxs do
if (_blocked(qxs[i],qys[i])) return
for i=1,#qxys do
if (not _possible_tiles(i)()) return
end
-- find cases where i am cut off diagonally
for i=3,#qxs do
local qx1,qy1=qxs[i-1],qys[i-1]
if qx1%2==0 and qy1%2==0 then
for i=3,#qxys do
local qx1,qy1=unpack(qxys[i-1])
if (qx1|qy1)&1==0 then
local ok
for m0 in all(_possible_tiles(qxs[i-2],qys[i-2])) do
for m2 in all(_possible_tiles(qxs[i],qys[i])) do
local mx0,my0=m0.mx,m0.my
local mx2,my2=m2.mx,m2.my
if not (level:mcoll(mx0,my0) or level:mcoll(mx2,my2)) then
local dmx,dmy=abs(mx2-mx0),abs(my2-my0)
if dmx==1 and dmy==1 and level:mcoll(mx0,my2) and level:mcoll(mx2,my0) then
else
ok=true
end
end
for m0 in _possible_tiles(i-2) do
for m2 in _possible_tiles(i) do
local mx0,my0=unpack(m0)
local mx2,my2=unpack(m2)
if (mx0==mx2 or my0==my2 or not level:mcoll{mx0,my2} or not level:mcoll{mx2,my0}) ok=true
end
end
@ -1631,7 +1616,7 @@ function rope:_calc_push(
local ops2,blocked={},{}
for o in all(ops) do
local mx,my=unpack(o)
if level:mcoll(mx,my) then
if level:mcoll{mx,my} then
if (not level:get_crate(mx, my)) break
if not level:can_move(false,o,0,0) then
add(blocked,o)