22 Commits

Author SHA1 Message Date
528e67045d Trimming
Trim up redundant nil checks, sequential assignments that could be on a shared line, and repeated references to a deeply nested variable.
2022-12-23 00:34:00 -08:00
1995501583 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.)
2022-12-23 00:18:50 -08:00
9d93f30426 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.
2022-12-23 00:02:02 -08:00
0fe3b1699f 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.
2022-12-22 23:15:03 -08:00
b10447bb86 comment the bullshit
it needs it
2022-12-22 22:50:34 -08:00
fe3a68284f 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.
2022-12-22 22:49:27 -08:00
10948ce4a5 Turn off debug again for now 2022-12-22 19:24:41 -08:00
cf352fd918 Golf one thing on rope 2022-12-22 19:23:41 -08:00
930e27a8e3 Golf player a bit 2022-12-22 19:22:23 -08:00
ae7dc8374e Golf level slightly 2022-12-22 19:07:43 -08:00
9fbccee378 Golf level selector 2022-12-22 18:52:54 -08:00
137a390b65 Golf tostring() 2022-12-22 18:51:05 -08:00
58bf1d70bf Golf keyboard 2022-12-22 18:49:03 -08:00
1be4846698 Golf _rast 2022-12-22 18:42:44 -08:00
ed25ef0f94 Golf sgn0 2022-12-22 18:35:24 -08:00
94e4aea20b Golf _apply 2022-12-22 18:33:48 -08:00
2d565873b3 Golf linefill slightly more 2022-12-22 18:32:14 -08:00
f3a0b04cc4 Golf linefill 2022-12-22 18:30:05 -08:00
d782f6eb14 Fix another rope bug 2022-12-22 11:25:31 -08:00
791b49934f Add another case I missed 2022-12-21 21:55:21 -08:00
197c68dd88 Actually, that special case causes unnecessary rope shortening 2022-12-21 21:40:16 -08:00
4072499c4c This case shouldn't need to be special 2022-12-21 21:37:26 -08:00

View File

