Rewrite rope #11

Merged
pyrex merged 12 commits from rewrite_rope into main 2022-12-21 05:44:16 +00:00
Showing only changes of commit 535fcf7601 - Show all commits

View File

@ -7,10 +7,6 @@ real_modules={}
frame=0 frame=0
function _init() function _init()
-- cls(0)
-- for i in _stepfrom(0.5,-2.5) do print(i) end
-- assert(false)
_doall("init") end _doall("init") end
function _update() function _update()
frame+=1 frame+=1
@ -97,13 +93,13 @@ function _apply(x,ts,a)
local t=deli(ts,1) local t=deli(ts,1)
for k,v in pairs(t) do for k,v in pairs(t) do
if k=="update" then if k=="update" then
if not v(x,a) then --
add(ts,t,1)
end
else else
x[k]=v x[k]=v
end end
end end
if (t and t.update and not t.update(x,a)) add(ts,t,1)
end end
function sgn0(x) function sgn0(x)
@ -401,28 +397,16 @@ end
function level:recollide() function level:recollide()
self._coll={} self._coll={}
self._coll_nocrate={}
for mx=0,15 do for mx=0,15 do
for my=0,15 do for my=0,15 do
local mxy=_mix(mx,my) local mxy=_mix(mx,my)
self._coll_nocrate[mxy]=
fget(self:_mget(mx,my),7)
self._coll[mxy]= self._coll[mxy]=
self._coll_nocrate[mxy] or fget(self:_mget(mx,my),7) or
self._crates[mxy]!=nil self._crates[mxy]!=nil
end end
end end
end end
function add_adjacent_anchors(tbl,mx,my)
for ax in all{mx*2-1,mx*2+2} do
for ay in all{my*2-1,my*2+2} do
local px,py=level:a2p(ax,ay)
tbl[_amix(ax,ay)]={ax=ax0,ay=ay0,x=px,y=py}
end
end
end
function level:reanchor() function level:reanchor()
local anch_new={} local anch_new={}
for dxy in all{{-1,-1},{1,-1},{-1,1},{1,1}} do for dxy in all{{-1,-1},{1,-1},{-1,1},{1,1}} do
@ -433,7 +417,7 @@ function level:reanchor()
local mx1,my1=mx0+dx,my0+dy local mx1,my1=mx0+dx,my0+dy
if ( if (
self:mcoll_nocrate(mx0,my0) and self:mcoll(mx0,my0) and not self:get_crate(mx0,my0) and
not self:mcoll(mx0,my1) and not self:mcoll(mx0,my1) and
not self:mcoll(mx1,my0) and not self:mcoll(mx1,my0) and
not self:mcoll(mx1,my1) not self:mcoll(mx1,my1)
@ -497,12 +481,6 @@ function level:get_open_pit(mx,my)
if (pit and pit.contents==nil) return pit if (pit and pit.contents==nil) return pit
end end
function level:point_anchor(px,py)
local ax,ay=self:p2a(px,py)
local anc=self._anch[_amix(ax,ay)]
return anc
end
function level:spawn_exit() function level:spawn_exit()
self._wins={} self._wins={}
local spawned=false local spawned=false
@ -516,9 +494,11 @@ function level:spawn_exit()
end end
local win_at=function(x,y) local win_at=function(x,y)
if (self:_mget(x,y)!=18) return if (self:_mget(x,y)!=18) return
for n in all(neighbors{x=x,y=y}) do for nx=x-1,x+1 do
if n.x<0 or n.y<0 or n.x>15 or n.y>15 then for ny=y-1,y+1 do
self._wins[_mix(n.x,n.y)]=true if nx<0 or ny<0 or nx>15 or ny>15 then
self._wins[_mix(nx,ny)]=true
end
end end
end end
end end
@ -529,22 +509,9 @@ function level:spawn_exit()
assert(spawned) assert(spawned)
end end
function level:p2a(px,py)
return px\4,py\4
end
function level:a2p(ax,ay)
local px=ax*4+3*(ax%2)
local py=ay*4+3*(ay%2)
return px,py
end
function level:mcoll(mx,my) function level:mcoll(mx,my)
return self._coll[_mix(mx,my)]!=false return self._coll[_mix(mx,my)]!=false
end end
function level:mcoll_nocrate(mx,my)
return self._coll_nocrate[_mix(mx,my)]!=false
end
function level:pcoll(px,py) function level:pcoll(px,py)
return self:mcoll(px\8,py\8) return self:mcoll(px\8,py\8)
@ -671,20 +638,16 @@ function level:tug_crate(mx0,my0,dmx,dmy)
local mx1,my1=mx0+dmx,my0+dmy local mx1,my1=mx0+dmx,my0+dmy
local mxy1=_mix(mx1,my1) local mxy1=_mix(mx1,my1)
existing.mx=mx1
existing.my=my1
existing.todo={ existing.todo={
{px=mx0*8+dmx*2,py=my0*8+dmy*2}, {px=mx1*8+dmx,py=my1*8+dmy,mx=mx1,my=my1,update=function()
{px=mx0*8+dmx*7,py=my0*8+dmy*7}, self:recollide()
{px=mx1*8,py=my1*8,update=function() self:reanchor()
self:reanchor(true)
return true return true
end} end},
{px=mx1*8,py=my1*8}
} }
self._crates[mxy1]=existing self._crates[mxy1]=existing
self:recollide()
self:reanchor(false)
end end
-->8 -->8
@ -955,8 +918,8 @@ function rope:update()
self.latch.rec!=nil self.latch.rec!=nil
then then
self:drag_src( self:drag_src(
self.latch.rec.px/8+0.5+self.latch.ax_offset, self.latch.rec.mx+0.5+self.latch.ax_offset,
self.latch.rec.py/8+0.5+self.latch.ay_offset self.latch.rec.my+0.5+self.latch.ay_offset
) )
if #self.latch.rec.todo==0 then if #self.latch.rec.todo==0 then
@ -1023,28 +986,34 @@ function rope:draw(artificial_dx,artificial_dy)
end end
-- draw latch -- draw latch
if self.latch!=nil and perc_to_show>=1.0 then if self.latch!=nil and self.latch.rec and perc_to_show>=1.0 then
local x,y=points[1].x,points[1].y local x,y=self.latch.rec.px,self.latch.rec.py
local ldx,ldy=self.latch.dx,self.latch.dy local ldx,ldy=self.latch.dx,self.latch.dy
local color=8 local color=8
if (highlight==0) color=12 if (highlight==0) color=12
if self.latch.dx==-1 and self.latch.dy==0 then if self.latch.dx==-1 and self.latch.dy==0 then
rectfill(x+1,y-1,x+3,y,color) rectfill(x,y+3,x+2,y+4,color)
elseif self.latch.dx==1 and self.latch.dy==0 then elseif self.latch.dx==1 and self.latch.dy==0 then
rectfill(x-1,y-1,x-3,y,color) rectfill(x+5,y+3,x+7,y+4,color)
elseif self.latch.dx==0 and self.latch.dy==-1 then elseif self.latch.dx==0 and self.latch.dy==-1 then
rectfill(x,y+1,x-1,y+3,color) rectfill(x+3,y,x+4,y+2,color)
elseif self.latch.dx==0 and self.latch.dy==1 then elseif self.latch.dx==0 and self.latch.dy==1 then
rectfill(x,y-1,x-1,y-3,color) rectfill(x+3,y+5,x+4,y+7,color)
end end
end end
local n1=self.src
-- debug
--[[ --[[
local n1=self.src
local sy=0 local sy=0
while true do while true do
if (n1==nil) break if (n1==nil) break
local x=n1.ax*8 local x=n1.ax*8
local y=n1.ay*8 local y=n1.ay*8
if n1.associated_with then
if (n1.associated_with.adx>0) x-=1
if (n1.associated_with.ady>0) y-=1
end
rectfill(x-1,y-1,x+1,y+1,12) rectfill(x-1,y-1,x+1,y+1,12)
print("ax="..n1.ax..",ay="..n1.ay,0,sy) print("ax="..n1.ax..",ay="..n1.ay,0,sy)
sy+=7 sy+=7
@ -1074,11 +1043,14 @@ function rope:draw(artificial_dx,artificial_dy)
end end
for _,p in pairs(level._anch) do for _,p in pairs(level._anch) do
pset(p.ax*8,p.ay*8,11) local x,y=p.ax*8,p.ay*8
pset(p.ax*8+p.adx,p.ay*8,11) if (p.adx>0) x-=1
pset(p.ax*8,p.ay*8+p.ady,11) if (p.ady>0) y-=1
pset(x,y,11)
pset(x+p.adx,y,11)
pset(x,y+p.ady,11)
end end
]]-- ]]
end end
function rope:drag_dst(x,y) function rope:drag_dst(x,y)
@ -1125,7 +1097,7 @@ function rope:relax()
local would,x1_new,y1_new=would_stick(x0,y0,n1.associated_with,x2,y2) local would,x1_new,y1_new=would_stick(x0,y0,n1.associated_with,x2,y2)
if not would and not (n1.ax==x1_new and n1.ay==y1_new) then if not would and not (n1.ax==x1_new and n1.ay==y1_new) then
printh("relaxing: "..tostring(n0.associated_with).."->"..tostring(n1.associated_with).."->"..tostring(n2.associated_with)) --printh("relaxing: "..tostring(n0.associated_with).."->"..tostring(n1.associated_with).."->"..tostring(n2.associated_with))
self:_drag(n1,x1_new,y1_new) self:_drag(n1,x1_new,y1_new)
n0=n1.prev n0=n1.prev
n2=n1.next n2=n1.next
@ -1133,7 +1105,6 @@ function rope:relax()
n2.prev=n0 n2.prev=n0
n1.next=nil n1.next=nil
n1.prev=nil n1.prev=nil
--n0=n0.next
else n0=n0.next end else n0=n0.next end
else n0=n0.next end else n0=n0.next end
end end
@ -1143,7 +1114,6 @@ function rope:_check_sane()
if (self.state.name!="latched") return true if (self.state.name!="latched") return true
if (level:busy()) return true if (level:busy()) return true
printh("start")
local n0=self.src local n0=self.src
local qxs,qys={},{} local qxs,qys={},{}
@ -1152,32 +1122,62 @@ function rope:_check_sane()
if (n1==nil) break if (n1==nil) break
for qx,qy in _rast(flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2)) do for qx,qy in _rast(flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2)) do
if not (qx==qxs[#qxs] and qy==qys[#qys]) then
add(qxs,qx) add(qxs,qx)
add(qys,qy) add(qys,qy)
end end
end
n0=n1 n0=n1
end end
local function _blocked(qx,qy) local function _possible_tiles(qx,qy)
local mx0=(qx-1)\2 local mx0=(qx-1)\2
local mx1=qx\2 local mx1=qx\2
local my0=(qy-1)\2 local my0=(qy-1)\2
local my1=qy\2 local my1=qy\2
return level:mcoll(mx0,my0) and level:mcoll(mx1,my1) local poss={}
for mx=mx0,mx1 do
for my=my0,my1 do
add(poss,{mx=mx,my=my})
end end
for i=1,#qxs do end
if (_blocked(qxs[i],qys[i])) printh("blocked"..qxs[i]..","..qys[i]) return false 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 false
end
return true
end end
-- find cases where i move through an impassable zone
for i=1,#qxs do
if (_blocked(qxs[i],qys[i])) return false
end
-- find cases where i am cut off diagonally
for i=3,#qxs do for i=3,#qxs do
local qx1,qy1=qxs[i-1],qys[i-1] local qx1,qy1=qxs[i-1],qys[i-1]
if qx1%2==0 and qy1%2==0 then if qx1%2==0 and qy1%2==0 then
local qx0,qy0=qxs[i-2],qys[i-2] local ok=false
local qx2,qy2=qxs[i],qys[i] for m0 in all(_possible_tiles(qxs[i-2],qys[i-2])) do
local mx0,my0=qx0\2,qy0\2 for m2 in all(_possible_tiles(qxs[i],qys[i])) do
local mx2,my2=qx2\2,qy2\2 local mx0,my0=m0.mx,m0.my
if (level:mcoll(mx0,my2) and level:mcoll(mx2,my0)) printh("not traversable") return false 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
--printh("ok! "..tostring({qxs[i-2],qys[i-2]})..tostring({qxs[i],qys[i]})..tostring(m0)..tostring(m2))
ok=true
end
end
end
end
if (not ok) return false
end end
end end
return true return true
@ -1213,8 +1213,6 @@ function would_stick(x0,y0,anchor,x2,y2)
return not wouldnt,x1_new,y1_new,adx,ady return not wouldnt,x1_new,y1_new,adx,ady
end end
-- TODO: Upon adding a point, start from there to see if we need another
-- rather than adding at most one
function rope:_drag(n1,ax1_new,ay1_new) function rope:_drag(n1,ax1_new,ay1_new)
local function _sweep_radar(ax_pivot,ay_pivot,ax_far0,ay_far0,ax_far1,ay_far1) local function _sweep_radar(ax_pivot,ay_pivot,ax_far0,ay_far0,ax_far1,ay_far1)
if (ax_far0==ax_far1 and ay_far0==ay_far1) return nil if (ax_far0==ax_far1 and ay_far0==ay_far1) return nil
@ -1268,8 +1266,6 @@ function rope:_drag(n1,ax1_new,ay1_new)
end end
ax_far_old=ax_far_new ax_far_old=ax_far_new
end end
else
assert(false, "wtf?")
end end
end end
@ -1283,7 +1279,7 @@ function rope:_drag(n1,ax1_new,ay1_new)
local anch=_sweep_radar(n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new) local anch=_sweep_radar(n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new)
if (anch==nil) break if (anch==nil) break
local n05={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n0,next=n1} local n05={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n0,next=n1}
printh("creating post: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with)) --printh("creating post: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with))
n0.next=n05 n0.next=n05
n1.prev=n05 n1.prev=n05
n0=n05 n0=n05
@ -1295,7 +1291,7 @@ function rope:_drag(n1,ax1_new,ay1_new)
local anch=_sweep_radar(n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new) local anch=_sweep_radar(n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new)
if (anch==nil) break if (anch==nil) break
local n15={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n1,next=n2} local n15={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n1,next=n2}
printh("creating post: "..tostring(n1.associated_with).."->"..tostring(n15.associated_with).."->"..tostring(n2.associated_with)) --printh("creating post: "..tostring(n1.associated_with).."->"..tostring(n15.associated_with).."->"..tostring(n2.associated_with))
n1.next=n15 n1.next=n15
n2.prev=n15 n2.prev=n15
n2=n15 n2=n15
@ -1329,24 +1325,10 @@ function _stepfrom(x0,x1)
end end
end end
function _in_box(x,y,x0,y0,x1,y1)
x0,x1=_mnmx(x0,x1)
y0,y1=_mnmx(y0,y1)
return x0<=x and y0<=y and x<=x1 and y<=y1
end
function _which_side(x,y,x0,y0,x1,y1) function _which_side(x,y,x0,y0,x1,y1)
return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0)) return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0))
end end
function _linedist(x0,v,x1)
return 100 * (sum_distance(x0,v,x1)-distance(x0,x1))/distance(x0,x1)
end
function sum_distance(x,y,z)
return distance(x,y) + distance(y,z)
end
function distance_dxy(dx,dy) function distance_dxy(dx,dy)
return sqrt(dx*dx+dy*dy) return sqrt(dx*dx+dy*dy)
end end
@ -1361,10 +1343,10 @@ function rope:collide_mrect(mx0,my0,mw,mh,exclude_src,exclude_dst)
local mx1,my1=mx0+mw,my0+mh local mx1,my1=mx0+mw,my0+mh
local n0=self.src local n0=self.src
mx0+=0.1 mx0+=0.4
my0+=0.1 my0+=0.4
mx1-=0.1 mx1-=0.4
my1-=0.1 my1-=0.4
while true do while true do
local n1=n0.next local n1=n0.next
@ -1401,18 +1383,6 @@ function _line_line(x1,y1,x2,y2,x3,y3,x4,y4)
return true return true
end end
function neighbors(p)
local r={}
for dx=-1,1,1 do
for dy=-1,1,1 do
if dx!=0 or dy!=0 then
add(r,{x=p.x+dx,y=p.y+dy})
end
end
end
return r
end
-->8 -->8
-- moved here because it's complicated -- moved here because it's complicated