pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
--animator
--custom animation tool
--◆caoimhe ni chaoimh◆
--oakreef.ie
--todo:
-- export
-- import
-- delete button does't work
function _init()
debug = true
poke(0x5f2d, 1)
chars={}
chari=0
layeri=0
cplayer=new_layer() --copied layer
creation=nil
playing = false
timer = 0
clock = 0
fill = false
ghost = false
ghostw = false
showcentre = true
sheet={} --represents the sprite sheet
toast = {timer=0,message=''}
spritesheetname = 'spritesheet.png'
metadataname = 'metasheet.png'
tempimagename = 'temp.png'
_online = type(stat(102)) == 'string'
numf = 10
charlist = {'1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',':',';','.',',',' ','-','='}
alphabet = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}
generate_elements()
active=nil
backspace = false
enter = false
cancel = false
sheet_width = 128
sheet_height = 64
input=''
mouse = {x=0,y=0,l=false,r=false,m=false}
keybuffer = {}
--memset(0, 0, 0x2000)
--cstore(0, 0, 0x2000)
_import()
update_current_layer()
update_frame()
end
function toaster(message)
toast.timer = 60
toast.message = message
flip()
rectfill(0,120,127,127,8)
print(toast.message,1,121,7)
end
function _export()
toaster('starting export')
sheet = {}
layers = {}
-- add all layers to a single list
for ci, c in pairs(chars) do
for ai, a in pairs(c.anim) do
for fi, f in pairs(a.frames) do
for li, l in pairs(f.layers) do
if not l:blank() then --disregard blank layers
l:trim()
add(layers, l)
end
end
end
end
end
-- sort by height and width
toaster('sorting layers')
layers = sort(layers)
-- wipe sprite sheet
memset(0, 0, 0x2000)
-- starting from the top left of the sheet
-- iterate over each column then row and
-- try to add image in each space
for i,l in pairs(layers) do
toaster('packing ' .. i .. ' of ' .. #layers)
for j,k in pairs(layers) do
if k.drawn and k:eq(l) then
l.loc = {}
l.loc.x = k.loc.x
l.loc.y = k.loc.y
l.drawn = true
break
end
end
if not l.drawn then
local drew = false
for i=0,sheet_width-1 do
for j=0,sheet_height-1 do
if can_fit_on_sheet(l, i, j) then
draw_to_sheet(l, i, j)
drew = true
break
end
end
if drew then break end
end
if not drew then
error("could not fit sprites on sheet")
end
end
end
toaster('exporting sheet')
-- save sprite sheet to cart
cstore(0, 0, 0x2000)
-- export sprite sheet
--export('stest.png')
export(spritesheetname)
-- plr={anim={
-- stand={
-- {20,{{0,24,10,9,-5,-17},{0,24,10,9,-5,-17}}},
-- {20,{{0,24,10,9,-5,-17},{0,24,10,9,-5,-17}}},
-- }
-- walk=={
-- {20,{{0,24,10,9,-5,-17},{0,24,10,9,-5,-17}}},
-- {20,{{0,24,10,9,-5,-17},{0,24,10,9,-5,-17}}},
-- }
-- }}
-- iterate over each character and animation
-- build lua code with animation data
toaster('exporting metadata')
local mds = '--animation data\n'
for ci, c in pairs(chars) do
mds = mds .. c.name .. ' = {anim={\n'
for ai, a in pairs(c.anim) do
mds = mds .. a.name .. '={'
for fi, f in pairs(a.frames) do
mds = mds .. '{' .. f.length .. ',{'
for li, l in pairs(f.layers) do
if l.loc != nil then
mds = mds .. build_layer_def(l) .. ','
end
end
mds = sub(mds,1,#mds-1)
mds = mds .. '}},\n'
end
mds = sub(mds,1,#mds-2)
mds = mds .. '},\n'
end
mds = sub(mds,1,#mds-2)
mds = mds .. '}}\n'
end
-- export animation data to text file
printh(mds, 'metadata', true)
-- build encoded animation data that can be reimported
local mde = ''
for ci, c in pairs(chars) do
mde = mde .. ':' .. c.name
for ai, a in pairs(c.anim) do
mde = mde .. ';' .. a.name
for fi, f in pairs(a.frames) do
mde = mde .. '.' .. f.length
for li, l in pairs(f.layers) do
if l.loc != nil then
mde = mde .. ',' .. l.loc.x .. ' ' .. l.loc.y .. ' ' .. l.trim.w .. ' ' .. l.trim.h .. ' ' .. l.offset.x .. ' ' .. l.offset.y
end
end
end
end
end
local mde = mde .. '='
if debug then
printh(mde, 'debug', true)
end
-- wipe sprite sheet
memset(0, 0, 0x2000)
cstore(0, 0, 0x2000)
-- write animation data to sprite sheet
for i=1,#mde do
if i > 0x1fff then
error("metadata beyond bounds of sprite sheet storage")
end
poke(i-1, encode(sub(mde,i,i)))
end
-- export sprite sheet
cstore(0, 0, 0x2000)
--export('mtest.png')
export(metadataname)
memset(0, 0, 0x2000)
cstore(0, 0, 0x2000)
layers={}
update_frame()
end
function build_layer_def(l)
local str='{'..l.loc.x..','..l.loc.y
str=str..','..l.trim.w..','..l.trim.h
str=str..','..l.offset.x..','..l.offset.y
str = str ..'}'
return str
end
function encode(char)
local num = 0
for i = 1,#charlist do
if char == charlist[i] then
num = i
break
end
end
if num == 0 then
error("couldn't encode character " .. char)
end
return num
end
function decode(num)
local char = charlist[num]
if char == nil then
error("couldn't decode character " .. num)
end
return char
end
function _import()
local str = ''
if _online then
--we're probably on the bbs so load demo data
str = ":plr;stand.20,0 45 10 9 -5 -17,8 0 9 7 -4 -22,16 24 2 3 -5 -13,6 43 2 2 4 -13,7 20 2 4 -2 -8,12 39 3 4 1 -8,15 38 5 5 -5 -4,17 0 3 5 1 -4,8 43 2 2 6 -13,9 33 2 2 -5 -10;walk.13,8 7 4 5 -3 -14,7 12 5 8 -2 -17,16 49 4 5 -1 -9,8 0 9 7 -4 -22,10 49 6 6 -4 -5,9 33 2 2 -3 -9,11 33 1 2 3 -10.17,18 29 5 4 -4 -13,0 12 7 12 -3 -16,17 13 3 5 3 -4,8 0 9 7 -4 -21,16 54 4 5 -5 -4,9 33 2 2 -5 -9,18 10 2 2 3 -9.13,12 33 3 6 0 -16,6 35 6 8 -3 -17,16 59 4 5 -1 -9,8 0 9 7 -4 -22,10 55 6 6 -4 -5,8 43 2 2 2 -11.17,17 43 3 5 2 -14,0 0 8 12 -4 -16,16 54 4 5 -5 -4,8 0 9 7 -4 -21,17 13 3 5 3 -4,9 20 7 7 0 -15;fire.5,10 61 6 3 -2 -15,9 27 9 6 8 -20,12 13 5 6 3 -19,8 43 2 2 3 -15,7 12 5 8 -3 -17,8 0 9 7 -5 -22,18 5 3 5 -3 -9,18 24 3 5 0 -9,17 0 3 5 1 -4,17 0 3 5 -4 -4.5,20 47 8 3 -1 -15,0 54 10 9 9 -21,10 43 7 6 4 -18,20 53 5 3 -2 -10,7 12 5 8 -2 -17,8 0 9 7 -4 -22,7 20 2 4 -2 -8,12 39 3 4 1 -8,17 0 3 5 1 -4,15 38 5 5 -5 -4.5,20 50 8 3 -1 -15,8 43 2 2 6 -15,10 43 7 6 5 -18,20 53 5 3 -2 -10,7 12 5 8 -2 -17,8 0 9 7 -4 -22,7 20 2 4 -2 -8,12 39 3 4 1 -8,17 0 3 5 1 -4,15 38 5 5 -5 -4;aim.20,20 50 8 3 -1 -15,8 43 2 2 6 -15,12 7 6 6 5 -18,20 53 5 3 -2 -10,7 12 5 8 -2 -17,8 0 9 7 -4 -22,7 20 2 4 -2 -8,12 39 3 4 1 -8,17 0 3 5 1 -4,15 38 5 5 -5 -4;rise.20,0 24 9 11 -3 -9,20 43 4 4 -7 -2.20,15 33 8 5 -3 -4,0 45 10 9 -5 -12,16 24 2 3 -5 -8,9 33 2 2 -5 -5,6 43 2 2 4 -8,8 43 2 2 6 -8,8 0 9 7 -4 -17;jump.20,20 15 5 4 -5 -16,7 12 5 8 -2 -17,8 0 9 7 -4 -22,9 33 2 2 -5 -12,0 35 6 10 -3 -10;rise.20,20 56 2 2 2 -20,16 19 5 5 -1 -18,7 12 5 8 -2 -17,16 54 4 5 -2 -4,8 0 9 7 -4 -22,20 38 2 5 0 -9;fall.20,20 0 3 5 4 -18,20 10 3 5 -6 -18,0 45 10 9 -5 -17,8 0 9 7 -4 -22,7 20 2 4 -2 -8,12 39 3 4 1 -8,20 56 2 2 -6 -20,20 56 2 2 5 -20,15 38 5 5 -5 -4,15 38 5 5 -1 -4"
else
--import any local data
import(metadataname)
reload(0, 0, 0x2000)
if peek(0) != 0 then --we had some data to import, yay!
for i =0,0x1fff do
local num = peek(i)
local inp = decode(num)
if inp == '=' then
break
else
str = str .. inp
end
end
end
end
if #str > 0 then
local imported_layers
-- : start of new character
-- ; start of new animation
-- . start of new frame
-- , start of new layer
-- = end of data
local model = split(str, ':')
for i=1,#model do
model[i] = split(model[i], ';')
local char = new_char(model[i][1])
add(chars, char)
for j=2,#model[i] do
model[i][j] = split(model[i][j], '.')
local anim = new_anim(model[i][j][1])
anim.parent = char
add(char.anim, anim)
for k=2,#model[i][j] do
model[i][j][k] = split(model[i][j][k], ',')
local frame = new_frame(k-1)
frame.length = tonum(model[i][j][k][1])
frame.parent = anim
add(anim.frames, frame)
local xmin = 999
local ymin = 999
local xmax = -999
local ymax = -999
local origx = 12
local origy = 12
local previ = anim.frames[k-2]
if previ then
origx = previ.centre.x
origy = previ.centre.y
end
for l=2,#model[i][j][k] do
local props = split(model[i][j][k][l],' ')
local layer = new_layer()
layer.loc = {}
layer.offset = {}
layer.loc.x = tonum(props[1])
layer.loc.y = tonum(props[2])
layer.w = tonum(props[3])
layer.h = tonum(props[4])
layer.offset.x = tonum(props[5])
layer.offset.y = tonum(props[6])
layer.parent = frame
frame.layers[l-1] = layer
--need to reconstruct frame from sprite sheet
--assume origin at 12,12
--check if offset and w/h of any sprite go outside of bounds
--readjust if so
if origx + layer.w + layer.offset.x - 1 > xmax then
xmax = origx + layer.w + layer.offset.x - 1
end
if origy + layer.h + layer.offset.y - 1 > ymax then
ymax = origy + layer.h + layer.offset.y - 1
end
if origx + layer.offset.x - 1 < xmin then
xmin = origx + layer.offset.x - 1
end
if origy + layer.offset.y - 1 < ymin then
ymin = origy + layer.offset.y - 1
end
end
if xmin < 1 then
origx -= xmin - 1
elseif xmax > 24 then
origx -= xmax - 24
end
if ymin < 1 then
origy -= ymin -1
elseif ymax > 24 then
origy -= ymax - 24
end
frame.centre.x = flr(origx)
frame.centre.y = flr(origy)
end
end
end
--actually import images now
if not _online then
import(spritesheetname)
reload(0, 0, 0x2000)
end
for i,c in pairs(chars) do
for j,a in pairs(c.anim) do
for k,f in pairs(a.frames) do
for l, layer in pairs(f.layers) do
if layer.loc != nil then
for x=0, layer.w - 1 do
for y=0, layer.h - 1 do
layer[flr(f.centre.x+layer.offset.x+x)][flr(f.centre.y+layer.offset.y+y)] = sget(flr(layer.loc.x+x), flr(layer.loc.y+y))
end
end
end
-- this line is a kludge to stop a bug
-- layers were disappearing if imported and re-exported
-- don't know why that's happening but clones of the layers
-- seem to export fine
f.layers[l] = layer:clone()
end
end
end
end
if #chars > 0 then
chari = 1
end
for i,c in pairs(chars) do
if #c.anim > 0 then
c.canim = 1
for i,a in pairs(c.anim) do
if #a.frames > 0 then
a.cframe = 1
end
end
end
end
if #get_char().anim > 0 then
get_char().canim = 1
end
if #get_anim().frames > 0 then
frame_reset()
end
memset(0, 0, 0x2000)
--cstore(0, 0, 0x2000)
end
end
-- print contents of `tbl`, with indentation.
-- `indent` sets the initial level of indentation.
function tprint (tbl,indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
formatting = ""
for i=1,indent do
formatting = formatting .. " "
end
formatting = formatting .. k .. ":"
if type(v) == "table" then
print(formatting)
tprint(v, indent+1)
else
print(formatting .. tostr(v))
end
end
end
function split(str, separator)
local parts = {}
local buffer = ''
for i = 1,#str do
--print(type(str))
c = sub(str,i,i)
if c == separator then
if buffer != '' then
add(parts, buffer)
buffer = ''
end
else
buffer = buffer .. c
end
end
if buffer != '' then
add(parts,buffer)
end
--if #parts == 1 then
-- return parts[1]
--end
return parts
end
function error(message)
cls()
color(7)
print(message)
assert(false)
end
function can_fit_on_sheet(layer, x, y)
if x+layer.trim.w > sheet_width then
return false
elseif y+layer.trim.h > sheet_height then
return false
end
local boxa = {x=x,y=y,w=layer.trim.w,h=layer.trim.h}
for k, l in pairs(layers) do
if l.drawn then
local boxb = {x=l.loc.x,y=l.loc.y,w=l.trim.w,h=l.trim.h}
if coll(boxa, boxb) then
return false
end
end
end
return true
end
function draw_to_sheet(layer, x, y)
for i=1,layer.trim.w do
for j=1,layer.trim.h do
local col = layer[layer.trim.xn+i-1][layer.trim.yn+j-1]
local x1,y1 = x+i-1, y+j-1
sset(x1, y1, col)
end
end
layer.loc = {}
layer.drawn = true
layer.loc.x = x
layer.loc.y = y
end
--quick and dirty bubble sort
function sort(list)
local changed = true
while changed do
changed = false
for i=2,#list do
if list[i-1]:lt(list[i]) then
changed = true
local holder = list[i-1]
list[i-1] = list[i]
list[i] = holder
end
end
end
return list
end
function _update60()
clock+=1
read_input()
if toast.timer > 0 then
toast.timer -= 1
end
if creation==nil then
local l = get_layer()
if l then
if btnp(0) then
for i=2,24 do
for j=1,24 do
l[i-1][j]=l[i][j]
end
end
for j=1,24 do
l[24][j]=0
end
update_frame()
elseif btnp(1) then
for i=23,1,-1 do
for j=1,24 do
l[i+1][j]=l[i][j]
end
end
for j=1,24 do
l[1][j]=0
end
update_frame()
elseif btnp(2) then
for i = 1,24 do
for j = 2,24 do
l[i][j-1]=l[i][j]
end
end
for i = 1,24 do
l[i][24] = 0
end
update_frame()
elseif btnp(3) then
for i = 1,24 do
for j = 23,1,-1 do
l[i][j+1]=l[i][j]
end
end
for i = 1,24 do
l[i][1] = 0
end
update_frame()
end
end
else
if backspace then
if #input>0 then
input=sub(input,0,#input-1)
end
elseif enter then
if #input>0 then
creation.name = input
new_thing(creation)
creation=nil
input = ''
update_frame()
end
elseif cancel then
input = ''
creation= nil
elseif #input<5 then
for i=1,#keybuffer do
input=input..keybuffer[i]
end
end
end
local anim = get_anim()
local frame = get_frame()
if playing and anim != nil and frame != nil then
timer += 1
if timer > frame.length then
anim.cframe += 1
timer = 0
if anim.cframe > #anim.frames then
anim.cframe = 1
end
end
end
end
function read_input()
poke(0x5f30,1) --unsuppress pause if it was previously set
local m = mouse
m.x=stat(32)
m.y=stat(33)
local mb=stat(34)
m.l=band(mb,1)>0--left
m.r=band(mb,2)>0--right
m.m=band(mb,4)>0--middle
if m.l then
if m.h then
m.c = false
else
m.c = true
m.h = true
end
else
m.c = false
m.h = false
end
if m.r then
if m.hr then
m.cr = false
else
m.cr = true
m.hr = true
end
else
m.cr = false
m.hr = false
end
for i,e in pairs(elems) do
if creation == nil and m.x >= e.x and m.x < e.x+e.w and m.y >= e.y and m.y < e.y+e.h then
if m.c then
e:onclick()
elseif m.l then
e:onhold()
elseif m.cr then
e:onrclick()
end
end
end
keybuffer = {}
enter = false
backspace = false
cancel = false
local keyin = stat(31)
for i=1,#keyin do
local key = sub(keyin, i, i)
if key == 'p' or key == '\r' then
poke(0x5f30,1) --suppress pause
end
if creation == nil then
local f = get_frame()
if f != nil then
if key == 'w' then
f.centre.y -= 1
elseif key == 'a' then
f.centre.x -= 1
elseif key == 's' then
f.centre.y += 1
elseif key == 'd' then
f.centre.x += 1
elseif key == 'c' then
cplayer = get_layer():clone()
elseif key == 'p' or key == 'v' then
f.layers[layeri] = cplayer:clone()
update_frame()
elseif key == '-' or key == '_' then
char_dn()
elseif key == '=' or key == '+' then
char_up()
elseif key == '[' or key == '{' then
anim_dn()
elseif key == ']' or key == '}' then
anim_up()
elseif key == '\'' or key == '"' then
frame_dn()
elseif key == '\\' or key == '|' then
frame_up()
end
if f.centre.x > 24 then
f.centre.x = 24
elseif f.centre.x < 1 then
f.centre.x = 1
end
if f.centre.y > 24 then
f.centre.y = 24
elseif f.centre.y < 1 then
f.centre.y = 1
end
end
else
if key == '\b' then
backspace = true
elseif key == '\r' then
enter = true
elseif key == '/' or key == '\\' then
cancel = true
else
for i=1,26 do
if key == alphabet[i] then
add(keybuffer, key)
break
end
end
end
end
end
end
function new_char(name)
local char = {
name=name,
anim={},
canim=nil
}
char.clone = function(c)
local clone = new_char()
clone.name = c.name
clone.anim = c.anim:clone()
return clone
end
return char
end
function new_anim(name)
local anim= {
name=name,
frames={},
cframe=nil
}
anim.clone = function(a)
local clone = new_anim()
clone.name = a.name
for i=1,#a.frames do
clone.frames[i] = a.frames[i]:clone()
end
return clone
end
return anim
end
function new_frame(name)
local frame={
name=name,
length=20,
layers = {},
centre = {x=12,y=12},
tcol=0
}
for i=1,numf do
local layer = new_layer()
add(frame.layers, layer)
layer.parent = frame
end
frame.clone = function(f)
local clone = new_frame()
clone.name = f.name
clone.length = f.length
clone.centre.x = f.centre.x
clone.centre.y = f.centre.y
clone.tcol = f.tcol
for i=1,numf do
clone.layers[i] = f.layers[i]:clone()
end
return clone
end
return frame
end
function new_layer()
local lay = {w=24,h=24}
for i=1,24 do
lay[i] = {}
for j=1,24 do
lay[i][j] = 0
end
end
lay.offset = {}
lay.clone = function(l)
local clone = new_layer()
for i=1,24 do
for j=1,24 do
clone[i][j] = l[i][j]
end
end
clone.parent = l.parent
clone.offset.x = l.offset.x
clone.offset.y = l.offset.y
setmetatable(clone, getmetatable(l))
return clone
end
lay.trim = function(l)
local xmin = 999
local ymin = 999
local xmax = 0
local ymax = 0
for i=1,l.w do
for j=1,l.h do
if l[i][j] != 0 then
if i < xmin then xmin = i end
if j < ymin then ymin = j end
if i > xmax then xmax = i end
if j > ymax then ymax = j end
end
end
end
if xmin <= xmax then
l.offset = {}
l.trim = {}
l.offset.x = xmin - l.parent.centre.x
l.offset.y = ymin - l.parent.centre.y
l.trim.w = xmax - xmin + 1
l.trim.h = ymax - ymin + 1
l.trim.xn = xmin
l.trim.yn = ymin
elseif not l:blank() then
local c = l.parent.parent.parent
local a = l.parent.parent
local f = l.parent
error("trim failure "..c.name.." "..a.name.." "..f.name)
end
return l
end
lay.blank = function(l)
for i=1,l.w do
for j=1,l.h do
if l[i][j] != 0 then
return false
end
end
end
return true
end
-- local metatable = {}
lay.eq = function (this, that)
if this.trim.w != that.trim.w or this.trim.h != that.trim.h then
return false
end
for i=1,this.trim.w do
for j=1,this.trim.h do
if this[this.trim.xn+i-1][this.trim.yn+j-1] != that[that.trim.xn+i-1][that.trim.yn+j-1] then
return false
end
end
end
return true
end
lay.lt = function(this, that)
if this.trim.h < that.trim.h then
return true
elseif this.trim.h == that.trim.h and this.trim.w < that.trim.w then
return true
end
return false
end
-- setmetatable(lay,metatable)
return lay
end
function new_thing(create_obj)
local mode = create_obj.mode
if create_obj.type=='character' then
local char = nil
if mode == 'copy' then
char = get_char(create_obj.name):clone()
else
char = new_char(create_obj.name)
end
if char != nil then
add(chars,char)
chari=#chars
end
elseif create_obj.type=='animation'then
local anim = nil
if mode == 'copy' then
anim = get_anim(create_obj.name):clone()
else
anim = new_anim(create_obj.name)
end
if anim != nil then
local char = get_char()
add(char.anim,anim)
anim.parent = char
char.canim = #char.anim
end
elseif create_obj.type=='frame'then
local frame = nil
if mode == 'copy' then
frame = get_frame(#get_anim().frames+1):clone()
else
frame = new_frame(#get_anim().frames+1)
end
if frame != nil then
local anim = get_anim()
add(anim.frames,frame)
frame.parent = anim
anim.cframe = #anim.frames
layeri = 1
end
end
end
function delete_thing(type)
if type == 'character' then
local c = get_char()
del(chars, c)
if chari > #chars then
chari = #chars
end
elseif type == 'animation' then
local c = get_char()
if c then
local a = get_anim()
del(c.anim, a)
if c.canim > #c.anim then
c.canim = #c.anim
end
end
elseif type == 'frame' then
local a = get_anim()
if a then
local f = get_frame()
del(a.frames, f)
if a.cframe > #a.frames then
a.cframe = #a.frames
end
end
end
end
function _draw()
rectfill(0,0,128,128,5)
for i,e in pairs(elems) do
e:draw()
end
local m = mouse
if clock%2!=0 or m.l or m.x<animw.x or m.x>animw.x+animw.w or m.y < animw.y or m.y > animw.y+animw.h then
line(m.x-2,m.y-1,m.x+2,m.y-1,0)
line(m.x-2,m.y+1,m.x+2,m.y+1,0)
line(m.x-1,m.y-2,m.x-1,m.y+2,0)
line(m.x+1,m.y-2,m.x+1,m.y+2,0)
line(m.x-1,m.y,m.x-2,m.y,7)
line(m.x+1,m.y,m.x+2,m.y,7)
line(m.x,m.y-1,m.x,m.y-2,7)
line(m.x,m.y+1,m.x,m.y+2,7)
end
if creation then
rectfill(1,32,126,50,5)
rect(1,32,126,50,6)
print('enter name for '..creation.type..':',3,34,6)
print(input,50,43,6)
--rect(6,32,120,64,6)
end
if toast.timer > 0 then
rectfill(0,120,127,127,8)
print(toast.message,1,121,7)
end
if debug then
print('\x98 '..(stat(0)/20.48)..'%', 28, 106, 0)
print('\x8c '..(stat(1)*100)..'%', 28, 112, 0)
end
end
function new_element(x,y,w,h)
local e = {x,y,w,h}
e.x=x
e.y=y
e.w=w
e.h=h
e.bcol=5--background colour
e.hcol=6--highlight colour
e.i=1 --index
e.onclick = function() end
e.onrclick = function() end
e.onrelease = function() end
e.onhold = function() end
e.label = ''
e.draw= function(e)
rectfill(e.x,e.y,e.x+e.w,e.y+e.h,e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
print(e.label, e.x+2, e.y+2, e.hcol)
end
add(elems,e)
return e
end
function dofill(layer,x,y,ncol,ocol)
if x < 1 or x > 24 or y < 1 or y > 24 then
return nil
end
if ocol == nil then
ocol = layer[x][y]
if ocol == ncol then
return nil
end
end
if layer[x][y] == ocol then
layer[x][y] = ncol
--store current working layers in spritesheet
local xx = flr((layeri-1)/numf*2)
local yy = flr((layeri-1)%flr(numf/2))
dofill(layer,x+1,y,ncol,ocol)
dofill(layer,x-1,y,ncol,ocol)
dofill(layer,x,y+1,ncol,ocol)
dofill(layer,x,y-1,ncol,ocol)
update_current_layer()
update_frame()
end
end
function char_up()
chari+=1
if chari>#chars then chari=1 end
update_frame()
end
function char_dn()
chari-=1
if chari<1 then chari=#chars end
update_frame()
end
function anim_up()
local c = get_char()
if c then
c.canim+=1
if c.canim>#c.anim then
c.canim=1
end
update_frame()
end
end
function anim_dn()
local c = get_char()
if c then
c.canim-=1
if c.canim<1 then
c.canim=#c.anim
end
update_frame()
end
end
function frame_up()
local a = get_anim()
if a then
a.cframe+=1
if a.cframe>#a.frames then
a.cframe=1
end
update_frame()
end
end
function frame_dn()
local a = get_anim()
if a then
a.cframe-=1
if a.cframe<1 then
a.cframe=#a.frames
end
update_frame()
end
end
function frame_reset()
local a = get_anim()
if not a or not a.frames or #a.frames < 1 then
a.cframe = 0
return nil
end
a.cframe=1
update_frame()
end
function change_frame(ni)
local a = get_anim()
if a == nil or ni == a.cframe then
return nil
end
-- memset(0, 0, 0x2000)
a.cframe = ni
-- local f = get_frame()
-- if not a or not a.frames or #a.frames == 0 or not f then
-- a.cframe = 0
-- return nil
-- end
-- for k=1,numf do
-- local lay = f.layers[k]
-- local xx = flr((k-1)/numf*2)
-- local yy = flr((k-1)%flr(numf/2))
-- for i=0,23 do
-- for j=0,23 do
-- local c = lay[i+1][j+1]
-- if c > 0 then
-- sset(layw.x+i+xx*25,layw.y+j+yy*25,c)
-- end
-- end
-- end
-- end
end
function draw_frame(w)
palt()
if playing then
local f = get_frame()
for k=numf,1,-1 do
local l = f.layers[k]
for i=0,23 do
for j=0,23 do
local c = l[i+1][j+1]
if c > 0 then
rect( w.x+i*2,
w.y+j*2,
w.x+i*2+1,
w.y+j*2+1,
c)
end
end
end
end
else
if ghost and clock%2==0 then --and clock%2==0 then
local anim = get_anim()
if ghostw or (anim and anim.cframe > 1) then
sspr(24,0,24,24,w.x,w.y,48,48)
end
end
sspr(0,0,24,24,w.x,w.y,48,48)
end
end
function update_current_layer()
-- local l = get_layer()
-- if l then
-- l = l:trim()
-- end
end
function update_frame()
memset(0, 0, 0x1000)
local f = get_frame()
if f then
local layers = f.layers
for k=#layers, 1, -1 do
for i=1,24 do
for j=1,24 do
local c = layers[k][i][j]
if c > 0 then
sset(i-1,j-1,c)
end
end
end
end
local anim = get_anim()
local onion_frame = anim.cframe - 1
if onion_frame < 1 then
onion_frame = #anim.frames
end
if onion_frame > 0 and onion_frame != anim.cframe then
local olayers = anim.frames[onion_frame].layers
for k=#olayers, 1, -1 do
for i=1,24 do
for j=1,24 do
local c = olayers[k][i][j]
if c > 0 then
sset(i+23,j-1,c)
end
end
end
end
end
end
end
function generate_elements()
elems = {}
--animation window
animw = new_element(1,1,48,48)
animw.bcol = 0
animw.hcol = 0
animw.draw = function(w)
rectfill(w.x,w.y,w.x+w.w,w.y+w.h,0)
local f = get_frame()
local efrm = clock % 2 == 0
-- if ghost and efrm then
-- draw_frame(w)
-- end
draw_frame(animw)
if showcentre and f != nil and clock % 2 != 0 then
local x = w.x+(f.centre.x-1)*2
local y = w.y+(f.centre.y-1)*2
rect(x, y, x+1, y+1, 1)
pset( x+flr((clock/16)) % 2,
y+flr(((clock+8)/16)) % 2,
7)
end
end
animw.onclick = function(w)
local x=flr((mouse.x-w.x)/2)+1
local y=flr((mouse.y-w.y)/2)+1
local l = get_layer()
if l != nil then
if fill then
dofill(l,x,y,palet.i)
else
l[x][y] = palet.i
--store current working layers in spritesheet
-- local xx = flr((layeri-1)/numf*2)
-- local yy = flr((layeri-1)%flr(numf/2))
-- sset(x+xx*25+76,y+yy*25,palet.i)
update_current_layer()
update_frame()
end
end
end
animw.onhold = animw.onclick
--palette
palet = new_element(51,1,12,48)
palet.a=palet.w*palet.h/16
palet.s=sqrt(palet.a)
palet.i=0
palet.draw = function(p)
local w = p.w/p.s
local h = p.h/p.s
local s = p.s
for i=0,w-1 do
for j=0,h-1 do
rectfill(p.x+i*s,p.y+j*s,p.x+i*s+s,p.y+j*s+s,i+j*w)
end
end
local i=(p.i)%w
local j=flr(p.i/w)
rect(p.x+i*s,
p.y+j*s,
p.x+i*s+s,
p.y+j*s+s,7)
rect(p.x+i*s-1,
p.y+j*s-1,
p.x+i*s+s+1,
p.y+j*s+s+1,0)
end
palet.onclick = function(p)
local w = p.w/p.s
local h = p.h/p.s
local s = p.s
local x=mouse.x-p.x
local y=mouse.y-p.y
if x>=0 and x<p.w and y>=0 and y<p.h then
local i = flr(x/p.s)
local j = flr(y/p.s)
p.i = i + j*w
end
end
--layers
layw=new_element(77,1,49,125)
layw.draw = function(l)
rectfill(l.x,l.y,l.x+l.w,l.y+l.h,0)
for i=0,numf do
fillp(0b1010010110100101)
line(
l.x,
l.y+i*25,
l.x+l.w,
l.y+i*25,5)
line(
l.x+25,
l.y,
l.x+25,
l.y+l.h,5)
fillp()
end
local f = get_frame()
if f!= nil and not playing then
for k=1,numf do
local lay = f.layers[k]
local xx = flr((k-1)/numf*2)
local yy = flr((k-1)%flr(numf/2))
palt(0,false)
--sspr(77,1,49,125,77,1)
for i=0,23 do
for j=0,23 do
local c = lay[i+1][j+1]
if c > 0 then
pset(l.x+i+xx*25,l.y+j+yy*25,c)
end
end
end
palt()
end
end
if layeri>0 then
rect( l.x + flr((layeri-1)/flr(numf/2))*25,
l.y+((layeri-1)%flr(numf/2))*25,
l.x + flr((layeri-1)/flr(numf/2))*25+25,
l.y+((layeri-1)%flr(numf/2))*25+25,
7)
end
end
layw.onclick = function(l)
local x = mouse.x-l.x
local y = mouse.y-l.y
layeri = flr(x/25)*5+flr(y/25)+1
end
function get_char()
return chars[chari]
end
function get_anim()
local char = get_char()
if char then
return chars[chari].anim[char.canim]
end
return nil
end
function get_frame()
local anim = get_anim()
if anim then
return anim.frames[anim.cframe]
end
return nil
end
function get_layer()
local frame = get_frame()
if frame then
return frame.layers[layeri]
end
return nil
end
local controls={
'character',
'animation',
'frame'}
timerelm = new_element(53,51,14,8)
timerelm.draw = function(e)
rectfill(e.x,e.y,e.x+e.w,e.y+e.h,e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
print(timer,e.x+2,e.y+2,e.hcol)
end
toolb = new_element(61,67,14,8)
toolb.bcol = 1
toolb.draw = function(e)
rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
print('p/f',e.x+2,e.y+2,e.bcol)
if fill then
print('f',e.x+10,e.y+2,e.hcol)
else
print('p',e.x+2,e.y+2,e.hcol)
end
end
toolb.onclick = function(e)
fill = not fill
end
ghostb = new_element(53,77,14,8)
ghostb.bcol = 1
ghostb.onclick = function()
ghost = not ghost
end
ghostb.draw = function(e)
color(ghost and e.hcol or e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h)
print('oni',e.x+2,e.y+2)
end
ghostwb = new_element(69,77,6,8)
ghostwb.bcol = 1
ghostwb.onclick = function()
ghostw = not ghostw
end
ghostwb.draw = function(e)
color(ghostw and e.hcol or e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h)
print('w',e.x+2,e.y+2)
end
centreb = new_element(53,87,18,8)
centreb.bcol = 1
centreb.onclick = function()
showcentre = not showcentre
end
centreb.draw = function(e)
color(showcentre and e.hcol or e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h)
print('orig',e.x+2,e.y+2)
end
local exportb = new_element(49,118,26,8)
exportb.label = 'export'
exportb.hcol = 15
exportb.onclick = function()
_export()
end
local coords = new_element(58,61,0,0)
coords.draw = function (e)
local x = flr((mouse.x - animw.x)/2)
local y = flr((mouse.y - animw.y)/2)
if x < 0 then x,y = 0,0 end
if x > 23 then x,y = 0,0 end
if y < 0 then x,y = 0,0 end
if y > 23 then x,y = 0,0 end
if x < 10 then x = '0' .. x end
if y < 10 then y = '0' .. y end
print(x, e.x, e.y, 1)
print(',', e.x + 8, e.y, 1)
print(y, e.x + 11, e.y, 1)
end
framelendec = new_element(0,112,7,7)
framelendec.draw=function(e)
print('⬅️',e.x,e.y+2,e.hcol)
end
framelendec.onclick = function()
local frame = get_frame()
if frame != nil then
frame.length -= 1
if frame.length < 1 then
frame.length = 1
end
end
end
frameleninc = new_element(18,112,7,7)
frameleninc.draw=function(e)
print('➡️',e.x,e.y+2,e.hcol)
end
frameleninc.onclick = function()
local frame = get_frame()
if frame != nil then
frame.length += 1
if frame.length > 999 then
frame.length = 999
end
end
end
framelen = new_element(5,112,14,8)
framelen.onclick = function()
local frame = get_frame()
if frame != nil then
frame.length += 1
if frame.length > 999 then
frame.length = 999
end
end
end
framelen.onrclick = function()
local frame = get_frame()
if frame != nil then
frame.length -= 1
if frame.length < 1 then
frame.length = 1
end
end
end
framelen.draw = function(e)
rectfill(e.x,e.y,e.x+e.w,e.y+e.h,e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
local frame = get_frame()
if frame != nil then
print(frame.length,e.x+2,e.y+2,e.hcol)
end
print('length',e.x-4,e.y-6)
end
playb = new_element(68,52,8,6)
playb.bcol = 1
playb.draw = function(e)
--rect(e.x,e.y,e.x+e.w,e.y+e.h,playing and e.hcol or e.bcol)
print('➡️',e.x+1,e.y+1,playing and e.hcol or e.bcol)
end
playb.onclick = function()
playing = not playing
timer = 0
if not playing then
update_frame()
end
end
for i,v in pairs(controls) do
local top = 50
local hgt = 18
local title= new_element(1,top+hgt*i-hgt,7,5)
title.draw=function(e)
print(v,e.x,e.y+2,e.hcol)
end
local prev = new_element(0,top+hgt*i+8-hgt,7,9)
prev.draw=function(e)
print('⬅️',e.x,e.y+2,e.hcol)
end
prev.onclick=function()
if v == 'character' then
char_dn()
elseif v == 'animation' then
anim_dn()
elseif v == 'frame' then
frame_dn()
end
end
local next=new_element(26,top+hgt*i+8-hgt,7,9)
next.draw=function(e)
print('➡️',e.x,e.y+2,e.hcol)
end
next.onclick=function()
if v == 'character' then
char_up()
elseif v == 'animation' then
anim_up()
elseif v == 'frame' then
frame_up()
end
end
local box=new_element(5,top+hgt*i+8-hgt,22,8)
box.list = {}
box.draw = function(e)
rectfill(e.x,e.y,e.x+e.w,e.y+e.h,e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
if v == 'character' then
local char = get_char()
if char then
print(get_char().name,e.x+2,e.y+2,e.hcol)
end
elseif v == 'animation' then
local anim = get_anim()
if anim then
print(get_anim().name,e.x+2,e.y+2,e.hcol)
end
elseif v == 'frame' then
local frame = get_frame()
if frame then
print(get_frame().name,e.x+2,e.y+2,e.hcol)
end
end
end
local dele=new_element(40,top+hgt*i+8-hgt,6,8)
dele.draw = function(e)
rectfill(e.x,e.y,e.x+e.w,e.y+e.h,e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
print('d',e.x+2,e.y+2,e.hcol)
end
dele.onclick=function()
delete_thing(v)
end
local new=new_element(34,top+hgt*i+8-hgt,6,8)
new.draw = function(e)
rectfill(e.x,e.y,e.x+e.w,e.y+e.h,e.bcol)
rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
print('n',e.x+2,e.y+2,e.hcol)
end
new.onclick=function()
if v == 'frame' then
new_thing({mode='new',type=v})
update_frame()
else
creation={mode='new',type=v}
end
end
-- local cpy=new_element(73,top+hgt*i+8-hgt,14,8)
-- cpy.draw = function(e)
-- rectfill(e.x,e.y,e.x+e.w,e.y+e.h,e.bcol)
-- rect(e.x,e.y,e.x+e.w,e.y+e.h,e.hcol)
-- print('cpy',e.x+2,e.y+2,e.hcol)
-- end
-- cpy.onclick=function()
-- if v == 'frame' then
-- new_thing({mode='copy',type=v})
-- else
-- creation={mode='copy',type=v}
-- end
-- end
end
end
--print text with colour and outline colour
function print2(_str, _x, _y, _col, _ecol)
print(_str,_x, _y+1,_ecol)
print(_str,_x, _y-1,_ecol)
print(_str,_x+1,_y, _ecol)
print(_str,_x-1,_y, _ecol)
print(_str,_x, _y, _col)
end
--collision between two boxes
function coll(a,b)
return a.x < b.x+b.w and
a.x+a.w > b.x and
a.y < b.y+b.h and
a.y+a.h > b.y
--return abs(a.x - b.x) * 2 <
-- a.w + b.w and
-- abs(a.y - b.y) * 2 <
-- a.h + b.h
end
__gfx__
000111000004944000110b3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001113100094499401c00b3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001113c00949f4f041100b3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001133109499fff001c0b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00113110949f9ff00111330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
031131100949ff000003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
131113100000ff000003b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
11011100033005005503b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0003b33003b006666603b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
003b013003b00465553b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
003b00133b01494660113b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
03b000133b03494000153b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001100001100440000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0011130011310055011003b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01cc11011cc1506601c0033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0131cd0111dc6665511000bbb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
013d7c0131d7465001c00b3330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0131dc01311d00600111b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01311101331100060000b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0011100011100000000b300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0133b000b0300000000b300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01313b03b03b000000b3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
013003b3b33b000033b3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
130003b3b303b0000bb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000994403103b00b33b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
004494994130031db333b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0149499490100011b303b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01d94911400c00000003b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01ddd1d10c00ccc00003b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
11111d1b000caca7c00033b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
333b113b00c7aaccac03bb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
3033b03b000c77cc003b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1113b03b0c000cc0003b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
111bb03b0111300033b3bbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000001111d13b011333311000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
003b100011103b01c3300c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
003bb10111113b01d001c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0003b10111cc03b11101110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0003b101131d030001113b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
003b0001131d33b011c03b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
031001011d3103b11c003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01c0c010113103b011003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
11101015111003b001103b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1c0c00bb1d0500550b00000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0110100b110666600b00010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000110010004655503b0101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0011133110494600503b101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
01cdd11dc149406000033bb03b1d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1ddccddcd144000000003333b3110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
011d7cc71000100003b0003b31100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0001dcc100011111003b0bbb33b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00031cc10011c0c0003b3333b3300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0001b110001c011033bb000033110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0003333b00101c00bb00300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0000000000111001110333b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
c000000c0000100001c0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00cca0000c0111111110d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000cc0001101c01c00110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ca0000ca001111101110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0ca0000000101c003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000cc000c00011103b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0c0000c0003b03b03b31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00c0000000333b303b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000003b3113b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__label__
55555555555555555555555555555555555555555555555555000000000555555555555555555555555555555555555555555555555555555555555555555555
50000000000449944440000000000000000000000000000000077777770111115555555555555050505050505050505050505050505494405050505050505055
50000000000449944440000000000000000000000000000000070000070111115555555555555000000000000000000000000000009449940000000000000005
500000000994444999944000000000000000000000000000000700000701111155555555555550000000000000000000000000500949f4f04000000000000005
500000000994444999944000000000000000000000000000000700000701111155555555555550000000000000000000000000009499fff00000000000000005
5000000994499ff44ff0044000000000000cc0000000000000070000070111115555555555555000000000000000000000000050949f9ff00000000000000005
5000000994499ff44ff0044000000000000cc00000000000000700000701111155555555555550000000000000000000000000000949ff000000000000000005
5000099449999ffffff000000555500cc0000cccccc00000000777777703333355555555555550000000000000000000000000500000ff000000000000000005
5000099449999ffffff000000555500cc0000cccccc0000000000000000333335555555555555000003b03b00000000000000000000000000000000000000005
50000994499ff99ffff0055006666000000ccaaccaa77cc00052222223333333555555555555500000333b300000000000000050000000000000000000000005
50000994499ff99ffff0055006666000000ccaaccaa77cc0005222222333333355555555555550000003b3110000000000000000000000000000000000000005
500000099441111ff0000666666555500cc77aaaaccccaacc0522222233333335555555555555000000000000000000000000050000000000000000000000005
500000099441111ff0000666666555500cc77aaaaccccaacc0522222233333335555555555555000000000000000000000000000000000000000000000000005
50000000000111133110044665500000000cc7777cccc00000544444455555555555555555555000000000000000000000000050000000000000000000000005
50000000000111133110044665500000000cc7777cccc00000544444455555555555555507055000000000000000000000000000000000000000000000000005
5000000001133bbcc33bb11dd660000cc000000cccc0000000544444455555555555555007005000000000000000000000000050000000000000000000000005
5000000001133bbcc33bb11dd660000cc000000cccc0000000544444455555555555555775775000000000000000000000000000000000000000000000000005
50000000011333333bb3311110066000000000000000000000544444455555555555555007005000000000000000000000000050000000000000000000000005
50000000011333333bb3311110066000000000000000000000544444455555555555555507055000000000000000000000000000000000000000000000000005
500000000113333bb331111000000000000000000000000000566666677777775555555555555000000000000000000000000050000000000000000000000005
500000000113333bb331111000000000000000000000000000566666677777775555555555555000000000000000000000000000000000000000000000000005
50000000011331111dd0000000000000000000000000000000566666677777775555555555555000000000000000000000000050000000000000000000000005
50000000011331111dd0000000000000000000000000000000566666677777775555555555555000000000000000000000000000000000000000000000000005
50000000011333311110000000000000000000000000000000566666677777775555555555555000000000000000000000000050000000000000000000000005
50000000011333311110000000000000000000000000000000566666677777775555555555555000000000000000000000000000000000000000000000000005
50000000000111111000000000000000000000000000000000588888899999995555555555555000000000000000000000000050000000000000000000000005
50000000000111111000000000000000000000000000000000588888899999995555555555555505050505050505050505050505050505050505050505050505
50000000000333333bb0000000000000000000000000000000588888899999995555555555555000000000000000000000000050000000000000000000000005
50000000000333333bb000000000000000000000000000000058888889999999555555555555500000000000000000c000000000000000000000000000000005
5000000000033bb3333bb00000000000000000000000000000588888899999995555555555555000000000000000c00ccc000050000000000000000000000005
5000000000033bb3333bb0000000000000000000000000000058888889999999555555555555500000000000000000caca7c0000000000000000000000000005
5000000000033bb0033bb000000000000000000000000000005aaaaaabbbbbbb55555555555550000000000000000c7aaccac050000000000000000000000005
5000000000033bb0033bb000000000000000000000000000005aaaaaabbbbbbb555555555555500000000000000000c77cc00000000000000000000000000005
5000000000033bb0033bb000000000000000000000000000005aaaaaabbbbbbb5555555555555000000000000000c000cc000050000000000000000000000005
5000000000033bb0033bb000000000000000000000000000005aaaaaabbbbbbb5555555555555000000000000000000000000000000000000000000000000005
50000000033bb000033bb000000000000000000000000000005aaaaaabbbbbbb5555555555555000000000000000000000000050000000000000000000000005
50000000033bb000033bb000000000000000000000000000005aaaaaabbbbbbb5555555555555000000000000000000000000000000000000000000000000005
500000000111100000011110000000000000000000000000005ccccccddddddd5555555555555000000000000000000000000050000000000000000000000005
500000000111100000011110000000000000000000000000005ccccccddddddd5555555555555000000000000000000000000000000000000000000000000005
500000011cc00000011cc000000000000000000000000000005ccccccddddddd5555555555555000000000000000000000000050000330000000000000000005
500000011cc00000011cc000000000000000000000000000005ccccccddddddd55555555555550000000000000000000000000000003b0000000000000000005
500000011110000001111000000000000000000000000000005ccccccddddddd55555555555550000000000000000000000000500003b0000000000000000005
500000011110000001111000000000000000000000000000005ccccccddddddd55555555555550000000000000000000000000000003b0000000000000000005
500000011cc00000011cc000000000000000000000000000005eeeeeefffffff5555555555555000000000000000000000000050003b00000000000000000005
500000011cc00000011cc000000000000000000000000000005eeeeeefffffff5555555555555000000000000000000000000000000000000000000000000005
500000011111100001111110000000000000000000000000005eeeeeefffffff5555555555555000000000000000000000000050000000000000000000000005
500000011111100001111110000000000000000000000000005eeeeeefffffff5555555555555000000000000000000000000000000000000000000000000005
500000000000000000000000000000000000000000000000005eeeeeefffffff5555555555555000000000000000000000000050000000000000000000000005
500000000000000000000000000000000000000000000000005eeeeeefffffff5555555555555000000000000000000000000000000000000000000000000005
500000000000000000000000000000000000000000000000005eeeeeefffffff5555555555555000000000000000000000000050000000000000000000000005
55555555555555555555555555555555555555555555555555555555555555555555555555555000000000000000000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555666666666666666555555555050505050505050505050505050505050505050505050505055
55665656566656665666556656665666566655555555555555555655555555555556555555555000000000000000000000000000000000000000000000000005
56555656565656565656565555655655565655555555555555555656665555555556551111155000000000000000000000000050000000000000000000000005
56555666566656655666565555655665566555555555555555555656565555555556511551115000000000000550000000000000000000000000000000000005
56555656565656565656565555655655565655555555555555555656565555555556511555115000000000050660000000000050000000000000000000000005
55665656565656565656556655655666565655555555555555555656565555555556511551115000000000066655000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555656665555555556551111155000000000046500000000000050000000000000000000000005
55555666666666666666666666665555556666666666666555555655555555555556555555555000000000000600000000000000000000000000000000000005
55555655555555555555555555565555556555556555556555555666666666666666555555555000000000000060000000000050000000000000000000000005
56666656665655566655555555566666556566556566556555555555555555555555555555555000000000000000000000000000000000000000000000000005
66655656565655565655555555565566656565656565656555555555551115111555511151115000000000000000000000000050000000000000000000000005
66555656665655566555555555565556656565656565656555555555551515151555515151515000000000000000000000000000000000000000000000000005
66655656555655565655555555565566656565656565656555555555551515151555515151515000000000000000000000000050000000000000000000000005
56666656555666565655555555566666556565656566656555555555551515151551515151515000000000000000000000000000000003b00000000000000005
555556555555555555555555555655555565555565555565555555555511151115155111511150000000000000000000000000500000033b0000000000000005
555556666666666666666666666655555566666666666665555555555555555555555555555550000000000000000000000000000000003b0000000000000005
555555555555555555555555555555555555555555555555555555555555566666666666666650000000000000000000000000500000003b0000000000000005
555555555555555555555555555555555555555555555555555555555555565555555555555650000000000000000000000000000000003b0000000000000005
55555555555555555555555555555555555555555555555555555555555556566655515111565000000000000000000000000050000000000000000000000005
56665665566656665666566656665566566555555555555555555555555556565655155155565000000000000000000000000000000000000000000000000005
56565656556556665656556555655656565655555555555555555555555556566655155115565000000000000000000000000050000000000000000000000005
56665656556556565666556555655656565655555555555555555555555556565555155155565000000000000000000000000000000000000000000000000005
56565656556556565656556555655656565655555555555555555555555556565551555155565000000000000000000000000050000000000000000000000005
56565656566656565656556556665665565655555555555555555555555556555555555555565000000000000000000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555555555556666666666666665000000000000000000000000050000000000000000000000005
55555666666666666666666666665555556666666666666555555555555555555555555555555505050505050505050505050505050505050505050505050505
55555655555555555555555555565555556555556555556555555111111111111111511111115000000000000000000000000050000000000000000000000005
56666656665666566656665555566666556566556566556555555155555555555551515555515000000000000000000000000000000000000000000000000005
66655656555565565656555555565566656565656565656555555155115115511151515151515000000000000000000000000050000000000000000000000005
66555656655565566556655555565556656565656565656555555151515151551551515151515000000000000000000000000000000000000000000000000005
66655656555565565656555555565566656565656565656555555151515151551551515151515000000000000000000000000050000000000000000000000005
56666656555666565656665555566666556565656566656555555151515151551551515111515000000000000000000000000000000000000000000000000005
5555565555555555555555555556555555655555655555655555515115515151115151511151500000000001d000000000000050000000000000000000000005
55555666666666666666666666665555556666666666666555555155555555555551515555515000000000011000000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555111111111111111511111115000000000000000000000000050000000000000000000000005
55555555555555555555555555555555555555555555555555555555555555555555555555555000000000000000000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555666666666666666666655555000000000000000000000000050000000000000000000000005
56665666566656665666555555555555555555555555555555555655555555555555555655555000000000000000000000000000000000000000000000000005
56555656565656665655555555555555555555555555555555555655665666566655665655555000000000000000000000000050000000000000000000000005
56655665566656565665555555555555555555555555555555555656565656556556555655555000000000000000000000000000000000000000000000000005
56555656565656565655555555555555555555555555555555555656565665556556555655555000000000000000000000000050000000000000000000000005
56555656565656565666555555555555555555555555555555555656565656556556565655555000000000000000000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555656655656566656665655555000000000000000000000000050000000000000000000000005
55555666666666666666666666665555556666666666666555555655555555555555555655555000000000000000000000000000000000011000000000000005
555556555555555555555555555655555565555565555565555556666666666666666666555550000000000000000000000000500000001c0000000000000005
56666656655555555555555555566666556566556566556555555555555555555555555555555000000000000000000000000000000000110000000000000005
666556556555555555555555555655666565656565656565555555555555555555555555555550000000000000000000000000500000001c0000000000000005
66555655655555555555555555565556656565656565656555555555555555555555555555555000000000000000000000000000000000111000000000000005
66655655655555555555555555565566656565656565656555555555555555555555555555555000000000000000000000000050000000000000000000000005
56666656665555555555555555566666556565656566656555555555555555555555555555555000000000000000000000000000000000000000000000000005
55555655555555555555555555565555556555556555556555555555555555555555555555555050505050505050505050505050505050505050505050505055
55555666666666666666666666665555556666666666666555555555555555555555555555555000000000000000000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555555555555555555555555555000000000000000000000000050000000000000000000000005
55555555555555555555555555555555555555555555555555555555555555555555555555555000000000000000000000000000000000000000000000000005
55555555555555555555555555555555555555555555555555555555555555555555555555555000000000000000000000000050000000000000000000000005
56555666566555665666565655550000000555550555000555550055000500050005050555555000001100000000000000000000000000000000000000000005
56555655565656555565565655555555555555550555050555555055550555050505550555555000001131000000000000000050000000000000000000000005
56555665565656555565566655550000000555550005050555555055500555050005505555555000011cc1000000000000000000000000000000000000000005
565556555656565655655656555555555555555505050505555550555505550505050555555550000111dc000000000000000050000000000000000000000005
566656665656566655655656555500000005555500050005505500050005550500050505555550000131d7000000000000000000000000000000000000000005
5555555555555555555555555555555555555555555555555555555555555555555555555555500001311d000000000000000050000000000000000000000005
55555666666666666666555555550000000555550555000555550005055500050005050555555000013311000000000000000000000000000000000000000005
55555655555555555556555555550500050555550555055555550555055505050555550555555000001110000000000000000050000000000000000000000005
56666656665555555556666655550000000555550005000555550005000500050005505555555000000000000000000000000000000000000000000000000005
66655656555555555556556665550555550555550505550555555505050505055505055555555000000000000000000000000050000000000000000000000005
66555656665555555556555665550000000555550005000550550005000500050005050555555000000000000000000000000000000000000000000000000005
66655655565555555556556665555555555555555555555555555555555555555555555555555000000000000000000000000050000000000000000000000005
5666665666555555555666665555555555555555555555555fffffffffffffffffffffffffff5000000000000000000000000000000000000000000000000005
5555565555555555555655555555555555555555555555555f5555555555555555555555555f5000000000000000000000000050001100000000000000000005
5555566666666666666655555555555555555555555555555f5fff5f5f5fff55ff5fff5fff5f500000000000000000000000000001c000000000000000000005
5555555555555555555555555555555555555555555555555f5f555f5f5f5f5f5f5f5f55f55f5000000000000000000000000050011000000000000000000005
5555555555555555555555555555555555555555555555555f5ff555f55fff5f5f5ff555f55f500000000000000000000000000001c000000000000000000005
5555555555555555555555555555555555555555555555555f5f555f5f5f555f5f5f5f55f55f5000000000000000000000000050011100000000000000000005
5555555555555555555555555555555555555555555555555f5fff5f5f5f555ff55f5f55f55f5000000000000000000000000000000000000000000000000005
5555555555555555555555555555555555555555555555555f5555555555555555555555555f5000000000000000000000000050000000000000000000000005
5555555555555555555555555555555555555555555555555fffffffffffffffffffffffffff5505050505050505050505050505050505050505050505050505
55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555