pico-8 cartridge // http://www.pico-8.com
version 8
__lua__
-- isaac's descent
-- by eevee
-- code licensed under MIT
-- art, music, and sound
-- licensed under CC4-BY-SA
--============================--
--==== begin engine code =====--
--============================--
--------------------------------
-- bad constants
animframedelay = 4
--------------------------------
-- debugging
reprdepth = 0
function _tablerepr(t)
if reprdepth > 1 then
return "
"
end
reprdepth += 1
local first = true
local ret = "{"
for k, v in pairs(t) do
if not first then
ret = ret .. ", "
end
first = false
local rv
if v == t then
rv = "<...>"
else
rv = repr(v)
end
ret = ret .. repr(k) .. ": " .. rv
end
reprdepth -= 1
return ret .. "}"
end
function repr(t)
if t == true then
return ""
elseif t == false then
return ""
elseif t == nil then
return ""
elseif type(t) == "function" then
return ""
elseif type(t) ~= "table" then
return "" .. t
elseif t.__repr then
return t:__repr()
elseif t.__name then
return ""
elseif t.new then
return ""
else
return _tablerepr(t)
end
end
function spew(arg)
local out = ""
for s in all(arg) do
out = out .. repr(s) .. " "
end
printh(out)
end
--------------------------------
-- misc utilities
-- smallest possible value
-- 1/256/256 == 1/65536
minfrac = 0.0000152587890625
function ceil(n)
return flr(n + 1 - minfrac)
end
-- copy values from b into a
function merge(a, b)
for k, v in pairs(b) do
a[k] = v
end
return a
end
function sort(list, keyfunc)
-- insertion sort
-- stable, fast enough for
-- small lists
local keys = {}
keyfunc = keyfunc or function(v) return v end
for i = 1, #list do
keys[i] = keyfunc(list[i])
end
for i = 2, #list do
local j = i
while j > 1 and keys[j - 1] > keys[j] do
keys[j], keys[j - 1] = keys[j - 1], keys[j]
list[j], list[j - 1] = list[j - 1], list[j]
j -= 1
end
end
end
-- print lines of text aligned
-- to given point (doesn't handle
-- screen edge or newlines!)
-- align should be two chars,
-- t/m/b + l/m/r.
-- if border given, a box will
-- be drawn around the text.
-- border is not counted in
-- alignment!
font_height = 6
font_width = 4
-- these characters are double
-- width, but alas, there's no
-- ord(), so...
-- todo chars 128 through 153
-- are all custom double-wides
widechars = {}
for _ch in all{
"‹", "‘", "”", "ƒ", "Ž", "—",
"\135", "\138",
} do
widechars[_ch] = true
end
function printat(lines, anchor, align, color, bordercolor, bgcolor)
local valign = sub(align, 1, 1)
local halign = sub(align, 2, 2)
--"multiplier" -- how much of
-- the height/width to subtract
local vm = ({t=0, m=0.5, b=1})[valign]
local hm = ({l=0, m=0.5, r=1})[halign]
if type(lines) == "string" then lines = {lines} end
local th = #lines * font_height - 1
local y = anchor.y - flr(th * vm)
linewidths = {}
for line in all(lines) do
local lw = 0
for n = 1, #line do
lw += font_width
if widechars[sub(line, n, n)] then
lw += font_width
end
end
add(linewidths, lw - 1)
end
if bordercolor or bgcolor then
local maxw = 0
for lw in all(linewidths) do
maxw = max(maxw, lw)
end
local x = anchor.x - flr(maxw * hm)
local rx, ry, rw, rh =
x - 4, y - 4,
x + maxw + 3, y + th + 3
if bgcolor then
rectfill(rx, ry, rw, rh, bgcolor)
end
if bordercolor then
rect(rx, ry, rw, rh, bordercolor)
end
end
for l, line in pairs(lines) do
local x = (
anchor.x
- flr(linewidths[l] * hm))
print(line, x, y, color)
y += font_height
end
end
--------------------------------
-- micro class type
function class(base, proto)
proto = proto or {}
proto.__index = proto
local meta = {}
setmetatable(proto, meta)
if base then
meta.__index = base
end
function meta:__call(...)
local this = setmetatable({}, self)
if this.init then
this:init(...)
end
return this
end
return proto
end
--------------------------------
-- vec2 type (point or size)
vec2 = class()
function vec2:init(x, y)
self.x = x or 0
self.y = y or 0
end
function vec2:copy()
return vec2(self.x, self.y)
end
function vec2:__repr()
return ""
end
function vec2:__eq(other)
return self.x == other.x
and self.y == other.y
end
function vec2:__add(other)
return vec2(
self.x + other.x,
self.y + other.y)
end
function vec2:__mul(n)
return vec2(
self.x * n,
self.y * n)
end
function vec2:__sub(other)
return self + other * -1
end
-- element-wise multiplication
function vec2:elemx(other)
return vec2(
self.x * other.x,
self.y * other.y)
end
function vec2:at(anchor)
return box(
anchor.x, anchor.y,
self.x, self.y)
end
-- box type (rectangle)
box = class()
function box:init(l, t, w, h)
if w < 0 then
l += w
w *= -1
end
if h < 0 then
t += h
h *= -1
end
self.l = l
self.t = t
self.w = w
self.h = h
end
function box:__repr()
return ""
end
function box.__index(self, key)
if key == "r" then
return self.l + self.w
elseif key == "b" then
return self.t + self.h
else
return box[key]
end
end
function box:__add(offset)
return box(self.l + offset.x, self.t + offset.y, self.w, self.h)
end
function box:overlaps(other)
-- don't count touching edges
-- as overlapping; the right
-- and bottom are exclusive
return (
self.l < other.r and
self.r > other.l and
self.t < other.b and
self.b > other.t
)
end
function box:touches(other)
return (
self.l <= other.r and
self.r >= other.l and
self.t <= other.b and
self.b >= other.t
)
end
--------------------------------
-- actor type
-- note that the base unit is the
-- tile (8px), not the pixel, as
-- that's what the map uses
actor = class{
__name = "actor",
enabled = true,
poses = {},
-- collision box, relative to
-- top-left corner
shape = box(0, 0, 1, 1),
-- draw order (ignored for
-- decor and other faux actors)
z = 0,
}
function actor:init(pos)
self.pos = pos
self:reset()
end
-- called when the map is
-- reloaded
function actor:reset()
-- sprite selection
self:set_pose("default")
end
-- whether to block mobactors;
-- default uses the rightmost
-- tile flag for the initial
function actor:blocks(actor, d)
local t = self.sprite:current()
if fget(t, 7) then
if fget(t, 5) then
return d.y > 0
end
return true
end
end
-- returns collision box
function actor:coll()
return self.shape + self.pos
end
-- called when a mobactor first
-- bumps into this one, even if
-- not blocked. delta is how
-- fast they're colliding, which
-- may or may not be meaningful,
-- but does indicate direction
function actor:oncollide(other, delta)
end
-- called every tic
function actor:update()
end
-- called every tic, but only
-- if actor is visible; this
-- should not change state!
-- by default actors are
-- assumed to be part of the
-- map and drawn by map()
function actor:draw()
end
-- set self.pose and switch to
-- sprite from self.poses;
-- used by subclasses
function actor:set_pose(pose)
if pose ~= self.pose and self.poses[pose] then
self.pose = pose
self:set_sprite(self.poses[pose])
end
end
-- change sprite (allows e.g.
-- decor to update the map)
function actor:set_sprite(s)
self.sprite = to_sprite(s)
end
--------------------------------
-- actor that can move, is
-- subject to gravity, etc.
-- supports a few builtin
-- poses: walking, jumping,
-- and falling
mobactor = class(actor, {
__name = "mobactor",
is_mobile = true,
height = 1,
width = 1,
z = 100,
-- physics
min_speed = 0.015625, -- 1/64
max_speed = 0.25, -- 1/4
friction = 0.625,
})
function mobactor:init(pos)
self.pos0 = self.pos0 or pos:copy()
actor.init(self, pos)
end
function mobactor:reset()
actor.reset(self)
-- reset movement stuff,
-- including original pos
self.pos = self.pos0:copy()
self.vel = vec2()
self.sprite_time = 0
self.facing_right = false
self.ground = true
end
function mobactor:blocks()
return true
end
gravity = 1/32
terminal_velocity = 7/8
-- todo would be nice to have a step height, so i could e.g. make the spikes not be a full tile tall and you wouldn't get stuck on them
-- todo does the wrong thing if you hit two drops in the same tic
function mobactor:update()
self.sprite_time += 1
-- used for player, to track
-- what usable object they're
-- touching
self.touching_mechanism = nil
local abs, vec2 = abs, vec2
-- speed adjustments
local vel = self.vel
local friction = self.friction
if not self.ground then
friction = 1 - (1 - friction) / 2
end
vel.x *= friction
if abs(vel.x) > self.max_speed then
vel.x = sgn(vel.x) * self.max_speed
elseif abs(vel.x) < self.min_speed then
vel.x = 0
end
if not self.floating then
vel.y = min(
vel.y + gravity,
terminal_velocity)
end
-- state based on velocity
local prevx = self._prevx or 0
self._prevx = vel.x
if vel.x ~= 0 then
self.facing_right = vel.x < 0
end
self.ground = false
-- ok, now deal with movement
-- velocity is in tiles per
-- tic, so every tic, move by
-- the velocity
local move = vel:copy()
-- round to a tile when very
-- close to one, so actors
-- can fall down gaps easily,
-- but only when slowing down
if abs(vel.x) < abs(prevx) then
local goalx = self.pos.x + move.x
local d1 = goalx - flr(goalx + 0.5)
-- 1/16 is half a pixel
if abs(d1) < 1/16 then
move.x -= d1
end
end
local coll = self:coll()
local delta = vec2(
abs(move.x),
abs(move.y))
local sign = vec2(
sgn(move.x),
sgn(move.y))
local nearx, farx, neary, fary = "l", "r", "t", "b"
if sign.x > 0 then
nearx, farx = farx, nearx
end
if sign.y > 0 then
neary, fary = fary, neary
end
-- trim to map bounds
local boundx = abs(curzone.box[nearx] - coll[nearx])
if delta.x > boundx then
delta.x = boundx
vel.x = 0
end
local boundy = abs(curzone.box[neary] - coll[neary])
if delta.y > boundy then
if vel.y > 0 then
self.ground = true
end
delta.y = boundy
vel.y = 0
end
-- find actors we might hit
local blockers = {}
local moverange = box(coll.l, coll.t, coll.w + delta.x, coll.h + delta.y)
if sign.x < 0 then
moverange.l -= delta.x
end
if sign.y < 0 then
moverange.t -= delta.y
end
local function add_blocker(other)
if not other.enabled then
return
end
if other.oncollide == actor.oncollide and not other:blocks(self, vel) then
return
end
local otherbox = other:coll()
if coll:overlaps(otherbox) then
-- since we're checking here
-- anyway, this is a good
-- place to look for whether
-- we're touching a gizmo
if self.is_player
and other.is_usable then
self.touching_mechanism = other
end
elseif moverange:overlaps(otherbox) then
local dist = vec2(
sign.x * (otherbox[farx] - coll[nearx]),
sign.y * (otherbox[fary] - coll[neary]))
-- sort in roughly the order we'll encounter actors
local order = max(0, dist.x) * delta.y + max(dist.y) * delta.x
add(blockers, {
actor = other,
dist = dist,
order = order,
coll = otherbox,
})
end
end
-- todo this is the slowest part! maybe i really do need a blockmap
for actor in all(curzone.mobs) do
if actor ~= self and
abs(self.pos.x - actor.pos.x) + abs(self.pos.y - actor.pos.y) <= 8
then
add_blocker(actor)
end
end
for x = flr(moverange.l), ceil(moverange.r) do
for y = flr(moverange.t), ceil(moverange.b) do
add_blocker(curzone:tile(vec2(x, y)))
end
end
sort(blockers, function (blocker)
return blocker.order
end)
local movedby = vec2()
for blocker in all(blockers) do
-- step 1: move to touch the
-- other actor
local dist = blocker.dist - movedby
dist.x = min(max(0, dist.x), delta.x)
dist.y = min(max(0, dist.y), delta.y)
local ymult = delta.y * dist.x
local xmult = delta.x * dist.y
local step = dist:copy()
if dist.x == 0 or dist.y == 0 then
-- already touching; no trim
elseif ymult > xmult then
-- touch side first, so trim y distance
step.y = delta.y * dist.x / delta.x
elseif xmult > ymult then
-- touch top/bottom first, so trim x distance
step.x = delta.x * dist.y / delta.y
end
delta -= step
movedby += step
coll += (step:elemx(sign))
-- step 2: if we were about
-- to collide, do oncollide,
-- and stop if solid.
if coll:touches(blocker.coll) then
local touchx = coll[nearx] == blocker.coll[farx]
local touchy = coll[neary] == blocker.coll[fary]
if touchx and touchy then
-- "corner" case, ho ho!
-- allow sliding in the
-- direction that we're
-- moving fastest in
if delta.x > delta.y then
touchx = false
else
touchy = false
end
end
local force = move:copy()
if not touchx or delta.x == 0 then
force.x = 0
end
if not touchy or delta.y == 0 then
force.y = 0
end
blocker.actor:oncollide(self, force)
if blocker.actor:blocks(self, force) then
if touchx then
delta.x = 0
vel.x = 0
else
delta.y = 0
if vel.y > 0 then
self.ground = true
end
vel.y = 0
end
end
end
end
-- leftover isn't blocked
movedby += delta
self.pos += (movedby:elemx(sign))
local pose = "default"
if self.is_dead then
-- dumb hack, but, shouldn't change pose away from the death state
pose = self.pose
elseif not self.ground then
if vel.y <= 0 then
pose = "jumping"
else
pose = "falling"
end
elseif vel.x ~= 0 then
pose = "walking"
end
self:set_pose(pose)
end
function mobactor:draw()
local p = self.pos:copy()
if self.floating then
p.y += 0.25 * (sin(curtime % 90 / 90) - 1)
end
self.sprite:drawat(p, self.sprite_time, self.facing_right)
end
function mobactor:set_sprite(s)
actor.set_sprite(self, s)
self.sprite_time = 0
end
--------------------------------
-- player actor type
-- main difference is that it
-- reads input every frame;
-- it also has is_player,
-- which other actors may check
-- for
playeractor = class(mobactor, {
__name = "playeractor",
is_player = true,
z = 1000,
-- controls
xaccel = 0.125, -- 1/8
max_jump_time = 4,
-- determined experimentally
-- to make max jump 2 tiles
yaccel = 7/64,
-- multiplied by xaccel while
-- airborne
aircontrol = 0.5,
})
function playeractor:reset()
self.is_dead = false
mobactor.reset(self)
self.jumptime = 0
end
function playeractor:update()
if self.is_dead then
mobactor.update(self)
return
end
local xmult = 1
if not self.ground then
xmult = self.aircontrol
end
if btn(0) then
self.vel.x -= self.xaccel * xmult
elseif btn(1) then
self.vel.x += self.xaccel * xmult
end
if btn(5) then -- —
progress.seenjumphint = true
if self.floating then
sfx(19)
self.floating = false
end
if self.jumptime < self.max_jump_time then
self.vel.y -= self.yaccel
if self.jumptime == 0 then
sfx(0)
end
self.jumptime += 1
end
elseif self.ground then
self.jumptime = 0
else
self.jumptime = 999
end
mobactor.update(self)
-- spawn particles sometimes
-- while floating
if self.floating and rnd() < 0.1 then
curzone:add_actor(particle(
self.pos + vec2(rnd(1), 2),
7, rnd(10) + 10, vec2(0, -0.0625)))
end
-- handle using an item last
if btnp(2) then -- ”
progress.seeninvhint = true
progress.curitem -= 1
if progress.curitem == 0 then
progress.curitem = #progress.inventory
end
elseif btnp(3) then -- ƒ
progress.seeninvhint = true
progress.curitem += 1
if progress.curitem > #progress.inventory then
progress.curitem = 1
end
elseif btnp(4) then -- Ž
if self.touching_mechanism then
progress.seenusehint = true
self.touching_mechanism:onactivate()
else
local item = progress.inventory[progress.curitem]
if item then
item:use(self)
end
end
end
end
firstjump = box(2, 7, 1, 1)
firststaff = box(8, 7, 2, 1)
function playeractor:draw()
mobactor.draw(self)
-- possibly draw instructional
-- thoughts
local hint = nil
if not progress.seenjumphint
and self:coll():overlaps(firstjump) then
hint = "—"
elseif not progress.seenstaffhint
and self:coll():overlaps(firststaff) then
hint = "Ž"
elseif not progress.seenusehint
and self.touching_mechanism then
hint = "Ž"
elseif not progress.seeninvhint
and #progress.inventory > 1 then
hint = "”ƒ"
end
if hint then
local ax = self.pos.x * 8
local ay = self.pos.y * 8
circfill(ax + 4, ay - 1, 1, 7)
circfill(ax + 8, ay - 5, 1, 7)
-- make a cloud out of circles
local cx, cy = ax + 4, ay - 13
circfill(cx + 5, cy - 0, 4, 7)
circfill(cx - 5, cy + 0, 4, 7)
circfill(cx - 0, cy - 2, 4, 7)
circfill(cx + 0, cy + 2, 4, 7)
printat({hint}, vec2(cx, cy), "mm")
end
end
function playeractor:die()
if self.is_dead then
return
end
self.is_dead = true
self:set_pose"dying"
game:die(self)
end
--------------------------------
-- transient actor type
-- used for performing collision
-- against map tiles that aren't
-- real actors; behavior can be
-- changed using declare_tile
transientactor = class(actor, {
-- indicates that the map
-- doesn't need to create and
-- store a permanent instance
is_transient = true,
})
function transientactor:init(...)
actor.init(self, ...)
if not self.sprite then
self.sprite = to_sprite(
mget(self.pos.x, self.pos.y))
end
end
--------------------------------
-- associate actor behavior with
-- particular map tiles
_tiledefs = {}
-- declare an actor type to be
-- used for a map tile
-- parent class can be given
-- explicitly as "class"; if
-- not, anything with update or
-- reset or draw methods will
-- use actor, and anything else
-- will use transientactor
function declare_tile(data)
-- clean up data if necessary
if data.sprite then
data.sprite = to_sprite(data.sprite)
end
if data.poses then
for name, sprref in pairs(data.poses) do
data.poses[name] = to_sprite(sprref)
end
end
-- which tiles?
local sprite = data.sprite or (data.poses and data.poses.default)
local for_tiles = data.for_tiles or sprite:get_tiles()
-- what actor class?
local cls = data.class
data.class = nil
if cls then
-- do nothing
elseif data.reset or data.update or
data.draw or data.poses or
-- todo check transparency too...
(sprite and sprite.is_animated)
then
-- anything that expects to
-- be called needs to at
-- least be decor
cls = decoractor
else
-- otherwise transient ok
cls = transientactor
end
local newcls = class(cls, data)
for _key, tileno in pairs(for_tiles) do
if not _tiledefs[tileno] then
_tiledefs[tileno] = class(
data,
{ sprite = to_sprite(tileno) })
end
end
return newcls
end
-- todo no way to specify what map this goes on!
_oneoff_actors = {}
function oneoff_actor(data)
setmetatable(data, data.class or actor)
add(_oneoff_actors, data)
return data
end
--------------------------------
-- decor: single-tile actors
-- that never move, so can be
-- mostly treated as part of
-- the map, but still get to
-- reset and update.
-- this is an optimization for
-- very simple tiles, to get
-- them out of normal collision
-- detection, which is slowww
decoractor = class(actor, {
__name = "decoractor",
is_decor = true,
_sprchange = false,
})
function decoractor:set_sprite(s)
actor.set_sprite(self, s)
mset(self.pos.x, self.pos.y, self.sprite:current())
self._sprchange = true
end
function decoractor:reset()
local t = 0
if self.enabled then
t = self.sprite:current()
end
mset(self.pos.x, self.pos.y, t)
end
function decoractor:update()
if curtime % animframedelay == 0 or
self._sprchange
then
mset(self.pos.x, self.pos.y, self.sprite:current())
self._sprchange = false
end
end
--------------------------------
-- particle
-- super simple actor: a pixel
-- of a given color. moves at
-- the given velocity, destroys
-- itself after some time
particle = class(actor, {
init = function(self, pos, col, ttl, vel)
actor.init(self, pos)
self.col = col
self.ttl = ttl
self.vel = vel or vec2()
end,
update = function(self)
self.ttl -= 1
if self.ttl <= 0 then
curzone:del_actor(self)
end
self.pos += self.vel
end,
draw = function(self)
local p = self.pos * 8
pset(p.x, p.y, self.col)
end,
})
--------------------------------
-- sprite properties
-- maps tileno to list of
-- transparent colors
_tiletrans = {}
-- declare a set of tiles to
-- have custom non-black
-- transparent colors
function declare_transparency(tiles)
local trans = tiles.trans
for tileno in all(tiles) do
_tiletrans[tileno] = trans
end
end
_spritedefs = {}
sprite = class()
function sprite:init(frames, skip)
self.frames = frames
self.skip = skip or 0
self.width = 1
self.height = 1
if type(frames[1]) == "table" then
self.height = #frames
else
self.frames = {frames}
end
self.size = self.width * self.height
self.is_animated = false
for frames in all(self.frames) do
if #frames > 1 then
self.is_animated = true
break
end
end
end
function sprite:get_tiles()
local seen = {}
local ret = {}
for frames in all(self.frames) do
for tileno in all(frames) do
if not seen[tileno] then
seen[tileno] = true
add(ret, tileno)
end
end
end
return ret
end
function sprite:current(n, dt)
n = n or 1
dt = dt or curtime
-- todo this sucks; should anyone else even call it?
local frames = self.frames[n]
local animlen = #frames * animframedelay
local time = dt % animlen
local frame = flr(time / animframedelay) + 1
if self.frames.stop and dt >= animlen then
frame = #frames
end
frame += self.skip
if frame > #frames then
frame -= #frames
end
return frames[frame]
end
function sprite:drawat(pos, dt, hflip, vflip)
for n = 1, self.size do
local tileno = self:current(n, dt)
local trans = _tiletrans[tileno]
if trans then
palt(0, false)
for color in all(trans) do
palt(color, true)
end
end
spr(tileno, pos.x * 8, (pos.y + n - 1) * 8,
1, 1, hflip, vflip)
if trans then
palt()
end
end
end
-- declare props for a sprite,
-- to be used anywhere it's
-- referenced, either on the
-- map or in actors. args are
-- one or more tiles (multiple
-- will be animated), optional
-- 'trans' list of transparent
-- colors, and optional 'name'
-- to use to refer to a sprite
function declare_sprite(args)
-- todo there's no way to register a custom sprite without making it a tile default
-- todo no way to /override/ transparency per frame
local skip = 0
for tileno in all(args) do
_spritedefs[tileno] = sprite(
args, skip)
if args.name then
_spritedefs[args.name] = _spritedefs[tileno]
end
skip += 1
end
return _spritedefs[args[1]]
end
function declare_sprites(defs)
foreach(defs, declare_sprite)
end
function to_sprite(val)
if type(val) == "number" then
return _spritedefs[val]
or declare_sprite{val}
elseif type(val) == "string" then
return _spritedefs[val]
elseif #val > 0 then
return declare_sprite(val)
else
return val
end
end
--------------------------------
-- some color stuff
-- create color ramps from a
-- list mapping each color to
-- the next one
function to_ramp(conv)
local ret = {}
for color = 0, 15 do
local ramp = {}
ret[color + 1] = ramp
while color do
add(ramp, color)
color = conv[color + 1]
end
end
return ret
end
blackramp = to_ramp{
nil, 0, 0, 1,
2, 1, 5, 6,
2, 8, 9, 3,
13, 5, 8, 14,
}
greenramp = to_ramp{
1, 3, 3, 11,
3, 1, 10, 10,
9, 10, 11, nil,
11, 12, 9, 9,
}
-- use pal() to create a fade
-- along a ramp. proportion
-- should be 0 to 1
function apply_ramp_fade(ramp, proportion, mode)
mode = mode or 1
pal()
for color = 0, 15 do
local colorramp = ramp[color + 1]
local slot = flr(#colorramp * proportion + 1)
pal(color, colorramp[slot], mode)
end
end
--------------------------------
-- mapzone type
-- defines a distinct area of
-- the map
mapzone = class()
function mapzone:init(...)
self.box = box(...)
self.actors = {}
-- mobile actors, ones not
-- bound to a single tile
self.mobs = {}
-- decor can update and reset
-- like any other actor, but
-- doesn't participate in
-- drawing, and acts like
-- a plain tile for collision.
-- also, these are indexed by
-- coordinate, so tile()
-- will return the decor
self.decor = {}
end
-- todo it would be nice to have an interface here for manually changing a tile in a decor-aware way (either adding or removing)
function mapzone:tile(pos)
local decor = self.decor[pos.y * 128 + pos.x]
if decor then return decor end
local tileno = mget(pos.x, pos.y)
if _tiledefs[tileno] then
return _tiledefs[tileno](pos)
end
return transientactor(pos)
end
function mapzone:add_actor(actor)
add(self.actors, actor)
if actor.is_decor then
self.decor[actor.pos.y * 128 + actor.pos.x] = actor
elseif actor.is_mobile then
add(self.mobs, actor)
end
-- todo lol
if actor.is_player then
player = actor
end
end
function mapzone:del_actor(actor)
del(self.actors, actor)
if actor.is_decor then
local x, y = actor.pos.x, actor.pos.y
self.decor[y * 128 + x] = nil
mset(x, y, 0)
elseif actor.is_mobile then
del(self.mobs, actor)
end
end
function mapzone:reset()
local mset, vec2 = mset, vec2
if not self.inited then
self.inited = true
cam.l, cam.t = self.box.l, self.box.t
for x = self.box.l, self.box.r - 1 do
for y = self.box.t, self.box.b - 1 do
local tilecls = _tiledefs[mget(x, y)]
if tilecls and
not tilecls.is_transient
then
local actor = tilecls(
vec2(x, y))
self:add_actor(actor)
if actor.is_mobile then
-- remove from actual map
mset(x, y, 0)
end
end
end
end
for actor in all(_oneoff_actors) do
self:add_actor(actor)
end
end
end
function mapzone:draw(cam, flag)
flag = flag or 0
camera(cam.l * 8, cam.t * 8)
local x = flr(cam.l)
local y = flr(cam.t)
map(x, y, x * 8, y * 8, 17, 17, flag)
end
--------------------------------
-- scenes and layers
-- (inspired by cocos2d)
scene = class{
-- called when a scene becomes
-- or stops being the active
-- scene. note that it may be
-- drawn even when not active
onenter = function() end,
onexit = function() end,
-- used by scene transitions to
-- start the music automatically
-- at the right time
get_music = function() end,
}
function scene:init(obj)
merge(self, obj or {})
end
curtime = 0
function scene:update()
-- 64 * 9 * 5 * 7
-- should be divisible by
-- most interesting numbers
-- todo this makes no sense in a scene, but scenefader needs to pause it
curtime = (curtime + 1) % 20160
for layer in all(self.layers) do
if layer.update then
layer:update()
end
end
end
function scene:draw(nocls)
local pal, camera = pal, camera
if not nocls then
cls()
end
for layer in all(self.layers) do
pal()
camera()
layer:draw()
end
end
-- simple transitional scene
-- that can fade from the
-- current scene to another
scenefader = class(scene)
function scenefader:init(newscene, duration, ramp, onbetween)
self.newscene = newscene
self.oldscene = game.scene
self.timer = 1
self.duration = duration
self.ramp = ramp or blackramp
self.onbetween = onbetween
if self.oldscene then
game:changemus(nil, self.duration)
else
self:doreverse()
end
end
function scenefader:doreverse()
self.reverse = true
self.timer = 1
game:changemus(self.newscene:get_music(), self.duration)
if self.onbetween then
self:onbetween()
end
end
function scenefader:onenter()
end
function scenefader:update()
self.timer += 1
if self.timer >= self.duration then
if not self.reverse then
self:doreverse()
elseif self.timer > 0 then
self.timer -= 1
game:set_scene(self.newscene)
end
end
end
function scenefader:draw()
rectfill(0, 0, 128, 128, 9)
if self.reverse then
self.newscene:draw()
else
self.oldscene:draw()
end
local prop = self.timer / self.duration
if self.reverse then
prop = 1 - prop
end
apply_ramp_fade(self.ramp, prop)
end
-- current camera, in tiles
cam = box(0, 0, 16, 16)
margin = 6
map_layer = {
update_camera = function(self)
local bounds = curzone.box
local focus = player:coll()
cam.l = max(
min(cam.l, max(bounds.l, focus.l - margin)),
min(bounds.r, focus.r + margin) - cam.w)
cam.t = max(
min(cam.t, max(bounds.t, focus.t - margin)),
min(bounds.b, focus.b + margin) - cam.h)
end,
reset = function(self)
curzone:reset()
for actor in all(curzone.actors) do
actor:reset()
end
self:update_camera()
progress.savepoint = nil
progress:backup()
end,
update = function(self)
for actor in all(curzone.actors) do
if actor.enabled then
actor:update()
end
end
self:update_camera()
-- advance if player reaches right edge
if player:coll().r == curzone.box.r then
game:set_scene(scenefader(
mainscene, 20, blackramp,
function()
-- todo probably need to, like, unload the current zone and then load the next one... that hasn't been an explicit step or anything so far
-- todo and yet, i don't know why the map /zone/ contains all that information in the first place. should it be on the map layer, and the zone list is just a list of boxes?
curzonen += 1
curzone = zones[curzonen]
map_layer:reset()
end
))
end
end,
draw = function(self)
curzone:draw(cam)
pal()
sort(
curzone.actors,
function (actor)
return actor.z
end)
for actor in all(curzone.actors) do
if actor.enabled and
actor:coll():overlaps(cam)
then
actor:draw()
end
end
end,
}
-- prompt shown on death
deadscene = class(scene)
function deadscene:init(wrapped)
self.wrapped = wrapped
end
function deadscene:update()
if btn(4) then
game:doreset()
elseif btn(5) and progress.savepoint then
game:doresurrect()
else
self.wrapped:update()
end
end
function deadscene:draw()
self.wrapped:draw()
pal()
palt()
local msg = {"Ž reset "}
if progress.savepoint then
add(msg, "— resurrect")
end
printat(msg, vec2(64, 64), "mm", 7, 7, 0)
end
-- singleton
game = {
pending_scene = nil,
scene = nil,
curmusic = -1,
taskhdl = 1,
tasks = {},
pending_tasks = {},
}
function game:initialize()
if self.curmusic then
self:_music(self.curmusic)
end
-- create automatic decor for
-- tiles with custom sprite
-- transparency or animation
for tileno, def in pairs(_spritedefs) do
if type(tileno) == "number" and
not _tiledefs[tileno] and
-- todo actually... transparent can't be decoractor, it can't be drawn by map()
(def.is_animated or _tiletrans[tileno])
then
declare_tile{
class = decoractor,
sprite = def,
}
end
end
-- initialize map
map_layer:reset()
end
-- schedule a function to be
-- called in the future
function game:schedule(tics, callback)
local handle = self.taskhdl
self.taskhdl += 1
self.pending_tasks[handle] = {
time = tics,
callback = callback,
}
return handle
end
function game:update()
for handle, task in pairs(self.tasks) do
task.time -= 1
if task.time <= 0 then
task.callback()
self.tasks[handle] = nil
end
end
if self.pending_scene then
if self.scene then
self.scene:onexit()
end
self.scene = self.pending_scene
self.pending_scene = nil
self.scene:onenter()
end
self.scene:update()
-- add pending tasks at the very end, for consistency -- otherwise e.g. a task might schedule a second task, which would then play immediately
merge(self.tasks, self.pending_tasks)
self.pending_tasks = {}
end
function game:draw()
self.scene:draw()
end
function game:set_scene(scene)
self.pending_scene = scene
end
-- change the current music,
-- with a fade. can fade
-- between two tracks
function game:changemus(track, fadelen)
track = track or -1
if track == self.curmusic then
return
end
-- todo doesn't handle being called again while in the middle of a fade, or while there's another fade scheduled
if self.curmusic ~= -1 and track ~= -1 then
self:_music(-1, fadelen)
self:schedule(fadelen, function()
self:_music(track, fadelen)
end)
else
self:_music(track, fadelen)
end
self.curmusic = track
end
function game:_music(track, fadelen)
if fadelen then
fadelen = fadelen * 100 / 3
end
music(track, fadelen)
end
-- death/reset handling
function game:die()
self:changemus(nil, 0)
sfx(2)
self:schedule(45, function()
self:set_scene(deadscene(self.scene))
end)
end
function game:doresurrect()
if not progress.savepoint then
-- how did you even get here
return
end
sfx(3)
self:changemus(nil)
self:set_scene(scenefader(
mainscene, 10, greenramp,
function()
player.pos = progress.savepoint.pos
player.is_dead = false
player:set_pose"default"
map_layer:update_camera()
end
))
end
function game:doreset()
-- this is just a regular reset of the map, plus reverting the player's
-- progress
self:changemus(nil)
self:set_scene(scenefader(
mainscene, 20, blackramp,
function()
-- revert progress first, since resetting the map creates a backup!
progress:restore()
map_layer:reset()
end
))
end
function game:win()
-- todo usual state change
-- caveats apply: we're still
-- in the middle of an update
-- and something might, say,
-- kill the player before it's
-- done
self:set_scene(winscene(
self.scene))
end
--------------------------------
-- pico-8 engine hooks
function _init()
game:initialize()
end
function _update()
game:update()
end
function _draw()
game:draw()
end
--============================--
--===== end engine code ======--
--============================--
-- main gameplay scene, map etc
mainscene = scene{
layers = {
-- background
{
update = function(self)
end,
draw = function(self)
camera()
rectfill(0, 0, 128, 128, 0)
end,
},
-- map
map_layer,
-- hud
{
draw = function(self)
local gizmo = player.touching_mechanism
if gizmo then
color(isaaccolors[isaaccolor][3])
else
color(7)
end
local t, l = 2, 2
rect(t + 1, l, t + 12, l + 13)
rect(t, l + 1, t + 13, l + 12)
rectfill(t + 2, l + 2, t + 11, l + 11, 0)
local iconpos = vec2(t + 3, l + 3) * 0.125
if gizmo then
if gizmo.usesprite:current() == 2 then
pal(
isaaccolors[1][1],
isaaccolors[isaaccolor][1])
end
gizmo.usesprite:drawat(iconpos)
pal()
else
item = progress.inventory[progress.curitem]
if item then
item.sprite:drawat(iconpos)
end
end
end,
},
-- framerate
{
update = function() end,
draw = function()
local fps = flr(30 / stat(1) + 0.5)
local color = 12
if fps < 30 then
color = 8
end
print(fps, 2, 128 - 5 - 2, color)
end,
},
},
}
function mainscene:get_music()
return 0
end
titlescene = scene{
slowwalk = declare_sprite{
{1}, {16, 16, 16, 16, 17, 17, 17, 17}},
update = function(self)
scene.update(self)
if btn(4) or btn(5) then
game:set_scene(scenefader(
mainscene, 30, blackramp))
end
end,
draw = function(self)
cls()
--pal(7, isaaccolors[isaaccolor][1])
pal(5, isaaccolors[isaaccolor][4])
sspr(64, 96, 64, 32, 0, 16, 128, 64)
pal()
-- todo wtb paltrans type?
for i = 1, 4 do
pal(
isaaccolors[1][i],
isaaccolors[isaaccolor][i])
end
self.slowwalk:drawat(vec2(0.5, 6))
pal()
to_sprite(24):drawat(vec2(14.5, 6.5))
printat(
{"ld36 edition"},
vec2(64, 72), "tm", isaaccolors[isaaccolor][4])
printat(
{"press Ž or —"},
vec2(64, 96), "mm", 7)
printat(
{"Ž = z — = x enter for menu"},
vec2(64, 128), "bm", 5)
end,
get_music = function()
return 20
end,
onenter = function(self)
game:changemus(self:get_music())
end,
}
game:set_scene(titlescene)
winscene = class(scene, {
init = function(self, wrapped)
self.wrapped = wrapped
scene.init(self)
end,
onenter = function(self)
game:changemus(nil)
sfx(9)
game:schedule(60, function()
game:set_scene(scenefader(
endscene, 60, blackramp))
end)
end,
draw = function(self)
self.wrapped:draw()
end,
})
endscene = scene{
timer = 0,
onenter = function()
-- used instead of get_music
-- to avoid the fade in,
-- since it's short and
-- doesn't loop
game:changemus(30)
end,
update = function(self)
self.timer += 1
end,
draw = function(self)
cls()
printat({
"you did it, isaac!",
"",
"you found the flurry, the",
"legendary enchanted sabre.",
"",
"now you just need to, ah,",
"get back out of here.",
"",
"good luck with that!",
}, vec2(64, 8), "tm", 7)
printat(
{"\135 thanks for playing! \135"},
vec2(64, 80), "mm", 14, 2, 2)
sspr(120, 48, 8, 16, 4, 108)
printat(
{"hastily made by eevee",
"@eevee",
"\138 http://eev.ee/"},
vec2(16, 124), "bl", 12)
end,
}
menuitem(1, "reset room", function()
game:doreset()
end)
-- todo hmm, wish i had an
-- itemactor type
items = {
staff = {
sprite = declare_sprite{48},
use = function(self, player)
progress.seenstaffhint = true
-- todo this concept requires
-- a second save for when
-- the player entered the
-- room; otherwise they can
-- screw themselves
local pos = player.pos:copy()
-- check that there's space
-- todo well this isn't quite
-- right
local tile = curzone:tile(pos)
-- todo this seems clumsy
if tile.sprite:current() ~= 0 then
-- todo play "nope" sound?
return
end
-- remove existing savepoint
if progress.savepoint then
curzone:del_actor(progress.savepoint)
progress.savepoint = nil
end
-- create new savepoint
progress.savepoint = savepointactor(pos)
curzone:add_actor(progress.savepoint)
-- sparkles and jingles
sfx(1)
for angle = 0.125, 1, 0.125 do
curzone:add_actor(particle(
player.pos + vec2(0.5, 0.5),
11, 8, vec2(cos(angle), sin(angle)) * 0.125
))
end
end,
},
spellbook = {
sprite = declare_sprite{50},
use = function(self, player)
if player.floating then
sfx(19)
player.floating = false
elseif player.ground then
sfx(8)
player.floating = true
end
end,
}
}
progress = {
inventory = {items.staff},
curitem = 1,
savepoint = nil,
-- called when entering a room to record your progress thusfar
backup = function(self)
self.savestate = {
inventory = merge({}, self.inventory),
curitem = self.curitem,
}
end,
restore = function(self)
self.inventory = merge({}, self.savestate.inventory)
self.curitem = self.savestate.curitem
-- savepoint is always gone after a restore
self.savepoint = nil
end,
}
gravity = 1/32
terminal_velocity = 1
zones = {
mapzone(0, 0, 24, 16),
mapzone(24, 0, 16, 16),
mapzone(40, 0, 40, 24),
mapzone(80, 0, 16, 24),
mapzone(96, 0, 32, 24),
mapzone(0, 16, 24, 32),
mapzone(24, 16, 16, 16),
mapzone(24, 32, 16, 16),
mapzone(40, 24, 40, 24),
mapzone(80, 24, 32, 24),
mapzone(112, 24, 16, 24),
}
curzonen = 1
curzone = zones[curzonen]
-- isaac (player)
declare_tile{
class = playeractor,
shape = box(0, 0.5, 1, 1.5),
height = 2,
poses = {
default = {{1}, {17}},
walking = {{1}, {16, 17}},
jumping = {{1}, {16}},
falling = {{1}, {16}},
dying = {{1, 3, 4, 5, 6}, {17, 19, 20, 21, 22}, stop = true},
},
draw = function(self)
for i = 1, 4 do
pal(
isaaccolors[1][i],
isaaccolors[isaaccolor][i])
end
playeractor.draw(self)
pal()
end,
}
-- randomize isaac's cloak and
-- skin tone
isaaccolors = {
{13, 2, 12, 1}, -- purple + blue
{13, 2, 14, 2}, -- purple + pink
{12, 1, 11, 3}, -- blue + green
{15, 9, 14, 2}, -- peach + pink
{11, 3, 10, 9}, -- green + yellow
{6, 5, 7, 6}, -- silver + white
{9, 4, 13, 2}, -- orange + purple
{1, 1, 8, 2}, -- navy + red
}
isaaccolor = flr(rnd(#isaaccolors)) + 1
-- save point
savepointactor = class(actor, {
sprite = declare_sprite{
24, 24, 24, 24, 24,
25, 26, 27, 28, 29,
},
is_savepoint = true,
-- todo ugh this hierarchy is so bad, one-off actors like this should not
-- be this confusing. but this code exists only in mobactor, which has
-- physics, which this should not have -- so either i inherit actor and
-- reimplement draw, or i inherit mobactor and blank out update
draw = function(self)
self.sprite:drawat(
self.pos + vec2(0, 0.5),
self.sprite_time,
self.facing_right)
end,
reset = function(self)
curzone:del_actor(self)
end,
})
-- spikes
declare_tile{
sprite = 8,
shape = box(0, 0.75, 1, 0.25),
oncollide = function(self, actor, d)
if d.y > 0 and actor.is_player then
actor:die()
end
end,
}
-- wooden switch (platforms)
declare_tile{
poses = {
default = {56},
switched = {57},
},
usesprite = declare_sprite{2},
-- todo ugh, this tricks both
-- declare_tile into giving us
-- a decoractor, and collision
-- into not skipping us
oncollide = function() end,
is_usable = true,
reset = function(self)
self.is_usable = true
self:set_pose"default"
end,
onactivate = function(self)
sfx(4)
for _pos, decor in pairs(curzone.decor) do
if decor.onuselever then
decor:onuselever(true)
end
end
self:set_pose"switched"
self.is_usable = false
end,
}
-- magical bridge
declare_tile{
sprite = 42,
shape = box(0, 0, 1, 0.25),
timer = 0,
reset = function(self)
-- disabled by default
self.enabled = false
decoractor.reset(self)
end,
onuselever = function(self)
-- todo should check for a
-- blocker and refuse to
-- materialize
self.enabled = true
self.timer = 25
end,
update = function(self)
decoractor.update(self)
if not self.enabled or self.timer <= 0 then
return
end
self.timer -= 1
if self.timer == 10 then
sfx(5)
end
if self.timer <= 10 then
end
end,
draw = function(self)
-- we're decor so we already get drawn by map(), but that's ok, just draw atop ourselves
if self.timer > 0 then
apply_ramp_fade(blackramp, self.timer / 10, 0)
self.sprite:drawat(self.pos)
pal()
end
end,
}
-- laser eye
declare_tile{
class = mobactor,
poses = {
default = {58},
awake = {59},
},
reset = function(self)
mobactor.reset(self)
self:sleep()
end,
sleep = function(self)
self.sleep_timer = 0
self:set_pose"default"
if self.laser then
curzone:del_actor(self.laser)
self.laser = nil
end
end,
update = function(self)
local pcoll = player:coll()
local scoll = self:coll()
local px = pcoll.l + pcoll.w / 2
local sx = scoll.l + scoll.w / 2
if abs(px - sx) < 2 then
self:set_pose"awake"
self.sleep_timer = 150
if not self.laser then
self.laser = laseractor(self.pos + vec2(0, 1))
curzone:add_actor(self.laser)
end
elseif self.pose == "awake" then
self.sleep_timer -= 1
if self.sleep_timer <= 0 then
self:sleep()
end
end
if self.pose == "awake" then
local dx = 0.125
local d0 = self.pos.x - self.pos0.x
if d0 > 4 then
self.reverse = true
elseif d0 < -4 then
self.reverse = false
end
if self.reverse then
dx *= -1
end
self.pos.x += dx
if self.laser then
self.laser.pos.x += dx
end
end
end,
}
laseractor = class(actor, {
init = function(self, pos)
actor.init(self, pos)
local bottom = pos:copy()
while pos.y < curzone.box.b - 1 do
bottom.y += 1
local tile = curzone:tile(bottom)
if tile:blocks(self) then
break
end
end
self.shape = box(
0.375, 0, 0.25, bottom.y - pos.y)
end,
update = function(self)
local coll = self:coll()
if curtime % 10 == 0 then
local ang = rnd() * 0.5
curzone:add_actor(particle(
vec2(coll.l, coll.b), 8, 8,
vec2(cos(ang), sin(ang)) * 0.125))
end
if coll:overlaps(player:coll()) then
player:die()
end
end,
draw = function(self)
local coll = self:coll()
rectfill(coll.l * 8, coll.t * 8, coll.r * 8 - 1, coll.b * 8 - 1, 8)
end,
})
-- wheel (stone doors)
-- todo largely copy/pasted
declare_tile{
poses = {
default = {62},
turning = {62, 63},
},
usesprite = declare_sprite{2},
-- todo ugh, this tricks both
-- declare_tile into giving us
-- a decoractor, and collision
-- into not skipping us
oncollide = function() end,
is_usable = true,
update = function(self)
-- todo this is what game's
-- schedule() is meant to be
-- for, but i don't want it
-- to survive through a
-- map reset
if self.turning_timer then
self.turning_timer -= 1
if self.turning_timer <= 0 then
self.turning_timer = nil
self:reset()
end
end
decoractor.update(self)
end,
reset = function(self)
self.is_usable = true
self:set_pose"default"
end,
onactivate = function(self)
sfx(18)
-- todo lol well this is awful
for actor in all(curzone.actors) do
if actor.onusewheel then
actor:onusewheel(true)
end
end
self:set_pose"turning"
self.is_usable = false
self.turning_timer = 30
end,
}
-- stone door
declare_tile{
class = mobactor,
sprite = 39,
reset = function(self)
mobactor.reset(self)
local x, y = self.pos0.x, self.pos0.y
local h = 1
while y > 0 do
if curzone:tile(vec2(x, y - 1)).sprite:current() == 38 then
h += 1
y -= 1
else
break
end
end
self.pos = vec2(x, y)
self.shape = box(0, 0, 1, h)
end,
update = function(self)
if self.direction and curtime % 3 == 0 then
local coll = self:coll()
-- todo would love to check
-- for any collider below,
-- but, don't have a way to
-- do that at the moment
if self.direction > 0
and coll.b == flr(coll.b)
and curzone:tile(vec2(coll.l, coll.b)):blocks(self)
then
self.direction = nil
return
end
if self.direction < 0
and coll.h <= 1
then
self.direction = nil
self.close_timer = 120
return
end
self.shape.h += self.direction
self.shape.b += self.direction
elseif self.close_timer then
self.close_timer -= 1
if self.close_timer <= 0 then
self.close_timer = nil
sfx(7)
self.direction = 0.125
end
end
end,
draw = function(self)
local sx = self.pos.x * 8
local coll = self:coll()
local sy = coll.b * 8 - 8
spr(39, sx, sy)
local h = coll.h * 8 - 8
while h >= 8 do
sy -= 8
h -= 8
spr(38, sx, sy)
end
if h > 0 then
-- todo haha super ugly and
-- hardcoded
sspr(6*8, 24 - h, 8, h, sx, sy - h)
end
end,
onusewheel = function(self)
if not self.direction and not self.close_timer then
sfx(7)
self.direction = -0.125
end
end,
}
-- door parts, only used as
-- markers
declare_tile{
class = decoractor,
sprite = 38,
enabled = false,
}
-- wooden bridge
declare_tile{
sprite = 47,
shape = box(0, 0.375, 1, 0.625),
}
-- spellbook
declare_tile{
class = mobactor,
sprite = 50,
shape = box(0.25, 0.25, 0.5, 0.5),
floating = true,
-- todo whoops, i guess this
-- is only automatic for decor
reset = function(self)
mobactor.reset(self)
self.enabled = true
end,
oncollide = function(self, actor, d)
if actor.is_player then
sfx(6)
add(progress.inventory, items.spellbook)
self.enabled = false
end
end
}
-- flurry
declare_tile{
class = mobactor,
sprite = 53,
shape = box(0.25, 0.25, 0.5, 0.5),
floating = true,
oncollide = function(self, actor, d)
if actor.is_player then
game:win()
end
end,
}
__gfx__
00000000c0000000000ddd0000000000000000000000000000000000000000000000000044440444000000000000000000000000000000000044444022242242
00000000ca0000000ddddd00c0000000000000000000000000000000000000000000000004444440000000000000000000000000000000004444444424224224
007007001ccc0000dddd0000ca000000000000000000000000000000000000000000000000000000000000000000000000000000000000004424424422424224
000770001accc000dddddddd1ccc0000c000000000000000001cc000000000000000000000000000000000000000000000000000000000002442242422422424
0007700001caca00dddddddd1accc0000ca000000ccca0000001cca0000000000080000000000000000000000000000000000000000000004224242242242422
00700700041cccc0dddd000001caca0001ccc00001cccc000001cccc000000000060002000000000000000000000000000000000000000002424222224242222
000000000117dd000ddddd00041cccc001accc00001accc00001accc000000000566006000000000000000000000000000000000000000002422422424224224
00000000022dddd0000ddd00011ddd00001caca0001ccac00001ccac000000005556655600000000000000000000000000000000000000002242242222422422
002dddd0002dddd0002dddd0002dddd0041cccc0004ccca000041cca00000000033333000333330003333300033333000bb33300033bb30003333b0000000000
0011cc000011cc000011cc000011cc00011dddd0002dddd000121ccc00000000330003303300033033000330bb0003303300033033000b30330003b000000000
011ccdc0011ccdc0011ccdc00111cd000011cc000012ddd00012dddd000000003003003330030033b003003330030033300b0033300300b33003003b00000000
21ccdd1c211ccdc0211ccdc0011ccdc00111cd000011cd000011cdd0000000003033303330333033b033303330bb30333033b033303330bb3033303300000000
1cc2dd1c11ccdd1c11ccdd1c111ccdc0011ccdc00111cd000111cd000000000003300030033000300bb0003003300030033000b0033000300330003000000000
1cc2ddc01cc2dd1c1cc2dd1c11ccdd1c111ccdc0011ccdc00111cdc0000000000000333000003330000033300000bb30000033b0000033300000333000000000
020000d000200d000002d00000200d0011ccdd1c11ccdd1c111ccdc0000000000003300000033000000bb0000003300000033000000330000003300000000000
2000000d00200d00000d200000200d000220dd0011c0dd1c11ccdd1c0000000000030000000b0000000300000003000000030000000300000003000000000000
044444404444422244444224444444440444044455555555056d6650056d665006760600055505000effffe00000000000000000555555554444422265000056
424422442444224404444440444400402424242426d666650566665005666650606007075050050502eeee20000000000000000066d666652444224407655670
22242444222424440000000004400400222022202226d66505d66d5005d66d5000700606005005050000000000000000000000006666d6652224244400766700
2222444422224444000000000040004000000000222266d5056d6650056d665007000060050000500022220000000000000000006d6666d522224444eeeeeeee
422422444224224400000000000000000000000042246d650566665005666650000600000005000000000000000000000000000066666d6542662d44ef2222fe
4244222442442224000000000000000000000000424426650566d6500566d6506760076055500550000000000ffffff000000000666d66654d66d66402ffff20
4244422242444222000000000000000000000000424442d505d6665005d666507070760650505505000000002e7eeee22ffffff26d66d6d556d666d502feef20
24444222244442220000000000000000000000002444422505666d50005555000060070700500505000000002e7eeee22e7eeee2666666655555555502feef20
00004440077777701cccccc00ff00000000000000000000600000000000000000000000000000000444444444444444400000000000000000002000000000020
000442447757557711c33cc09f9f0e00000000000000006000000000000000004000000000000004446666444466664450000000000000050004000020000400
00042444777777771cccc3c099fffe00000000000000060000000000000000004400000000000044462222644622226455000000000000550020420004204200
00444240775575771cc3ccc0fffffeee00000000090060000000000000000000040000000000004062244226622ee22605000000000000500044404200444000
004400000777777011cc33c00fffeff00000000000960000000000000000000000500000000005002244442222eeee2200600000000006002404440000044400
04400000000077001cccccc0000effff0000000004490000555555555555555500252200002252002222222222e88e2200262200002262000024020000240240
44000000000070001ffffff00000ffff00000000440f90006d666d666d666d660244442002444420022442200228822002444420024444200000400000400002
40000000000700001111111000000ff00000000044f0000066666666666666662444444224444442002222000022220024444442244444420000200002000000
66666666606566660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
60000000066550600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
60000000000605060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
60000000000650550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
66666666000066560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00006000000000650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00006000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00006000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200200
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002202200
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024e2400
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eee4400
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e414100
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004444e40
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000444400
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff4f00
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff0
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffff0
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004fff40
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f420
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004244420
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff442400
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff42400
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040400
12020000000032121212121212121212121212000000001212121212121212121212121212121212121202000000000000000022321212121212000012120000
00000000000002121200000012121212120200000000000032221212120200003232323232000000000000000000001212520000000000000000000012121212
12120000000000221212122232e23232121212808002021212121212121212121212121212121212121212000000000000000000002222322212000012320000
00000000020212121200000012121212121202020000000000002212121200000000000000000000000000000000021212120000000000000000000012121212
12120200000000001212220000620000221212121212121212121212121212121212121212121212121212420000000000000000000000000012000032000000
00000202121212121200000012121212121212120202020000000012121202020000000002020202000000e30000121212120000000000000000000212121212
12121200000000001222000000620000002212121212121212121232223222e22232121212121212121212000000000000000000000000000022000000000000
02021212121212121202000012121212121212121212120242424212121212120000000012121212020000000002121212120000000000000000001212121212
12121202000000001200000000720000000032121212121212123200000000620000222212121212121212424200000000000000000000000000000000000202
12121212121212121212000022121212121212121212121200000012121212120000000022121212120202020212121212125200000000000000001212121212
12121212000000021200000002020202000000221212121212120000000000620000000032121212121212000000000000000000000000000000000000021212
12121212121212121212000000121212121212121212122200000212121212120000000000121212121212121212121212121200000000000000001212121212
12121222000000121202000022121212020000002212121212220000000000620000000000221212121212024242000000000000000000000000000202121222
22323222121212121212000000121212121212121232220000001212121212220000000000141212121212121212121212121200000000000000001412121212
12123200000002121212000000223212120200000012121212000000000000620000000000001212121212120000000000000000000000000000002222322200
00000000221212121212020000121212121212222200000000021212121212000000000000001212e23222121212121212121200000000000000000012121212
12320000000012121212020000000022121200000032121212000000a20000620000000200002212121212120200000000000000000000000000000000000000
0000e300001212121212120000121212121222000000000002121212121232000000000000003222620000221412121212121252000000000000000014121212
12000000000212121212120000000000121202000000121212020000000000620000001200000012121212121200000000000000000000000000000000000000
00000000003212121212120000321212121200000000000212121212122200000000000000000000620000000022141212121212000000000000000000121212
12000000021212121212120200000000121212000000221212120000000000620000001200000012121212121252000000000000000000000000000000000000
00000000000012121212120000001212123200000000002232323222220000000000000000000000720000000000001212121212000000000000000000321212
12020000223212121212122200000002121212020000003222120200000000620000001202000012121212121212000000000000000000000000000000000000
00000000000012121212120200002212220000000200000000000000000000000000000000000000020202520000001412121212520000000000000000001212
12120000000022322232320000000012121212120000000000121202000000620000001212000032121212121212020000000000000000000000020200000000
00000000000012121212121200000012100000021202020000000000000000000000000000000002121212125200000012121212120000000000000000021212
1212020000000000000000000000021212121212000000001022223200e300720000831212000000121212121212120200000000000000000202121202020200
00000000000212121212121202000032000002121212120202000000000000000000000000000012121212121252000012121212125200000000530000121212
12121202020000000000000002021212121212120202000000000000000000020000121212020000121212121212121202028080800202021212121212121202
02020202021212121212121212020000020212121212121212020202020000008080800000000012121212121212520012121212121200000000f20002121212
12121212120202020202020212121212121212121212020202020202020202120202121212120202121212121212121212121212121212121212121212121212
12121212121212121212121212120202121212121212121212121212120202021212120202020212121212121212125212121212121252d2d2d2d2d212121212
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007700000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000005700000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000007500000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000550000777000007777000007777000000777005000777000000000
00000000000000000000000000000000000000000000000000000000000000000000000007770007777700077777700077777700007777700007777700000000
00000000000000000000000000000000000000000000000000000000000000000000000005770007775500055557700055557700077755700007775500000000
00000000000000000000000000000000000000000000000000000000000000000000000000770005777000007777700007777700077500500005777000000000
00000000000000000000000000000000000000000000000000000000000000000000000000770000577700077557700077557700077700000000577700000000
00000000000000000000000000000000000000000000000000000000000000000000000000770007777700077777700077777700057777700007777700000000
00000000000000000000000000000000000000000000000000000000000000000000000007777005777500057777770057777770005777500005777500000000
00000000000000000000000000000000000000000000000000000000000000000000000005555000555000005555550005555550000555000000555000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000070000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000070000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000070000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000777700000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000777700077700077700777000777007077700575500000000000
00000000000000000000000000000000000000000000000000000000000000000000000000007555700755570755507555707555705755570070000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000007000700777750577007000507777500700070070000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000007000700755500055707000707555000700070070000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000005777570577700777505777505777000700070057700000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000555050055500555000555000555000500050005500000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__gff__
000000000000000000000000000080800000000000000000000000000000000080804040a080008000008000008080800000000000000000000080800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
21212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121222300003a0000222321212121212121212121212121212121
2121212121212121212121212121212121212121212121212121212121212121212121212121212121212222222222222221212123232222222322222221212121222223232223222222222222212121222223222221212121212121212121212121212223222200000000000000000022222121212121212121212121212121
2121212121212121212121212121212121212121212121212121212121212121212121212121212122220000000000000022212200000000000000000022232321000000000000000000000000232121010000000023212121212121212121212121220000000000000000000000000000002223222221212121212121212121
2121212121212121212121212121212121212121212121212121232223223a22232222212121212100000000000000000000210000000000000000000000000021000000000000000000000000002121000000000000222121212121212121212121000000000000000000000000000000000000000022222121212121212121
2121222322222121212121212121212121212121212121232222000000000000000000222223212101000000000000000000210000000000000020200000000022000000000000002a20000000002121202000000000002121212121212121212123000000202000000000000000000020202020242424242121212121212121
22220000000022222321212121222223222121212323220001000000000000000000000000002221000000000000202000002200200000000000222300000000000000000000002a0021000000002121212100000000002221212121212121212100000020212120202020202020202021212121000000002221212121212121
010000000000000000222322220000000023222200000000000000000000000000000000000000212020200000002222000000002200000000000000000000000000000000002a000021200000002121212100000000000021212121212121212100000022232121212121212121212323232121202024242421212121212121
0000002020000000000000000000000000000000000020202020202020202020202020000000002121212100000000000000002000000000000000000000000020200000002000000021210000002221212120000000000023212121212121212100000000002321212121212323230000002222222200000021212121212121
2020202121202000000000000000000020202020202021212121212121212121212121200000002121212300000000000000002200000000000000000000000023220000002300000021210000000021212121000000000000222121212121212100320000000023232323230000000000000000000000002021212121212121
21212121212121202020202a2a2a2a2a212121212121212121212121212121212121212100000021212100000000000000002000000000000000000000000000000000000000000000212100000000212121210000000000000021212121212121002f0000000000000000000000000020000000000000202121212121212121
21212121212121212121210000000000212121212121212121212121212121212121212120000021212100000000000000002300000000000000000000000000000000000000000000212100000000212121212a2a2a2a2a2a2a2121212121212120212020080808080808080808082021000000002020212121212121212121
2121212121232322212121000000000021212121212121212121212121212121212121212100002321210000000000000000000000000000000000000000000000000000000000000022210000000021212121000000000000002222222322232121212121212121212121212121212122000020202121212121212121212121
2121212222000000222322000000202021212121212121212121212121212121212121212100000021210000000000000000000000000000000000000000000000000000000000000000210000000021212121000000000000000000000000002121212121212121212122232222222200002021212121212121212121212121
2121230000003800000000000020212121212121212121212121212121212121212121212120000021210000000000000000000000000000000000000000000000000000000000000000212000000021212121000000000000000000000000002121212121212122222200000000000000202121212121212121212121212121
212108080820212020202020202121212121212121212121212121212121212121212121212120202121000000000000000000000000000000000000000000000000000000000000000021210000002121212100000000000000002a202020202121212121222200000000002020202020212121212121212121212121212121
2121212121212121212121212121212121212121212121212121212121212121212121212121212121230000000000000000000000000000000000000000000000000000000000000000212100000021212121000000000000002a08212121212121212223000000000020202121212121212121212121212121212121212121
21212121212121212121212121212121212121212121212121212121212121212121212121212121210000000000000000000000000000000000000000000000000000000000000000002121000000212121212a2a2a2a2a2a2a0821212121212121220000000000202021212121212223222121212121212121212222222221
2121212122222221212122222322212121212121212121212323232223212121212121212121212121000000000000000000000000000000000000000000000000000000000000000008212100000021212121000000000000002121212121212121000000000020212121212222230000002223222323222223220000000021
21222322000000232e2200000000222223212121212121210100000000222121212121212121212121000000000000000000000000000000000000000000000000000000000000000021212100000022212121000000000000002121212121212123000000000022222322220000000000000000000000000000000000000022
220000000000000026000000000000000022222e23212121000000000000222e23222e222221212121000000000000000000000000000000000000000000000000080808000000000821212100000000212121080000000000002121212121212200000020000000000000000000000020000000000000000000000820000000
0100003e00000000260000000000000000000026002221212000000000000026000026000023212121000008080000000000000000000000000000000000000808212121080000082121212120000000212121210000000000002121212121210100002021202008080000000008082021202008080000000008082121200000
00000000000000002700000000000000000000260000212121200000003e0026000026000000222121003821210800080808000000000000080000080008082121212121210808212121212121000000212121210000380000082121212121210000202121212121210808080821212121212121210808080821212121212000
2020202020000020202020200820082020000027000023212121200000000026000027000000002121082121212108212121080808080808210808210821212121212121212121212121212121002020212121210820212008212121212121212020212121212121212121212121212121212121212121212121212121212120
2121212121202021212121202020202121202020000000212121212020202026202020202000002121212121212121212121212121212121212121212121212121212121212121212121212121202121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121
212121212121212123222323222223222e22222200000021212121212121212621212121220000212121212121212121212e21212121212121212121212e212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121
2121212122232322000000000000000026000000000000212121212121212126212121230000202121212121222222232226222121212121212121212226222121222223222223232222212121212121212121212222232222232322222223222321212121212121212121212121212121212121232341212121212121212121
21212222000000000000000000003e0026000000000000212121212121212126212121000020212122222323000000000026002222212121212123220026002223000000000000000000212121212121212121220000000000000000000000000023212121212121212121212121212123232323000000232321212121212121
2123000000000000000000000000000027000000000020212121212122222226212122000021212101000000000000000026000000222323222200000026000000000000000000000000232121212121212123000000000000000000000000000000212121212121212121212121212101000000000000000021212121212121
2100000000000000202020202020202020200000002021212121212300000027212100000022222200000000000000000026000000000000000000000026000000000000000000200000002121212121212200000000202008080808080000080808212121212121212222232321212100000000000000000041212121212121
210000000020202021212121212121212121200000232321212121080808202121212020000000002000000000000000002700000000000000000000002738000000000000002a210000002121212121210000000020212121212121210000212121212121212122230000000022212125000000000000000000232121212121
2100000020212121212121212121212121212100000000212121212121212121212121212020000021000000242424000020202020202000000000002020210000000000000000210000002221212121210000242421212121212121210000222121212121212200000000000000232121000000000000000000002121212121
2100000022222121212121212121212121212100003e00212121212121212121212121212121202021200000000000000022222121212120202000002121230000000000000000212000000021212121210000000022232221212121210000002121212121220000000000000000002121000000000000000000004121212121
__sfx__
010200000c0700c070110701307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
010c00001f3751c375233752330523305233050030500305003050030500305003050030500305003050030500305003050030500305003050030500305003050030500305003050030500305003050030500305
0108000017070170701707017070110701107011070110700e0700c0700e0710e0710e0710e0710e0710e07100000000000000000000000000000000000000000000000000000000000000000000000000000000
01020000186111861118621186211d631216312364126641296412d64130641346413764137641376413764137641376413764137641296412964124641246411d6411d641186311863111621116210c6110c611
01100000136550065000655006050c605006050060500605006050060500605006050060500605006050060500605006050060500605006050060500605006050060500605006050060500605006050060500605
01040000115741a504135741557415570005040050400504005040050400504005040050400504005040050400504005040050400504005040050400504005040050400504005040050400504005040050400504
0108000028075260752d0751700513005040050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005
010c0000246102b6102f61000616246102b6102f61000616006060060600606006060060600606006060060600606006060060600606006060060600606006060060600606006060060600606006060060600606
010c00000e774107740e7741377413770137701377013770007040070400704007040070400704007040070400704007040070400704007040070400704007040070400704007040070400704007040070400704
010c0000217701c7001d7701f770217701a70021770007001f7702177023770217002477024770247702477023700237002370023700237002370023700237000070000700007000070000700007000070000700
0110000005070050700507005070070700707005070050700b0700b0700b0700b0700907009070090700907005070050700507005070040700407002070020700707007070050700507002070020700007000070
011000001c0021c0021c0521c0521c0021c0021c0521c052000020000200002000021f0521f0521f0521f05200002000021d0521d0521f0521f05219002180021f0521f0521f0521d05218052180521800218002
01100000050700507005000050000407004070050000500007070070700707007070187430900007000070000907009070040700407005070050700200002000040700407004070040701a743187430000000000
01100000077430670305703057030c743077030070300703057030570305743057030c743057030b70300703077430670305703057030c743077030070300703057030570305743007430c743057030b70300703
01100000180521a0521f0521f0021f0521f0021f0521f0521f0021f0021f0521f0521d0521d0521f0521c05218052180021805218002180521a0521d0521a0521805218052180520e0021a0521a0521a05205002
011000000707007070070700707007070070700707007070050700507005070050700407004070020700207007070070700907009070050700507007070070700507005070050700507002070020700207002070
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
010c00003b0740000429074000043b0740000429074000043b0740000429074000040000400004000040000400004000040000400004000040000400004000040000400004000040000400004000040000400004
0106000013770107700c7700c7700c7700c7751370013700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
011000001103500005000050000513035110051103500005150301503500005000051303013035000050000510030100301003010035000050000500005000051003010030100301003500005000050000500005
011000001103500000000000000013035000001103500000150301503500000000001303013035000000000010035100351003510035130351303513035130351703517035170351703511035110351103511035
011000001703511035130350000017035110351303500000100301003500000000001003010035000000000017035110351303500000170351103513035000001003010035000000000010030100350000000000
011000001703511035130350000018035150351703500000170351103513035000001803515035170350000018035150351303511035170351303517035130051803515035130351103517035130351703513005
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
011000001c770007002170021700217702177021770007001d7001d7001f7001c7001d7701f7001f7701f7001d7701d7001a7701a7701a7001a7001a7001a70021770007001d770007001c7701c7700070000700
011000001a770007001c770007001d7701d77000700007001f7701f7001c770007001f7701c7001d770007001f7701f7701f7701f7701c7001c7000070000700187701a770187701877018770187701877018770
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__music__
01 0a424344
00 0c424d44
00 0c420d44
00 0a4b0d44
00 0f4b0d44
00 0f4e0d44
02 0c4e0d44
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
01 14424344
00 15424344
00 14424344
00 16424344
02 17424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
01 1e424344
04 1f424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344
00 41424344