forked from pyrex/chameleonic
		
	Compare commits
	
		
			16 Commits
		
	
	
		
			dc33b46260
			...
			sprintf
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						e028209adf
	
				 | 
					
					
						|||
| 
						
						
							
						
						ce3fc83221
	
				 | 
					
					
						|||
| 
						
						
							
						
						3e2229be65
	
				 | 
					
					
						|||
| 
						
						
							
						
						46f1339e19
	
				 | 
					
					
						|||
| 
						
						
							
						
						f86e52d3bd
	
				 | 
					
					
						|||
| 
						
						
							
						
						e6c35dbeda
	
				 | 
					
					
						|||
| 
						
						
							
						
						3516d2855e
	
				 | 
					
					
						|||
| 
						
						
							
						
						2264349e72
	
				 | 
					
					
						|||
| 
						
						
							
						
						93c154f876
	
				 | 
					
					
						|||
| 
						
						
							
						
						3494c48e74
	
				 | 
					
					
						|||
| 
						
						
							
						
						e878717c31
	
				 | 
					
					
						|||
| a6debc3974 | |||
| 693cdaa11d | |||
| f052186c97 | |||
| 0d0a2c41a7 | |||
| 71b150cb33 | 
							
								
								
									
										501
									
								
								chameleonic.p8
									
									
									
									
									
								
							
							
						
						
									
										501
									
								
								chameleonic.p8
									
									
									
									
									
								
							@@ -8,6 +8,7 @@ real_modules={}
 | 
				
			|||||||
frame=0
 | 
					frame=0
 | 
				
			||||||
function _init()
 | 
					function _init()
 | 
				
			||||||
 -- printh("restarting")
 | 
					 -- printh("restarting")
 | 
				
			||||||
 | 
					 music_on()
 | 
				
			||||||
 _doall("init") end
 | 
					 _doall("init") end
 | 
				
			||||||
function _update()
 | 
					function _update()
 | 
				
			||||||
 frame+=1
 | 
					 frame+=1
 | 
				
			||||||
@@ -15,6 +16,61 @@ function _update()
 | 
				
			|||||||
