chameleonic/chameleonic.p8

1462 lines
48 KiB
Lua
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

pico-8 cartridge // http://www.pico-8.com
version 38
__lua__
modules={}
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
function _doall(x)
for n in names(x) do
for mod in all(modules) do
local f=mod[n]
if (f) f(mod)
end
end
end
-- source: https://www.lexaloffle.com/bbs/?pid=78990
gaps=split"57,23,10,4,1"
--{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
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
local d=max(abs(dx),abs(dy))
local n=min(abs(dx),abs(dy))/d
d*=sqrt(n*n+1)
if(d<0.001) return
local ca,sa=dx/d,-dy/d
-- polygon points
local s={
{0,-r},{d,-r},{d,r},{0,r}
}
local u,v,spans=s[4][1],s[4][2],{}
local x0,y0=ax+u*ca+v*sa,ay-u*sa+v*ca
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
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]
if span then
rectfill(x0,y,span,y)
else
spans[y]=x0
end
x0+=dx
end
x0,y0=_x1,_y1
end
end
function _apply(x,ts,a)
local t=deli(ts,1)
for k,v in pairs(t) do
if k=="update" then
if not v(x,a) then
add(ts,t,1)
end
else
x[k]=v
end
end
end
function sgn0(x)
if (x==0) return x
return sgn(x)
end
function _mnmx(x,y)
return min(x,y),max(x,y)
end
-->8
bg={}
add(modules,bg)
function bg:draw0()
cls(0)
end
-->8
level={}
add(modules,level)
function level:init()
level:reinit(0)
end
function level:reinit(n)
self.ix=n
self.todo={}
self.bigx=(n%16)
self.bigy=(n\16)
self:load_dynobjs()
self:recollide()
self:reanchor(true)
self:spawn_exit()
end
function level:advance()
self:reinit(self.ix+1)
end
function level:draw()
map(
self.bigx*16,self.bigy*16,
0,0,16,16,
64 -- flag 6: visible
)
for _,crate in pairs(self._crates) do
spr(crate.s,crate.px,crate.py)
end
end
function level:busy()
for _,crate in pairs(self.crates) do
if (#crate.todo>0) return true
end
return false
end
function level:update()
_apply(self, self.todo)
for _,crate in pairs(self._crates) do
_apply(crate, crate.todo)
end
end
function level:load_dynobjs()
self._crates={}
for mx=0,15,1 do
for my=0,15,1 do
local mxy=_mix(mx,my)
local s=self:_mget(mx,my)
local def=self:_get_cratedef(s)
if def!=nil then
self._crates[mxy]={
s=s,def=def,
mx=mx,my=my,
px=mx*8,py=my*8,
todo={}
}
end
end
end
end
function level:recollide()
self._coll={}
for mx=0,15,1 do
for my=0,15,1 do
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(remove)
if remove or self._anch==nil then
self._anch={}
end
for ax0=0,31,1 do
for ay0=0,31,1 do
local ax1,ay1=ax0-1+2*(ax0%2),ay0-1+2*(ay0%2)
local mx0,my0=ax0\2,ay0\2
local mx1,my1=ax1\2,ay1\2
if (
not self:mcoll(mx0,my0) and
not self:mcoll(mx0,my1) and
not self:mcoll(mx1,my0) and
self:mcoll(mx1,my1)
) then
local px0,py0=level:a2p(ax0,ay0)
self._anch[_amix(ax0,ay0)]={ax=ax0,ay=ay0,x=px0,y=py0}
end
end
end
end
function level:win_at(mx,my)
return self._wins[_mix(mx,my)]
end
function level:anchor_points()
return pairs(self._anch)
end
function level:anchors_in(px0,py0,px1,py1)
ancs={}
for ax=px0\4,(px1+3)\4 do
for ay=py0\4,(py1+3)\4 do
local anc=self._anch[_amix(ax,ay)]
if (anc!=nil) add(ancs, anc)
end
end
return ancs
end
function level:point_anchor(px,py)
local ax,ay=self:p2a(px,py)
local anc=self._anch[_amix(ax,ay)]
return anc
end
function level:spawn_exit()
self._wins={}
local spawned=false
local spawn_at=function(x,y)
if (self:_mget(x,y)!=1) return
assert(not spawned,x..","..y)
spawned=true
player:reinit(x,y)
player.orientx=-1
if (x<8) player.orientx=1
end
local win_at=function(x,y)
if (self:_mget(x,y)!=4) return
for n in all(neighbors{x=x,y=y}) do
if n.x<0 or n.y<0 or n.x>15 or n.y>15 then
self._wins[_mix(n.x,n.y)]=true
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
function level:p2a(px,py)
return px\4,py\4
end
function level:a2p(ax,ay)
local px=ax*4+3*(ax%2)
local py=ay*4+3*(ay%2)
return px,py
end
function level:mcoll(mx,my)
return self._coll[_mix(mx,my)]!=false
end
function level: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
--if (ax<0 or ay<0 or ax>31 or ay>31) return nil
--return ay*32+ax
end
function _mix(mx,my)
return mx..","..my
--if (mx<0 or my<0 or mx>15 or my>15) return nil
--return my*16+mx
end
function level:_get_cratedef(s)
if (s<64 or s>=80) return nil
local s2=s-64
return {
up=s2&1!=0,
right=s2&2!=0,
down=s2&4!=0,
left=s2&8!=0
}
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]
if crate then
if
(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 {
el="crate",
dx=-dx,dy=-dy,
px_offset=px-crate.px-sgn0(dx),
py_offset=py-crate.py-sgn0(dy),
rec=crate
}
end
end
local m=self:_mget(mx,my)
if
(m==60 and dy>0) or
(m==61 and dx<0) or
(m==62 and dy<0) or
(m==63 and dx>0)
then
return {
el="eyehook",
dx=-dx,dy=-dy,
mx=mx,my=my
}
end
end
function level:can_move(
is_player,
mx0,my0,dmx,dmy,exclude_src,exclude_dst
)
if is_player and self:win_at(mx0+dmx,my0+dmy) then
return true
end
if self:mcoll(mx0+dmx,my0+dmy) then
return false
end
-- todo: check tongue collision
if player.rope then
local px,py=mx0*8,my0*8
local chk=false
if dmx==0 and dmy==-1 then
chk=player.rope:collide_rect(px+3,py-5,px+4,py+5,exclude_src,exclude_dst)
elseif dmx==0 and dmy==1 then
chk=player.rope:collide_rect(px+3,py+3,px+4,py+13,exclude_src,exclude_dst)
elseif dmx==-1 and dmy==0 then
chk=player.rope:collide_rect(px-5,py+3,px+5,py+4,exclude_src,exclude_dst)
elseif dmx==1 and dmy==0 then
chk=player.rope:collide_rect(px+3,py+3,px+13,py+4,exclude_src,exclude_dst)
end
if (chk) return false
end
return true
end
function level:tug_crate(mx0,my0,dmx,dmy)
local mxy0=_mix(mx0,my0)
local existing=self._crates[mxy0]
if (existing==nil) return
self._crates[mxy0]=nil
local mx1,my1=mx0+dmx,my0+dmy
local mxy1=_mix(mx1,my1)
existing.mx=mx1
existing.my=my1
existing.todo={
{px=mx0*8+dmx*2,py=my0*8+dmy*2},
{px=mx0*8+dmx*7,py=my0*8+dmy*7},
{px=mx1*8,py=my1*8,update=function()
self:reanchor(true)
return true
end}
}
self._crates[mxy1]=existing
self:recollide()
self:reanchor(false)
end
-->8
player={}
add(modules,player)
function player:init()
--self:reinit(8,14)
end
function player:reinit(x,y)
self.x=x
self.y=y
self.px=0
self.py=0
self.todo={}
self.orientx=-1
self.orienty=0
self.rope=nil
end
function player:any_busy()
if (#self.todo>0) return true
if (level:busy()) return true
if (self.rope!=nil and self.rope:busy()) return true
return false
end
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
if not self:any_busy() then
if level:win_at(self.x,self.y) then
level:advance()
return
end
if btn() then
if level:can_move(true,self.x,self.y,-1,0,0,2) then
self.todo=f4({{orientx=-1,orienty=0,px=-2},{px=-7},{x=self.x-1}})
else
self.orientx=-1
self.orienty=0
end
elseif btn() then
if level:can_move(true,self.x,self.y,1,0,0,2) then
self.todo=f4({{orientx=1,orienty=0,px=2},{px=7},{x=self.x+1}})
else
self.orientx=1
self.orienty=0
end
elseif btn() then
if level:can_move(true,self.x,self.y,0,-1,0,2) then
self.todo=f4({{orienty=-1,py=-2},{py=-7},{y=self.y-1}})
else
self.orienty=-1
end
elseif btn() then
if level:can_move(true,self.x,self.y,0,1,0,2) then
self.todo=f4({{orienty=1,py=2},{py=7},{y=self.y+1}})
else
self.orienty=1
end
elseif btn(🅾) then
if self.rope==nil then
local rx,ry,rx2,ry2=self:_rope_pos()
local dx,dy=12*self.orientx,12*self.orienty
if (dy!=0) dx=0
self.rope=rope:new(rx,ry,rx2,ry2,dx,dy)
self.todo={{
update=function()
return self.rope==nil or not self.rope:casting()
end
},{},{}}
else
self.rope:tug()
self.todo={{},{},{}}
end
elseif btn() then
if self.rope!=nil then
self.rope=nil
end
end
end
_apply(self,self.todo)
if self.rope then
self.rope:update()
local rx,ry=self:_rope_pos()
self.rope:drag_dst(rx,ry)
if self.rope:done() then
self.rope=nil
add(self.todo,{})
add(self.todo,{})
add(self.todo,{})
end
end
end
function player:_rope_pos()
local px=self.x*8+self.px
local px2=px+4
if self.orientx==-1 then
px+=2
else
px+=6
end
local py=self.y*8+self.py+2
local py2=py+1
return px,py,px2,py2
end
function player:draw()
local px=self.x*8+self.px
local py=self.y*8+self.py
local head=2-self.orienty
if self.orientx==-1 then
spr(16,px+6,py-2,1,1)
if (self.rope) self.rope:draw()
spr(17,px+1,py,1,1)
spr(head,px-3,py-3,1,1)
else
spr(16,px-6,py-2,1,1,true)
if (self.rope) self.rope:draw()
spr(17,px-1,py,1,1,true)
spr(head,px+3,py-3,1,1,true)
end
--spr(17,px+3,py)
--spr(17,px+6,py)
-- if spr(2,self.x*8+self.px)
end
-->8
rope={}
rope.__index=rope
function rope:new(
x,y,src_x,src_y,dx,dy
)
local r={
id=0,
src={x=src_x,y=src_y,todo={}},
ancs={},
dst={x=x,y=y,todo={}},
cast={dx=dx,dy=dy},
latch=nil,
latch_frame=0,
under_destruction=false,
}
setmetatable(r,rope)
return r
end
function rope:casting()
return self.cast!=nil
end
function rope:done()
return self.latch_frame>=2 and (
self.latch==nil or
self.under_destruction
)
end
function rope:busy()
for i=0,#self.ancs+1 do
if (#(self:_anc(i).todo)>0) return true
end
return false
end
function rope:update()
if self.cast!=nil then
self:continue_cast()
return
end
self.latch_frame+=1
if self.latch_frame>=10 then
self.latch_frame=10
end
self:_make_consistent()
end
function rope:_make_consistent()
for i=0,#self.ancs+1 do
local anc=self:_anc(i)
_apply(anc,anc.todo,i)
end
if
not self.under_destruction and
self.latch!=nil and
self.latch.rec!=nil
then
self:drag_src(
self.latch.rec.px+self.latch.px_offset,
self.latch.rec.py+self.latch.py_offset
)
if #self.latch.rec.todo==0 then
for i=0,#self.ancs do
local a0=self:_anc(i)
local a1=self:_anc(i+1)
if not self:_can_stretch(a0, a1) then
self.under_destruction=true
break
end
end
end
end
end
function rope:continue_cast()
local dx,dy=self.cast.dx,self.cast.dy
local x0=self.src.x
local y0=self.src.y
local x1=x0+dx
local y1=y0+dy
for x,y in self:_rast(
x0,y0,x1,y1
) do
local latch=
level:get_latch(dx,dy,x,y)
if latch!=nil or level:pcoll(x,y) then
self.latch=latch
self.cast=nil
break
end
self.src={x=x,y=y,todo={}}
end
end
function rope:_reindex()
self.src.ix=0
self.dst.ix=#self.ancs
for i,anc in ipairs(self.ancs) do
anc.ix=i
end
end
function rope:draw()
local points=self:_anchors_simplified()
for i=1,(#points-1) do
local src=points[i]
local dst=points[i+1]
local x,y=src.x,src.y
local dx,dy=dst.x-x,dst.y-y
linefill(x,y,x+0.25*dx,y+0.25*dy,1.0,8)
linefill(x+0.25*dx,y+0.25*dy,x+1*dx,y+1*dy,0.5,8)
linefill(x+0.9*dx,y+0.9*dy,x+dx,y+dy,1.0,8)
circfill(x+0.5,y+0.5,1.0,8)
end
for i,p in ipairs(self.ancs) do
rectfill(p.x-1,p.y-1,p.x+1,p.y+1,12)
print(p.id..":"..p.x..","..p.y..","..#p.todo,0,-8+i*8,9)
end
for _,p in pairs(level._anch) do
pset(p.x,p.y,11)
end
if self.all_ops!=nil then
for i,o in ipairs(self.all_ops) do
rect(o.mx*8,o.my*8,o.mx*8+7,o.my*8+7,4)
--print(o.mx..","..o.my,0,i*8,3)
end
end
end
function rope:_anc(i)
if (i==0) return self.src
if (i==#self.ancs+1) return self.dst
return self.ancs[i]
end
function rope:drag_dst(x,y)
self:drag(function() return #self.ancs+1 end,x,y)
end
function rope:drag_src(x,y)
self:drag(function() return 0 end,x,y)
end
function rope:drag(
i,x,y
)
local anc=self:_anc(i())
local busy=self:busy()
for x,y in self:_rast(
anc.x,anc.y,x,y
) do
local a=self:_anc(i())
if not (_point_eq(a,{x=x,y=y})) then
a.x=x
a.y=y
a.dirty=true
self.dirty=true
if (not busy) self:_tidy_up_gen()
end
end
end
function rope:_tidy_up_gen()
if (self.under_destruction) return
if (not self.dirty) return
local settled=true
local touched={}
local loop=function(f)
local a=0
while a<=#self.ancs+1 do
local anc=self:_anc(a)
if anc.dirty then
anc.seen=true
if self[f](self,a) then
settled=false anc.changed=true
end
end
a+=1
end
end
local mark_unseen=function()
touched={}
for a=0,#self.ancs+1,1 do
local anc=self:_anc(a)
anc.seen=false
anc.changed=false
end
end
local propagate_dirty=function(f)
for a=0,#self.ancs+1,1 do
local a1=self:_anc(a)
if a1.dirty then
local a0=self:_anc(a-1)
if (a0!=nil) a0.dirty=true
local a2=self:_anc(a+1)
if (a2!=nil) a2.dirty=true
end
end
end
while true do
settled=true
mark_unseen()
propagate_dirty()
loop("_find_needed_anchors")
loop("_find_touched_anchors")
loop("_elide_point")
for a=0,#self.ancs+1,1 do
local anc=self:_anc(a)
if (anc.seen) anc.dirty=anc.changed
end
if (settled) break
end
self.dirty=false
end
function rope:_find_needed_anchors(i)
if (i<=0) return false
if (#self.ancs+1<i) return false
local a0=self:_anc(i-1)
local a2=self:_anc(i)
if (level:pcoll(a2.x,a2.y)) return false
if (level:pcoll(a0.x,a0.y)) return false
if (self:_can_stretch(a0,a2)) return false
local anchors_bydist={}
local x0,x2=_mnmx(a0.x,a2.x)
local y0,y2=_mnmx(a0.y,a2.y)
for a1 in all(level:anchors_in(x0-1,y0-1,x2+1,y2+1)) do
add(anchors_bydist,{el=a1,key=_linedist(a0,a1,a2)})
end
shellsort(anchors_bydist)
for a1 in all(anchors_bydist) do
a1=a1.el
if self:_can_stretch(a0,a1) and
self:_can_stretch(a1,a2)
then
local id=self.id
add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i)
self.id+=1
return true
end
end
end
function rope:_find_touched_anchors(i)
if (i<=0) return false
if (#self.ancs<i) return false
local a0=self:_anc(i-1)
local a2=self:_anc(i)
if (level:pcoll(a0.x,a0.y)) return false
if (level:pcoll(a2.x,a2.y)) return false
for bx,by in self:_rast(a0.x,a0.y,a2.x,a2.y) do
local a1=level:point_anchor(bx,by)
if
a1!=nil and not _point_eq(a0,a1) and not _point_eq(a1,a2)
and _linedist(a0,a1,a2) == 0.0
-- and self:_can_stretch(p,a2)
then
local id=self.id
add(self.ancs,{id=id,x=a1.x,y=a1.y,dirty=true,todo={}},i)
self.id+=1
return true
end
end
return false
end
function rope:_elide_point(i)
if (i<=0) return false
if (#self.ancs<i) return false
local a0=self:_anc(i-1)
local a1=self:_anc(i)
local a2=self:_anc(i+1)
local level_anc=level:point_anchor(a1.x,a1.y)
if _point_eq(a0,a1) or _point_eq(a1,a2) or level_anc==nil then
-- do it unconditionally
else
if _linedist(a0,a1,a2) < 0.1 then
return false
end
if not self:_can_stretch(a0,a2) then
return false
end
local midpoint={
x=(a0.x+a2.x)\2,
y=(a0.y+a2.y)\2
}
if not self:_can_move_midpoint(a0,a1,midpoint,a2) then
return false
end
end
deli(self.ancs,i)
return true
end
function rope:_can_move_midpoint(a0,a1_0,a1_1,a2)
if (level:pcoll(a0.x,a0.y)) return false
if (level:pcoll(a2.x,a2.y)) return false
if (level:pcoll(a1_0.x,a1_0.y)) return false
if (level:pcoll(a1_1.x,a1_1.y)) return false
if not self:_can_stretch(a1_0, a1_1) then
return false
end
if not self:_can_stretch(a0,a1_1) then
return false
end
if not self:_can_stretch(a1_1,a2) then
return false
end
for x,y in self:_rastn(a1_0.x,a1_0.y,a1_1.x,a1_1.y,8,8) do
local tm={x=x,y=y}
if not self:_can_stretch(a0,tm) then
return false
end
if not self:_can_stretch(tm,a2) then
return false
end
end
return true
end
function _linedist(x0,v,x1)
return 100 * (sum_distance(x0,v,x1)-distance(x0,x1))/distance(x0,x1)
end
function sum_distance(x,y,z)
return distance(x,y) + distance(y,z)
end
function distance(p1,p2)
local dx=p2.x-p1.x
local dy=p2.y-p1.y
return sqrt(dx*dx+dy*dy)
end
function rope:collide_rect(x1,y1,x2,y2,exclude_src,exclude_dst)
local last=#self.ancs-exclude_dst
for i=exclude_src,last,1 do
local a0=self:_anc(i)
local a1=self:_anc(i+1)
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y1,x2,y1)) return true
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y1,x1,y2)) return true
if (_line_line(a0.x,a0.y,a1.x,a1.y,x1,y2,x2,y2)) return true
if (_line_line(a0.x,a0.y,a1.x,a1.y,x2,y1,x2,y2)) return true
end
return false
end
function _line_line(x1,y1,x2,y2,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
function rope:_can_stretch(
p1,p2
)
-- faster implementation for straight lines
if p1.y\8==p2.y\8 then
local my=p2.y\8
for mx=p1.x\8,p2.x\8 do
if (level:mcoll(mx,my)) return false
end
end
if p1.x\8==p2.x\8 then
local mx=p2.x\8
for my=p1.y\8,p2.y\8 do
if (level:mcoll(mx,my)) return false
end
end
if (level:pcoll(p1.x,p1.y)) return false
if (level:pcoll(p2.x,p2.y)) return false
local res=true
for x,y in self:_rastn(p1.x,p1.y,p2.x,p2.y,8,8) do
if level:pcoll(x,y) then
res=false
break
end
end
return res
end
function rope:_rastn(
x0,y0,x1,y1,dx,dy
)
-- todo: more optimized implementation?
local iter=self:_rast(x0,y0,x1,y1)
local prevx,prevy=nil,nil
local done=false
return function()
while not done do
local x,y=iter()
if (x==nil) done=true return x1, y1
local x8 = x\dx
local y8 = y\dy
if not (x8==prevx and y8==prevy) then
prevx,prevy=x8,y8
return x,y
end
end
end
end
function rope:_rast(
x0,y0,x1,y1
)
local dx=abs(x1-x0)
local dy=abs(y1-y0)
local x=x0
local y=y0
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
return function()
if (done) return
if (x==x1) done=true return x1,y1
local oldx,oldy=x,y
err-=dy
if (err<0) y+=sy err+=dx
x+=sx
return oldx,oldy
end
else
err=dy/2.0
return function()
if (done) return
if (y==y1) done=true return x1,y1
local oldx,oldy=x,y
err-=dx
if (err<0) x+=sx err+=dy
y+=sy
return oldx,oldy
end
end
end
function _point_eq(p1,p2)
return p1.x==p2.x and p1.y==p2.y
end
function neighbors(p)
local r={}
for dx=-1,1,1 do
for dy=-1,1,1 do
if dx!=0 or dy!=0 then
add(r,{x=p.x+dx,y=p.y+dy})
end
end
end
return r
end
-->8
-- moved here because it's complicated
function rope:tug()
self:_make_consistent()
if (self.under_destruction) return
self:_tug()
self:_make_consistent()
end
function rope:_tug()
local ancs=self:_anchors_simplified()
local touched={}
for i=#ancs-1,2,-1 do
local ops= self:_calc_push(ancs[i+1],ancs[i],ancs[i-1])
for o in all(ops) do
add(self.all_ops,o)
end
local can_do=true
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 or touched[_mix(o.mx,o.my)] then
can_do=false
else
if not level:can_move(false,o.mx,o.my,o.dmx,o.dmy,0,0) then
can_do=false
end
end
end
if (not can_do) break
end
if can_do and #ops>=1 then
local dmx,dmy=ops[1].dmx,ops[1].dmy
for o in all(ops) do
touched[_mix(o.mx,o.my)]=true
touched[_mix(o.mx+dmx,o.my+dmy)]=true
level:tug_crate(
o.mx,o.my,dmx,dmy
)
end
for node=ancs[i-1].ix,ancs[i].ix do
local anc=self:_anc(node)
local x0,y0=anc.x,anc.y
local upd=function(x,y,force)
return {update=function(s,i)
if force or not level:pcoll(x,y) then
s.x=x
s.y=y
self.dirty=true
end
return true
end}
end
anc.todo={
{},
upd(x0+dmx*2,y0+dmy*2),
upd(x0+dmx*7,y0+dmy*7),
upd(x0+dmx*8,y0+dmy*8),
}
end
for node=ancs[i-1].ix-1,ancs[i].ix+1 do
local anc=self:_anc(node)
end
return
end
end
local latch=self.latch
if (latch==nil) return
if latch.el=="crate" then
local dmx,dmy=
sgn0(latch.dx),
sgn0(latch.dy)
local lanc=ancs[2]
local mx0=latch.rec.mx
local my0=latch.rec.my
local mxa=(lanc.x+dmx)\8
local mya=(lanc.y+dmy)\8
local too_far=false
if
sgn0(mx0-mxa)!=
sgn0(mx0+dmx-mxa) or
sgn0(my0-mya)!=
sgn0(my0+dmy-mya)
then
too_far=true
end
if not too_far and
not touched[_mix(mx0,my0)] and
level:can_move(false,mx0,my0,dmx,dmy,1,0)
then
level:tug_crate(
mx0,my0,
dmx,dmy
)
-- be busy for 4 ticks while the crate moves
self:_anc(0).todo={{},{},{},{}}
end
end
end
function rope:_calc_push(
an,a0,a1
)
local ops={}
if a0.x==a1.x then
local y0,y1=_mnmx(a0.y,a1.y)
local my0,my1=(y0+1)\8,(y1-1)\8
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
for my=my0,my1,1 do
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)
local mx0,mx1=(x0+1)\8,(x1-1)\8
local my,dmy
if a0.y%8==0 and a0.y>an.y+6 then
-- push up
my=(a0.y-1)\8
dmy=-1
elseif a0.y%8==7 and a0.y<an.y-3 then
-- push down
my=(a0.y+1)\8
dmy=1
else
return {}
end
for mx=mx0,mx1,1 do
add(ops,{mx=mx,my=my,dmx=0,dmy=dmy})
end
end
return ops
end
function rope:_anchors_simplified()
-- todo: cache this
self:_reindex()
local points={}
local _slope = function(p0,p1)
return atan2(p1.y-p0.y,p1.x-p0.x)
end
for i=0,#self.ancs+1,1 do
local anc=self:_anc(i)
if #points<=1 then
add(points,anc)
elseif abs(
_slope(points[#points-1],points[#points])-
_slope(points[#points],anc)
)==0 then -- epsilon?
points[#points]=anc
else
add(points,anc)
end
end
return points
end
__gfx__
00000000000300000000003300030000000000000000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
000000000333330000003333033333000aa00aa00000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
000000009933399000399330933333900aaaaaa00000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
000000009a333a90033a9330933333900aaaaaa00000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
00000000333333303333330003333300009999000000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
0000000003333300000033000333330000aaaa000000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
0000000000333c0003333c0000333000000aa0000000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
000000000000cc000000cc000000cc00004444000000000000000000000000000000000000000000000000000000000077777777000000000000000000000000
0000ee00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000e00e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00e0000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00e0e00e00c0c0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00ee00ee00ccccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000ee00ccccccc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00eeee000c00c00c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
eeee0000cc0cc0cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000a90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000aaaaaaa91000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000aaaaaa1a91100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0aaaaaaaaa1a91110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0aaaaaaaa41a91a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0a000aa4441a91a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00a0044449a110a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000aa111991111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000991000000000000000000000000000000000000000000000000000000000000000000000000000000000000077700777777777777777777777777777
00000000990000000000000000000000000000000000000000000000000000000000000000000000000000000000000077700777777777777777777777777777
00000000990000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777777777777777777777777777
00000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000077700777777007007770077700700777
00000000aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000077700777777007007770077700700777
0000000077a000000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777777777777777777777777777
00000007777a00000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777777777777770077777777777
00044444444444000000000000000000000000000000000000000000000000000000000000000000000000000000000077777777777777777770077777777777
dd0dd0ddddd00ddddd0dd0ddddd00ddddd0dd0ddddd00ddddd0dd0ddddd00ddddd0dd0ddddd00ddddd0dd0ddddd00ddddd0dd0ddddd00ddddd0dd0ddddd00ddd
ddddddddddd00dddddddddddddd00dddddddddddddd00dddddddddddddd00dddddddddddddd00dddddddddddddd00dddddddddddddd00dddddddddddddd00ddd
0dddddd00dddddd00ddddddd0ddddddd0dddddd00dddddd00ddddddd0dddddddddddddd0ddddddd0ddddddddddddddddddddddd0ddddddd0dddddddddddddddd
ddd00dddddd00dddddd00d00ddd00d00ddd00dddddd00dddddd00d00ddd00d0000d00ddd00d00ddd00d00d0000d00d0000d00ddd00d00ddd00d00d0000d00d00
ddd00dddddd00dddddd00d00ddd00d00ddd00dddddd00dddddd00d00ddd00d0000d00ddd00d00ddd00d00d0000d00d0000d00ddd00d00ddd00d00d0000d00d00
0dddddd00dddddd00ddddddd0ddddddd0dddddd00dddddd00ddddddd0dddddddddddddd0ddddddd0ddddddddddddddddddddddd0ddddddd0dddddddddddddddd
ddddddddddddddddddddddddddddddddddd00dddddd00dddddd00dddddd00dddddddddddddddddddddddddddddddddddddd00dddddd00dddddd00dddddd00ddd
dd0dd0dddd0dd0dddd0dd0dddd0dd0ddddd00dddddd00dddddd00dddddd00ddddd0dd0dddd0dd0dddd0dd0dddd0dd0ddddd00dddddd00dddddd00dddddd00ddd
__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__
000000000000000000000000c00000000000000000000000000000000000000040400000000000000000000000000000404000000000000000000000c0c0c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c000000000000000c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c000000000000000c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01000000000000000c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c000000000000000c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c000000000000000c0c0c0c0c0c0c0c0c00000000000020210000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c000000000000000000000c0c0c0c0c0c00000000000030310000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0000000c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c00000000000000040100000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000