chameleonic/chameleonic.p8

1959 lines
75 KiB
Plaintext
Raw Normal View History

2022-12-17 20:16:26 +00:00
pico-8 cartridge // http://www.pico-8.com
version 39
2022-12-17 20:16:26 +00:00
__lua__
-- setup
2022-12-17 20:16:26 +00:00
modules={}
2022-12-18 04:38:49 +00:00
real_modules={}
2022-12-17 20:16:26 +00:00
frame=0
function _init()
_doall("init") end
function _update()
frame+=1
if (frame%1==0) _doall("update") end
function _draw()
_doall("draw") end
mnames={}
function names(root)
local n=mnames[root]
if(n)return all(n)
n={root.."0", root, root.."2", root.."3"}
mnames[root]=n
return all(n)
end
2022-12-17 20:16:26 +00:00
function _doall(x)
for n in names(x) do
2022-12-17 20:16:26 +00:00
for mod in all(modules) do
local f=mod[n]
if (f) f(mod)
2022-12-17 20:16:26 +00:00
end
end
end
-- source: https://www.lexaloffle.com/bbs/?pid=78990
gaps=split"57,23,10,4,1"
2022-12-17 20:16:26 +00:00
--{701,301,132,57,23,10,4,1}
function shellsort(a)
for gap in all(gaps) do
for i=gap+1,#a do
local x,j=a[i],i-gap
2022-12-17 20:16:26 +00:00
while j>=1 and a[j].key>x.key do
a[j+gap]=a[j]
j-=gap
end
a[j+gap]=x
end
end
end
function linefill(ax,ay,bx,by,r,c)
if(c) color(c)
local dx,dy=bx-ax,by-ay
-- avoid overflow
-- credits: https://www.lexaloffle.com/bbs/?tid=28999
2022-12-23 02:30:05 +00:00
local n,d=_mnmx(abs(dx),abs(dy))
n/=d
2022-12-17 20:16:26 +00:00
d*=sqrt(n*n+1)
if(d<0.001) return
local ca,sa=dx/d,-dy/d
2022-12-17 20:16:26 +00:00
-- polygon points
2022-12-23 02:30:05 +00:00
local spans={}
local function calcxy(u,v) return ax+u*ca+v*sa,ay-u*sa+v*ca end
local x0,y0=calcxy(0,r)
2022-12-23 02:32:14 +00:00
for s in all{{0,-r},{d,-r},{d,r},{0,r}} do
local x1,y1=calcxy(unpack(s))
local _x1,_y1=x1,y1
if(y0>y1) x0,y0,x1,y1=x1,y1,x0,y0
local dx=(x1-x0)/(y1-y0)
if(y0<0) x0-=y0*dx y0=-1
local cy0=y0\1+1
-- sub-pix shift
x0+=(cy0-y0)*dx
for y=y0\1+1,min(y1\1,127) do
-- open span?
local span=spans[y]
2022-12-23 02:30:05 +00:00
if (span) rectfill(x0,y,span,y)
spans[y]=x0
x0+=dx
2022-12-17 20:16:26 +00:00
end
x0,y0=_x1,_y1
end
2022-12-17 20:16:26 +00:00
end
function _apply(x,ts,a)
local t=deli(ts,1)
for k,v in pairs(t) do
2022-12-23 02:33:48 +00:00
if (k!="update") x[k]=v
2022-12-17 20:16:26 +00:00
end
if (t and t.update and not t.update(x,a)) add(ts,t,1)
2022-12-17 20:16:26 +00:00
end
function sgn0(x)
2022-12-23 02:35:24 +00:00
return x!=0 and sgn(x) or 0
2022-12-17 20:16:26 +00:00
end
function _mnmx(x,y)
if (x>y)return y,x
return x,y
2022-12-17 20:16:26 +00:00
end
2022-12-18 04:38:49 +00:00
2022-12-20 05:36:11 +00:00
function _rast(
2022-12-23 02:42:44 +00:00
xs,ys,x0,y0,x1,y1
2022-12-20 05:36:11 +00:00
)
2022-12-23 02:42:44 +00:00
local function _add()
local n=#xs
if (n==0 or xs[n]!=x0 or ys[n]!=y0) add(xs,x0) add(ys,y0)
end
2022-12-20 05:36:11 +00:00
2022-12-23 02:42:44 +00:00
local dx,dy=abs(x1-x0),abs(y1-y0)
2022-12-20 05:36:11 +00:00
local sx=-1
local sy=-1
if (x0<x1) sx=1
if (y0<y1) sy=1
local done=false,err
if dx>dy then
err=dx/2.0
2022-12-23 02:42:44 +00:00
while x0!=x1 do
_add()
2022-12-20 05:36:11 +00:00
err-=dy
2022-12-23 02:42:44 +00:00
if (err<0) y0+=sy err+=dx
x0+=sx
2022-12-20 05:36:11 +00:00
end
else
err=dy/2.0
2022-12-23 02:42:44 +00:00
while y0!=y1 do
_add()
2022-12-20 05:36:11 +00:00
err-=dx
2022-12-23 02:42:44 +00:00
if (err<0) x0+=sx err+=dy
y0+=sy
2022-12-20 05:36:11 +00:00
end
end
2022-12-23 02:42:44 +00:00
_add()
2022-12-20 05:36:11 +00:00
end
2022-12-18 04:38:49 +00:00
-->8
-- input
2022-12-18 04:38:49 +00:00
kbd={}
add(real_modules,kbd)
function kbd:init()
2022-12-20 00:25:38 +00:00
self.real=btn()
2022-12-23 02:49:03 +00:00
self.state={btn=0}
2022-12-18 04:38:49 +00:00
end
function kbd:update()
2022-12-20 00:25:38 +00:00
-- figure out what keys are _really_ pressed
2022-12-23 02:49:03 +00:00
local now_real,was_real=btn(),self.real
2022-12-20 00:25:38 +00:00
self.real=now_real
-- add keys that are really pressed
-- if they weren't really pressed before
-- (they may have been force-
-- released by :release())
2022-12-23 02:49:03 +00:00
local real_pressed=~was_real&now_real
2022-12-20 00:25:38 +00:00
2022-12-23 02:49:03 +00:00
local state=self.state
local now_down=state.btn&now_real|real_pressed
local was_down=state.btn
2022-12-20 00:25:38 +00:00
-- deduce pressed/released by changes in down
2022-12-23 02:49:03 +00:00
state.btn,state.btnp,state.btnr=
now_down,
~was_down&now_down,
~now_down&was_down
2022-12-20 00:25:38 +00:00
end
2022-12-23 02:49:03 +00:00
for _kbdi in all(split"btn,btnp,btnr") do
kbd[_kbdi]=function(self,i,t) return 1<<i&self.state[_kbdi]!=0 end
2022-12-20 00:25:38 +00:00
end
2022-12-18 04:38:49 +00:00
function kbd:release(i)
2022-12-23 02:49:03 +00:00
self.state.btn&=~(1<<i)
2022-12-18 04:38:49 +00:00
end
function tostring(any)
if type(any)=="table" then
2022-12-23 02:51:05 +00:00
local str = "{ "
for k,v in pairs(any) do
str=str..tostring(k).."->"..tostring(v).." "
end
return str.."}"
end
2022-12-23 02:51:05 +00:00
return tostr(any)
end
2022-12-18 04:38:49 +00:00
-->8
-- title screen
2022-12-18 04:38:49 +00:00
title={}
add(modules,title)
2022-12-23 02:52:54 +00:00
blinkcol=10
2022-12-18 04:38:49 +00:00
function title:draw()
cls(0)
-- this is right for 72x32
2022-12-18 05:36:25 +00:00
spr(3,28,56,9,2)
print("pyrex",32,73,7)
print("[nyeogmi]",62,73,7)
print("kistaro",32,79,7)
local lvlstr = "⬅️ "..start_level.." ➡️"
print(lvlstr,50,91,1)
print(lvlstr,51,90,blinkcol)
2022-12-18 04:38:49 +00:00
end
2022-12-23 02:52:54 +00:00
start_level=0
max_level=15
2022-12-18 04:38:49 +00:00
function title:update()
2022-12-23 02:52:54 +00:00
blinkcol=9
if (time()*4\1%2==0) blinkcol=10
2022-12-23 02:52:54 +00:00
if (btnp"0") start_level-=1
if (btnp"1") start_level+=1
start_level%=max_level
if (btnp"4" or btnp"5") modules=real_modules _init() music(0)
2022-12-18 04:38:49 +00:00
end
2022-12-20 00:38:21 +00:00
2022-12-17 20:16:26 +00:00
-->8
--level behaviors
2022-12-17 20:16:26 +00:00
level={}
2022-12-18 04:38:49 +00:00
add(real_modules,level)
2022-12-17 20:16:26 +00:00
function level:init()
level:reinit(start_level)
2022-12-17 20:16:26 +00:00
end
function level:reinit(n)
self.ix=n
self.todo={}
2022-12-23 03:07:43 +00:00
self.bigx,self.bigy=n%8,n\8
2022-12-17 20:16:26 +00:00
self:load_dynobjs()
self:recollide()
2022-12-17 23:15:56 +00:00
self:reanchor(true)
2022-12-17 23:08:54 +00:00
self:spawn_exit()
end
2022-12-18 00:25:20 +00:00
function level:restart()
self:reinit(self.ix)
end
2022-12-17 23:08:54 +00:00
function level:advance()
self:reinit(self.ix+1)
2022-12-17 20:16:26 +00:00
end
2022-12-21 07:22:27 +00:00
pitpal = {[0]=1,[7]=0,[6]=1,[4]=1}
2022-12-17 20:16:26 +00:00
function level:draw()
2022-12-17 23:48:52 +00:00
cls(1)
pal(1,0)
2022-12-17 20:16:26 +00:00
map(
2022-12-17 23:08:54 +00:00
self.bigx*16,self.bigy*16,
2022-12-17 20:16:26 +00:00
0,0,16,16,
64 -- flag 6: visible
)
2022-12-17 23:48:52 +00:00
for _,pit in pairs(self._pits) do
spr(pit.s,pit.px,pit.py)
if pit.contents then
pal(pitpal)
2022-12-17 23:48:52 +00:00
palt(0,false)
spr(pit.contents,pit.px,pit.py)
pal()
pal(1,0)
end
2022-12-17 23:48:52 +00:00
end
2022-12-17 20:16:26 +00:00
for _,crate in pairs(self._crates) do
spr(crate.s,crate.px,crate.py)
end
2022-12-17 23:48:52 +00:00
pal()
2022-12-17 20:16:26 +00:00
end
function level:busy()
for _,crate in pairs(self._crates) do
2022-12-17 20:16:26 +00:00
if (#crate.todo>0) return true
end
return false
end
function level:update()
_apply(self, self.todo)
2022-12-17 23:48:52 +00:00
local remove={}
for cix,crate in pairs(self._crates) do
2022-12-17 20:16:26 +00:00
_apply(crate, crate.todo)
2022-12-17 23:48:52 +00:00
if #crate.todo==0 then
local pit=self._pits[_mix(crate.mx,crate.my)]
if pit and not pit.contents then
2022-12-17 23:48:52 +00:00
add(remove,cix)
crate.dead=true
pit.contents=crate.s
end
end
end
for cix in all(remove) do
self._crates[cix]=nil
end
if #remove>0 then
self:recollide()
2022-12-23 03:07:43 +00:00
self:reanchor()
2022-12-17 20:16:26 +00:00
end
end
function level:load_dynobjs()
self._crates={}
2022-12-17 23:48:52 +00:00
self._pits={}
2022-12-23 03:07:43 +00:00
local crate_id=1
2022-12-17 20:16:26 +00:00
for mx=0,15,1 do
for my=0,15,1 do
local mxy=_mix(mx,my)
2022-12-17 23:48:52 +00:00
local px,py=mx*8,my*8
2022-12-17 20:16:26 +00:00
local s=self:_mget(mx,my)
local def=self:_get_cratedef(s)
if def then
2022-12-17 20:16:26 +00:00
self._crates[mxy]={
s=s,def=def,
2022-12-23 03:07:43 +00:00
id=crate_id,
2022-12-17 20:16:26 +00:00
mx=mx,my=my,
2022-12-17 23:48:52 +00:00
px=px,py=py,
2022-12-17 20:16:26 +00:00
todo={}
}
2022-12-23 03:07:43 +00:00
crate_id+=1
2022-12-17 20:16:26 +00:00
end
2022-12-17 23:48:52 +00:00
2022-12-23 03:07:43 +00:00
-- pit
if (s==28) self._pits[mxy]={s=s,mx=mx,my=my,px=px,py=py}
2022-12-17 20:16:26 +00:00
end
end
end
function level:recollide()
self._coll={}
for mx=0,15 do
for my=0,15 do
2022-12-17 20:16:26 +00:00
local mxy=_mix(mx,my)
self._coll[mxy]=
fget(self:_mget(mx,my),7) or
self._crates[mxy]!=nil
end
end
end
function level:reanchor()
local anch_new={}
for dxy in all{{-1,-1},{1,-1},{-1,1},{1,1}} do
local dx,dy=unpack(dxy)
assert(dx!=0 and dy!=0)
for mx0=0,15 do
for my0=0,15 do
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)
) then
local key="GEOM"..mx0..","..my0..","..dx..","..dy
anch_new[key]= {
ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy
}
end
end
2022-12-20 02:01:02 +00:00
end
for _,cr in pairs(self._crates) do
local key="CRATE"..cr.id..","..dx..","..dy
local mx0,my0=cr.mx,cr.my
local mx1,my1=mx0+dx,my0+dy
anch_new[key]={
ax=max(mx0,mx1),ay=max(my0,my1),adx=-dx,ady=-dy
}
end
2022-12-17 20:16:26 +00:00
end
local anch_old=self._anch
if (anch_old==nil) anch_old={}
for _,old in pairs(anch_old) do
old.dropped=true
end
2022-12-17 20:16:26 +00:00
for k,new in pairs(anch_new) do
local old=anch_old[k]
if old then
anch_new[k]=old
old.ax_old,old.ay_old,old.ax,old.ay,old.adx,old.ady=old.ax,old.ay,new.ax,new.ay,new.adx,new.ady
old.dropped=nil
2022-12-17 20:16:26 +00:00
end
end
self._anch=anch_new
self._anch_keys={}
for k,_ in pairs(self._anch) do
add(self._anch_keys,{key=k})
2022-12-19 01:37:00 +00:00
end
shellsort(self._anch_keys)
for point in self:anchor_points() do
2022-12-23 03:07:43 +00:00
if (point.ax_old and player.rope) player.rope:be_pushed_by(point,point.ax_old,point.ay_old)
point.ax_old,point.ay_old=nil,nil
end
2022-12-19 01:37:00 +00:00
2022-12-23 03:07:43 +00:00
if (player.rope) player.rope:relax()
2022-12-17 20:16:26 +00:00
end
2022-12-17 23:08:54 +00:00
function level:win_at(mx,my)
return self._wins[_mix(mx,my)]
end
2022-12-17 20:16:26 +00:00
function level:anchor_points()
keys=all(self._anch_keys)
return function()
local k=keys()
if (k==nil) return nil
return self._anch[k.key]
end
end
2022-12-17 23:48:52 +00:00
function level:get_open_pit(mx,my)
local pit=self._pits[_mix(mx,my)]
if (pit and pit.contents==nil) return pit
end
2022-12-17 23:08:54 +00:00
function level:spawn_exit()
self._wins={}
local spawned=false
local spawn_at=function(x,y)
if (self:_mget(x,y)!=1) return
assert(not spawned,x..","..y)
spawned=true
player:reinit(x,y)
2022-12-17 23:15:56 +00:00
player.orientx=-1
if (x<8) player.orientx=1
2022-12-17 23:08:54 +00:00
end
local win_at=function(x,y)
2022-12-18 04:39:58 +00:00
if (self:_mget(x,y)!=18) return
for nx=x-1,x+1 do
for ny=y-1,y+1 do
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
-- next check: is at least one of
-- nx or ny out of range [0, 15]?
if (nx | ny) & 0xFFF0 ~= 0 then
self._wins[_mix(nx,ny)]=true
end
2022-12-17 23:08:54 +00:00
end
end
end
for f in all{spawn_at,win_at} do
for x=1,14 do f(x,0) f(x,15) end
for y=0,15 do f(0,y) f(15,y) end
end
assert(spawned)
end
2022-12-17 20:16:26 +00:00
function level:mcoll(mx,my)
2022-12-17 23:08:54 +00:00
return self._coll[_mix(mx,my)]!=false
2022-12-17 20:16:26 +00:00
end
function level:pcoll(px,py)
return self:mcoll(px\8,py\8)
end
function level:get_crate(mx,my)
return self._crates[_mix(mx,my)]
end
function level:_mget(mx,my)
return mget(
self.bigx*16+mx,
self.bigy*16+my
)
end
function _amix(ax,ay)
return ax..","..ay
end
function _mix(mx,my)
return mx..","..my
end
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
-- crate spec:
-- "up" == 1
-- "right" == 2
-- "down" == 4
-- "left" == 8
--
-- +1+
-- 8 2
-- +4+
2022-12-17 20:16:26 +00:00
function level:_get_cratedef(s)
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
if (s<64 or s>=80) return
return s & 0x000F
2022-12-17 20:16:26 +00:00
end
function level:get_latch(dx,dy,px,py)
local mx,my=px\8,py\8
local mxy=_mix(mx,my)
local crate=self._crates[mxy]
2022-12-19 00:46:46 +00:00
local dx1,dy1=-sgn0(dx),-sgn0(dy)
2022-12-17 20:16:26 +00:00
if crate then
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
if crate.def & dy1*dy1*(2.5+1.5*dy1)+dx1*dx1*(5-3*dx1) ~= 0 then
2022-12-17 20:16:26 +00:00
return {
el="crate",
2022-12-19 00:46:46 +00:00
dx=dx1,dy=dy1,
ax_offset=dx1*0.5,
ay_offset=dy1*0.5,
2022-12-17 20:16:26 +00:00
rec=crate
}
end
end
local m=self:_mget(mx,my)
if
2022-12-19 00:46:46 +00:00
(m==60 and dy1<0) or
(m==61 and dx1>0) or
(m==62 and dy1>0) or
(m==63 and dx1<0)
2022-12-17 20:16:26 +00:00
then
return {
el="eyehook",
2022-12-19 00:46:46 +00:00
dx=dx1,dy=dy1,
ax_offset=dx1*0.5,
ay_offset=dy1*0.5,
rec={mx=mx,my=my,px=mx*8,py=my*8},
2022-12-17 20:16:26 +00:00
}
end
end
ropecheck=split"-0.8,0.4,0.2"
2022-12-17 20:16:26 +00:00
function level:can_move(
2022-12-17 23:08:54 +00:00
is_player,
2022-12-17 20:16:26 +00:00
mx0,my0,dmx,dmy,exclude_src,exclude_dst
)
2022-12-23 03:07:43 +00:00
local mx1,my1=mx0+dmx,my0+dmy
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()
2022-12-17 23:08:54 +00:00
2022-12-23 03:07:43 +00:00
if (self:mcoll(mx1,my1) or player.x==mx1 and player.y==my1) return false
2022-12-18 00:57:47 +00:00
2022-12-17 20:16:26 +00:00
if player.rope then
2022-12-23 03:07:43 +00:00
local w,h=1.6,0.2
if (dmx==0) w,h=0.2,1.6
if (player.rope:collide_mrect(mx0+ropecheck[dmx+2],my0+ropecheck[dmy+2],w,h,exclude_src,exclude_dst)) return false
2022-12-17 20:16:26 +00:00
end
return true
end
function level:tug_crate(mx0,my0,dmx,dmy)
local mxy0=_mix(mx0,my0)
local existing=self._crates[mxy0]
2022-12-23 03:07:43 +00:00
if (not existing) return
2022-12-17 20:16:26 +00:00
self._crates[mxy0]=nil
local mx1,my1=mx0+dmx,my0+dmy
2022-12-23 03:07:43 +00:00
local px1,py1=mx1*8,my1*8
2022-12-17 20:16:26 +00:00
existing.todo={
2022-12-23 03:07:43 +00:00
{px=px1+dmx,py=py1+dmy,mx=mx1,my=my1,update=function()
self:recollide()
self:reanchor()
2022-12-17 20:16:26 +00:00
return true
end},
2022-12-23 03:07:43 +00:00
{px=px1,py=py1}
2022-12-17 20:16:26 +00:00
}
2022-12-23 03:07:43 +00:00
self._crates[_mix(mx1,my1)]=existing
2022-12-20 05:36:11 +00:00
end
2022-12-17 20:16:26 +00:00
-->8
--player handling
2022-12-17 20:16:26 +00:00
player={}
2022-12-18 04:38:49 +00:00
add(real_modules,player)
2022-12-17 20:16:26 +00:00
function player:init()
2022-12-18 00:25:20 +00:00
-- don't change this on reinit:
-- it stays the same when the level is changed or reloaded
self.vanish_frame=0
2022-12-17 20:16:26 +00:00
end
function player:reinit(x,y)
2022-12-23 03:22:23 +00:00
self.x,self.y=x,y
self.px,self.py=0,0
2022-12-17 20:16:26 +00:00
self.todo={}
2022-12-17 23:48:52 +00:00
self.fall_frame=0
2022-12-17 20:16:26 +00:00
2022-12-23 03:22:23 +00:00
self.orientx,self.orienty=-1,0
2022-12-17 20:16:26 +00:00
end
function player:update()
2022-12-18 00:25:20 +00:00
-- this is a non-gameplay action that takes precedence over
-- all gameplay actions
self:_vanish_if_requested()
2022-12-23 03:22:23 +00:00
if not (#self.todo>0 or level:busy()) then
2022-12-17 23:08:54 +00:00
if level:win_at(self.x,self.y) then
level:advance()
return
end
2022-12-17 23:48:52 +00:00
if level:get_open_pit(self.x,self.y) then
self.todo={{update=self._fall}}
return
end
2022-12-18 04:38:49 +00:00
if kbd:btn(0) then
2022-12-20 00:25:38 +00:00
self.orientx=-1
self.orienty=0
2022-12-18 04:38:49 +00:00
elseif kbd:btn(1) then
2022-12-20 00:25:38 +00:00
self.orientx=1
self.orienty=0
2022-12-18 04:38:49 +00:00
elseif kbd:btn(2) then
2022-12-20 00:25:38 +00:00
self.orienty=-1
2022-12-18 04:38:49 +00:00
elseif kbd:btn(3) then
2022-12-20 00:25:38 +00:00
self.orienty=1
end
if kbd:btn(4) then
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
if kbd:btnp(4) and self.rope then
2022-12-20 00:25:38 +00:00
self.rope:destroy()
kbd:release(4)
2022-12-17 20:16:26 +00:00
end
2022-12-20 00:25:38 +00:00
-- wait for user to release it
else
2022-12-23 03:22:23 +00:00
local function try_move(dx,dy,f)
if (level:can_move(true,self.x,self.y,dx,dy,0,2)) self.todo=f return
wrongbleep:bleep()
end
2022-12-20 00:25:38 +00:00
if kbd:btn(0) then
2022-12-23 03:22:23 +00:00
try_move(-1,0,{{orientx=-1,orienty=0,px=-2},{px=-7},{x=self.x-1,px=0}})
2022-12-20 00:25:38 +00:00
elseif kbd:btn(1) then
2022-12-23 03:22:23 +00:00
try_move(1,0,{{orientx=1,orienty=0,px=2},{px=7},{x=self.x+1,px=0}})
2022-12-20 00:25:38 +00:00
elseif kbd:btn(2) then
2022-12-23 03:22:23 +00:00
try_move(0,-1,{{orienty=-1,py=-2},{py=-7},{y=self.y-1,py=0}})
2022-12-20 00:25:38 +00:00
elseif kbd:btn(3) then
2022-12-23 03:22:23 +00:00
try_move(0,1,{{orienty=1,py=2},{py=7},{y=self.y+1,py=0}})
elseif not self.rope and kbd:btnr(4) then
local dx,dy=self.orientx,self.orienty
2022-12-17 20:16:26 +00:00
if (dy!=0) dx=0
local x,y=self.x,self.y
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,
2022-12-22 01:50:06 +00:00
self.x+0.5,self.y+0.5,
level:get_latch(dx,dy,x*8,y*8)
)
2022-12-17 20:16:26 +00:00
self.todo={{
update=function()
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
return not self.rope or self.rope:latched()
2022-12-17 20:16:26 +00:00
end
2022-12-20 00:25:38 +00:00
}}
elseif kbd:btnp(5) then
2022-12-23 03:22:23 +00:00
if (self.rope and not self.rope:tug()) wrongbleep:bleep(9)
2022-12-17 20:16:26 +00:00
end
end
end
_apply(self,self.todo)
if self.rope then
self.rope:update()
2022-12-22 03:54:09 +00:00
if self.rope:done_reeling() then
2022-12-23 03:22:23 +00:00
local latch=self.rope.latch
self.x=latch.rec.mx+latch.dx
self.y=latch.rec.my+latch.dy
2022-12-22 03:54:09 +00:00
end
2022-12-23 03:22:23 +00:00
self.rope:drag_dst(
self.x+self.px/8+0.5,
self.y+self.py/8+0.5
)
2022-12-17 20:16:26 +00:00
2022-12-18 00:57:47 +00:00
local tdx,tdy=self.rope:tug_orientxy()
2022-12-23 03:22:23 +00:00
if (tdx) self.orientx=tdx
if (tdy) self.orienty=tdy
2022-12-18 00:57:47 +00:00
2022-12-23 03:22:23 +00:00
if (self.rope:done()) self.rope=nil
2022-12-17 20:16:26 +00:00
end
end
2022-12-18 00:25:20 +00:00
function player:_vanish_if_requested()
2022-12-18 04:38:49 +00:00
if kbd:btn(5) then
2022-12-18 00:25:20 +00:00
self.vanish_frame+=1
2022-12-18 00:26:30 +00:00
if (self.fall_frame>0 or self.vanish_frame>20) then
self.rope=nil
2022-12-18 00:25:20 +00:00
level:restart()
2022-12-18 04:38:49 +00:00
kbd:release(5)
2022-12-18 00:26:30 +00:00
self.vanish_frame=20
2022-12-18 00:25:20 +00:00
end
else
self.vanish_frame-=1
2022-12-17 23:48:52 +00:00
end
2022-12-18 00:25:20 +00:00
self.vanish_frame=max(self.vanish_frame,0)
end
function player:_fall()
if (self.fall_frame<10) self.fall_frame+=1
2022-12-17 23:48:52 +00:00
end
2022-12-17 20:16:26 +00:00
function player:draw()
local px=self.x*8+self.px+wrongbleep:vibrate()
local py=self.y*8+self.py+wrongbleep:vibrate()
2022-12-18 04:38:49 +00:00
local head=1-self.orienty
2022-12-17 23:48:52 +00:00
local vanish_level=max((self.vanish_frame-4)/16,0)
2022-12-18 00:25:20 +00:00
local invis_level=max(self.fall_frame/10,4*(vanish_level-0.75))
if (invis_level>=1.0) return
2022-12-23 03:22:23 +00:00
--[[
local HEAD=14--3
local BODY=12--12
local TAIL=14--14
local IRIS=7--9
local PUPIL=0--0
2022-12-23 03:22:23 +00:00
]]
-- in order: head,body,iris,pupil,body again,tail
local palette=split"-1,14,14,12,12,-1,-1,-1,7,0,-1,12,14,14,14"
local function setpal()
--[[
-- head
nil,14,14,
--body
[2]=HEAD,
[3]=HEAD,
[4]=BODY,
[5]=BODY,
[9]=IRIS,
[10]=PUPIL,
[12]=BODY,
[13]=TAIL,
[14]=TAIL,
[15]=TAIL,
2022-12-23 03:22:23 +00:00
]]
pal(palette)
-- vanish colors
local vanish=split"13,15,14,5,4,12,2,3,9,10"
for i,ilc in ipairs(vanish) do
if (vanish_level>i/#vanish) pal(ilc,1)
end
2022-12-18 00:25:20 +00:00
2022-12-23 03:22:23 +00:00
if (self.fall_frame>3) local zc=@0x5f00&0xf0 for i=0x5f00,0x5f0c,4 do poke4(i,0x0101.0101) end poke(0x5f00,zc|0x01)
2022-12-17 23:48:52 +00:00
end
2022-12-22 03:54:09 +00:00
local rx,ry=self.x*8+self.px+1,self.y*8+self.py+2
if (self.orientx==1) rx+=6
if self.rope then
local rx_adj,ry_adj=self.rope:affected_src_xy(rx,ry)
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
if rx_adj then
2022-12-22 03:54:09 +00:00
local drx,dry=rx_adj-rx,ry_adj-ry
rx,ry=rx+drx,ry+dry
px,py=px+drx,py+dry
end
end
2022-12-17 20:16:26 +00:00
if self.orientx==-1 then
setpal()
2022-12-17 20:16:26 +00:00
spr(16,px+6,py-2,1,1)
spr(17,px+1,py,1,1)
2022-12-22 02:11:19 +00:00
if (self.rope and invis_level<=0.25) pal() self.rope:draw(self.x*8+self.px+1,self.y*8+self.py+2) setpal()
2022-12-17 20:16:26 +00:00
spr(head,px-3,py-3,1,1)
else
setpal()
2022-12-17 20:16:26 +00:00
spr(16,px-6,py-2,1,1,true)
spr(17,px-1,py,1,1,true)
2022-12-22 02:11:19 +00:00
if (self.rope and invis_level<=0.25) pal() self.rope:draw(self.x*8+self.px+7,self.y*8+self.py+2) setpal()
2022-12-17 20:16:26 +00:00
spr(head,px+3,py-3,1,1,true)
end
2022-12-17 23:48:52 +00:00
pal()
2022-12-17 20:16:26 +00:00
end
-->8
-- rope physics
2022-12-17 20:16:26 +00:00
rope={}
rope.__index=rope
function rope:new(
src_ax,src_ay,dst_ax,dst_ay,latch
2022-12-17 20:16:26 +00:00
)
local r={
id=0,
anchors={
2022-12-23 03:23:41 +00:00
{ax=src_ax,ay=src_ay},
{ax=dst_ax,ay=dst_ay}
},
state={name="cast",frame=0},
latch=latch,
2022-12-17 20:16:26 +00:00
}
r.src=r.anchors[1]
r.dst=r.anchors[2]
r.src.next=r.dst
r.dst.prev=r.src
2022-12-17 20:16:26 +00:00
setmetatable(r,rope)
return r
end
2022-12-18 04:10:01 +00:00
function rope:latched()
return self.state.name=="latched"
2022-12-17 20:16:26 +00:00
end
function rope:done()
2022-12-18 04:10:01 +00:00
return self.state.name=="done"
2022-12-17 20:16:26 +00:00
end
2022-12-22 03:54:09 +00:00
function rope:done_reeling()
return self.state.name=="done" and self.state.reelin
end
2022-12-17 20:16:26 +00:00
function rope:update()
2022-12-18 04:10:01 +00:00
if self.state.name=="cast" then
self.state.frame+=1
if (self.state.frame>=3) self.state={name="latched"}
2022-12-18 04:10:01 +00:00
elseif self.state.name=="latched" then
if (self.latch==nil) wrongbleep:bleep(5) self:destroy() return
2022-12-19 00:07:15 +00:00
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
if self.latch and self.latch.rec then
2022-12-19 00:07:15 +00:00
self:drag_src(
self.latch.rec.mx+0.5+self.latch.ax_offset,
self.latch.rec.my+0.5+self.latch.ay_offset
2022-12-19 00:07:15 +00:00
)
if self.latch.rec.dead==true then
self:destroy()
2022-12-19 00:07:15 +00:00
end
end
if (not self:_check_sane()) self:destroy()
2022-12-18 04:10:01 +00:00
elseif self.state.name=="destroy" then -- destroy
self.state.frame+=1
2022-12-22 03:54:09 +00:00
if (self.state.frame>=5) self.state={name="done",reelin=self.state.reelin}
2022-12-18 22:53:58 +00:00
else
-- done state
2022-12-17 20:16:26 +00:00
end
2022-12-18 04:10:01 +00:00
end
2022-12-17 20:16:26 +00:00
2022-12-22 03:54:09 +00:00
function rope:destroy(reelin)
2022-12-18 04:10:01 +00:00
if (self.state.name=="destroy" or self.state.name=="done") return
2022-12-22 03:54:09 +00:00
self.state={name="destroy",frame=0,reelin=reelin}
end
function rope:affected_src_xy(artificial_px,artificial_py)
-- this is the loop from :draw but simplified
if (not self.state.reelin) return
perc_to_show=(1.0-self.state.frame/8)^2
local points=self:_anchors_simplified()
points[#points]={x=artificial_px,y=artificial_py}
local len=0
for i=1,#points-1 do len+=distance(points[i],points[i+1]) end
local len_to_show=perc_to_show*len
local len_cumulative=0
for i=1,#points-1 do
local src=points[i]
local dst=points[i+1]
local x,y=dst.x,dst.y
local dx,dy=src.x-x,src.y-y
local len_here=len_to_show-len_cumulative
local dist_base=distance_dxy(dx,dy)
len_cumulative+=dist_base
if len_here>0 and dist_base>0 then
local coef=min(len_here/dist_base,1.0)
return x+dx-dx*coef,y+dy-dy*coef
end
end
return points[1]
2022-12-17 20:16:26 +00:00
end
2022-12-22 02:11:19 +00:00
function rope:draw(artificial_px,artificial_py)
2022-12-18 22:53:58 +00:00
local points,highlight=self:_tug(true)
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
local n,perc_to_show,from_end = self.state.name,1.0,false
if (n=="done") return
if (n=="cast") perc_to_show=self.state.frame/2
if (n=="destroy") perc_to_show=(1.0-self.state.frame/8)^2
2022-12-22 03:54:09 +00:00
if (self.state.reelin) from_end=true
2022-12-18 04:10:01 +00:00
2022-12-22 02:11:19 +00:00
points[#points]={x=artificial_px,y=artificial_py}
2022-12-19 02:14:15 +00:00
2022-12-18 04:10:01 +00:00
local len=0
for i=1,#points-1 do
len+=distance(points[i],points[i+1])
end
local len_to_show=perc_to_show*len
local len_cumulative=0
2022-12-22 03:54:09 +00:00
local ia,iz,istep=#points-1,1,-1
if (from_end) ia,iz,istep=1,#points-1,1
for i=ia,iz,istep do
2022-12-17 20:16:26 +00:00
local src=points[i]
local dst=points[i+1]
2022-12-18 04:10:01 +00:00
local x,y=dst.x,dst.y
local dx,dy=src.x-x,src.y-y
local len_here=len_to_show-len_cumulative
local dist_base=distance_dxy(dx,dy)
2022-12-22 03:54:09 +00:00
len_cumulative+=dist_base
2022-12-18 04:10:01 +00:00
if len_here>0 and dist_base>0 then
local coef=min(len_here/dist_base,1.0)
2022-12-22 03:54:09 +00:00
if from_end then
x,y=x+dx-dx*coef,y+dy-dy*coef
dx,dy=dx*coef,dy*coef
else
dx,dy=dx*coef,dy*coef
end
2022-12-17 20:16:26 +00:00
2022-12-18 22:53:58 +00:00
local color=8
2022-12-19 00:46:46 +00:00
if (highlight==i) color=12
2022-12-18 22:53:58 +00:00
linefill(x,y,x+0.25*dx,y+0.25*dy,1.0,color)
linefill(x+0.25*dx,y+0.25*dy,x+1*dx,y+1*dy,0.5,color)
linefill(x+0.9*dx,y+0.9*dy,x+dx,y+dy,1.0,color)
circfill(x+dx+0.5,y+dy+0.5,1.0,color)
2022-12-18 04:10:01 +00:00
end
2022-12-17 20:16:26 +00:00
end
2022-12-19 00:46:46 +00:00
-- draw latch
2022-12-22 03:54:09 +00:00
if self.latch!=nil and self.latch.rec and (perc_to_show>=1.0 or from_end) then
local x,y=self.latch.rec.px,self.latch.rec.py
2022-12-19 00:46:46 +00:00
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,y+3,x+2,y+4,color)
2022-12-19 00:46:46 +00:00
elseif self.latch.dx==1 and self.latch.dy==0 then
rectfill(x+5,y+3,x+7,y+4,color)
2022-12-19 00:46:46 +00:00
elseif self.latch.dx==0 and self.latch.dy==-1 then
rectfill(x+3,y,x+4,y+2,color)
2022-12-19 00:46:46 +00:00
elseif self.latch.dx==0 and self.latch.dy==1 then
rectfill(x+3,y+5,x+4,y+7,color)
2022-12-19 00:46:46 +00:00
end
end
-- debug
2022-12-23 03:24:41 +00:00
--[[
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
local n0=n1.prev
local n2=n1.next
if n0!=nil and n2!=nil then
if n1.associated_with then
local _,_,_,adx,ady=would_stick(n0.ax,n0.ay,n1.associated_with,n2.ax,n2.ay)
assert(adx==-1 or adx==0 or adx==1)
assert(ady==-1 or ady==0 or ady==1)
--assert(not (adx==0 and ady==0))
local c=3
if (n1.associated_with.dropped) c=4
rectfill(x+2,y+2,x+4,y+4,c)
pset(x+adx*2,y,9)
pset(x,y+ady*2,9)
else
rectfill(x+2,y+2,x+4,y+4,2)
end
else
rectfill(x+2,y+2,x+4,y+4,4)
end
n1=n1.next
end
2022-12-17 20:16:26 +00:00
for _,p in pairs(level._anch) do
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)
2022-12-17 20:16:26 +00:00
end
2022-12-23 03:24:41 +00:00
]]--
2022-12-17 20:16:26 +00:00
end
function rope:drag_dst(x,y)
self:drag(self.dst,x,y)
2022-12-17 20:16:26 +00:00
end
function rope:drag_src(x,y)
self:drag(self.src,x,y)
2022-12-17 20:16:26 +00:00
end
function rope:drag(n1,ax_new,ay_new)
self:relax()
self:_drag(n1,ax_new,n1.ay)
self:_drag(n1,ax_new,ay_new)
self:relax()
2022-12-20 02:01:02 +00:00
end
function rope:relax()
local n0=self.src
while true do
local n1=n0.next
if (n1==nil) break
local n2=n1.next
if n0.ax==n1.ax and n0.ay==n1.ay then
n0.next=n2
2022-12-22 19:25:31 +00:00
if (n2!=nil) n2.prev=n0
else
n0=n0.next
end
end
local n0=self.src
while true do
if (n0==nil) return
local n1=n0.next
if (n1==nil) return
local n2=n1.next
if (n2==nil) return
if n1.associated_with!=nil then
local x0,y0=n0.ax,n0.ay
local x1,y1=n1.ax,n1.ay
local x2,y2=n2.ax,n2.ay
2022-12-22 19:25:31 +00:00
if x1!=n1.associated_with.ax or y1!=n1.associated_with.ay then
-- printh("dragging home: "..tostring{n1.ax,n1.ay}.."->"..tostring(n1.associated_with))
self:_drag(n1,n1.associated_with.ax,n1.associated_with.ay)
end
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
2022-12-22 19:25:31 +00:00
-- 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
n0.next=n2
n2.prev=n0
n1.next=nil
n1.prev=nil
else n0=n0.next end
else n0=n0.next end
end
end
function rope:_check_sane()
2022-12-22 03:54:09 +00:00
if (not self:latched()) return true
if (level:busy()) return true
local n0=self.src
local qxs,qys={},{}
while true do
local n1=n0.next
if (n1==nil) break
2022-12-23 02:42:44 +00:00
_rast(qxs,qys,flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2))
n0=n1
end
2022-12-17 21:52:37 +00:00
local function _possible_tiles(qx,qy)
local mx0=(qx-1)\2
local mx1=qx\2
local my0=(qy-1)\2
local my1=qy\2
2022-12-19 00:07:15 +00:00
local poss={}
for mx=mx0,mx1 do
for my=my0,my1 do
add(poss,{mx=mx,my=my})
end
2022-12-19 00:07:15 +00:00
end
return poss
2022-12-19 00:07:15 +00:00
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
-- 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 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
2022-12-19 00:07:15 +00:00
if (not ok) return false
end
end
return true
2022-12-17 20:16:26 +00:00
end
function would_stick(x0,y0,anchor,x2,y2)
local x1,y1=anchor.ax,anchor.ay
2022-12-17 20:16:26 +00:00
local dx=x2-x0
local dy=y2-y0
2022-12-17 20:16:26 +00:00
2022-12-22 05:37:26 +00:00
-- there is no reason for an acute angle to stick around in this world
--[[
2022-12-22 05:37:26 +00:00
local ang0=atan2(x2-x1,y2-y1)
local ang2=atan2(x0-x1,y0-y1)
local diff=abs((ang0-ang2 + 0.5)%1-0.5)
if (diff<0.25) return false,x0,y0,0,0
]]--
2022-12-22 05:37:26 +00:00
local adx,ady
local x1_new,y1_new
if abs(dx)>abs(dy) then
if (x0>x2) dx,x0,y0,x2,y2=-dx,x2,y2,x0,y0
local dprop=(x1-x0)/dx
x1_new,y1_new=x1,y0+dprop*(y2-y0)
ady=sgn0(y1_new-y1)
adx=0
if (y0>y2) adx=ady
if (y0<y2) adx=-ady
else
if (y0>y2) dy,x0,y0,x2,y2=-dy,x2,y2,x0,y0
local dprop=(y1-y0)/dy
x1_new,y1_new=x0+dprop*(x2-x0),y1
adx=sgn0(x1_new-x1)
ady=0
if (x0>x2) ady=adx
if (x0<x2) ady=-adx
2022-12-17 20:16:26 +00:00
end
local wouldnt=anchor.dropped or (anchor.adx!=adx or anchor.ady!=ady)
2022-12-17 20:16:26 +00:00
return not wouldnt,x1_new,y1_new,adx,ady
2022-12-17 20:16:26 +00:00
end
function rope:be_pushed_by(anchor,ax_old,ay_old)
local n0=self.src
local ax_new,ay_new=anchor.ax,anchor.ay
while true do
n1=n0.next
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
if (not n1) return
local nx0,ny0=n0.ax,n0.ay
local nx1,ny1=n1.ax,n1.ay
if
2022-12-22 05:55:21 +00:00
(ax_new==ax_old and nx0<=anchor.ax and anchor.ax<=nx1) and
(ay_new==ay_old and ny0<=anchor.ay and anchor.ay<=ny1) and
not (anchor.ax==nx0 and anchor.ay==ny0) and
not (anchor.ax==nx1 and anchor.ay==ny1) and
2022-12-22 05:55:21 +00:00
(_which_side(ax_old,ay_old,nx0,ny0,nx1,ny1)!=
_which_side(ax_new,ay_new,nx0,ny0,nx1,ny1)
) and would_stick(nx0,ny0,anchor,nx1,ny1)
then
local nx05,ny05
if ax_new==ax_old then
nx05=anchor.ax
ny05=ny0+(nx05-nx0)/(nx1-nx0) * (ny1-ny0)
--printh("found (x): "..tostring({nx05,ny05}))
elseif ay_new==ay_old then
ny05=anchor.ay
nx05=nx0+(ny05-ny0)/(ny1-ny0) * (nx1-nx0)
--printh("found (y): "..tostring({nx05,ny05}))
else
assert(false,"wtf?")
end
local n05={ax=nx05,ay=ny05,associated_with=anchor,prev=n0,next=n1}
--printh("adding: "..tostring({nx05,ny05,anchor}))
n0.next=n05
n1.prev=n05
self:_drag(n05,anchor.ax,anchor.ay)
-- printh("dragged: "..tostring({n05.ax,n05.ay,anchor}))
-- printh("local: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with))
else
n0=n0.next
end
end
end
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
2022-12-17 20:16:26 +00:00
if ax_far0==ax_far1 then
local ax_far=ax_far0
local ax0,ax1=_mnmx(ax_pivot,ax_far)
ay_far_old=ay_far0
for ay_far_new in _stepfrom(ay_far0,ay_far1) do
for anchor in level:anchor_points() do
if
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and
2022-12-22 19:25:31 +00:00
-- not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and
not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and
(ax0<=anchor.ax and anchor.ax<=ax1) and
would_stick(ax_pivot,ay_pivot,anchor,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
ay_far_old=ay_far_new
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
for ax_far_new in _stepfrom(ax_far0,ax_far1) do
for anchor in level:anchor_points() do
if
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and
2022-12-22 19:25:31 +00:00
-- not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and
not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and
would_stick(ax_pivot,ay_pivot,anchor,ax_far_new,ay_far) and
(ay0<=anchor.ay and anchor.ay<=ay1) and
(
_which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far_old,ay_far) !=
_which_side(anchor.ax,anchor.ay,ax_pivot,ay_pivot,ax_far_new,ay_far)
)
then
return anchor
end
end
ax_far_old=ax_far_new
end
2022-12-17 20:16:26 +00:00
end
end
local ax1_old,ay1_old=n1.ax,n1.ay
n1.ax=ax1_new
n1.ay=ay1_new
2022-12-17 20:16:26 +00:00
local n0=n1.prev
while true do
if (n0==nil) break
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}
2022-12-22 19:25:31 +00:00
-- printh("creating pre: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with))
n0.next=n05
n1.prev=n05
n0=n05
end
2022-12-17 20:16:26 +00:00
local n2=n1.next
while true do
if (n2==nil) break
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}
2022-12-22 19:25:31 +00:00
-- printh("creating post: "..tostring(n1.associated_with).."->"..tostring(n15.associated_with).."->"..tostring(n2.associated_with))
n1.next=n15
n2.prev=n15
n2=n15
2022-12-17 20:16:26 +00:00
end
end
function _stepfrom(x0,x1)
local done=false
if x0==x1 then
return function()
Save some tokens in horrible, horrible ways. (#13) replace comparisons with bit math bullshit integers in the range [0, 15] fit entirely in the bit mask 0x000F. integers out of that range will have at least one bit 0x0010 or higher, or will have the sign bit 0x8000 set. so to find out if one of two numbers is out of range [0, 15], we can check the bit mask of their bitwise or. this saves tokens and cycles. it is also completely illegible. very in the spirit of Pico-8, I love it. comment the bullshit it needs it packed crate representation don't bother exploding crates into four bools, and then comparing them all individually to a bunch of conditions. absurd bit manipulation bullshit saves cycles and tokens. leaving a crate's movement rule represented as four bits means we can exploit our previous calculation of dx1 and dy1, which must each either be 0x0001 or 0x8FFF, and violently hammer them down to align with this bit-packed representation, giving this glorious little atrocity. Fix crate math. I forgot that -1 & 1 = 1 rather than 0 so all the bit math didn't work. But I can fix it with polynomial algebra! this is much better. Save tokens on movemebnt checks I promise this is mathematically equivalent-ish to the original. (0.2 and its multiples are nonterminating decimals in base 2, so there's a little jank when the negative shift right is a shift left.) Trimming Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable. Reviewed-on: https://git.chromaticdragon.app/pyrex/chameleonic/pulls/13 Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Co-committed-by: Kistaro Windrider <kistaro@gmail.com>
2022-12-24 00:08:10 +00:00
if (done) return
done=true return x0
2022-12-17 20:16:26 +00:00
end
end
local mul=0.5
x0*=2
x1*=2
if (x0>x1) x0,x1,mul=-x0,-x1,-mul
local i=flr(x0)
local top=flr(x1)
return function()
if (done) return nil
i+=1
if i>top then
done = true
if (x1!=flr(x1)) return mul*x1
return nil
end
return mul*i
end
2022-12-17 20:16:26 +00:00
end
function _which_side(x,y,x0,y0,x1,y1)
return sgn0((x1-x0)*(y-y0) - (y1-y0)*(x-x0))
2022-12-17 20:16:26 +00:00
end
2022-12-18 04:10:01 +00:00
function distance_dxy(dx,dy)
return sqrt(dx*dx+dy*dy)
end
2022-12-17 20:16:26 +00:00
function distance(p1,p2)
local dx=p2.x-p1.x
local dy=p2.y-p1.y
return sqrt(dx*dx+dy*dy)
end
function rope:collide_mrect(mx0,my0,mw,mh,exclude_src,exclude_dst)
local mx1,my1=mx0+mw,my0+mh
local n0=self.src
while true do
local n1=n0.next
if (n1==nil) return false
local nd=n0
for i=1,exclude_dst do
nd=nd.next
if (nd==nil) return false
end
2022-12-22 19:25:31 +00:00
local x1,y1,x2,y2=n0.ax,n0.ay,n1.ax,n1.ay
local function _line_line(x3,y3,x4,y4)
local denom=((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1))
local ua=
((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))/denom
if (ua<0 or ua>1) return false
local ub=
((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))/denom
if (ub<0 or ub>1) return false
return true
end
if exclude_src<=0 then
2022-12-22 19:25:31 +00:00
if (_line_line(mx0,my0,mx1,my0) or _line_line(mx0,my0,mx0,my1) or _line_line(mx0,my1,mx1,my1) or _line_line(mx1,my0,mx1,my1)) return true
end
exclude_src-=1
n0=n1
2022-12-17 20:16:26 +00:00
end
end
-->8
-- moved here because it's complicated
2022-12-18 00:57:47 +00:00
function rope:tug_orientxy()
local a1=self.dst
local a0=self.dst.prev
local dx=a0.ax-a1.ax
2022-12-23 03:22:23 +00:00
local tdx=nil
if (dx>3/8) tdx=1
if (dx<-3/8) tdx=-1
2022-12-18 00:57:47 +00:00
local dy=a0.ay-a1.ay
2022-12-23 03:22:23 +00:00
local tdy=nil
2022-12-18 00:57:47 +00:00
if abs(dy)>abs(dx)/2 then
if (dy>3/8) tdy=1
if (dy<-3/8) tdy=-1
2022-12-18 00:57:47 +00:00
end
return tdx,tdy
end
2022-12-17 20:16:26 +00:00
function rope:tug()
2022-12-18 04:10:01 +00:00
if (not self:latched()) return
return self:_tug()
2022-12-17 20:16:26 +00:00
end
2022-12-18 22:53:58 +00:00
function rope:_tug(hypothetically)
2022-12-17 20:16:26 +00:00
local ancs=self:_anchors_simplified()
local touched={}
for i=#ancs-1,2,-1 do
local ops_before_trash=self:_calc_push(ancs[i+1],ancs[i],ancs[i-1],ancs[i-2])
2022-12-20 02:01:02 +00:00
local ops_to_do,corners={}
2022-12-19 00:07:15 +00:00
if #ops_before_trash>0 then
ops_to_do=ops_before_trash
else
local ops_after_trash=self:_calc_push(ancs[i-2],ancs[i-1],ancs[i],ancs[i+1])
2022-12-19 00:46:46 +00:00
ops_to_do=ops_after_trash
end
local ops=ops_to_do
2022-12-19 00:07:15 +00:00
2022-12-18 22:53:58 +00:00
if #ops>0 then
if (hypothetically) return ancs,i-1
2022-12-17 20:16:26 +00:00
local dmx,dmy=ops[1].dmx,ops[1].dmy
for o in all(ops) do
2022-12-20 02:01:02 +00:00
level:tug_crate(o.mx,o.my,o.dmx,o.dmy)
2022-12-17 20:16:26 +00:00
end
2022-12-20 00:38:21 +00:00
return true
2022-12-17 20:16:26 +00:00
end
end
local latch=self.latch
2022-12-22 03:54:09 +00:00
if latch!=nil and latch.el=="eyehook" then
if (hypothetically) return ancs,0
player.todo={{
update=function(s)
if s.rope==nil or s.rope:done() then
return true
end
end
}}
self:destroy(true)
return true
end
2022-12-20 00:38:21 +00:00
if latch!=nil and latch.el=="crate" then
2022-12-17 20:16:26 +00:00
local dmx,dmy=
sgn0(latch.dx),
sgn0(latch.dy)
2022-12-19 00:07:15 +00:00
local obj_anc=ancs[1]
local pull_anc=ancs[2]
2022-12-19 00:07:15 +00:00
local pull_dx=pull_anc.x-obj_anc.x
local pull_dy=pull_anc.y-obj_anc.y
2022-12-17 20:16:26 +00:00
local mx0=latch.rec.mx
local my0=latch.rec.my
2022-12-19 00:07:15 +00:00
local mxa=(pull_anc.x+dmx)\8
local mya=(pull_anc.y+dmy)\8
2022-12-17 20:16:26 +00:00
local invalid_move=false
2022-12-17 20:16:26 +00:00
if
2022-12-19 00:07:15 +00:00
(dmx!=0 and sgn0(pull_dx)!=dmx) or
(dmy!=0 and sgn0(pull_dy)!=dmy) or
2022-12-17 20:16:26 +00:00
sgn0(mx0-mxa)!=
sgn0(mx0+dmx-mxa) or
sgn0(my0-mya)!=
sgn0(my0+dmy-mya)
then
invalid_move=true
2022-12-17 20:16:26 +00:00
end
if not invalid_move and
2022-12-17 23:08:54 +00:00
level:can_move(false,mx0,my0,dmx,dmy,1,0)
2022-12-17 20:16:26 +00:00
then
2022-12-19 00:46:46 +00:00
if (hypothetically) return ancs,0
2022-12-18 22:53:58 +00:00
level:tug_crate(mx0,my0,dmx,dmy)
2022-12-20 00:38:21 +00:00
return true
2022-12-17 20:16:26 +00:00
end
end
2022-12-18 22:53:58 +00:00
2022-12-20 00:38:21 +00:00
if (hypothetically) return ancs,nil
return false
2022-12-17 20:16:26 +00:00
end
function rope:_calc_push(
2022-12-19 01:20:59 +00:00
an,a0,a1,af
2022-12-17 20:16:26 +00:00
)
local ops={}
2022-12-19 00:50:19 +00:00
if (an==nil) return ops
2022-12-19 01:20:59 +00:00
2022-12-17 20:16:26 +00:00
if a0.x==a1.x then
2022-12-19 01:20:59 +00:00
-- no far side applying pressure?
2022-12-17 20:16:26 +00:00
local y0,y1=_mnmx(a0.y,a1.y)
2022-12-18 22:53:58 +00:00
local my0,my1,smy=(y0+1)\8,(y1-1)\8,1
if a0.y>a1.y then
my0,my1=my1,my0
smy=-smy
end
2022-12-17 20:16:26 +00:00
local mx,dmx
if a0.x%8==0 and a0.x>an.x+7 then
-- push left
mx=(a0.x-1)\8
dmx=-1
elseif a0.x%8==7 and a0.x<an.x-7 then
-- push right
mx=(a0.x+1)\8
dmx=1
else
return {}
end
2022-12-18 22:53:58 +00:00
for my=my0,my1,smy do
2022-12-17 20:16:26 +00:00
add(ops,{mx=mx,my=my,dmx=dmx,dmy=0})
end
end
if a0.y==a1.y then
local x0,x1=_mnmx(a0.x,a1.x)
2022-12-18 22:53:58 +00:00
local mx0,mx1,smx=(x0+1)\8,(x1-1)\8,1
if a0.x>a1.x then
mx0,mx1=mx1,mx0
smx=-smx
end
2022-12-17 20:16:26 +00:00
local my,dmy
if a0.y%8==0 and a0.y>an.y+6 then
-- push up
my=(a0.y-1)\8
dmy=-1
2022-12-19 00:07:15 +00:00
elseif a0.y%8==7 and a0.y<an.y-6 then
2022-12-17 20:16:26 +00:00
-- push down
my=(a0.y+1)\8
dmy=1
else
return {}
end
2022-12-18 22:53:58 +00:00
for mx=mx0,mx1,smx do
2022-12-17 20:16:26 +00:00
add(ops,{mx=mx,my=my,dmx=0,dmy=dmy})
end
end
2022-12-19 00:46:46 +00:00
local ops2={}
for o in all(ops) do
if not level:mcoll(o.mx,o.my) then
-- great!
else
local crate=level:get_crate(o.mx,o.my)
if crate==nil then
break
else
if not level:can_move(false,o.mx,o.my,o.dmx,o.dmy,0,0) then
break
end
end
add(ops2,o)
end
end
return ops2
2022-12-17 20:16:26 +00:00
end
function rope:_anchors_simplified()
-- todo: cache this
local points={}
local _slope = function(p0,p1)
return atan2(p1.y-p0.y,p1.x-p0.x)
end
a=self.src
while a!=nil do
local point={
x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5),
ax=a.ax,ay=a.ay
}
2022-12-22 19:25:31 +00:00
local aw=a.associated_with
local l=self.latch
if aw then
if (aw.adx==1) point.x-=1
if (aw.ady==1) point.y-=1
elseif a.prev==nil and l then
if (l.ax_offset<0) point.x-=1
if (l.ay_offset<0) point.y-=1
end
2022-12-22 19:25:31 +00:00
local p0,p1=points[#points-1],points[#points]
if p0==nil then
add(points,point)
2022-12-22 19:25:31 +00:00
elseif _slope(p0,p1)==_slope(p1,point) then -- epsilon?
points[#points]=point
2022-12-17 20:16:26 +00:00
else
add(points,point)
2022-12-17 20:16:26 +00:00
end
a=a.next
2022-12-17 20:16:26 +00:00
end
return points
end
2022-12-20 00:38:21 +00:00
-->8
--wrongbleeps
wrongbleep={}
add(real_modules,wrongbleep)
function wrongbleep:init()
self.duration=0
self.continuous=0
2022-12-20 00:38:21 +00:00
end
function wrongbleep:update()
if (self.duration>5) self.duration=5
if self.duration>0 then sfx(63,3) self.continuous+=1
else self.continuous=0 end
self.duration=max(self.duration-1,-4)
2022-12-20 00:38:21 +00:00
end
function wrongbleep:bleep(duration)
self.duration+=duration or 2
end
function wrongbleep:vibrate(duration)
if (self.continuous<10) return 0
return (rnd()*2-1)*min(self.continuous/10,2)
end
function wrongbleep:adequately_warned(duration)
return self.continuous>45
end
2022-12-20 00:38:21 +00:00
2022-12-17 20:16:26 +00:00
2022-12-22 02:11:19 +00:00
-->8
-- text
level_text={by_lvl={}}
add(real_modules,level_text)
level_text_raw={
"9`9`11`\f7\#0press 🅾️ to mlem & unmlem",
"9`33`17`\f7\#0❎ to yoink"
}
function level_text:init()
for i=0,32 do level_text.by_lvl[i]={} end
for row in all(level_text_raw) do
if row then
2022-12-22 19:25:31 +00:00
lvlxys=split(row,"`")
add(level_text.by_lvl[lvlxys[1]],lvlxys)
2022-12-22 02:11:19 +00:00
end
end
end
function level_text:draw()
for xys in all(level_text.by_lvl[level.ix]) do
2022-12-22 19:25:31 +00:00
print(xys[4],xys[2],xys[3],6)
2022-12-22 02:11:19 +00:00
end
end
2022-12-17 20:16:26 +00:00
__gfx__
000030000000002200003000000cc0cc0cccccccccccccccccccccccccccccccc0bb0000000000000000000000000000dddddddd000000000005000000000000
003333300000332200333330000cc0cc0000cc0000000000000000000cc0000000bb0bb0bbbb0bbbbb0bbbbb0bbb0000dddddddd000000000000500000000000
2022-12-19 01:53:13 +00:00
099333990039932009333339000cc0cc0cc0cc0cc0cccccccc0ccccc0cc0ccccc0bb0bb000bb0000bb0bb0bb0bb0b000dddddddd000000000000000000000000
09a333a9033a932009333339000cc0cc0cc0cc0cc0cc0cc0cc0000cc0cc0cc0cc0bb0bb0bb000bbbbb0bbb000bb0b000dddddddd000000005005005000000000
023333323333320000222220000cc0cc0cc0cc0cc0cc0cc0cc0ccccc0cc0ccccc0bb0bb0bbbb0bbbbb0bb0bb0bbbb000dddddddd000000000500500500000000
2022-12-19 01:53:13 +00:00
002222200000220000222220000cc0cc0cc0000cc0cc0cc0cc0cc0cc0cc0cc0000bb0000000000000000000000000000dddddddd000000000000000000000000
000222c002222c0000022200000ccccc0ccccc0cc0cc0cc0cc0ccccc0cc0ccccc0bbbbbbbbbbbbbbbbbbbbbbbbbbb000dddddddd000000000005000000000000
00000cc00000cc0000000cc0000000000000000000000000000000000000000000000000000000000000000000000000dddddddd000000000000500000000000
2022-12-19 01:53:13 +00:00
0000ff00000000000000000088888888888888888888880aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa11111111000000000000000000000000
000f00f0000000000aa00aa00088000000088000000000000000000000000aa00000000000000000aa0000000000000011111111000000000000000000000000
00d0000f000000000aaaaaa000880888880880888880880aaa00aaa0aaaa0aa0aaaaa0aa0a0aaaa0aa0aa0aaaaa0aaa011111111000000000000000000000000
00d0d00f00c040500aaaaaa000880880880880000880880aa0a0aa00aa000aa0aa0aa0aa0a0aa000aa0aa0aa0aa0aa0a11111111000000000000000000000000
00dd00ee00c445500099990000880880880880888880880aa0a0aa0000aa0aa0aaa000aa0a0aa000aa0aa0aa0aa0aa0a11111111000000000000000000000000
00000ee00c44455500aaaa0000880880880880880880880aaaa0aaa0aaaa0aa0aa0aa0aaaa0aaaa0aa0aa0aaaaa0aa0a11111111000000000000000000000000
00eeee000c004005000aa00000880888880880888880880000000000000000000000000000000000000000000000000011111111000000000000000000000000
eeee0000cc0440550044440000000000000000000000888888800000000000000000000000000000000000000000000011111111000000000000000000000000
2022-12-18 05:36:25 +00:00
00000000000a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000aaaaaaa91000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000aaaaaa1a91100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0aaaaaaaaa1a91110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0aaaaaaaa41a91a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0a000aa4441a91a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00a0044449a110a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000aa111991111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2022-12-19 02:59:45 +00:00
000000009910000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00ddddddddddddddddddddddddddd
000000009900000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00ddddddddddddddddddddddddddd
000000009900000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd77ddddddddddddddddddddddddddd
000000000900000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00dddddd00700ddd00ddd00700ddd
00000000aa00000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddd00dddddd00700ddd00ddd00700ddd
0000000077a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddddddddddddddddddd77ddddddddddd
00000007777a000000000000000000000000000000000000000000000000000000000000000000000000000000000000ddddddddddddddddddd00ddddddddddd
000444444444440000000000000000000000000000000000000000000000000000000000000000000000000000000000ddddddddddddddddddd00ddddddddddd
2022-12-21 07:22:27 +00:00
44444444444004444444444444444444444444444440044444444444444004444444444444400444444444444440044444444444444004444444444444400444
47766774477007744776677447700774477667744770077447766774477007744776677447700774477667744770077447766774477007744776677447700774
47777774477777744777777447777774477777744777777447777774477777744777777447777774477777744777777447777774477777744777777447777774
46700764467007644670070046700700467007644670076446700700467007000070076400700764007007000070070000700764007007640070070000700700
46700764467007644670070046700700467007644670076446700700467007000070076400700764007007000070070000700764007007640070070000700700
47777774477777744777777447777774477777744777777447777774477777744777777447777774477777744777777447777774477777744777777447777774
47766774477667744776677447766774477007744770077447700774477007744776677447766774477667744776677447700774477007744770077447700774
44444444444444444444444444444444444004444440044444400444444004444444444444444444444444444444444444400444444004444440044444400444
2022-12-17 20:16:26 +00:00
__label__
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000000777667777776677700000000000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000000777667777776677700000000000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700000000000000000000000000000000000000000000000077777777
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
77766777000000000000000077766777000000000000000000000000000000000000000000000000000000000000000077766777000000000000000077766777
77766777000000000000000077766777000000000000000000000000000000000000000000000000000000000000000077766777000000000000000077766777
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
77777777000000000000000077777777000000000000000000000000000000000000000000000000000000000000000077777777000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000077766777000000000000000077766777000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000077766777000000000000000077766777000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777777000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
77766777000000007776677700000000777667770000000000000000000000000000000000000000000000007776677700000000777667770000000077766777
77766777000000007776677700000000777667770000000000000000000000000000000000000000000000007776677700000000777667770000000077766777
77777777000000007777777700000000777777770000000000000000000000000000000000000000000000007777777700000000777777770000000077777777
77777777000000007777777700000000777777770000000000000008000000000000000080000000000000007777777700000000777777770000000077777777
77777777000000007777777700000000777777770000000000000088888888888888888888000000000000007777777700000000777777770000000077777777
77777777000000000000000000000000000000000000000000000088888877777778888888800000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088877777777777777788880000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088877777777777777708888000000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000088877667777776677700888800000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000088777667777776677700088880000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000088777777777777777700008888000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088777777777777777700000888000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088777777777777777700000008880000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088777777777777777700000000888000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088777777777777777700000000088800000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088777777777777777700000000008880000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000088777667777776677700000000000888000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000088877667777776677700000000000088800000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000088877777777777777700000000000008880000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088877777777777777700000000000000888000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088877777777777777700000000000000088800000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088880000000000000000000000000000008880000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000088888800000000000000000000000000000888000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000088888000000000000000000000000000088800000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000000000088880000000000000000000000000000888000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000000000000088880000000000000000000000000888800000000000000000000000077766777
77777777000000000000000000000000000000000000000000000000000000000888880000000000000000000000088880000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000008888880000000000000000000008888000000033000000000000077777777
777777770000000000000000000000000000000000000000000000000000000000000888880000000000000000000008883330003bb300000000000077777777
777777770000000077777777000000007777777700000000000000007777777777777778880000000000000077777777833b33003ab337770000000077777777
77777777000000007777777700000000777777770000000000000000777777777777777888800000000000007777777733333300331137770000000077777777
77777777000000007777777700000000777777770000000000000000777777777777777788800000000000007777777700883330711337770000000077777777
77766777000000007776677700000000777667770000000000000000777667777776677788800000000000007776677703333333733367770000000077766777
77766777000000007776677700000000777667770000000000000000777667777776677708880000000000007776677700333330333667770000000077766777
77777777000000007777777700000000777777770000000000000000777777777777777700880000000000007777777700033133311777770000000077777777
77777777000000007777777700000000777777770000000000000000777777777777777700888000000000007777777700003100317777770000000077777777
77777777000000007777777700000000777777770000000000000000777777777777777700088000000000007777777700033103317777770000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000088800000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000008880000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000000000000000000000000000888000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000000000000000000000000000888000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000000000000000000000000000888800000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000088800000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000088880000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777778800000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000077766777000000000000000077766778800000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000077766777000000000000000077766778800000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000077777777000000000000000077777778800000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000077777777000000000000000077777778880000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700000088880000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700000888800000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777700008888000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000000777667777776677700088800000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000000777667777776677700880000000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000000777777777777777708800000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777777788000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000777777777777778880000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000888800000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000008888000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000008880000000000000000000000000000000000000000000000000077777777
77766777000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000077766777
77766777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077766777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
77766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777777667777776677777766777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
__gff__
2022-12-18 05:36:25 +00:00
000000000808080808080808c00000000000000008080808080808080000000040400000080808080808080800000000404000000808080808080808c0c0c0c000000000080808080808080800000000000000000808080808080808000000000000000008080808080808080000000000000000080808080808080800000000
2022-12-17 20:16:26 +00:00
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
2022-12-22 19:25:31 +00:00
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c00000000000000000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c0000000000000c001c1c000c0c000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c000000000044000c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c0000000000000000000000000c000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0000000000000000000000000000000c00000000000000000000000000000c0c00004f0c0c0000000c000000001c120e00000000000e0e0e0e0000000000000e000000000e000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
3d1c000000001c0000000000000000000000000000000000000000000000000c3d000c000c0c0000003f0c0c0000000c0e00000000000000000e0000000000000e000000000e000e00000000000000000e0000000000000000000000000000000e0000000000000e0e000000000000000e00000000000e0e0e0e000000000000
0c0000000000000000000000000000410000000000000000000000000000000c0c000c0000000000000000000000000c0e00000000000000000e0000000000000e000000000e000e00000000000000000e00000000000e0e0e000000000000000e00000000000e0000000000000000000e00000000000000000e000000000000
0c000000000000000c0c0c0c0c0c0c0c0c00000000000020210000000000000c01000c0c00000000000c0c004f00000c0e0000000000000e0e0e0000000000000e000000000e0e0e0e0e0000000000000e00000000000e0000000000000000000e00000000000e0e0e000000000000000e000000000000000e00000000000000
0c0c0c0c0c0c00000000000c0c0c0c0c0c00000000000030310000000000000c0c0000000000000c00000c000000000c0e00000000000000000e0000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e00000000000e00000e0000000000000e0000000000000e0000000000000000
0c00000000000c0c004f000c0c0c0c0c0c00000000000000000000000000000c0c00004f0000000c0c000c0000000c0c0e00000000000e0e0e0e0000000000000e0000000000000e00000000000000000e000000000000000e000000000000000e0000000000000e0e000000000000000e0000000000000e0000000000000000
0c00000c4f00000000000000000000120100000000000000000000000000000c0c00000000000000000000000000000c0e0000000000000000000000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e0000000000000000000000000000000e000000000000000000000000000000
3d0000000000003f0c000c0c0c0c0c0c0c00000000000000000000000000000c0c00000c00000000000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0000000000000000000c0c0c0c0c0c0c00000000000000000000000000000c0c000c0c0c0000000c0c0c004f00000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
010000000000000c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c00000c00000000000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c00000000001c00000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c00410c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
0c00000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c004f000000000c001c1c000c0c000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c3e0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c0000000000000000000000000c000c0c00000000000000000c00000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c000000000000000000000c0c0c0c0c0c0000000000000000000c000000000c0c000000000000000000001c0000000c0e000000000e000000000000000000000e000000000000000000000000000000
0c0000000c0c0000000c000000001c120100000000000000004f000000000012010000000000001c004f0000000000120100000000000000004f1c000000001201000000000000000047000000000012010000000000000000401c00000000120e000000000e0000000e0000000000000e000000000e00000e0e0e0000000000
0c000c000c0c0000000c0c0c0000000c0c00000000000000000c00000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c000000000000000000000c0c0c0c0c0c0000000000000000000c000000000c0c000000000000000000001c0000000c0e000000000e0000000e000e000000000e000000000e00000e00000000000000
0c000c0000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c3c0c0c0c0c0c0e000000000e0000000e0e0e0e0000000e000000000e00000e0e0e0000000000
01000c0c00000000000c0c004f00000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e000000000e00000000000e000000000e000000000e000000000e0000000000
0c0000000000000c00000c000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e000000000e00000000000e000000000e000000000e000000000e0000000000
0c00004f0000000c0c000c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000e00000e0e0e0000000000
0c00000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c00000c00000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c000c0c0c0000000c0c0c004f00000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c00000c00000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c00000000001c00000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
2022-12-18 07:25:42 +00:00
__sfx__
2022-12-24 00:05:38 +00:00
00110000250002500025030250302503000000230350000023030230302303023030230302303023030230302103021030210302103021030210300000000000177401774017740177311e7501e7501e7501e750
00110000290202a0212a0202a0202a0202a02025030250052503025030250302503025030250302503025030250302503025030250302503225030230322504526030260302a040000002d0402d0402d0402d040
001100001e7401e7401e7401e74010730107301073010730157301573015730157301573015730157301573015730157301573015730000000000000000000000000000000000000000019030190300000000000
001100002d0422d0402a0302a0302c0302c0302c0322c0322d0402d0312d0302d0302d0302d0302d0302d0302d0302d0302d0322d03200000000000000000000000000000000000000002b0402c0410000000000
001100001274012740127401274012740127401274012740177301773017730177301773017730177301773014730147301474014740107401074010740000001573015730157301573009720097300973009730
001100002a0402a0412a0412a0402a0402a0402a042290412a0412a0402a0402a0402a0402a0402a0422903128041280402804028040280402804226032000002504025040250402603026030260322803200000
001100000e0300e0300e0300e0300e0300e0300000000000000000000000000000000000000000150301503014030140301403014030120301203012030120300d0200d0200d0200d0200d0200d0200d0200d020
001100002804028040280402804028040280402104000000210402104021040210402104021040150001500014000140001400014000120001200012000240342503125030250302503025030250322503225032
00110000150301503015030150301503015030150301503015030150301503015030150301503015030150300b0200b0200b0200b0200b0200b0200b0200b0200b0200b0200b0200b02000000000000000000000
001100002501425010250102501025010250102501025010250212502025020250202502125020250202502027540275402754027540275402754027540275402703027030270302703027030270302703027030
001100002312023120231202312023120231202312023120231202312023120231202312023120231202212123141231402314023140231402314021140201401e1401e1401e1401e1401c140001001e14020140
00110000000000000006322063250d3320d33209320093200932009325093200932509320000001703017030170300b0200b0200b0200b02017030170300b0301403014030140301403514030140300000014330
0011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b0301b0301b030000001b0301b0301b030000001b0301b0301b03000000
0011000020140201402013020130201302013020130201301d1401e1411e1401e1401c140002001b2401b2401b240000000000022554235512355023550235402354023540235402354023540235402314023140
0011000000000150301503000000000000e0300e0300e0300e0320e0320e0320e0320e0300e0300e030000000d0300d0300d0300d0300d0300d0300d0300d0300d0300d0300d0300d0300d0300d0300d0300d030
00110000190331903019030000001a0331a0301a0301a0301a0301a0301a0301a0301a0301a0301a0300000027320273202732027320000000000027320273202732027320273202732000000000000000000000
00110000211402d1402d145000002a1302a1302a1302a1302a1322a1322a1322a1322a1322a13000100000002c3202c3202d3202d3202f320003002d3302d3302d3302d3302c3312c3302a3302a3302833000000
001100000b0300b0300b0000b0000b0300b0300b0300b0300b0300b0300b0300b0300b0300b0300b0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001100002704027040000000000027040270402704027040270402704027040270402704027040000000000028020280202a020000002c030000002a0202a02000000000002c0302c0302c0302c0300000000000
001100002a3302a3302c330003002a3302a3302a3302a3302a3302a3322a3322a3322a3322a332283322a3322c3302c3302d330003002f3302f3052d3302d33000300003002f3302f3302f3302f3302804028045
00110000000000000015310153101531015310153101531000000000001032010320103201032010320103200e3200e3200e3200e3200e3200e3200e3200e32000000000000d3200d3200d3200d3200d3200d320
001100003102031022310223102231022310222f0322d0302c030000002a0400000028030000002603026030260302603026030260302603026030000000000029040000002a040000002c040000002d0502d050
0111000034040340403404034042340423404232042310422f040000002d040000002c040000002a0402a0402a0402a0402a0422a0422a0422a042290402a0402c040000002d040000002f040000003104031040
001100001203012030120351230010030100301003010030020200202002020020200202002020020200202002020020200202002020020220202202022020220b0400b040000000000010040100400000000000
0011000000000000002c0402c04000000000002a0302a0302a0302a0302a0302a0302a0302a0302a0302a0302a0302a0302a0302a0302a0302a0302a030000002604026040000000000028040280400000000000
0011000000000000002f0402f04000000000002d0402d0402d0422d0422d0422d0422d0422d0422d0402d0402d0402d0402d0402d0402d0402d0402d040000002a0402a04000000000002c0302c0300000000000
001100000932209322093220932209322093220932209322043220432204322043220432204322023220232202322023220232202322023120231204312023120131000000033100000005310000000632006320
00110000250402504025040250402504025040230402104020040000001e040000001c040000001a0401a0401a0401a0401a0401a0401a0400000000000000000000000000000000000000000000000000000000
0011000028030280302803028030280302803026030250402304000000210400000020040000001e0401e0401e0401e0401e0401e0401e040000001d0401e0402004000000210400000023040000002504025040
00110000063200632012310123100431004310103101031002310023100231002310023150200002745017450b7351770017735060001274506000107550400004000107550b7550400004755010000172001722
00110000250502505023040230402304023040250402303021050210502105221050210502105021050210502a030000002d030000003203000000310403104031040310402f0302d0402f0502f0502d0402c040
001100000e7450e7050000012745000000070010740107401074210742107421074210740000000e7400e7400d7450d00500000117450000000000127401274012742127421e7421e7421c7401c7451074010745
001100002a05512005000003205500000000002f0502f0502f0502f0502f0502f0502f050000002c0402a0502905500000000003105500000000002d0402d0402d0402d0402d0402d0402c0402c0402c0402c040
001100000e0400e0400e0400e0400e0400e0400d040000000b0400b0400b0400b0400b0400b040020400000004040040400404004040040400404504040000000404004040040300400001000010000104001030
001100002a0402a0402a0402a0400000000000260302503023030230302303023030320503205232052320523104031040310403104031040310402f040000002f0402f0402f0402f0002a0402c0402a04028040
001100001731517310173151731517020170251033010330103301033010330103300233002325023300232501330013300133501335013300133506330063300633006330063300633004040040400404004040
00110000173601733023030233300b6630b3352a66317330173302a6532c230282302c230282302a6531a230190301903025030250330b6650b6702a6231e0302a7001e7302a6231e730287301c7302a6231c730
001100002634026340263403234032340323402f3402f3402f3422f3422f3422f3422f3422f34228342263402533025330253303135031350313502d3402d3402d3422d3422d3422b3412c3412c3422c34229341
001100000e7300e7300e7300e7300e7300e7300d7300d7300b7400b7400b7400e7400e7400e740100401004010030100300403004030040300403004030040300403004030040300403004030040300403000000
00110000260301a030260301a030260301a03000000000002304017040230402603017030260302a0401c0402a0401c0402a0401c0402a0401c0402a0401c040280401c040280401c04028040000001c04000000
00110000293402a3412a3422a3422a3422a34228350000002634026340263403234032340323402f3502f3502f3522f3522f3522f3422f3422f3422f3422f3422f3422f3422f3422f3422f340000002d3402d345
001100001004010040100401004010040100401004010040100301003010030100301003010030100301003010020100201000010000100051000010000100000000000000000000000000000000000000000000
001100002604028040260302803026040280402603028030260202802026020280202601028010260102801025010250152500028000250052800025000340000d5100d0300d0300000000000125140603006030
001100002d3322d3322d3322d3322d3322d3322d3322d3322d3222d3222d3222d3222d3222d3222d3222d3222d4122d4122d4022d4052d4002d4002d400000003843038430384303843500000000003473034730
001100000601006015000000000000000000000000000000215401a030210400000000000000001c540150301c0400000000000000001e540170301e040000000000000000195401203019040120300d0350d005
0011000034720347203472034720347250000000000001003173031730317302f7352d735001002c7402c7402c7402d7452f745007002d7502d7502d7502c7452a74500700287402874028740007002574500100
001100001a0302a0321a0301a0351a0001a00000000000000000000000000000000000000000000000000000000000000000000000002f0401c0222f04000000000001c0202d0422502019040190401904019040
00110000217302173021710217102171021715217002170021000210002100021000210002100021000210000000000000000001c700387303873038730387300000000000347303473034730347303473034730
0111000025020250202d0402c0402a140022150e0251202012020151250d2152502019020280351a030230251702026030260301703023030200001c000200301c02023040040200402004020040200000000000
001100003403034030317302f7302d7302d7302d7202f72031720001002f7402f7402f740007002d740007002a7502a75032750327502f7402f7402f7402f7422f7422f7422f7422f74500700007001c75000700
00110000253401c34009360093600936009340093401734004340043400434004340043401734002340023400234002340023401a340023400434002340023400134000300033400030005340003000635006350
001100001c567285303453034540345403454032540315402f540255402d540255402c540255402a5402a5402a5402a54021540215402154021540295302a5302c540235402d540255402f540255403155031550
00110000000000000000000000000000000000000000000021440204401e4401e4401e4401e4401e4401e4401a44000000174401a000174401a00012440124401224012240102401024010240102400d0000d000
001100000635006350123401234004350043501034010340023400234002340023400234002340023400234017340230001a3402a0001a340000002d3402d3402d3402d3402c3402a3402c3402c3402d0352c035
0011000031560255602f5602f5602f56025560315602f5602d5602f5602d5602d5602d5602d5602d5602c5601e16000100211500000026130000002514025140251402514023130211402315023155201001e100
011100002804026040280402604028030260302803026030280302603028030260302802026020280202602028020250202802025020280102501028010250102801025010280102501028010250102802025020
001120002d3202d3202d3202d3202d3202d3202d3202d3202d3202d3202d3202d3202d3202d3202d3202d3202d3112d3102d3102d3102d3102d3102d310014000140001400014000140001400014000140001400
0111000034530345323453234532345323453232532315302f540005002d540005002c540005002a5402a5402a5402a5402a5402a5402a5402a540295402a5402c540005002d540005002f540001003104031040
2022-12-20 00:38:21 +00:00
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
010300000015000250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2022-12-18 07:25:42 +00:00
__music__
2022-12-24 00:05:38 +00:00
01 00014140
00 02034340
00 04054540
00 06074740
00 08090a40
00 0b0c0d40
00 0e0f1040
00 11121340
00 14151640
00 17181940
00 1a1b1c40
00 1d1e5e40
00 1f206040
00 21226240
00 23242540
00 26272840
00 292a2b40
00 2c2d6d40
00 2e2f6f40
00 30317140
00 14153940
00 17181940
00 32335472
00 34353640
00 1f204040
00 21224040
00 23242561
00 26272840
02 37387840