function _draw()
 | 
					function _draw()
 | 
				
			||||||
 _doall("draw") end
 | 
					 _doall("draw") end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function music_on()
 | 
				
			||||||
 | 
					 music(0)
 | 
				
			||||||
 | 
					 menuitem(3, "music: on", music_off)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function music_off()
 | 
				
			||||||
 | 
					 music(-1)
 | 
				
			||||||
 | 
					 menuitem(3, "music: off", music_on)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function gsv(s)
 | 
				
			||||||
 | 
					 local ret=split(s,"\n")
 | 
				
			||||||
 | 
					 for i,v in ipairs(ret) do
 | 
				
			||||||
 | 
					  ret[i] = type(v) == "string" and split(v,"`") or {v} end
 | 
				
			||||||
 | 
					 return ret
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function cycle(tbl,period)
 | 
				
			||||||
 | 
					 period = period or 1
 | 
				
			||||||
 | 
					 return tbl[t()%period*#tbl\period+1]
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- fake sprintf function
 | 
				
			||||||
 | 
					-- %~ for literal "%"
 | 
				
			||||||
 | 
					-- %v for param
 | 
				
			||||||
 | 
					-- %! for tostring(param)
 | 
				
			||||||
 | 
					--    which dumps tables
 | 
				
			||||||
 | 
					function fmt(f, ...)
 | 
				
			||||||
 | 
					 local out, i = "", 0
 | 
				
			||||||
 | 
					 for s in all(split(f,"%")) do
 | 
				
			||||||
 | 
					  if i == 0 then
 | 
				
			||||||
 | 
					   -- before first format directive
 | 
				
			||||||
 | 
					   out ..= s
 | 
				
			||||||
 | 
					   i = 1
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					   local m = s[1]
 | 
				
			||||||
 | 
					   if m == "~" then
 | 
				
			||||||
 | 
					    out ..= "%"
 | 
				
			||||||
 | 
					   else
 | 
				
			||||||
 | 
					    local p = select(i,...)
 | 
				
			||||||
 | 
					    i+=1
 | 
				
			||||||
 | 
					    if m == "v" then
 | 
				
			||||||
 | 
					     out ..= p
 | 
				
			||||||
 | 
					    elseif m == "!" then
 | 
				
			||||||
 | 
					     out ..= tostring(p)
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					     assert(false, tostr(m).."is not a formatting directive")
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					   end
 | 
				
			||||||
 | 
					   out ..=sub(s,2)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					 end
 | 
				
			||||||
 | 
					 return out
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mnames={}
 | 
					mnames={}
 | 
				
			||||||
function names(root)
 | 
					function names(root)
 | 
				
			||||||
 local n=mnames[root]
 | 
					 local n=mnames[root]
 | 
				
			||||||
@@ -97,6 +153,15 @@ function sgn0(x)
 | 
				
			|||||||
 return x!=0 and sgn(x) or 0
 | 
					 return x!=0 and sgn(x) or 0
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function inorder(tbl)
 | 
				
			||||||
 | 
					 local prev
 | 
				
			||||||
 | 
					 for v in all(tbl) do
 | 
				
			||||||
 | 
					  if (prev and v < prev) return
 | 
				
			||||||
 | 
					  prev = v
 | 
				
			||||||
 | 
					 end
 | 
				
			||||||
 | 
					 return true
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function _mnmx(x,y)
 | 
					function _mnmx(x,y)
 | 
				
			||||||
 if (x>y)return y,x
 | 
					 if (x>y)return y,x
 | 
				
			||||||
 return x,y
 | 
					 return x,y
 | 
				
			||||||
@@ -138,6 +203,41 @@ function _rast(
 | 
				
			|||||||
 _add()
 | 
					 _add()
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-->8
 | 
				
			||||||
 | 
					-- anchor operations (for the rope code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function _anch_eq(a0,a1) 
 | 
				
			||||||
 | 
					 if (a0 and a1) return a0[1]==a1[1] and a0[2]==a1[2]
 | 
				
			||||||
 | 
					 return a0==a1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					--[[
 | 
				
			||||||
 | 
					function _anch_unpack(anch)
 | 
				
			||||||
 | 
					 assert(anch[1])
 | 
				
			||||||
 | 
					 assert(anch[2])
 | 
				
			||||||
 | 
					 return anch[1],anch[2]
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					]]--
 | 
				
			||||||
 | 
					_anch_unpack=unpack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function _anch_new(prev,next,xy)
 | 
				
			||||||
 | 
					 local out={prev=prev,next=next,_anch_unpack(xy)}
 | 
				
			||||||
 | 
					 if (prev) prev.next=out
 | 
				
			||||||
 | 
					 if (next) next.prev=out
 | 
				
			||||||
 | 
					 return out
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function _anch_del(n1,xy)
 | 
				
			||||||
 | 
					 local n0,n2=n1.prev,n1.next
 | 
				
			||||||
 | 
					 if (n0) n0.next=n2
 | 
				
			||||||
 | 
					 if (n2) n2.prev=n0
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function _anch_update(a0,a1)
 | 
				
			||||||
 | 
					 a0[1]=a1[1]
 | 
				
			||||||
 | 
					 a0[2]=a1[2]
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-->8
 | 
					-->8
 | 
				
			||||||
-- input
 | 
					-- input
 | 
				
			||||||
@@ -179,14 +279,12 @@ function kbd:release(i)
 | 
				
			|||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function tostring(any)
 | 
					function tostring(any)
 | 
				
			||||||
 if type(any)=="table" then
 | 
					 if (type(any)!="table") return tostr(any)
 | 
				
			||||||
  local str = "{ "
 | 
					 local str = "{ "
 | 
				
			||||||
  for k,v in pairs(any) do
 | 
					 for k,v in pairs(any) do
 | 
				
			||||||
      str=str..tostring(k).."->"..tostring(v).." "
 | 
					  str..=tostring(k).."->"..tostring(v).." "
 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
  return str.."}"
 | 
					 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 return tostr(any)
 | 
					 return str.."}"
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-->8
 | 
					-->8
 | 
				
			||||||
@@ -202,7 +300,7 @@ function title:draw()
 | 
				
			|||||||
 print("pyrex",32,73,7)
 | 
					 print("pyrex",32,73,7)
 | 
				
			||||||
 print("[nyeogmi]",62,73,7)
 | 
					 print("[nyeogmi]",62,73,7)
 | 
				
			||||||
 print("kistaro",32,79,7)
 | 
					 print("kistaro",32,79,7)
 | 
				
			||||||
 local lvlstr = "⬅️ "..start_level.." ➡️"
 | 
					 local lvlstr = fmt("⬅️ %v ➡️",start_level)
 | 
				
			||||||
 print(lvlstr,50,91,1)
 | 
					 print(lvlstr,50,91,1)
 | 
				
			||||||
 print(lvlstr,51,90,blinkcol) 
 | 
					 print(lvlstr,51,90,blinkcol) 
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
@@ -231,6 +329,7 @@ function level:init()
 | 
				
			|||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function level:reinit(n)
 | 
					function level:reinit(n)
 | 
				
			||||||
 | 
					 self.hintlevel = 0
 | 
				
			||||||
 self.ix=n
 | 
					 self.ix=n
 | 
				
			||||||
 self.todo={}
 | 
					 self.todo={}
 | 
				
			||||||
 self.bigx,self.bigy=n%8,n\8
 | 
					 self.bigx,self.bigy=n%8,n\8
 | 
				
			||||||
@@ -371,20 +470,18 @@ function level:recollide_reanchor()
 | 
				
			|||||||
     not self:mcoll(mx1,my0) and
 | 
					     not self:mcoll(mx1,my0) and
 | 
				
			||||||
     not self:mcoll(mx1,my1)
 | 
					     not self:mcoll(mx1,my1)
 | 
				
			||||||
    ) then
 | 
					    ) then
 | 
				
			||||||
     local key="GEOM"..mx0..","..my0..","..dx..","..dy
 | 
					     anch_new[fmt("GEOM%v,%v,%v,%v",mx0,my0,dx,dy)]= {
 | 
				
			||||||
     anch_new[key]= {
 | 
					      max(mx0,mx1),max(my0,my1),adx=-dx,ady=-dy
 | 
				
			||||||
      ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy
 | 
					 | 
				
			||||||
     }
 | 
					     }
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
   end
 | 
					   end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for _,cr in pairs(self._crates) do
 | 
					  for _,cr in pairs(self._crates) do
 | 
				
			||||||
   local key="CRATE"..cr.id..","..dx..","..dy
 | 
					 | 
				
			||||||
   local mx0,my0=cr.mx,cr.my
 | 
					   local mx0,my0=cr.mx,cr.my
 | 
				
			||||||
   local mx1,my1=mx0+dx,my0+dy
 | 
					   local mx1,my1=mx0+dx,my0+dy
 | 
				
			||||||
   anch_new[key]={
 | 
					   anch_new[fmt("CRATE%v,%v,%v",cr.id,dx,dy)]={
 | 
				
			||||||
    ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy
 | 
					    max(mx0,mx1),max(my0,my1),adx=-dx,ady=-dy
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
@@ -394,17 +491,19 @@ function level:recollide_reanchor()
 | 
				
			|||||||
  local old=(self._anch or {})[k]
 | 
					  local old=(self._anch or {})[k]
 | 
				
			||||||
  if old then
 | 
					  if old then
 | 
				
			||||||
   anch_new[k]=new
 | 
					   anch_new[k]=new
 | 
				
			||||||
   if (old.ax!=new.ax or old.ay!=new.ay) add(moves,{old.ax,old.ay,new.ax,new.ay,old,key=k})
 | 
					   if (not _anch_eq(old,new)) add(moves,{old,new,key=k})
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 self._anch=anch_new
 | 
					 self._anch=anch_new
 | 
				
			||||||
 self._anch_keys={}
 | 
					 self._anch_keys={}
 | 
				
			||||||
 for k,_ in pairs(self._anch) do
 | 
					 self._anch_by_position={}
 | 
				
			||||||
 | 
					 for k,v in pairs(self._anch) do
 | 
				
			||||||
  add(self._anch_keys,{key=k})
 | 
					  add(self._anch_keys,{key=k})
 | 
				
			||||||
 | 
					  local pkey=_mix(_anch_unpack(v))
 | 
				
			||||||
 | 
					  self._anch_by_position[pkey]=self._anch_by_position[pkey] or v
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 shellsort(self._anch_keys)
 | 
					 shellsort(self._anch_keys)
 | 
				
			||||||
 shellsort(moves)
 | 
					 shellsort(moves)
 | 
				
			||||||
 --printh("!!STARTING!!")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 if player.rope then
 | 
					 if player.rope then
 | 
				
			||||||
  player.rope:experience_anchor_moves(moves)
 | 
					  player.rope:experience_anchor_moves(moves)
 | 
				
			||||||
@@ -428,10 +527,8 @@ function level:anchor_points()
 | 
				
			|||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function level:anchor_at(ax,ay)
 | 
					function level:anchor_at(point)
 | 
				
			||||||
 for i in self:anchor_points() do
 | 
					 return self._anch_by_position[_mix(_anch_unpack(point))]
 | 
				
			||||||
  if (i.ax==ax and i.ay==ay) return i
 | 
					 | 
				
			||||||
 end
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function level:get_open_pit(mx,my)
 | 
					function level:get_open_pit(mx,my)
 | 
				
			||||||
@@ -485,10 +582,6 @@ function level:_mget(mx,my)
 | 
				
			|||||||
 )
 | 
					 )
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function _amix(ax,ay)
 | 
					 | 
				
			||||||
 return ax..","..ay
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function _mix(mx,my)
 | 
					function _mix(mx,my)
 | 
				
			||||||
  return mx..","..my
 | 
					  return mx..","..my
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
@@ -672,8 +765,8 @@ function player:update()
 | 
				
			|||||||
    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(
 | 
					    self.rope=rope:new(
 | 
				
			||||||
     x+0.5-dx*0.5,y+0.5-dy*0.5,
 | 
					     {x+0.5-dx*0.5,y+0.5-dy*0.5},
 | 
				
			||||||
     self.x+0.5,self.y+0.5,
 | 
					     {self.x+0.5,self.y+0.5},
 | 
				
			||||||
     level:get_latch(dx,dy,x*8,y*8)
 | 
					     level:get_latch(dx,dy,x*8,y*8)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -700,10 +793,10 @@ function player:update()
 | 
				
			|||||||
   self.y=latch.rec.my+latch.dy
 | 
					   self.y=latch.rec.my+latch.dy
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  self.rope:drag_dst(
 | 
					  self.rope:drag_dst{
 | 
				
			||||||
   self.x+self.px/8+0.5,
 | 
					   self.x+self.px/8+0.5,
 | 
				
			||||||
   self.y+self.py/8+0.5
 | 
					   self.y+self.py/8+0.5
 | 
				
			||||||
  )
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local tdx,tdy=self.rope:tug_orientxy()
 | 
					  local tdx,tdy=self.rope:tug_orientxy()
 | 
				
			||||||
  if (tdx) self.orientx=tdx
 | 
					  if (tdx) self.orientx=tdx
 | 
				
			||||||
@@ -815,19 +908,15 @@ rope={}
 | 
				
			|||||||
rope.__index=rope
 | 
					rope.__index=rope
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rope:new(
 | 
					function rope:new(
 | 
				
			||||||
 src_ax,src_ay,dst_ax,dst_ay,latch
 | 
					 src,dst,latch
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 local r={
 | 
					 local r={
 | 
				
			||||||
  id=0,
 | 
					  id=0,
 | 
				
			||||||
  anchors={
 | 
					 | 
				
			||||||
   {ax=src_ax,ay=src_ay},
 | 
					 | 
				
			||||||
   {ax=dst_ax,ay=dst_ay}
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  state={name="cast",frame=0},
 | 
					  state={name="cast",frame=0},
 | 
				
			||||||
  latch=latch,
 | 
					  latch=latch,
 | 
				
			||||||
 }
 | 
					 }
 | 
				
			||||||
 r.src=r.anchors[1]
 | 
					 r.src=src
 | 
				
			||||||
 r.dst=r.anchors[2]
 | 
					 r.dst=dst
 | 
				
			||||||
 r.src.next=r.dst
 | 
					 r.src.next=r.dst
 | 
				
			||||||
 r.dst.prev=r.src
 | 
					 r.dst.prev=r.src
 | 
				
			||||||
 setmetatable(r,rope)
 | 
					 setmetatable(r,rope)
 | 
				
			||||||
@@ -855,10 +944,10 @@ function rope:update()
 | 
				
			|||||||
  if (not self.latch) wrongbleep:bleep(5) self:destroy() return
 | 
					  if (not self.latch) wrongbleep:bleep(5) self:destroy() return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if self.latch.rec then
 | 
					  if self.latch.rec then
 | 
				
			||||||
   self:drag_src(
 | 
					   self:drag_src{
 | 
				
			||||||
    self.latch.rec.mx+0.5+self.latch.ax_offset,
 | 
					    self.latch.rec.mx+0.5+self.latch.ax_offset,
 | 
				
			||||||
    self.latch.rec.my+0.5+self.latch.ay_offset
 | 
					    self.latch.rec.my+0.5+self.latch.ay_offset
 | 
				
			||||||
   )
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   if self.latch.rec.dead==true then 
 | 
					   if self.latch.rec.dead==true then 
 | 
				
			||||||
    self:destroy()
 | 
					    self:destroy()
 | 
				
			||||||
@@ -991,7 +1080,7 @@ function rope:draw(artificial_px,artificial_py)
 | 
				
			|||||||
 local sy=0
 | 
					 local sy=0
 | 
				
			||||||
 while true do
 | 
					 while true do
 | 
				
			||||||
  if (n1==nil) break
 | 
					  if (n1==nil) break
 | 
				
			||||||
  local anch=level:anchor_at(n1.ax,n1.ay)
 | 
					  local anch=level:anchor_at(n1)
 | 
				
			||||||
  local x=n1.ax*8
 | 
					  local x=n1.ax*8
 | 
				
			||||||
  local y=n1.ay*8
 | 
					  local y=n1.ay*8
 | 
				
			||||||
  if anch then
 | 
					  if anch then
 | 
				
			||||||
@@ -999,7 +1088,7 @@ function rope:draw(artificial_px,artificial_py)
 | 
				
			|||||||
   if (anch.ady>0) y-=1
 | 
					   if (anch.ady>0) y-=1
 | 
				
			||||||
  end
 | 
					  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,72,sy)
 | 
					  print(fmt("ax=%v,ay=%v",n1.ax,n1.ay),72,sy)
 | 
				
			||||||
  sy+=7
 | 
					  sy+=7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local n0=n1.prev
 | 
					  local n0=n1.prev
 | 
				
			||||||
@@ -1032,18 +1121,18 @@ function rope:draw(artificial_px,artificial_py)
 | 
				
			|||||||
  ]]
 | 
					  ]]
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rope:drag_dst(x,y)
 | 
					function rope:drag_dst(xy)
 | 
				
			||||||
 self:drag(self.dst,x,y)
 | 
					 self:drag(self.dst,xy)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rope:drag_src(x,y)
 | 
					function rope:drag_src(xy)
 | 
				
			||||||
 self:drag(self.src,x,y)
 | 
					 self:drag(self.src,xy)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rope:drag(n1,ax_new,ay_new)
 | 
					function rope:drag(n1,axy)
 | 
				
			||||||
 self:relax()
 | 
					 self:relax()
 | 
				
			||||||
 self:_drag(n1,ax_new,n1.ay)
 | 
					 self:_drag(n1,{axy[1],n1[2]})
 | 
				
			||||||
 self:_drag(n1,ax_new,ay_new)
 | 
					 self:_drag(n1,axy)
 | 
				
			||||||
 self:relax()
 | 
					 self:relax()
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1053,11 +1142,8 @@ function rope:relax()
 | 
				
			|||||||
  local n1=n0.next
 | 
					  local n1=n0.next
 | 
				
			||||||
  if (not n1) break
 | 
					  if (not n1) break
 | 
				
			||||||
  local n2=n1.next
 | 
					  local n2=n1.next
 | 
				
			||||||
 | 
					  if _anch_eq(n0,n1) then
 | 
				
			||||||
 | 
					   _anch_del(n1)
 | 
				
			||||||
  if n0.ax==n1.ax and n0.ay==n1.ay then 
 | 
					 | 
				
			||||||
   n0.next=n2 
 | 
					 | 
				
			||||||
   if (n2) n2.prev=n0
 | 
					 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
   n0=n0.next
 | 
					   n0=n0.next
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@@ -1070,20 +1156,11 @@ function rope:relax()
 | 
				
			|||||||
  local n2=n1.next
 | 
					  local n2=n1.next
 | 
				
			||||||
  if (not n2) return
 | 
					  if (not n2) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local x0,y0=n0.ax,n0.ay
 | 
					  local anch=level:anchor_at(n1)
 | 
				
			||||||
  local x1,y1=n1.ax,n1.ay
 | 
					  local wouldstick,position_new=would_stick(anch,n0,n1,n2)
 | 
				
			||||||
  local x2,y2=n2.ax,n2.ay
 | 
					  if not (wouldstick or _anch_eq(n1,position_new)) then
 | 
				
			||||||
 | 
					   self:_drag(n1,position_new,{_anch_unpack(n1)})
 | 
				
			||||||
  local anch=level:anchor_at(n1.ax,n1.ay)
 | 
					   _anch_del(n1)
 | 
				
			||||||
  local would,x1_new,y1_new=would_stick(anch,x0,y0,x1,y1,x2,y2)
 | 
					 | 
				
			||||||
  if not would and not (n1.ax==x1_new and n1.ay==y1_new) then
 | 
					 | 
				
			||||||
   self:_drag(n1,x1_new,y1_new,n1.ax,n1.ay)
 | 
					 | 
				
			||||||
   n0=n1.prev
 | 
					 | 
				
			||||||
   n2=n1.next
 | 
					 | 
				
			||||||
   n0.next=n2
 | 
					 | 
				
			||||||
   n2.prev=n0
 | 
					 | 
				
			||||||
   n1.next=nil
 | 
					 | 
				
			||||||
   n1.prev=nil
 | 
					 | 
				
			||||||
  else n0=n0.next end
 | 
					  else n0=n0.next end
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
@@ -1099,7 +1176,9 @@ function rope:_check_sane()
 | 
				
			|||||||
  local n1=n0.next
 | 
					  local n1=n0.next
 | 
				
			||||||
  if (not n1) break 
 | 
					  if (not n1) break 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _rast(qxs,qys,flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2)) 
 | 
					  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)) 
 | 
				
			||||||
  n0=n1
 | 
					  n0=n1
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1143,7 +1222,6 @@ function rope:_check_sane()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      if dmx==1 and dmy==1 and level:mcoll(mx0,my2) and level:mcoll(mx2,my0) then
 | 
					      if dmx==1 and dmy==1 and level:mcoll(mx0,my2) and level:mcoll(mx2,my0) then
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
       --printh("ok! "..tostring({qxs[i-2],qys[i-2]})..tostring({qxs[i],qys[i]})..tostring(m0)..tostring(m2))
 | 
					 | 
				
			||||||
       ok=true
 | 
					       ok=true
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
     end
 | 
					     end
 | 
				
			||||||