@ -53,21 +53,18 @@ function linefill(ax,ay,bx,by,r,c)
local dx,dy=bx-ax,by-ay local dx,dy=bx-ax,by-ay
-- avoid overflow -- avoid overflow
-- credits: https://www.lexaloffle.com/bbs/?tid=28999 -- credits: https://www.lexaloffle.com/bbs/?tid=28999
local d=max(abs(dx),abs(dy)) local n,d=_mnmx(abs(dx),abs(dy))
local n=min(abs(dx),abs(dy))/d n/=d
d*=sqrt(n*n+1) d*=sqrt(n*n+1)
if(d<0.001) return if(d<0.001) return
local ca,sa=dx/d,-dy/d local ca,sa=dx/d,-dy/d
-- polygon points -- polygon points
local s={ local spans={}
{0,-r},{d,-r},{d,r},{0,r} local function calcxy(u,v) return ax+u*ca+v*sa,ay-u*sa+v*ca end
} local x0,y0=calcxy(0,r)
local u,v,spans=s[4][1],s[4][2],{} for s in all{{0,-r},{d,-r},{d,r},{0,r}} do
local x0,y0=ax+u*ca+v*sa,ay-u*sa+v*ca local x1,y1=calcxy(unpack(s))
for i=1,4 do
local u,v=s[i][1],s[i][2]
local x1,y1=ax+u*ca+v*sa,ay-u*sa+v*ca
local _x1,_y1=x1,y1 local _x1,_y1=x1,y1
if(y0>y1) x0,y0,x1,y1=x1,y1,x0,y0 if(y0>y1) x0,y0,x1,y1=x1,y1,x0,y0
local dx=(x1-x0)/(y1-y0) local dx=(x1-x0)/(y1-y0)
@ -78,11 +75,8 @@ function linefill(ax,ay,bx,by,r,c)
for y=y0\1+1,min(y1\1,127) do for y=y0\1+1,min(y1\1,127) do
-- open span? -- open span?
local span=spans[y] local span=spans[y]
if span then if (span) rectfill(x0,y,span,y)
rectfill(x0,y,span,y)
else
spans[y]=x0 spans[y]=x0
end
x0+=dx x0+=dx
end end
x0,y0=_x1,_y1 x0,y0=_x1,_y1
@ -92,19 +86,14 @@ end
function _apply(x,ts,a) function _apply(x,ts,a)
local t=deli(ts,1) local t=deli(ts,1)
for k,v in pairs(t) do for k,v in pairs(t) do
if k=="update" then if (k!="update") x[k]=v
--
else
x[k]=v
end
end end
if (t and t.update and not t.update(x,a)) add(ts,t,1) if (t and t.update and not t.update(x,a)) add(ts,t,1)
end end
function sgn0(x) function sgn0(x)
if (x==0) return x return x!=0 and sgn(x) or 0
return sgn(x)
end end
function _mnmx(x,y) function _mnmx(x,y)
@ -114,13 +103,14 @@ end
function _rast( function _rast(
x0,y0,x1,y1 xs,ys,x0,y0,x1,y1
) )
local dx=abs(x1-x0) local function _add()
local dy=abs(y1-y0) local n=#xs
local x=x0 if (n==0 or xs[n]!=x0 or ys[n]!=y0) add(xs,x0) add(ys,y0)
local y=y0 end
local dx,dy=abs(x1-x0),abs(y1-y0)
local sx=-1 local sx=-1
local sy=-1 local sy=-1
if (x0<x1) sx=1 if (x0<x1) sx=1
@ -129,27 +119,22 @@ function _rast(
local done=false,err local done=false,err
if dx>dy then if dx>dy then
err=dx/2.0 err=dx/2.0
return function() while x0!=x1 do
if (done) return _add()
if (x==x1) done=true return x1,y1
local oldx,oldy=x,y
err-=dy err-=dy
if (err<0) y+=sy err+=dx if (err<0) y0+=sy err+=dx
x+=sx x0+=sx
return oldx,oldy
end end
else else
err=dy/2.0 err=dy/2.0
return function() while y0!=y1 do
if (done) return _add()
if (y==y1) done=true return x1,y1
local oldx,oldy=x,y
err-=dx err-=dx
if (err<0) x+=sx err+=dy if (err<0) x0+=sx err+=dy
y+=sy y0+=sy
return oldx,oldy
end end
end end
_add()
end end
-->8 -->8
@ -158,63 +143,40 @@ kbd={}
add(real_modules,kbd) add(real_modules,kbd)
function kbd:init() function kbd:init()
self.real=btn() self.real=btn()
self.down=0 self.state={btn=0}
end end
function kbd:update() function kbd:update()
-- figure out what keys are _really_ pressed -- figure out what keys are _really_ pressed
local now_real=btn() local now_real,was_real=btn(),self.real
local was_real=self.real
self.real=now_real self.real=now_real
-- add keys that are really pressed -- add keys that are really pressed
-- if they weren't really pressed before -- if they weren't really pressed before
-- (they may have been force- -- (they may have been force-
-- released by :release()) -- released by :release())
local real_pressed=(~was_real)&now_real local real_pressed=~was_real&now_real
local now_down=(self.down&now_real)|real_pressed local state=self.state
local was_down=self.down local now_down=state.btn&now_real|real_pressed
self.down=now_down local was_down=state.btn
-- deduce pressed/released by changes in down -- deduce pressed/released by changes in down
local pressed=(~was_down)&now_down state.btn,state.btnp,state.btnr=
local released=(~now_down)&was_down now_down,
~was_down&now_down,
self.pressed=pressed ~now_down&was_down
self.released=released
end end
function kbd:btn(i) for _kbdi in all(split"btn,btnp,btnr") do
return self.down&(1<<i)!=0 kbd[_kbdi]=function(self,i,t) return 1<<i&self.state[_kbdi]!=0 end
end
function kbd:btnp(i)
return self.pressed&(1<<i)!=0
end
function kbd:btnr(i)
return self.released&(1<<i)!=0
end end
function kbd:release(i) function kbd:release(i)
self.down&=~(1<<i) self.state.btn&=~(1<<i)
end end
function tostring(any) function tostring(any)
if type(any)=="function" then
return "function"
end
if any==nil then
return "nil"
end
if type(any)=="string" then
return any
end
if type(any)=="boolean" then
if any then return "true" end
return "false"
end
if type(any)=="table" then if type(any)=="table" then
local str = "{ " local str = "{ "
for k,v in pairs(any) do for k,v in pairs(any) do
@ -222,10 +184,7 @@ function tostring(any)
end end
return str.."}" return str.."}"
end end
if type(any)=="number" then return tostr(any)
return ""..any
end
return "unknown" -- should never show
end end
-->8 -->8
@ -233,11 +192,7 @@ end
title={} title={}
add(modules,title) add(modules,title)
function title:init()
end
blinkcol=10 blinkcol=10
function title:draw() function title:draw()
cls(0) cls(0)
-- this is right for 72x32 -- this is right for 72x32
@ -254,25 +209,14 @@ start_level = 0
max_level=15 max_level=15
function title:update() function title:update()
if time()*4\1%2==0 then
blinkcol=10
else
blinkcol=9 blinkcol=9
end if (time()*4\1%2==0) blinkcol=10
if btnp(0) then if (btnp"0") start_level-=1
start_level -= 1 if (btnp"1") start_level+=1
if (start_level<0) start_level=max_level start_level%=max_level
end
if btnp(1) then if (btnp"4" or btnp"5") modules=real_modules _init() music(0)
start_level += 1
if (start_level>max_level) start_level=0
end
if btnp(4) or btnp(5) then
modules=real_modules
_init()
music(0)
end
end end
-->8 -->8
@ -287,9 +231,7 @@ end
function level:reinit(n) function level:reinit(n)
self.ix=n self.ix=n
self.todo={} self.todo={}
self.bigx=(n%8) self.bigx,self.bigy=n%8,n\8
self.bigy=(n\8)
self.next_crate_id=1
self:load_dynobjs() self:load_dynobjs()
self:recollide() self:recollide()
@ -358,7 +300,7 @@ function level:update()
end end
if #remove>0 then if #remove>0 then
self:recollide() self:recollide()
self:reanchor(true) self:reanchor()
end end
end end
@ -366,6 +308,7 @@ function level:load_dynobjs()
self._crates={} self._crates={}
self._pits={} self._pits={}
local crate_id=1
for mx=0,15,1 do for mx=0,15,1 do
for my=0,15,1 do for my=0,15,1 do
local mxy=_mix(mx,my) local mxy=_mix(mx,my)
@ -375,22 +318,16 @@ function level:load_dynobjs()
if def then if def then
self._crates[mxy]={ self._crates[mxy]={
s=s,def=def, s=s,def=def,
id=self.next_crate_id, id=crate_id,
mx=mx,my=my, mx=mx,my=my,
px=px,py=py, px=px,py=py,
todo={} todo={}
} }
self.next_crate_id+=1 crate_id+=1
end end
if s==28 then -- pit -- pit
self._pits[mxy]={ if (s==28) self._pits[mxy]={s=s,mx=mx,my=my,px=px,py=py}
s=s,
mx=mx,my=my,
px=px,py=py,
contents=nil
}
end
end end
end end
end end
@ -461,17 +398,11 @@ function level:reanchor()
end end
shellsort(self._anch_keys) shellsort(self._anch_keys)
for point in self:anchor_points() do for point in self:anchor_points() do
if point.ax_old!=nil then if (point.ax_old and player.rope) player.rope:be_pushed_by(point,point.ax_old,point.ay_old)
if (player.rope!=nil) player.rope:be_pushed_by(point,point.ax_old,point.ay_old) point.ax_old,point.ay_old=nil,nil
point.ax_old=nil
point.ay_old=nil
end
end
for point in self:anchor_points() do
assert(not point.dropped)
end end
if (player.rope!=nil) player.rope:relax() if (player.rope) player.rope:relax()
end end
function level:win_at(mx,my) function level:win_at(mx,my)
@ -507,7 +438,9 @@ function level:spawn_exit()
if (self:_mget(x,y)!=18) return if (self:_mget(x,y)!=18) return
for nx=x-1,x+1 do for nx=x-1,x+1 do
for ny=y-1,y+1 do for ny=y-1,y+1 do
if nx<0 or ny<0 or nx>15 or ny>15 then -- 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 self._wins[_mix(nx,ny)]=true
end end
end end
@ -541,26 +474,24 @@ end
function _amix(ax,ay) function _amix(ax,ay)
return ax..","..ay return ax..","..ay
--if (ax<0 or ay<0 or ax>31 or ay>31) return nil
--return ay*32+ax
end end
function _mix(mx,my) function _mix(mx,my)
return mx..","..my return mx..","..my
--if (mx<0 or my<0 or mx>15 or my>15) return nil
--return my*16+mx
end end
-- crate spec:
-- "up" == 1
-- "right" == 2
-- "down" == 4
-- "left" == 8
--
-- +1+
-- 8 2
-- +4+
function level:_get_cratedef(s) function level:_get_cratedef(s)
if (s<64 or s>=80) return nil if (s<64 or s>=80) return
return s & 0x000F
local s2=s-64
return {
up=s2&1!=0,
right=s2&2!=0,
down=s2&4!=0,
left=s2&8!=0
}
end end
function level:get_latch(dx,dy,px,py) function level:get_latch(dx,dy,px,py)
@ -571,12 +502,7 @@ function level:get_latch(dx,dy,px,py)
local dx1,dy1=-sgn0(dx),-sgn0(dy) local dx1,dy1=-sgn0(dx),-sgn0(dy)
if crate then if crate then
if if crate.def & dy1*dy1*(2.5+1.5*dy1)+dx1*dx1*(5-3*dx1) ~= 0 then
(crate.def.up and dy>0) or
(crate.def.down and dy<0) or
(crate.def.left and dx>0) or
(crate.def.right and dx<0)
then
return { return {
el="crate", el="crate",
dx=dx1,dy=dy1, dx=dx1,dy=dy1,
@ -609,35 +535,23 @@ function level:can_move(
is_player, is_player,
mx0,my0,dmx,dmy,exclude_src,exclude_dst mx0,my0,dmx,dmy,exclude_src,exclude_dst
) )
if is_player and self:win_at(mx0+dmx,my0+dmy) then local mx1,my1=mx0+dmx,my0+dmy
return true if (is_player and self:win_at(mx1,my1)) return true
end if (is_player and self:get_open_pit(mx1,my1)) return wrongbleep:adequately_warned()
if is_player and self:get_open_pit(mx0+dmx,my0+dmy) then
return wrongbleep:adequately_warned()
end
if self:mcoll(mx0+dmx,my0+dmy) then if (self:mcoll(mx1,my1) or player.x==mx1 and player.y==my1) return false
return false
end
if player.x==mx0+dmx and player.y==my0+dmy then
return false
end
-- todo: check tongue collision
if player.rope then if player.rope then
local chk=false local chk=false
if dmx==0 and dmy==-1 then local w,h=1.6,0.2
chk=player.rope:collide_mrect(mx0+0.4,my0-0.8,0.2,1.6,exclude_src,exclude_dst) if dmx==0 then
elseif dmx==0 and dmy==1 then w,h=0.2,1.6
chk=player.rope:collide_mrect(mx0+0.4,my0+0.2,0.2,1.6,exclude_src,exclude_dst) else
elseif dmx==-1 and dmy==0 then dmy = 0
chk=player.rope:collide_mrect(mx0-0.8,my0+0.4,1.6,0.2,exclude_src,exclude_dst)
elseif dmx==1 and dmy==0 then
chk=player.rope:collide_mrect(mx0+0.2,my0+0.4,1.6,0.2,exclude_src,exclude_dst)
end end
rectx,recty=dmx*(0.4>>>dmx),dmy*(0.4>>>dmy)
if (chk) return false if (player.rope:collide_mrect(mx0+rectx,my0+recty,w,h,exclude_src,exclude_dst)) return false
end end
return true return true
@ -646,22 +560,21 @@ end
function level:tug_crate(mx0,my0,dmx,dmy) function level:tug_crate(mx0,my0,dmx,dmy)
local mxy0=_mix(mx0,my0) local mxy0=_mix(mx0,my0)
local existing=self._crates[mxy0] local existing=self._crates[mxy0]
if (existing==nil) return if (not existing) return
self._crates[mxy0]=nil self._crates[mxy0]=nil
local mx1,my1=mx0+dmx,my0+dmy local mx1,my1=mx0+dmx,my0+dmy
local mxy1=_mix(mx1,my1) local px1,py1=mx1*8,my1*8
existing.todo={ existing.todo={
{px=mx1*8+dmx,py=my1*8+dmy,mx=mx1,my=my1,update=function() {px=px1+dmx,py=py1+dmy,mx=mx1,my=my1,update=function()
self:recollide() self:recollide()
self:reanchor() self:reanchor()
return true return true
end}, end},
{px=mx1*8,py=my1*8} {px=px1,py=py1}
} }
self._crates[mxy1]=existing self._crates[_mix(mx1,my1)]=existing
end end
-->8 -->8
@ -670,54 +583,27 @@ player={}
add(real_modules,player) add(real_modules,player)
function player:init() function player:init()
--self:reinit(8,14)
-- don't change this on reinit: -- don't change this on reinit:
-- it stays the same when the level is changed or reloaded -- it stays the same when the level is changed or reloaded
self.vanish_frame=0 self.vanish_frame=0
end end
function player:reinit(x,y) function player:reinit(x,y)
self.x=x self.x,self.y=x,y
self.y=y self.px,self.py=0,0
self.px=0
self.py=0
self.todo={} self.todo={}
self.fall_frame=0 self.fall_frame=0
self.reset_frame=0
self.orientx=-1 self.orientx,self.orienty=-1,0
self.orienty=0
self.rope=nil
end
function player:any_busy()
if (#self.todo>0) return true
if (level:busy()) return true
return false
end end
function player:update() function player:update()
local _addall=function(t,xs)
for i in all(xs) do
add(t,i)
end
end
local f4 = function(xs)
-- todo: other anim stuff
xs[#xs].px=0
xs[#xs].py=0
return xs
end
-- this is a non-gameplay action that takes precedence over -- this is a non-gameplay action that takes precedence over
-- all gameplay actions -- all gameplay actions
self:_vanish_if_requested() self:_vanish_if_requested()
if not self:any_busy() then if not (#self.todo>0 or level:busy()) then
if level:win_at(self.x,self.y) then if level:win_at(self.x,self.y) then
level:advance() level:advance()
return return
@ -740,29 +626,25 @@ function player:update()
end end
if kbd:btn(4) then if kbd:btn(4) then
if kbd:btnp(4) and self.rope!=nil then if kbd:btnp(4) and self.rope then
self.rope:destroy() self.rope:destroy()
kbd:release(4) kbd:release(4)
end end
-- wait for user to release it -- wait for user to release it
else else
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
if kbd:btn(0) then if kbd:btn(0) then
if level:can_move(true,self.x,self.y,-1,0,0,2) then try_move(-1,0,{{orientx=-1,orienty=0,px=-2},{px=-7},{x=self.x-1,px=0}})
self.todo=f4({{orientx=-1,orienty=0,px=-2},{px=-7},{x=self.x-1}})
else wrongbleep:bleep() end
elseif kbd:btn(1) then elseif kbd:btn(1) then
if level:can_move(true,self.x,self.y,1,0,0,2) then try_move(1,0,{{orientx=1,orienty=0,px=2},{px=7},{x=self.x+1,px=0}})
self.todo=f4({{orientx=1,orienty=0,px=2},{px=7},{x=self.x+1}})
else wrongbleep:bleep() end
elseif kbd:btn(2) then elseif kbd:btn(2) then
if level:can_move(true,self.x,self.y,0,-1,0,2) then try_move(0,-1,{{orienty=-1,py=-2},{py=-7},{y=self.y-1,py=0}})
self.todo=f4({{orienty=-1,py=-2},{py=-7},{y=self.y-1}})
else wrongbleep:bleep() end
elseif kbd:btn(3) then elseif kbd:btn(3) then
if level:can_move(true,self.x,self.y,0,1,0,2) then try_move(0,1,{{orienty=1,py=2},{py=7},{y=self.y+1,py=0}})
self.todo=f4({{orienty=1,py=2},{py=7},{y=self.y+1}}) elseif not self.rope and kbd:btnr(4) then
else wrongbleep:bleep() end
elseif self.rope==nil and kbd:btnr(4) then
local dx,dy=self.orientx,self.orienty local dx,dy=self.orientx,self.orienty
if (dy!=0) dx=0 if (dy!=0) dx=0
@ -777,41 +659,35 @@ function player:update()
self.todo={{ self.todo={{
update=function() update=function()
return self.rope==nil or self.rope:latched() return not self.rope or self.rope:latched()
end end
}} }}
elseif kbd:btnp(5) then elseif kbd:btnp(5) then
if self.rope!=nil then if (self.rope and not self.rope:tug()) wrongbleep:bleep(9)
if (not self.rope:tug()) wrongbleep:bleep(9)
end
end end
end end
end end
if self.rope then
self.rope:update()
end
_apply(self,self.todo) _apply(self,self.todo)
if self.rope then if self.rope then
self.rope:update() self.rope:update()
if self.rope:done_reeling() then if self.rope:done_reeling() then
self.x=self.rope.latch.rec.mx+self.rope.latch.dx local latch=self.rope.latch
self.y=self.rope.latch.rec.my+self.rope.latch.dy self.x=latch.rec.mx+latch.dx
self.y=latch.rec.my+latch.dy
end end
local rx=self.x+self.px/8+0.5 self.rope:drag_dst(
local ry=self.y+self.py/8+0.5 self.x+self.px/8+0.5,
-- do the hokey pokey to work out kinks in the rope self.y+self.py/8+0.5
self.rope:drag_dst(rx,ry) )
local tdx,tdy=self.rope:tug_orientxy() local tdx,tdy=self.rope:tug_orientxy()
if (tdx!=0) self.orientx=tdx if (tdx) self.orientx=tdx
if (tdy!=0) self.orienty=tdy if (tdy) self.orienty=tdy
if self.rope:done() then if (self.rope:done()) self.rope=nil
self.rope=nil
end
end end
end end
@ -840,23 +716,27 @@ function player:draw()
local px=self.x*8+self.px+wrongbleep:vibrate() local px=self.x*8+self.px+wrongbleep:vibrate()
local py=self.y*8+self.py+wrongbleep:vibrate() local py=self.y*8+self.py+wrongbleep:vibrate()
local head=1-self.orienty local head=1-self.orienty
local vanish_level=max((self.vanish_frame-4)/16,0) local vanish_level=max((self.vanish_frame-4)/16,0)
local invis_level=max(self.fall_frame/10,4*(vanish_level-0.75)) local invis_level=max(self.fall_frame/10,4*(vanish_level-0.75))
if (invis_level>=1.0) return if (invis_level>=1.0) return
--px+=sin(vanish_level*16)*max(vanish_level-0.1,0)*1 --[[
local HEAD=14--3 local HEAD=14--3
local BODY=12--12 local BODY=12--12
local TAIL=14--14 local TAIL=14--14
local IRIS=7--9 local IRIS=7--9
local PUPIL=0--0 local PUPIL=0--0
]]
local setpal=function() -- in order: head,body,iris,pupil,body again,tail
-- base colors local palette=split"-1,14,14,12,12,-1,-1,-1,7,0,-1,12,14,14,14"
pal{ local function setpal()
--[[
-- head
nil,14,14,
--body
[2]=HEAD, [2]=HEAD,
[3]=HEAD, [3]=HEAD,
[4]=BODY, [4]=BODY,
@ -867,7 +747,8 @@ function player:draw()
[13]=TAIL, [13]=TAIL,
[14]=TAIL, [14]=TAIL,
[15]=TAIL, [15]=TAIL,
} ]]
pal(palette)
-- vanish colors -- vanish colors
local vanish=split"13,15,14,5,4,12,2,3,9,10" local vanish=split"13,15,14,5,4,12,2,3,9,10"
@ -875,11 +756,7 @@ function player:draw()
if (vanish_level>i/#vanish) pal(ilc,1) if (vanish_level>i/#vanish) pal(ilc,1)
end end
if self.fall_frame>3 then if (self.fall_frame>3) local zc=@0x5f00&0xf0 for i=0x5f00,0x5f0c,4 do poke4(i,0x0101.0101) end poke(0x5f00,zc|0x01)
local zc=@0x5f00&0xf0
for i=0x5f00,0x5f0c,4 do poke4(i,0x0101.0101) end
poke(0x5f00,zc|0x01)
end
end end
local rx,ry=self.x*8+self.px+1,self.y*8+self.py+2 local rx,ry=self.x*8+self.px+1,self.y*8+self.py+2
@ -887,7 +764,7 @@ function player:draw()
if self.rope then if self.rope then
local rx_adj,ry_adj=self.rope:affected_src_xy(rx,ry) local rx_adj,ry_adj=self.rope:affected_src_xy(rx,ry)
if rx_adj!=nil then if rx_adj then
local drx,dry=rx_adj-rx,ry_adj-ry local drx,dry=rx_adj-rx,ry_adj-ry
rx,ry=rx+drx,ry+dry rx,ry=rx+drx,ry+dry
px,py=px+drx,py+dry px,py=px+drx,py+dry
@ -921,8 +798,8 @@ function rope:new(
local r={ local r={
id=0, id=0,
anchors={ anchors={
{ax=src_ax,ay=src_ay,prev=nil,next=nil}, {ax=src_ax,ay=src_ay},
{ax=dst_ax,ay=dst_ay,prev=nil,next=nil} {ax=dst_ax,ay=dst_ay}
}, },
state={name="cast",frame=0}, state={name="cast",frame=0},
latch=latch, latch=latch,
@ -955,10 +832,7 @@ function rope:update()
elseif self.state.name=="latched" then elseif self.state.name=="latched" then
if (self.latch==nil) wrongbleep:bleep(5) self:destroy() return if (self.latch==nil) wrongbleep:bleep(5) self:destroy() return
if if self.latch and self.latch.rec then
self.latch!=nil and
self.latch.rec!=nil
then
self:drag_src( self:drag_src(
self.latch.rec.mx+0.5+self.latch.ax_offset, self.latch.rec.mx+0.5+self.latch.ax_offset,
self.latch.rec.my+0.5+self.latch.ay_offset self.latch.rec.my+0.5+self.latch.ay_offset
@ -1020,11 +894,10 @@ end
function rope:draw(artificial_px,artificial_py) function rope:draw(artificial_px,artificial_py)
local points,highlight=self:_tug(true) local points,highlight=self:_tug(true)
if (self.state.name=="done") return local n,perc_to_show,from_end = self.state.name,1.0,false
local perc_to_show=1.0 if (n=="done") return
local from_end=false if (n=="cast") perc_to_show=self.state.frame/2
if (self.state.name=="cast") perc_to_show=self.state.frame/2 if (n=="destroy") perc_to_show=(1.0-self.state.frame/8)^2
if (self.state.name=="destroy") perc_to_show=(1.0-self.state.frame/8)^2
if (self.state.reelin) from_end=true if (self.state.reelin) from_end=true
points[#points]={x=artificial_px,y=artificial_py} points[#points]={x=artificial_px,y=artificial_py}
@ -1134,7 +1007,7 @@ function rope:draw(artificial_px,artificial_py)
pset(x+p.adx,y,11) pset(x+p.adx,y,11)
pset(x,y+p.ady,11) pset(x,y+p.ady,11)
end end
]] ]]--
end end
function rope:drag_dst(x,y) function rope:drag_dst(x,y)
@ -1153,18 +1026,6 @@ function rope:drag(n1,ax_new,ay_new)
end end
function rope:relax() function rope:relax()
local n=self.src
while true do
if (n==nil) break
if (n.associated_with) then
self:_drag(n,n.associated_with.ax,n.associated_with.ay)
end
n=n.next
end
local n0=self.src local n0=self.src
while true do while true do
local n1=n0.next local n1=n0.next
@ -1173,7 +1034,7 @@ function rope:relax()
if n0.ax==n1.ax and n0.ay==n1.ay then if n0.ax==n1.ax and n0.ay==n1.ay then
n0.next=n2 n0.next=n2
n2.prev=n0 if (n2!=nil) n2.prev=n0
else else
n0=n0.next n0=n0.next
end end
@ -1193,6 +1054,11 @@ function rope:relax()
local x1,y1=n1.ax,n1.ay local x1,y1=n1.ax,n1.ay
local x2,y2=n2.ax,n2.ay local x2,y2=n2.ax,n2.ay
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) local would,x1_new,y1_new=would_stick(x0,y0,n1.associated_with,x2,y2)
if not would and not (n1.ax==x1_new and n1.ay==y1_new) then if not would and not (n1.ax==x1_new and n1.ay==y1_new) then
-- printh("relaxing: "..tostring(n0.associated_with).."->"..tostring(n1.associated_with).."->"..tostring(n2.associated_with)) -- printh("relaxing: "..tostring(n0.associated_with).."->"..tostring(n1.associated_with).."->"..tostring(n2.associated_with))
@ -1219,12 +1085,7 @@ function rope:_check_sane()
local n1=n0.next local n1=n0.next
if (n1==nil) break if (n1==nil) break
for qx,qy in _rast(flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2)) do _rast(qxs,qys,flr(n0.ax*2),flr(n0.ay*2),flr(n1.ax*2),flr(n1.ay*2))
if not (qx==qxs[#qxs] and qy==qys[#qys]) then
add(qxs,qx)
add(qys,qy)
end
end
n0=n1 n0=n1
end end
@ -1287,6 +1148,14 @@ function would_stick(x0,y0,anchor,x2,y2)
local dx=x2-x0 local dx=x2-x0
local dy=y2-y0 local dy=y2-y0
-- there is no reason for an acute angle to stick around in this world
--[[
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
]]--
local adx,ady local adx,ady
local x1_new,y1_new local x1_new,y1_new
if abs(dx)>abs(dy) then if abs(dx)>abs(dy) then
@ -1317,14 +1186,17 @@ function rope:be_pushed_by(anchor,ax_old,ay_old)
local ax_new,ay_new=anchor.ax,anchor.ay local ax_new,ay_new=anchor.ax,anchor.ay
while true do while true do
n1=n0.next n1=n0.next
if (n1==nil) return if (not n1) return
local nx0,ny0=n0.ax,n0.ay local nx0,ny0=n0.ax,n0.ay
local nx1,ny1=n1.ax,n1.ay local nx1,ny1=n1.ax,n1.ay
if if
(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==nx0 and anchor.ay==ny0) and
not (anchor.ax==nx1 and anchor.ay==ny1) and not (anchor.ax==nx1 and anchor.ay==ny1) and
(_which_side(ax_old,ay_old,nx0,ny0,nx1,ny1)!= (_which_side(ax_old,ay_old,nx0,ny0,nx1,ny1)!=
_which_side(ax_new,ay_new,nx0,ny0,nx1,ny1) _which_side(ax_new,ay_new,nx0,ny0,nx1,ny1)
) and would_stick(nx0,ny0,anchor,nx1,ny1) ) and would_stick(nx0,ny0,anchor,nx1,ny1)
@ -1368,7 +1240,7 @@ function rope:_drag(n1,ax1_new,ay1_new)
for anchor in level:anchor_points() do for anchor in level:anchor_points() do
if if
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and
not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and -- not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and
not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and not (anchor.ax==ax_far1 and anchor.ay==ay_far1) and
(ax0<=anchor.ax and anchor.ax<=ax1) and (ax0<=anchor.ax and anchor.ax<=ax1) and
would_stick(ax_pivot,ay_pivot,anchor,ax_far,ay_far_new) and would_stick(ax_pivot,ay_pivot,anchor,ax_far,ay_far_new) and
@ -1391,7 +1263,7 @@ function rope:_drag(n1,ax1_new,ay1_new)
for anchor in level:anchor_points() do for anchor in level:anchor_points() do
if if
not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and not (anchor.ax==ax_pivot and anchor.ay==ay_pivot) and
not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and -- not (anchor.ax==ax_far0 and anchor.ay==ay_far0) and
not (anchor.ax==ax_far1 and anchor.ay==ay_far1) 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 would_stick(ax_pivot,ay_pivot,anchor,ax_far_new,ay_far) and
(ay0<=anchor.ay and anchor.ay<=ay1) and (ay0<=anchor.ay and anchor.ay<=ay1) and
@ -1418,7 +1290,7 @@ function rope:_drag(n1,ax1_new,ay1_new)
local anch=_sweep_radar(n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new) local anch=_sweep_radar(n0.ax,n0.ay,ax1_old,ay1_old,ax1_new,ay1_new)
if (anch==nil) break if (anch==nil) break
local n05={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n0,next=n1} local n05={ax=anch.ax,ay=anch.ay,associated_with=anch,prev=n0,next=n1}
--printh("creating post: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with)) -- printh("creating pre: "..tostring(n0.associated_with).."->"..tostring(n05.associated_with).."->"..tostring(n1.associated_with))
n0.next=n05 n0.next=n05
n1.prev=n05 n1.prev=n05
n0=n05 n0=n05
@ -1441,7 +1313,7 @@ function _stepfrom(x0,x1)
local done=false local done=false
if x0==x1 then if x0==x1 then
return function() return function()
if (done) return nil if (done) return
done=true return x0 done=true return x0
end end
end end
@ -1492,18 +1364,8 @@ function rope:collide_mrect(mx0,my0,mw,mh,exclude_src,exclude_dst)
if (nd==nil) return false if (nd==nil) return false
end end
if exclude_src<=0 then local x1,y1,x2,y2=n0.ax,n0.ay,n1.ax,n1.ay
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx0,my0,mx1,my0)) return true local function _line_line(x3,y3,x4,y4)
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx0,my0,mx0,my1)) return true
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx0,my1,mx1,my1)) return true
if (_line_line(n0.ax,n0.ay,n1.ax,n1.ay,mx1,my0,mx1,my1)) return true
end
exclude_src-=1
n0=n1
end
end
function _line_line(x1,y1,x2,y2,x3,y3,x4,y4)
local denom=((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1)) local denom=((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1))
local ua= local ua=
@ -1517,6 +1379,15 @@ function _line_line(x1,y1,x2,y2,x3,y3,x4,y4)
return true return true
end end
if exclude_src<=0 then
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
end
end
-->8 -->8
-- moved here because it's complicated -- moved here because it's complicated
@ -1524,12 +1395,12 @@ function rope:tug_orientxy()
local a1=self.dst local a1=self.dst
local a0=self.dst.prev local a0=self.dst.prev
local dx=a0.ax-a1.ax local dx=a0.ax-a1.ax
local tdx=0 local tdx=nil
if (dx>3/8) tdx=1 if (dx>3/8) tdx=1
if (dx<-3/8) tdx=-1 if (dx<-3/8) tdx=-1
local dy=a0.ay-a1.ay local dy=a0.ay-a1.ay
local tdy=0 local tdy=nil
if abs(dy)>abs(dx)/2 then if abs(dy)>abs(dx)/2 then
if (dy>3/8) tdy=1 if (dy>3/8) tdy=1
if (dy<-3/8) tdy=-1 if (dy<-3/8) tdy=-1
@ -1717,20 +1588,20 @@ function rope:_anchors_simplified()
x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5), x=flr(a.ax*8+0.5),y=flr(a.ay*8+0.5),
ax=a.ax,ay=a.ay ax=a.ax,ay=a.ay
} }
if a.associated_with then local aw=a.associated_with
if (a.associated_with.adx==1) point.x-=1 local l=self.latch
if (a.associated_with.ady==1) point.y-=1 if aw then
elseif a.prev==nil and self.latch then if (aw.adx==1) point.x-=1
if (self.latch.ax_offset<0) point.x-=1 if (aw.ady==1) point.y-=1
if (self.latch.ay_offset<0) 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 end
if #points<=1 then local p0,p1=points[#points-1],points[#points]
if p0==nil then
add(points,point) add(points,point)
elseif abs( elseif _slope(p0,p1)==_slope(p1,point) then -- epsilon?
_slope(points[#points-1],points[#points])-
_slope(points[#points],point)
)==0 then -- epsilon?
points[#points]=point points[#points]=point
else else
add(points,point) add(points,point)
@ -1778,14 +1649,14 @@ function level_text:init()
for i=0,32 do level_text.by_lvl[i]={} end for i=0,32 do level_text.by_lvl[i]={} end
for row in all(level_text_raw) do for row in all(level_text_raw) do
if row then if row then
lvl,x,y,s=unpack(split(row,"`")) lvlxys=split(row,"`")
add(level_text.by_lvl[lvl],{x,y,s}) add(level_text.by_lvl[lvlxys[1]],lvlxys)
end end
end end
end end
function level_text:draw() function level_text:draw()
for xys in all(level_text.by_lvl[level.ix]) do for xys in all(level_text.by_lvl[level.ix]) do
print(xys[3],xys[1],xys[2],6) print(xys[4],xys[2],xys[3],6)
end end
end end
__gfx__ __gfx__
@ -1963,22 +1834,22 @@ __gff__
000000000808080808080808c00000000000000008080808080808080000000040400000080808080808080800000000404000000808080808080808c0c0c0c000000000080808080808080800000000000000000808080808080808000000000000000008080808080808080000000000000000080808080808080800000000 000000000808080808080808c00000000000000008080808080808080000000040400000080808080808080800000000404000000808080808080808c0c0c0c000000000080808080808080800000000000000000808080808080808000000000000000008080808080808080000000000000000080808080808080800000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__ __map__
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c00000000000000000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c0000000000000c001c1c000c0c000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c000000000044000c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c000000000044000c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c0000000000000000000000000c000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0000000000000000000000000000000c00000000000000000000000000000c000000000000000000000000000000000e00000000000e0e0e0e0000000000000e000000000e000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c0000000000000000000000000000000c00000000000000000000000000000c0c00004f0c0c0000000c000000001c120e00000000000e0e0e0e0000000000000e000000000e000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
3d1c000000001c0000000000000000000000000000000000000000000000000c000000000000000000000000000000000e00000000000000000e0000000000000e000000000e000e00000000000000000e0000000000000000000000000000000e0000000000000e0e000000000000000e00000000000e0e0e0e000000000000 3d1c000000001c0000000000000000000000000000000000000000000000000c3d000c000c0c0000003f0c0c0000000c0e00000000000000000e0000000000000e000000000e000e00000000000000000e0000000000000000000000000000000e0000000000000e0e000000000000000e00000000000e0e0e0e000000000000
0c0000000000000000000000000000410000000000000000000000000000000c0000000000000e0e0e000000000000000e00000000000000000e0000000000000e000000000e000e00000000000000000e00000000000e0e0e000000000000000e00000000000e0000000000000000000e00000000000000000e000000000000 0c0000000000000000000000000000410000000000000000000000000000000c0c000c0000000000000000000000000c0e00000000000000000e0000000000000e000000000e000e00000000000000000e00000000000e0e0e000000000000000e00000000000e0000000000000000000e00000000000000000e000000000000
0c000000000000000c0c0c0c0c0c0c0c0c00000000000020210000000000000c00000000000e00000e0e0000000000000e0000000000000e0e0e0000000000000e000000000e0e0e0e0e0000000000000e00000000000e0000000000000000000e00000000000e0e0e000000000000000e000000000000000e00000000000000 0c000000000000000c0c0c0c0c0c0c0c0c00000000000020210000000000000c01000c0c00000000000c0c004f00000c0e0000000000000e0e0e0000000000000e000000000e0e0e0e0e0000000000000e00000000000e0000000000000000000e00000000000e0e0e000000000000000e000000000000000e00000000000000
0c0c0c0c0c0c00000000000c0c0c0c0c0c00000000000030310000000000000c000000000000000e0e000000000000000e00000000000000000e0000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e00000000000e00000e0000000000000e0000000000000e0000000000000000 0c0c0c0c0c0c00000000000c0c0c0c0c0c00000000000030310000000000000c0c0000000000000c00000c000000000c0e00000000000000000e0000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e00000000000e00000e0000000000000e0000000000000e0000000000000000
0c00000000000c0c004f000c0c0c0c0c0c00000000000000000000000000000c0000000000000e0e00000000000000000e00000000000e0e0e0e0000000000000e0000000000000e00000000000000000e000000000000000e000000000000000e0000000000000e0e000000000000000e0000000000000e0000000000000000 0c00000000000c0c004f000c0c0c0c0c0c00000000000000000000000000000c0c00004f0000000c0c000c0000000c0c0e00000000000e0e0e0e0000000000000e0000000000000e00000000000000000e000000000000000e000000000000000e0000000000000e0e000000000000000e0000000000000e0000000000000000
0c00000c4f00000000000000000000120100000000000000000000000000000c00000000000e0e0e0e0e0000000000000e0000000000000000000000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c00000c4f00000000000000000000120100000000000000000000000000000c0c00000000000000000000000000000c0e0000000000000000000000000000000e0000000000000e00000000000000000e00000000000e0e0e000000000000000e0000000000000000000000000000000e000000000000000000000000000000
3d0000000000003f0c000c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 3d0000000000003f0c000c0c0c0c0c0c0c00000000000000000000000000000c0c00000c00000000000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0000000000000000000c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c0000000000000000000c0c0c0c0c0c0c00000000000000000000000000000c0c000c0c0c0000000c0c0c004f00000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
010000000000000c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 010000000000000c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c00000c00000000000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c0c00000000001c00000000000000000c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c00410c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c000000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000 0c0c0c0c00410c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
0c00000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000 0c00000000000000000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c004f000000000c001c1c000c0c000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c3e0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000 0c004f000000000c001c1c000c0c000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0c0c0c0c0c0c0c0c0c0c00000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c3e0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
@ -1996,18 +1867,18 @@ __map__
0c00000000001c00000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000 0c00000000001c00000000000000000c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0000000000000000000000000000000e000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
__sfx__ __sfx__
01320000050350c03511045185451d55511515115000050001035080350d04514545195551b5551a5301b5401a5551a51516555145001554015545000000000013005130350d035100450c045100201d0530c053 01280000050550c05511055180551d05500000000000000000055070550c0550f055130550f0550c0550705501055080550d055140551905500000000000000000055070550f0551305518055130550f0550c055
0132000000000000001f0001f035200452001520000180001b0001b00500000190351b0451d0451c0551d0451c0551c015180551b000170401704519000140001800000000130051305517055170251701500000 0128000000000000001f0001f055200551f0551d055180551b055000000000000000000000000000000000000000000000000001b0551d0551b05519055140551805500000000000000000000000000000000000
01280000050350c03511045185451d5550c515115150051501515011150c0000f000130000f0000c0001403314550145530c023080141950000000000000000000000070000f0001300018000130000f0000c000 01280000050550c05511055180551d05518055110550d0550c055130551b055240552b0551b05518055130550a055110551a05522055290550e0550a05505055000550705510055180551f055100550c05507055
012800000000000000130001f055220552005500000270551f0551d05500000000000000000000000000000024050240501d0261a0030c0040000000000000000000000000000000000000000000000000000000 012800000000000000130001f055220552005500000270551f0550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
013200001102511025110250c000140001d0451c0411904018040160401404013040110500d00508005264002740027400080000f000180001400026400244002240022400030000a0001f4001f4001b4001b400 012800001d4521d452050550c05514055110551f452204522445224452050550c055140551105526452264522745227452080550f055180551405526452244522245222452030550a0551f4521f4521b4521b452
013200002c555295552955508000115002c5552b55528555285552b5552955528545295451853518535265002750027500075000e5001f5001f4002640026400244002440000000070000f0000f0000e0000c000 012800001d4521d4520105508055110550d0551f452204522445224452050550c055140551105526452264522745227452070550e0551f4521f4522645226452244522445200055070550f0520f0550e0550c055
013200000000000000000000000013000190001805116050140501305011050100510d0350d0350d0350000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00280000000000000000000000000505500000050550c055000000000000000050050505500000050550c055000000000000000000000805500000080550f05500000000000000000000030550a0550205509055
012800000122401222000000000001055000000105508055052220522200000000000505500000050550c05507222072220000000000022220222202222022220022200222000000000000055070550005507055 012800000122401222000000000001055000000105508055052220522200000000000505500000050550c05507222072220000000000022220222202222022220022200222000000000000055070550005507055
012800001d3141f3142032420300203040000027324273201f320000001d3001d3241b324000001f324000001d3141f3142031422314243142631427324293242b3240000024324273002932129320293102b310 012800001d3541f3542035420300203040000027354273501f350000001d3001d3541b354000001f354000001d3541f3542035422354243542635027354293502b3540000024354000002935429350293502b350
012800000000000000010550805501055080050105508055000550800000000070550005507055000550705501055000000100508005010050800501055080550005500000070550000000050000000705500000 012800000000000000010550805501055080050105508055000550800000000070550005507055000550705500000000000105508055010550805501055080550005500000070550000000055000000705500000
01280010183241a3241b3240000000000000002232400000213240000026324000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 01280010183541a3541b3540000000000000002235400000213540000026354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01281000080050f005080250f02501055000000f025000000e3250000013325000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 01281000080050f005080550f05501055000000f055000000e3550000013355000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
@ -2063,9 +1934,8 @@ __sfx__
__music__ __music__
01 00014344 01 00014344
00 02034344 00 02034344
00 04050644 00 04064344
00 05074344 00 05074344
00 08094344 00 08094344
02 0a0b4344 02 0a0b4344
00 0c424344