diff --git a/chameleonic.p8 b/chameleonic.p8 index abc25a6..af59265 100644 --- a/chameleonic.p8 +++ b/chameleonic.p8 @@ -7,10 +7,6 @@ real_modules={} frame=0 function _init() - -- cls(0) - -- for i in _stepfrom(0.5,-2.5) do print(i) end - -- assert(false) - _doall("init") end function _update() frame+=1 @@ -97,13 +93,13 @@ function _apply(x,ts,a) local t=deli(ts,1) for k,v in pairs(t) do if k=="update" then - if not v(x,a) then - add(ts,t,1) - end + -- else x[k]=v end end + + if (t and t.update and not t.update(x,a)) add(ts,t,1) end function sgn0(x) @@ -401,28 +397,16 @@ end function level:recollide() self._coll={} - self._coll_nocrate={} for mx=0,15 do for my=0,15 do local mxy=_mix(mx,my) - self._coll_nocrate[mxy]= - fget(self:_mget(mx,my),7) self._coll[mxy]= - self._coll_nocrate[mxy] or + fget(self:_mget(mx,my),7) or self._crates[mxy]!=nil 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() local anch_new={} 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 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(mx1,my0) and not self:mcoll(mx1,my1) @@ -497,12 +481,6 @@ function level:get_open_pit(mx,my) if (pit and pit.contents==nil) return pit 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() self._wins={} local spawned=false @@ -516,9 +494,11 @@ function level:spawn_exit() end local win_at=function(x,y) if (self:_mget(x,y)!=18) return - for n in all(neighbors{x=x,y=y}) do - if n.x<0 or n.y<0 or n.x>15 or n.y>15 then - self._wins[_mix(n.x,n.y)]=true + for nx=x-1,x+1 do + for ny=y-1,y+1 do + if nx<0 or ny<0 or nx>15 or ny>15 then + self._wins[_mix(nx,ny)]=true + end end end end @@ -529,22 +509,9 @@ function level:spawn_exit() assert(spawned) 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) return self._coll[_mix(mx,my)]!=false end -function level:mcoll_nocrate(mx,my) - return self._coll_nocrate[_mix(mx,my)]!=false -end function level:pcoll(px,py) 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 mxy1=_mix(mx1,my1) - existing.mx=mx1 - existing.my=my1 existing.todo={ - {px=mx0*8+dmx*2,py=my0*8+dmy*2}, - {px=mx0*8+dmx*7,py=my0*8+dmy*7}, - {px=mx1*8,py=my1*8,update=function() - self:reanchor(true) + {px=mx1*8+dmx,py=my1*8+dmy,mx=mx1,my=my1,update=function() + self:recollide() + self:reanchor() return true - end} + end}, + {px=mx1*8,py=my1*8} } self._crates[mxy1]=existing - self:recollide() - self:reanchor(false) end -->8 @@ -955,8 +918,8 @@ function rope:update() self.latch.rec!=nil then self:drag_src( - self.latch.rec.px/8+0.5+self.latch.ax_offset, - self.latch.rec.py/8+0.5+self.latch.ay_offset + self.latch.rec.mx+0.5+self.latch.ax_offset, + self.latch.rec.my+0.5+self.latch.ay_offset ) if #self.latch.rec.todo==0 then @@ -1023,28 +986,34 @@ function rope:draw(artificial_dx,artificial_dy) end -- draw latch - if self.latch!=nil and perc_to_show>=1.0 then - local x,y=points[1].x,points[1].y + if self.latch!=nil and self.latch.rec and perc_to_show>=1.0 then + local x,y=self.latch.rec.px,self.latch.rec.py local ldx,ldy=self.latch.dx,self.latch.dy local color=8 if (highlight==0) color=12 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 - 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 - 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 - rectfill(x,y-1,x-1,y-3,color) + rectfill(x+3,y+5,x+4,y+7,color) end end - local n1=self.src + + -- debug --[[ + local n1=self.src local sy=0 while true do if (n1==nil) break local x=n1.ax*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) print("ax="..n1.ax..",ay="..n1.ay,0,sy) sy+=7 @@ -1074,11 +1043,14 @@ function rope:draw(artificial_dx,artificial_dy) end for _,p in pairs(level._anch) do - pset(p.ax*8,p.ay*8,11) - pset(p.ax*8+p.adx,p.ay*8,11) - pset(p.ax*8,p.ay*8+p.ady,11) + local x,y=p.ax*8,p.ay*8 + if (p.adx>0) x-=1 + if (p.ady>0) y-=1 + pset(x,y,11) + pset(x+p.adx,y,11) + pset(x,y+p.ady,11) end - ]]-- + ]] end 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) 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) n0=n1.prev n2=n1.next @@ -1133,7 +1105,6 @@ function rope:relax() n2.prev=n0 n1.next=nil n1.prev=nil - --n0=n0.next else n0=n0.next end else n0=n0.next end end @@ -1143,7 +1114,6 @@ function rope:_check_sane() if (self.state.name!="latched") return true if (level:busy()) return true - printh("start") local n0=self.src local qxs,qys={},{} @@ -1152,32 +1122,62 @@ function rope:_check_sane() 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 - add(qxs,qx) - add(qys,qy) + if not (qx==qxs[#qxs] and qy==qys[#qys]) then + add(qxs,qx) + add(qys,qy) + end end n0=n1 end - local function _blocked(qx,qy) + local function _possible_tiles(qx,qy) local mx0=(qx-1)\2 local mx1=qx\2 local my0=(qy-1)\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 + return poss end - for i=1,#qxs do - if (_blocked(qxs[i],qys[i])) printh("blocked"..qxs[i]..","..qys[i]) return false + 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 + -- 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 local qx1,qy1=qxs[i-1],qys[i-1] if qx1%2==0 and qy1%2==0 then - local qx0,qy0=qxs[i-2],qys[i-2] - local qx2,qy2=qxs[i],qys[i] - local mx0,my0=qx0\2,qy0\2 - local mx2,my2=qx2\2,qy2\2 - if (level:mcoll(mx0,my2) and level:mcoll(mx2,my0)) printh("not traversable") return false + local ok=false + 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 + --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 return true @@ -1213,8 +1213,6 @@ function would_stick(x0,y0,anchor,x2,y2) return not wouldnt,x1_new,y1_new,adx,ady 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) 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 @@ -1268,8 +1266,6 @@ function rope:_drag(n1,ax1_new,ay1_new) end ax_far_old=ax_far_new end - else - assert(false, "wtf?") 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) if (anch==nil) break 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 n1.prev=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) if (anch==nil) break 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 n2.prev=n15 n2=n15 @@ -1329,24 +1325,10 @@ function _stepfrom(x0,x1) 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) return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0)) 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) return sqrt(dx*dx+dy*dy) 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 n0=self.src - mx0+=0.1 - my0+=0.1 - mx1-=0.1 - my1-=0.1 + mx0+=0.4 + my0+=0.4 + mx1-=0.4 + my1-=0.4 while true do local n1=n0.next @@ -1401,18 +1383,6 @@ function _line_line(x1,y1,x2,y2,x3,y3,x4,y4) return true 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 -- moved here because it's complicated