@@ -1156,12 +1234,12 @@ function rope:_check_sane()
 | 
				
			|||||||
 return true
 | 
					 return true
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function would_stick(anchor,x0,y0,x1,y1,x2,y2)
 | 
					function would_stick(anchor,xy0,xy1,xy2)
 | 
				
			||||||
 x1,y1=x1 or anchor.ax,y1 or anchor.ay
 | 
					 local x0,y0=_anch_unpack(xy0)
 | 
				
			||||||
 | 
					 local x1,y1=_anch_unpack(xy1 or anchor)
 | 
				
			||||||
 | 
					 local x2,y2=_anch_unpack(xy2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 local dx,dy=x2-x0,y2-y0
 | 
					 local dx,dy=x2-x0,y2-y0
 | 
				
			||||||
 if (x1==x0 and y1==y0) return 
 | 
					 | 
				
			||||||
 if (x1==x2 and y1==y2) return 
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 local function switch_ends() 
 | 
					 local function switch_ends() 
 | 
				
			||||||
  dx,dy,x0,y0,x2,y2=-dx,-dy,x2,y2,x0,y0
 | 
					  dx,dy,x0,y0,x2,y2=-dx,-dy,x2,y2,x0,y0
 | 
				
			||||||
@@ -1185,7 +1263,7 @@ function would_stick(anchor,x0,y0,x1,y1,x2,y2)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 return 
 | 
					 return 
 | 
				
			||||||
  anchor and anchor.adx==adx and anchor.ady==ady,
 | 
					  anchor and anchor.adx==adx and anchor.ady==ady,
 | 
				
			||||||
  x1_new,y1_new
 | 
					  {x1_new,y1_new}
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rope:experience_anchor_moves(moves)
 | 
					function rope:experience_anchor_moves(moves)
 | 
				
			||||||
@@ -1198,15 +1276,15 @@ function rope:_be_dragged_by(moves)
 | 
				
			|||||||
 local n=self.src
 | 
					 local n=self.src
 | 
				
			||||||
 while n do
 | 
					 while n do
 | 
				
			||||||
  for t in all(moves) do
 | 
					  for t in all(moves) do
 | 
				
			||||||
   local ax_old,ay_old,ax_new,ay_new=unpack(t)
 | 
					   local xy_old,xy_new=unpack(t)
 | 
				
			||||||
   if (ax_old==n.ax and ay_old==n.ay) n.dest={ax_new,ay_new} break
 | 
					   if (_anch_eq(xy_old,n)) n.dest=xy_new break
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  n=n.next
 | 
					  n=n.next
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 n=self.src
 | 
					 n=self.src
 | 
				
			||||||
 while n do
 | 
					 while n do
 | 
				
			||||||
  if (n.dest) self:_drag(n,unpack(n.dest)) n.dest=nil
 | 
					  if (n.dest) self:_drag(n,n.dest) n.dest=nil
 | 
				
			||||||
  n=n.next
 | 
					  n=n.next
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
@@ -1217,14 +1295,18 @@ function rope:_be_pushed_by(moves)
 | 
				
			|||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rope:_be_pushed_by1(ax_old,ay_old,ax_new,ay_new,anch)
 | 
					function rope:_be_pushed_by1(anch_old,anch_new)
 | 
				
			||||||
 local n0=self.src
 | 
					 local n0=self.src
 | 
				
			||||||
 while true do
 | 
					
 | 
				
			||||||
 | 
					 local ax_old,ay_old=_anch_unpack(anch_old)
 | 
				
			||||||
 | 
					 local ax_new,ay_new=_anch_unpack(anch_new)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 while n0 do
 | 
				
			||||||
  n1=n0.next
 | 
					  n1=n0.next
 | 
				
			||||||
  if (not n1) return
 | 
					  if (not n1) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local nx0,ny0=n0.ax,n0.ay
 | 
					  local nx0,ny0=_anch_unpack(n0)
 | 
				
			||||||
  local nx1,ny1=n1.ax,n1.ay
 | 
					  local nx1,ny1=_anch_unpack(n1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local nxmn,nxmx = _mnmx(nx0,nx1)
 | 
					  local nxmn,nxmx = _mnmx(nx0,nx1)
 | 
				
			||||||
  local nymn,nymx = _mnmx(ny0,ny1)
 | 
					  local nymn,nymx = _mnmx(ny0,ny1)
 | 
				
			||||||
@@ -1233,9 +1315,9 @@ function rope:_be_pushed_by1(ax_old,ay_old,ax_new,ay_new,anch)
 | 
				
			|||||||
   (ax_new!=ax_old or (nxmn<ax_new and ax_new<nxmx)) and 
 | 
					   (ax_new!=ax_old or (nxmn<ax_new and ax_new<nxmx)) and 
 | 
				
			||||||
   (ay_new!=ay_old or (nymn<ay_new and ay_new<nymx)) and 
 | 
					   (ay_new!=ay_old or (nymn<ay_new and ay_new<nymx)) and 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   (_which_side(ax_old,ay_old,nx0,ny0,nx1,ny1)!= 
 | 
					   (_which_side(anch_old,n0,n1)!= 
 | 
				
			||||||
    _which_side(ax_new,ay_new,nx0,ny0,nx1,ny1) 
 | 
					    _which_side(anch_new,n0,n1) 
 | 
				
			||||||
   ) and would_stick(anch,nx0,ny0,nil,nil,nx1,ny1)
 | 
					   ) and would_stick(anch_new,n0,nil,n1)
 | 
				
			||||||
  then
 | 
					  then
 | 
				
			||||||
   local nx05,ny05
 | 
					   local nx05,ny05
 | 
				
			||||||
   if ax_new==ax_old then
 | 
					   if ax_new==ax_old then
 | 
				
			||||||
@@ -1246,101 +1328,84 @@ function rope:_be_pushed_by1(ax_old,ay_old,ax_new,ay_new,anch)
 | 
				
			|||||||
    nx05=nx0+(ny05-ny0)/(ny1-ny0) * (nx1-nx0)
 | 
					    nx05=nx0+(ny05-ny0)/(ny1-ny0) * (nx1-nx0)
 | 
				
			||||||
   end
 | 
					   end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   local n05={ax=nx05,ay=ny05,prev=n0,next=n1}
 | 
					   local n05=_anch_new(n0,n1,{nx05,ny05})
 | 
				
			||||||
   n0.next=n05
 | 
					   self:_drag(n05,{ax_new,ay_new})
 | 
				
			||||||
   n1.prev=n05
 | 
					 | 
				
			||||||
   -- printh("creating: "..tostring{anch,{n0.ax,n0.ay},{n05.ax,n05.ay},{n1.ax,n1.ay}})
 | 
					 | 
				
			||||||
   -- printh("dragging: "..tostring{anch,{n05.ax,n05.ay},{ax_new,ay_new}})
 | 
					 | 
				
			||||||
   self:_drag(n05,ax_new,ay_new)
 | 
					 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
   n0=n0.next
 | 
					   n0=n0.next
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rope:_drag(n1,ax1_new,ay1_new,ax_removing,ay_removing)
 | 
					function rope:_drag(n1,new,removing)
 | 
				
			||||||
 local function _sweep_radar(ax_lhs,ay_lhs,ax_rhs,ay_rhs,ax_pivot,ay_pivot,ax_far0,ay_far0,ax_far1,ay_far1)
 | 
					 local function _sweep_radar(lhs,rhs,pivot,src,dst)
 | 
				
			||||||
 | 
					  if (_anch_eq(src,dst)) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local function _uncreatable(anchor)
 | 
					  local function _uncreatable(anchor)
 | 
				
			||||||
   return (anchor.ax==ax_lhs and anchor.ay==ay_lhs) or
 | 
					   return _anch_eq(anchor,lhs) or _anch_eq(anchor,lhs) or _anch_eq(anchor,removing)
 | 
				
			||||||
    (anchor.ax==ax_rhs and anchor.ay==ay_rhs) or
 | 
					 | 
				
			||||||
    (anchor.ax==ax_removing and anchor.ay==ay_removing)
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (ax_far0==ax_far1 and ay_far0==ay_far1) return 
 | 
					  local function _sweep(extent_orig,extent_final,cb_in_bounds,cb_make_point)
 | 
				
			||||||
 | 
					   local eligible={}
 | 
				
			||||||
 | 
					   local point_orig=cb_make_point(extent_orig)
 | 
				
			||||||
 | 
					   local point_final=cb_make_point(extent_final)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ax_far0==ax_far1 then
 | 
					   for anchor in level:anchor_points() do
 | 
				
			||||||
   local ax_far=ax_far0
 | 
					    -- figure out which anchors we even can stick to
 | 
				
			||||||
   local ax0,ax1=_mnmx(ax_pivot,ax_far)
 | 
					    if cb_in_bounds(anchor) and not _uncreatable(anchor) then 
 | 
				
			||||||
 | 
					     local side_orig=_which_side(anchor,pivot,point_orig)
 | 
				
			||||||
 | 
					     local side_final=_which_side(anchor,pivot,point_final)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   ay_far_old=ay_far0
 | 
					     if (side_orig!=side_final and would_stick(anchor,pivot,nil,point_final)) add(eligible,{anchor,side_final})
 | 
				
			||||||
   for ay_far_new in _stepfrom(ay_far0,ay_far1) do
 | 
					 | 
				
			||||||
    for anchor in level:anchor_points() do
 | 
					 | 
				
			||||||
     if 
 | 
					 | 
				
			||||||
      not _uncreatable(anchor) and
 | 
					 | 
				
			||||||
      (ax0<=anchor.ax and anchor.ax<=ax1) and 
 | 
					 | 
				
			||||||
      would_stick(anchor,ax_pivot,ay_pivot,nil,nil,ax_far,ay_far_new) and
 | 
					 | 
				
			||||||
      (
 | 
					 | 
				
			||||||
        _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far,ay_far_old) !=
 | 
					 | 
				
			||||||
        _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far,ay_far_new)
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
     then
 | 
					 | 
				
			||||||
      return anchor
 | 
					 | 
				
			||||||
     end
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    ay_far_old=ay_far_new
 | 
					 | 
				
			||||||
   end
 | 
					   end
 | 
				
			||||||
  elseif ay_far0==ay_far1 then
 | 
					 | 
				
			||||||
   local ay_far=ay_far0
 | 
					 | 
				
			||||||
   local ay0,ay1=_mnmx(ay_pivot,ay_far)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   ax_far_old=ax_far0
 | 
					   -- if no one's in the race, don't raycast
 | 
				
			||||||
   for ax_far_new in _stepfrom(ax_far0,ax_far1) do
 | 
					   if (#eligible==0) return 
 | 
				
			||||||
    for anchor in level:anchor_points() do
 | 
					   if (#eligible==1) return eligible[1][1]
 | 
				
			||||||
     if 
 | 
					
 | 
				
			||||||
      not _uncreatable(anchor) and
 | 
					   -- see who wins the race
 | 
				
			||||||
      (ay0<=anchor.ay and anchor.ay<=ay1) and 
 | 
					   for extent in _stepfrom(extent_orig,extent_final) do
 | 
				
			||||||
      would_stick(anchor,ax_pivot,ay_pivot,nil,nil,ax_far_new,ay_far) and
 | 
					    local point = cb_make_point(extent)
 | 
				
			||||||
      (
 | 
					    for anchor_final in all(eligible) do
 | 
				
			||||||
        _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far_old,ay_far) !=
 | 
					     if (_which_side(anchor_final[1],pivot,point)==anchor_final[2]) return anchor_final[1]
 | 
				
			||||||
        _which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far_new,ay_far)
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
     then
 | 
					 | 
				
			||||||
      return anchor
 | 
					 | 
				
			||||||
     end
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    ax_far_old=ax_far_new
 | 
					 | 
				
			||||||
   end
 | 
					   end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local ax_pivot,ay_pivot=_anch_unpack(pivot)
 | 
				
			||||||
 | 
					  local ax_src,ay_src=_anch_unpack(src)
 | 
				
			||||||
 | 
					  local ax_dst,ay_dst=_anch_unpack(dst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ax_src==ax_dst then
 | 
				
			||||||
 | 
					   return _sweep(
 | 
				
			||||||
 | 
					    ay_src,ay_dst,
 | 
				
			||||||
 | 
					    function(anchor) return mid(ax_pivot,anchor[1],ax_dst)==anchor[1] end,
 | 
				
			||||||
 | 
					    function(ay) return {ax_dst,ay} end
 | 
				
			||||||
 | 
					   )
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					   return _sweep(
 | 
				
			||||||
 | 
					    ax_src,ax_dst,
 | 
				
			||||||
 | 
					    function(anchor) return mid(ay_pivot,anchor[2],ay_dst)==anchor[2] end,
 | 
				
			||||||
 | 
					    function(ax) return {ax,ay_dst} end
 | 
				
			||||||
 | 
					   )
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 local ax1_old,ay1_old=n1.ax,n1.ay
 | 
					 local old={_anch_unpack(n1)}
 | 
				
			||||||
 n1.ax=ax1_new
 | 
					 _anch_update(n1,new)
 | 
				
			||||||
 n1.ay=ay1_new
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 local n0=n1.prev
 | 
					 local n0=n1.prev
 | 
				
			||||||
 while n0 do
 | 
					 while n0 do
 | 
				
			||||||
  local anch=_sweep_radar(
 | 
					  local anch=_sweep_radar(n0,n1,n0,old,new)
 | 
				
			||||||
   n0.ax,n0.ay,n1.ax,n1.ay,
 | 
					 | 
				
			||||||
   n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new
 | 
					 | 
				
			||||||
   )
 | 
					 | 
				
			||||||
  if (not anch) break
 | 
					  if (not anch) break
 | 
				
			||||||
  local n05={ax=anch.ax,ay=anch.ay,prev=n0,next=n1}
 | 
					  n0=_anch_new(n0,n1,anch)
 | 
				
			||||||
  n0.next=n05
 | 
					 | 
				
			||||||
  n1.prev=n05
 | 
					 | 
				
			||||||
  n0=n05
 | 
					 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 local n2=n1.next
 | 
					 local n2=n1.next
 | 
				
			||||||
 while n2 do
 | 
					 while n2 do
 | 
				
			||||||
  local anch=_sweep_radar(
 | 
					  local anch=_sweep_radar(n1,n2,n2,old,new)
 | 
				
			||||||
   n1.ax,n1.ay,n2.ax,n2.ay,
 | 
					 | 
				
			||||||
   n2.ax,n2.ay,ax1_old,ay1_old,ax1_new,ay1_new
 | 
					 | 
				
			||||||
  )
 | 
					 | 
				
			||||||
  if (not anch) break
 | 
					  if (not anch) break
 | 
				
			||||||
  local n15={ax=anch.ax,ay=anch.ay,prev=n1,next=n2}
 | 
					  n2=_anch_new(n1,n2,anch)
 | 
				
			||||||
  n1.next=n15
 | 
					 | 
				
			||||||
  n2.prev=n15
 | 
					 | 
				
			||||||
  n2=n15
 | 
					 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1353,9 +1418,7 @@ function _stepfrom(x0,x1)
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 local mul=0.5
 | 
					 local mul=1
 | 
				
			||||||
 x0*=2
 | 
					 | 
				
			||||||
 x1*=2
 | 
					 | 
				
			||||||
 if (x0>x1) x0,x1,mul=-x0,-x1,-mul
 | 
					 if (x0>x1) x0,x1,mul=-x0,-x1,-mul
 | 
				
			||||||
 local i=flr(x0)
 | 
					 local i=flr(x0)
 | 
				
			||||||
 local top=flr(x1)
 | 
					 local top=flr(x1)
 | 
				
			||||||
@@ -1371,7 +1434,11 @@ function _stepfrom(x0,x1)
 | 
				
			|||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function _which_side(x,y,x0,y0,x1,y1)
 | 
					function _which_side(xy,x0y0,x1y1)
 | 
				
			||||||
 | 
					 local x,y=_anch_unpack(xy)
 | 
				
			||||||
 | 
					 local x0,y0=_anch_unpack(x0y0)
 | 
				
			||||||
 | 
					 local x1,y1=_anch_unpack(x1y1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0))
 | 
					 return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0))
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1399,7 +1466,8 @@ function rope:collide_mrect(mx0,my0,mw,mh,exclude_src,exclude_dst)
 | 
				
			|||||||
   if (not nd) return
 | 
					   if (not nd) return
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local x1,y1,x2,y2=n0.ax,n0.ay,n1.ax,n1.ay
 | 
					  local x1,y1=_anch_unpack(n0)
 | 
				
			||||||
 | 
					  local x2,y2=_anch_unpack(n1)
 | 
				
			||||||
  local function _line_line(x3,y3,x4,y4)
 | 
					  local function _line_line(x3,y3,x4,y4)
 | 
				
			||||||
   local denom=(y4-y3)*(x2-x1)-(x4-x3)*(y2-y1)
 | 
					   local denom=(y4-y3)*(x2-x1)-(x4-x3)*(y2-y1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1429,12 +1497,15 @@ end
 | 
				
			|||||||
function rope:tug_orientxy()
 | 
					function rope:tug_orientxy()
 | 
				
			||||||
 local a1=self.dst
 | 
					 local a1=self.dst
 | 
				
			||||||
 local a0=self.dst.prev
 | 
					 local a0=self.dst.prev
 | 
				
			||||||
 local dx=a0.ax-a1.ax
 | 
					 local ax0,ay0=_anch_unpack(a0)
 | 
				
			||||||
 | 
					 local ax1,ay1=_anch_unpack(a1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 local dx=ax0-ax1
 | 
				
			||||||
 local tdx
 | 
					 local tdx
 | 
				
			||||||
 if (dx>3/8) tdx=1
 | 
					 if (dx>3/8) tdx=1
 | 
				
			||||||
 if (dx<-3/8) tdx=-1
 | 
					 if (dx<-3/8) tdx=-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 local dy=a0.ay-a1.ay
 | 
					 local dy=ay0-ay1
 | 
				
			||||||
 local tdy
 | 
					 local tdy
 | 
				
			||||||
 if abs(dy)>abs(dx)/2 then 
 | 
					 if abs(dy)>abs(dx)/2 then 
 | 
				
			||||||
  if (dy>3/8) tdy=1
 | 
					  if (dy>3/8) tdy=1
 | 
				
			||||||
@@ -1619,11 +1690,12 @@ function rope:_anchors_simplified()
 | 
				
			|||||||
 end
 | 
					 end
 | 
				
			||||||
 a=self.src
 | 
					 a=self.src
 | 
				
			||||||
 while a do
 | 
					 while a do
 | 
				
			||||||
 | 
					  local ax,ay=_anch_unpack(a)
 | 
				
			||||||
  local point={
 | 
					  local point={
 | 
				
			||||||
   x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5),
 | 
					   ax,ay,
 | 
				
			||||||
   ax=a.ax,ay=a.ay
 | 
					   x=flr(ax*8+0.5),y=flr(ay*8+0.5),
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  local aw=level:anchor_at(a.ax,a.ay)
 | 
					  local aw=level:anchor_at(a)
 | 
				
			||||||
  local l=self.latch
 | 
					  local l=self.latch
 | 
				
			||||||
  if aw then
 | 
					  if aw then
 | 
				
			||||||
   if (aw.adx==1) point.x-=1
 | 
					   if (aw.adx==1) point.x-=1
 | 
				
			||||||
@@ -1694,6 +1766,107 @@ function level_text:draw()
 | 
				
			|||||||
  print(xys[4],xys[2],xys[3],6)
 | 
					  print(xys[4],xys[2],xys[3],6)
 | 
				
			||||||
 end
 | 
					 end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-->8
 | 
				
			||||||
 | 
					--hint system
 | 
				
			||||||
 | 
					function rot13(s)
 | 
				
			||||||
 | 
					 local sord = pack(ord(s,1,#s))
 | 
				
			||||||
 | 
					 for i,c in ipairs(sord) do
 | 
				
			||||||
 | 
					  if (inorder{65, c, 77} or inorder{97, c, 109}) sord[i]=c+13
 | 
				
			||||||
 | 
					  if (inorder{78, c, 90} or inorder{110, c, 122}) sord[i]=c-13
 | 
				
			||||||
 | 
					 end
 | 
				
			||||||
 | 
					 return chr(unpack(sord))
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--hint file format:
 | 
				
			||||||
 | 
					-- each row is one hint.
 | 
				
			||||||
 | 
					-- 4 or 5 columns
 | 
				
			||||||
 | 
					-- separated with a
 | 
				
			||||||
 | 
					-- grave (`) character
 | 
				
			||||||
 | 
					-- [1] room# 
 | 
				
			||||||
 | 
					-- [2] x coord
 | 
				
			||||||
 | 
					-- [3] y coord
 | 
				
			||||||
 | 
					-- [4] message line 1 (rot13)
 | 
				
			||||||
 | 
					-- [5] message llne 2 (rot13)
 | 
				
			||||||
 | 
					-- row 5 can be omitted
 | 
				
			||||||
 | 
					-- for a 1-line hint
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- multiple hints for the same
 | 
				
			||||||
 | 
					-- room are revealed in order
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hints = {}
 | 
				
			||||||
 | 
					add(real_modules,hints)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function hints:init()
 | 
				
			||||||
 | 
					 local h = gsv[[0`42`57`🅾️ yVPX`  ■
 | 
				
			||||||
 | 
					0`42`73`❎, ❎ cHYY
 | 
				
			||||||
 | 
					1`35`34`⁘ sVYY
 | 
				
			||||||
 | 
					1`99`82`■ cHYY
 | 
				
			||||||
 | 
					1`42`98`⁘`VTABER
 | 
				
			||||||
 | 
					2`75`65`i <`⁘
 | 
				
			||||||
 | 
					2`104`73` ■`cHYY
 | 
				
			||||||
 | 
					2`27`42`⁘
 | 
				
			||||||
 | 
					3`51`106`■ cHYY
 | 
				
			||||||
 | 
					3`27`81`⁘ HAOYBPX ZR
 | 
				
			||||||
 | 
					3`91`33`■ FGNAQ`  URER]]
 | 
				
			||||||
 | 
					 for rec in all(h) do
 | 
				
			||||||
 | 
					  rec[4]=rot13(rec[4])
 | 
				
			||||||
 | 
					  if(rec[5]) rec[5]=rot13(rec[5])
 | 
				
			||||||
 | 
					  local lh = self[rec[1]]
 | 
				
			||||||
 | 
					  if lh then
 | 
				
			||||||
 | 
					   add(lh,rec)
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					   self[rec[1]] = {rec}
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					 end
 | 
				
			||||||
 | 
					 menuitem(1,"get hint",function() level.hintlevel+=1 end)
 | 
				
			||||||
 | 
					 menuitem(2,"hide hints",function() level.hintlevel=0 end)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function shdprint(txt,x,y,c)
 | 
				
			||||||
 | 
					 print(txt,x-1,y+1,1)
 | 
				
			||||||
 | 
					 print(txt,x,y,c)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hintflicker=split"7,10,9,8,8,9,10,7"
 | 
				
			||||||
 | 
					function hints:draw2()
 | 
				
			||||||
 | 
					 pal()
 | 
				
			||||||
 | 
					 local c=cycle(hintflicker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 for i,h in ipairs(self[level.ix]) do
 | 
				
			||||||
 | 
					  if (i > level.hintlevel) return
 | 
				
			||||||
 | 
					  local _,x,y,txt,txt2=unpack(h)
 | 
				
			||||||
 | 
					  shdprint(txt,x,y,c)
 | 
				
			||||||
 | 
					  if (txt2) shdprint(txt2,x,y+8,c)
 | 
				
			||||||
 | 
					 end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-->8
 | 
				
			||||||
 | 
					-- debug mouse support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					debugmouse = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- comment this out to disable debug mode
 | 
				
			||||||
 | 
					add(real_modules, debugmouse)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function debugmouse:init()
 | 
				
			||||||
 | 
					 poke(0x5f2d,1)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					debugflicker=split"5,6,7,15,14,8,2,4,9,10,11,3,12,13"
 | 
				
			||||||
 | 
					debugchs = split" ,x, ,□"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function debugmouse:draw3()
 | 
				
			||||||
 | 
					 if (stat(34) == 0) return
 | 
				
			||||||
 | 
					 pal(15,cycle(debugflicker,1.5))
 | 
				
			||||||
 | 
					 local x, y, c = stat(32), stat(33), cycle(debugchs,2)
 | 
				
			||||||
 | 
					 if (c == " ") spr(50,x,y)
 | 
				
			||||||
 | 
					 print(c,x,y,15)
 | 
				
			||||||
 | 
					 local px, py = mid(0,x,89), mid(0, y > 111 and y - 12 or y + 6, 117)
 | 
				
			||||||
 | 
					 print(fmt("(%v, %v)\n[%v, %v]",x,y,x\8,y\8),px,py,15)
 | 
				
			||||||
 | 
					 pal()
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__gfx__
 | 
					__gfx__
 | 
				
			||||||
000030000000002200003000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeff1ff1ff1fffffff1ffffff1fffffff1dddddddd111111110005000000000000
 | 
					000030000000002200003000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeff1ff1ff1fffffff1ffffff1fffffff1dddddddd111111110005000000000000
 | 
				
			||||||
003333300000332200333330eeffffffffffffffffffffeee5e555e55e555e5eff1ff1ffffffffffffffffffffffffffdddddddd111111110000500000000000
 | 
					003333300000332200333330eeffffffffffffffffffffeee5e555e55e555e5eff1ff1ffffffffffffffffffffffffffdddddddd111111110000500000000000
 | 
				
			||||||
@@ -1719,10 +1892,10 @@ eeee0000cc04405500444400efeeee5e11111111e5eeeefeeeeeeeeeeeeeeeeeffffffffffffffff
 | 
				
			|||||||
0a000aa4441a91a1bbabbbbbeffeeeeeeeeeeeeeeeeeeffeff1ff1ff11111111ff1111ff00000000000000000000000000000000000000000000000000000000
 | 
					0a000aa4441a91a1bbabbbbbeffeeeeeeeeeeeeeeeeeeffeff1ff1ff11111111ff1111ff00000000000000000000000000000000000000000000000000000000
 | 
				
			||||||
00a0044449a110a1bbbbbbbbeeffffffffffffffffffffeeff1ff1ffffffffffffffffff00000000000000000000000000000000000000000000000000000000
 | 
					00a0044449a110a1bbbbbbbbeeffffffffffffffffffffeeff1ff1ffffffffffffffffff00000000000000000000000000000000000000000000000000000000
 | 
				
			||||||
000aa111991111103bbbbbb3eeeeeeeeeeeeeeeeeeeeeeeeff1ff1ffffffffffffffffff00000000000000000000000000000000000000000000000000000000
 | 
					000aa111991111103bbbbbb3eeeeeeeeeeeeeeeeeeeeeeeeff1ff1ffffffffffffffffff00000000000000000000000000000000000000000000000000000000
 | 
				
			||||||
00000000991000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111999999111111111
 | 
					0000000099100000f765000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111999999111111111
 | 
				
			||||||
00000000990000000000000000000000000000000000000000000000000000000000000000000000000000000000000019911991999999911999999119999999
 | 
					00000000990000007700000000000000000000000000000000000000000000000000000000000000000000000000000019911991999999911999999119999999
 | 
				
			||||||
00000000990000000000000000000000000000000000000000000000000000000000000000000000000000000000000019977991999999911999999119999999
 | 
					00000000990000006060000000000000000000000000000000000000000000000000000000000000000000000000000019977991999999911999999119999999
 | 
				
			||||||
00000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000019911991999117111991199111711999
 | 
					00000000090000005005000000000000000000000000000000000000000000000000000000000000000000000000000019911991999117111991199111711999
 | 
				
			||||||
00000000aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000019911991999117111991199111711999
 | 
					00000000aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000019911991999117111991199111711999
 | 
				
			||||||
0000000077a000000000000000000000000000000000000000000000000000000000000000000000000000000000000019999991999999911997799119999999
 | 
					0000000077a000000000000000000000000000000000000000000000000000000000000000000000000000000000000019999991999999911997799119999999
 | 
				
			||||||
00000007777a00000000000000000000000000000000000000000000000000000000000000000000000000000000000019999991999999911991199119999999
 | 
					00000007777a00000000000000000000000000000000000000000000000000000000000000000000000000000000000019999991999999911991199119999999
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user