11 Commits

Author SHA1 Message Date
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
@ -1087,7 +1046,6 @@ function rope:draw(artificial_px,artificial_py)
end end
-- debug -- debug
--[[
local n1=self.src local n1=self.src
local sy=0 local sy=0
while true do while true do
@ -1134,7 +1092,6 @@ 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 +1110,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 +1118,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 +1138,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 +1169,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 +1232,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
@ -1323,8 +1276,11 @@ function rope:be_pushed_by(anchor,ax_old,ay_old)
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 +1324,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 +1347,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 +1374,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
@ -1492,18 +1448,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 +1463,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
@ -1717,20 +1672,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 +1733,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 +1918,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