-- title: TileMan
-- author: ArchaicVirus
-- desc: Generates infinite procedural terrain with Auto-Map
-- site: https://github.com/archaicvirus
-- license: MIT License
-- version: 3.0
-- script: lua
--load in generation settings defs
-- ore props:
-- color_keys - transparent color (despite plural name)
-- sprite_id - highest sprite index for this ore
-- biome_id - biome this can occur in (only one)
-- map_cols - palette indices for drawing tile on world map
ores = {
[1] = {
name = 'Iron',
offset = 15000,
id = 3,
scale = 0.011,
min = 15,
max = 16,
bmin = 45,
bmax = 100,
color_keys = 4,
tile_id = 162,
sprite_id = 178,
biome_id = 2,
map_cols = {8,11,12,13,14,15},
},
[2] = {
name = 'Copper',
offset = 10000,
id = 4,
scale = 0.013,
min = 15,
max = 16,
bmin = 33,
bmax = 40,
color_keys = 1,
tile_id = 161,
sprite_id = 177,
biome_id = 2,
map_cols = {2,3,4,15},
},
[3] = {
name = 'Coal',
offset = 50000,
id = 6,
scale = 0.020,
min = 14,
max = 17,
bmin = 35,
bmax = 75,
color_keys = 4,
tile_id = 163,
sprite_id = 179,
biome_id = 3,
map_cols = {0,14,15},
},
[4] = {
name = 'Stone',
offset = 22500,
id = 5,
scale = 0.018,
min = 15,
max = 16,
bmin = 20,
bmax = 70,
color_keys = 4,
tile_id = 160,
sprite_id = 176,
biome_id = 1,
map_cols = {12,13,14,15},
},
}
-- biome props:
-- tree_id - top-left sprite index for tree
-- color_key - transparent color for tree/clutter
biomes = {
[1] = {
name = 'Desert',
tile_id_offset = 0,
min = 20,
max = 30,
t_min = 21,
t_max = 25,
tree_id = 193,
tree_density = 0.05,
color_key = 0,
map_col = 4,
clutter = 0.02
},
[2] = {
name = 'Prairie',
tile_id_offset = 16,
min = 30,
max = 45,
t_min = 33,
t_max = 40,
tree_id = 196,
tree_density = 0.05,
color_key = 1,
map_col = 6,
clutter = 0.08
},
[3] = {
name = 'Forest',
tile_id_offset = 32,
min = 45,
max = 101,
t_min = 47,
t_max = 99,
tree_id = 199,
tree_density = 0.05,
color_key = 1,
map_col = 7,
clutter = 0.05
},
}
TileManager = {}
TileManager.__index = TileManager
auto_map = {
--N E S W
--tiles surrounding land
--0 is land, 1 is water or other biome
['1000'] = {sprite_id = 1, rot = 0},
['0100'] = {sprite_id = 1, rot = 1},
['0010'] = {sprite_id = 1, rot = 2},
['0001'] = {sprite_id = 1, rot = 3},
['1100'] = {sprite_id = 2, rot = 1},
['0110'] = {sprite_id = 2, rot = 2},
['0011'] = {sprite_id = 2, rot = 3},
['1001'] = {sprite_id = 2, rot = 0},
['1101'] = {sprite_id = 3, rot = 0},
['1110'] = {sprite_id = 3, rot = 1},
['0111'] = {sprite_id = 3, rot = 2},
['1011'] = {sprite_id = 3, rot = 3},
['0101'] = {sprite_id = 4, rot = 0},
['1010'] = {sprite_id = 4, rot = 1},
['1111'] = {sprite_id = 0, rot = 0},
}
function ore_sample(x, y, tile)
local biome = tile.biome
for i = 1, #ores do
local scale = ores[i].scale -- ((4 - biome)/100)
local noise = (simplex.Noise2D(x * scale + ((ores[i].offset * biome) * scale) + offset * scale, (y * scale) + ((ores[i].offset * biome) * scale) + (offset * scale)) / 2 + 0.5) * 16
if noise >= ores[i].min and noise <= ores[i].max and tile.noise >= ores[i].bmin and tile.noise <= ores[i].bmax then return i end
end
return false
end
function AutoMap(x, y)
local tile = TileMan.tiles[y][x]
TileMan.tiles[y][x].visited = true
--Here, 'adj' is the north, east, south, and west 'neighboring' tiles (in local space)
local adj = {
[1] = {x = 0, y = -1},
[2] = {x = 1, y = 0},
[3] = {x = 0, y = 1},
[4] = {x = -1, y = 0},
}
local key = ''
for i = 1, 4 do
--Grab the neighbor tile
local near = TileMan.tiles[y + adj[i].y][x + adj[i].x]
--Determine if neighbor is a '0' or '1', meaning 0 is land, 1 is water or a different biome
if not near.is_land or near.biome < tile.biome then
key = key .. '1'
TileMan.tiles[y][x].border_col = biomes[near.biome].map_col
else
key = key .. '0'
end
end
--Try to index the key we just created
local new_tile = auto_map[key]
--If key exists, then valid config detected, so set tile to the returned value, otherwise return
if not new_tile then return end
TileMan.tiles[y][x].sprite_id = new_tile.sprite_id + 11 + biomes[tile.biome].tile_id_offset
TileMan.tiles[y][x].is_border = true
--TileMan.tiles[y][x].is_tree = false
TileMan.tiles[y][x].ore = false
TileMan.tiles[y][x].flip = 0
TileMan.tiles[y][x].rot = new_tile.rot
end
function TileManager.new()
--Creates a TileManager instance - cache's all the generated terrain in memory
--Here, using __index metemethod, we can automatically trigger the create_tile
--method whenever a non-existent value is indexed
local self = setmetatable({}, TileManager)
local tile_mt = {
__index = function(row, x)
--Here's where the magic happens, in create_tile
local tile = TileManager.create_tile(x, row.y)
row[x] = tile
return tile
end
}
local tiles_mt = {
__index = function(tiles, y)
local row = setmetatable({y = y}, tile_mt)
tiles[y] = row
return row
end
}
self.tiles = setmetatable({}, tiles_mt)
return self
end
function TileManager.create_tile(x, y)
--Replace with your own function, this gets called once whenever a 'new' tile is indexed
local scale = 0.0005
local scale2 = 0.025
--Here we sample 2 noise values and blend them together
local base_noise = (simplex.Noise2D(x * scale + offset * scale, (y * scale) + (offset * scale)) / 2 + 0.5) * 100
local addl_noise = (simplex.Noise2D(x * scale2 + offset * scale2, (y * scale2) + (offset * scale2))) * 100
--Now base_noise is used to determine biome and land/water
--base_noise = ((base_noise * 3) + addl_noise) / 4
base_noise = lerp(base_noise, addl_noise, 0.05)
local tile = {
noise = base_noise,
is_land = base_noise >= 20 and true or false,
biome = 1,
is_border = false,
is_tree = false,
visited = false,
b_visited = false,
rot = 0,
offset = {x = math.random(1, 2), y = math.random(1, 4)},
}
for i = 1, #biomes do
if base_noise > biomes[i].min and base_noise < biomes[i].max then
tile.biome = i
break
end
end
tile.flip = math.random() > 0.5 and 1 or 0
--If base_noise value is high enough, then try to generate an ore type
tile.ore = tile.is_land and base_noise > 21 and ore_sample(x, y, tile) or false
if not tile.is_land then
--Water tile
tile.color = floor(math.random(2)) + 8
tile.sprite_id = WATER_SPRITE
tile.rot = floor(math.random(0,3))
else
tile.sprite_id = biomes[tile.biome].tile_id_offset
tile.color = biomes[tile.biome].map_col
end
--If ore-generation was successful, then set sprite_id and color
if tile.ore then
tile.color = ores[tile.ore].map_cols[floor(math.random(#ores[tile.ore].map_cols))]
tile.rot = math.random(4) % 4
end
if tile.is_land and not tile.ore then
--Generate clutter based on biome clutter scale, ex grass, rocks, trees, etc
scale = 0.001
local tree = base_noise
--local tree = (simplex.Noise2D((x * scale) + (offset * scale), (y * scale) + (offset * scale)) / 2 + 0.5) * 100
local tmin = biomes[tile.biome].t_min
local tmax = biomes[tile.biome].t_max
--local flip = math.random(0, 1)
--trace('Tspawn try: ' .. biomes[tile.biome].name .. ', tmin: ' .. tmin .. ", tmax" .. tmax .. ', tnoise: ' .. tree .. ', tflip = ' .. flip)
if tree >= biomes[tile.biome].t_min and tree <= biomes[tile.biome].t_max and math.random(0, 100) < (biomes[tile.biome].tree_density * 100) then
--trace('trying to spawn a tree')
tile.is_tree = true
--tile.flip = flip
elseif math.random(100) <= (biomes[tile.biome].clutter * 100) then
local rand = floor(math.random(10))
tile.sprite_id = biomes[tile.biome].tile_id_offset + rand
--tile.flip = math.random(1) > 0.5 and 1 or 0
if rand == 1 then
tile.rot = math.random(4) % 4
end
else
tile.rot = math.random(4) % 4
end
end
return tile
end
function TileManager:set_tile(x, y, tile_id)
local tile = self.tiles[y][x]
tile_id = tile_id or biomes[tile.biome].tile_id_offset
if tile.is_land and not tile.ore and not tile.is_border then
self.tiles[y][x].sprite_id = tile_id
self.tiles[y][x].is_tree = false
end
if tile.ore then
self.tiles[y][x].ore = false
self.tiles[y][x].is_tree = false
self.tiles[y][x].sprite_id = biomes[tile.biome].tile_id_offset
end
end
function TileManager:draw_terrain(player, screenWidth, screenHeight)
local cameraTopLeftX = player.x - 116
local cameraTopLeftY = player.y - 64
local subTileX = cameraTopLeftX % 8
local subTileY = cameraTopLeftY % 8
local startX = floor(cameraTopLeftX / 8)
local startY = floor(cameraTopLeftY / 8)
for screenY = 1, screenHeight do
for screenX = 1, screenWidth do
local worldX = startX + screenX
local worldY = startY + screenY
local tile = self.tiles[worldY][worldX]
local sx = (screenX - 1) * 8 - subTileX
local sy = (screenY - 1) * 8 - subTileY
--Here, AutoMap is called once per tile during draw
--AutoMap is what sets the 'border' or edge tiles
if not tile.visited and tile.is_land then AutoMap(worldX, worldY) end
if tile.ore then
rect(sx, sy, 8, 8, biomes[tile.biome].map_col)
sspr(ores[tile.ore].tile_id, sx, sy, ores[tile.ore].color_keys, 1, 0, tile.rot)
elseif not tile.is_border then
local id, rot, flip = tile.sprite_id, tile.rot, tile.flip
if not tile.is_land then
--for water tiles only
if worldX % 2 == 1 and worldY % 2 == 1 then
flip = 3 -- Both horizontal and vertical flip
elseif worldX % 2 == 1 then
flip = 1 -- Horizontal flip
elseif worldY % 2 == 1 then
flip = 2 -- Vertical flip
end
--procedural water sprite id = 224
sspr(224, sx, sy, 0, 1, flip, rot)
else
--else is land
rect(sx, sy, 8, 8, biomes[tile.biome].map_col)
sspr(biomes[tile.biome].tile_id_offset, sx, sy, biomes[tile.biome].map_col, 1, 0, tile.rot)
if id ~= biomes[tile.biome].tile_id_offset then
sspr(id, sx, sy, biomes[tile.biome].map_col, 1, flip)
end
end
else
if tile.biome == 1 then
local flip = 0
if worldX % 2 == 1 and worldY % 2 == 1 then
flip = 3 -- Both horizontal and vertical flip
elseif worldX % 2 == 1 then
flip = 1 -- Horizontal flip
elseif worldY % 2 == 1 then
flip = 2 -- Vertical flip
end
sspr(224, sx, sy, -1, 1, flip)
sspr(tile.sprite_id, sx, sy, 0, 1, 0, tile.rot)
else
sspr(tile.sprite_id, sx, sy, -1, 1, 0, tile.rot)
end
--if tile.ore then sspr(ores[tile.ore].tile_id, sx, sy, ores[tile.ore].color_keys, 1, tile.flip, tile.rot) end
end
--rectb(sx, sy, 8, 8, 4)
--sspr(340, sx, sy, -1)
end
end
end
function TileManager:draw_clutter(player, screenWidth, screenHeight)
local cameraTopLeftX = player.x - 116
local cameraTopLeftY = player.y - 64
local subTileX = cameraTopLeftX % 8
local subTileY = cameraTopLeftY % 8
local startX = floor(cameraTopLeftX / 8)
local startY = floor(cameraTopLeftY / 8)
for screenY = 1, screenHeight do
for screenX = 1, screenWidth do
local worldX = startX + screenX
local worldY = startY + screenY
local tile = self.tiles[worldY][worldX]
local sx = (screenX - 1) * 8 - subTileX
local sy = (screenY - 1) * 8 - subTileY
--Here, the 19, 25, and 41 are just randomly chosen biome tiles
--picked to spawn trees on, but you can use any tiles to limit trees to certain biomes
if tile.is_tree then
--trace('drawing tree')
sspr(biomes[tile.biome].tree_id, sx - 9 + tile.offset.x, sy - 27 + tile.offset.y, biomes[tile.biome].color_key, 1, tile.flip, 0, 3, 4)
--rectb(sx, sy, 8,8,2)
end
-- if tile.sprite_id == 19 then
-- sspr(201, sx - 9 + tile.offset.x, sy - 28 + tile.offset.y, 0, 1, tile.flip, 0, 3, 4)
-- elseif tile.sprite_id == 25 then
-- sspr(198, sx - 6 + tile.offset.x, sy - 28 + tile.offset.y, 0, 1, tile.flip, 0, 3, 4)
-- elseif tile.sprite_id == 41 then
-- sspr(201, sx - 8 + tile.offset.x, sy - 28 + tile.offset.y, 0, 1, tile.flip, 0, 3, 4)
-- end
end
end
end
function TileManager:draw_worldmap(player, x, y, width, height, center)
--Simple pixel map, using the tile's assigned biome in - biome[i].map_col
width, height = width or 240, height or 136
x, y = x or 120 - (width/2), y or 68 - (height/2)
if center then
x = (240/2) - (width/2)
y = (136/2) - (height/2)
end
local map_x, map_y = x or 120 - (width/2) + 1, y or 68 - (height/2) + 2
local startX, startY = floor(player.x/8 - (width/2) + 1), floor(player.y/8 - (height/2) + 2)
local biome_col = biomes[self.tiles[startY][startX].biome].map_col
local skipped = 0
rectb(map_x - 1, map_y - 1, width + 2, height + 2, 9)
rect(map_x, map_y, width, height, biome_col)
--rect(map_x, map_y, width, height, biome_col)
local biome = self.tiles[startY][startX].biome
start_col = biomes[biome].map_col
for y = 0, height - 1 do
if y == 0 then
end
for x = 0, width - 1 do
local tile = self.tiles[startY + y - 1][startX + x - 1]
if tile.color ~= start_col or tile.ore or tile.is_tree or not tile.is_land or not tile.biome == biome then
--*** For optional fog of war effect ***
if rawget(self.tiles, startY + y - 1) and rawget(self.tiles[startY + y - 1], startX + x - 1) then
-- local tile = self.tiles[startY + y - 1][startX + x - 1]
-- if self.tiles[startY + y - 1][startX + x - 1].ore then
pix(x + map_x, y + map_y, tile.is_tree and 6 or tile.color)
end
--else
--skipped = skipped + 1
end
end
end
--trace('skipped drawing ' .. skipped .. ' pixels')
--trace('start color: ' .. biome_col)
end
function TileManager:save_worldmap(player, width, height)
--Simple pixel map, using the tile's assigned biome in - biome[i].map_col
width, height = width or 240, height or 136
x, y = 0, 0
local map_x, map_y = x or 120 - (width/2) + 1, y or 68 - (height/2) + 2
local startX, startY = floor(player.x/8 - (width/2) + 1), floor(player.y/8 - (height/2) + 2)
local biome_col = biomes[self.tiles[startY][startX].biome].map_col
local skipped = 0
rectb(map_x - 1, map_y - 1, width + 2, height + 2, 9)
rect(map_x, map_y, width, height, biome_col)
--rect(map_x, map_y, width, height, biome_col)
for y = 0, height - 1 do
if y == 0 then
local biome = self.tiles[startY + y - 1][startX + x - 1].biome
start_col = biomes[biome].map_col
end
for x = 0, width - 1 do
local tile = self.tiles[startY + y - 1][startX + x - 1]
pix(x + map_x, y + map_y, tile.is_tree and 6 or tile.color)
end
end
end
local math = math
local table = table
local tonumber = tonumber
local ipairs = ipairs
local error = error
simplex = {}
simplex.DIR_X = 0
simplex.DIR_Y = 1
simplex.DIR_Z = 2
simplex.DIR_W = 3
simplex.internalCache = false
local Gradients3D = {{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}}
local Gradients4D = {{0,1,1,1}, {0,1,1,-1}, {0,1,-1,1}, {0,1,-1,-1},
{0,-1,1,1}, {0,-1,1,-1}, {0,-1,-1,1}, {0,-1,-1,-1},
{1,0,1,1}, {1,0,1,-1}, {1,0,-1,1}, {1,0,-1,-1},
{-1,0,1,1}, {-1,0,1,-1}, {-1,0,-1,1}, {-1,0,-1,-1},
{1,1,0,1}, {1,1,0,-1}, {1,-1,0,1}, {1,-1,0,-1},
{-1,1,0,1}, {-1,1,0,-1}, {-1,-1,0,1}, {-1,-1,0,-1},
{1,1,1,0}, {1,1,-1,0}, {1,-1,1,0}, {1,-1,-1,0},
{-1,1,1,0}, {-1,1,-1,0}, {-1,-1,1,0}, {-1,-1,-1,0}}
local p = {151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
-- To remove the need for index wrapping, double the permutation table length
for i=1,#p do
p[i-1] = p[i]
p[i] = nil
end
for i=1,#Gradients3D do
Gradients3D[i-1] = Gradients3D[i]
Gradients3D[i] = nil
end
for i=1,#Gradients4D do
Gradients4D[i-1] = Gradients4D[i]
Gradients4D[i] = nil
end
local perm = {}
for i=0,255 do
perm[i] = p[i]
perm[i+256] = p[i]
end
-- A lookup table to traverse the sim around a given point in 4D.
-- Details can be found where this table is used, in the 4D noise method.
local sim = {
{0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0},
{0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0},
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
{1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0},
{1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0},
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
{2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0},
{2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}
local function Dot2D(tbl, x, y)
return tbl[1]*x + tbl[2]*y;
end
local function Dot3D(tbl, x, y, z)
return tbl[1]*x + tbl[2]*y + tbl[3]*z
end
local function Dot4D( tbl, x,y,z,w)
return tbl[1]*x + tbl[2]*y + tbl[3]*z + tbl[3]*w;
end
local Prev2D = {}
function simplex.seed(seed)
seed = seed or tstamp()
math.randomseed(seed * seed)
for i = 1, 256 do
p[i] = math.floor(math.random()*256)
end
end
-- 2D simplex noise
function simplex.Noise2D(xin, yin)
if simplex.internalCache and Prev2D[xin] and Prev2D[xin][yin] then return Prev2D[xin][yin] end
local n0, n1, n2; -- Noise contributions from the three corners
-- Skew the input space to determine which simplex cell we're in
local F2 = 0.5*(math.sqrt(3.0)-1.0);
local s = (xin+yin)*F2; -- Hairy factor for 2D
local i = math.floor(xin+s);
local j = math.floor(yin+s);
local G2 = (3.0-math.sqrt(3.0))/6.0;
local t = (i+j)*G2;
local X0 = i-t; -- Unskew the cell origin back to (x,y) space
local Y0 = j-t;
local x0 = xin-X0; -- The x,y distances from the cell origin
local y0 = yin-Y0;
local i1, j1; -- Offsets for second (middle) corner of simplex in (i,j) coords
if(x0>y0) then
i1=1
j1=0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
else
i1=0
j1=1 -- upper triangle, YX order: (0,0)->(0,1)->(1,1)
end
local x1 = x0 - i1 + G2; -- Offsets for middle corner in (x,y) unskewed coords
local y1 = y0 - j1 + G2;
local x2 = x0 - 1.0 + 2.0 * G2; -- Offsets for last corner in (x,y) unskewed coords
local y2 = y0 - 1.0 + 2.0 * G2;
-- Work out the hashed gradient indices of the three simplex corners
local ii = i & 255
local jj = j & 255
local gi0 = perm[ii+perm[jj]] % 12;
local gi1 = perm[ii+i1+perm[jj+j1]] % 12;
local gi2 = perm[ii+1+perm[jj+1]] % 12;
-- Calculate the contribution from the three corners
local t0 = 0.5 - x0*x0-y0*y0;
if t0<0 then
n0 = 0.0;
else
t0 = t0 * t0
n0 = t0 * t0 * Dot2D(Gradients3D[gi0], x0, y0);
end
local t1 = 0.5 - x1*x1-y1*y1;
if (t1<0) then
n1 = 0.0;
else
t1 = t1*t1
n1 = t1 * t1 * Dot2D(Gradients3D[gi1], x1, y1);
end
local t2 = 0.5 - x2*x2-y2*y2;
if (t2<0) then
n2 = 0.0;
else
t2 = t2*t2
n2 = t2 * t2 * Dot2D(Gradients3D[gi2], x2, y2);
end
local retval = 70.0 * (n0 + n1 + n2)
if simplex.internalCache then
if not Prev2D[xin] then Prev2D[xin] = {} end
Prev2D[xin][yin] = retval
end
return retval;
end
TileMan = TileManager.new()
t = 0
m = {x = 0, y = 0, l = false}
last_time = 0
fps = 60
player = {x = -1000, y = 0}
sspr = spr
floor = math.floor
--toggle to show world-map
show_map = false
--toggle to show debug info
debug = true
--help menu
show_help = true
help = {
[1] = 'SHIFT - Inspect tile (debug mode only)',
[2] = 'TAB - Toggle debug mode',
[3] = 'M - Toggle world map view',
[4] = 'H - Toggle this menu',
}
water_anim = 0
dir = 1
--For a SET seed
math.randomseed(666)
--For RANDOM seed each re-load
-- math.randomseed(tstamp())
offset = math.random(100000, 500000)
simplex.seed()
function get_sprite_pixel(sprite_id, x, y)
local byte = peek(0x04000 + sprite_id * 32 + y * 4 + math.floor(x / 2))
return x % 2 == 0 and byte % 16 or byte // 16
end
-- Function to set a pixel color in a sprite
-- Arguments: sprite_id (0-511), x (0-7), y (0-7), color (palette index 0-15)
function set_sprite_pixel(sprite_id, x, y, color)
local addr = 0x04000 + sprite_id * 32 + y * 4 + math.floor(x / 2)
local byte = peek(addr)
if x % 2 == 0 then poke(addr, (byte - byte % 16) + color) else poke(addr, (color * 16) + byte % 16) end
end
--from wiki, linear interpolation
function lerp(a,b,mu)
return a*(1-mu)+b*mu
end
-- Set the size of the tiling texture
local num_colors = 3
local start_color = 8
local tileSize = 8
local tileCount = 1
-- Set the water effect parameters
local amplitude = num_colors
local frequency = 0.22
local speed = 0.002
-- Function to update the water effect
function update_water_effect(time)
for sprite_id = 0, (tileCount * tileCount) - 1 do
for y = 0, tileSize - 1 do
for x = 0, tileSize - 1 do
-- Get world coords for the current pixel
local worldX = (sprite_id % tileCount) * tileSize + x
local worldY = math.floor(sprite_id / tileCount) * tileSize + y
-- Modulo for tiling texture
local tileX = worldX % (tileSize * tileCount)
local tileY = worldY % (tileSize * tileCount)
-- Calculate the noise value using world coordinates and time
local noiseValue = simplex.Noise2D(tileX * frequency, (tileY + time * speed) * frequency)
-- Convert the noise value to a pixel color (palette index 0-15)
local color = math.floor(((noiseValue + 1) / 2) * amplitude) + start_color
-- Set the pixel color in the sprite
set_sprite_pixel(224, x, y, color)
end
end
end
end
function get_screen_cell(mouse_x, mouse_y)
local cam_x, cam_y = 116 - player.x, 64 - player.y
local mx = floor(cam_x) % 8
local my = floor(cam_y) % 8
return mouse_x - ((mouse_x - mx) % 8), mouse_y - ((mouse_y - my) % 8)
end
function get_world_cell(mouse_x, mouse_y)
local cam_x = player.x - 116
local cam_y = player.y - 64
local sub_tile_x = cam_x % 8
local sub_tile_y = cam_y % 8
local sx = floor((mouse_x + sub_tile_x) / 8)
local sy = floor((mouse_y + sub_tile_y) / 8)
local wx = floor(cam_x / 8) + sx + 1
local wy = floor(cam_y / 8) + sy + 1
return TileMan.tiles[wy][wx], wx, wy
end
function clamp(value, min, max)
return math.min(math.max(min, value), max)
end
function draw_debug(data, x, y)
if debug then
local width = 4
local height = #data * 7
for i = 1, #data do
local length = print(data[i], 2, -10, 2, false, 1, true)
if length > width then width = length + 4 end
end
x, y = clamp(x, 0, 240 - width), clamp(y, 0, 136 - height)
rectb(x, y, width, height, 10)
rect(x + 1, y + 1, width -2, height - 2, 8)
for i = 1, #data do
print(data[i], x + 2, i*6 - 4 + y, 11, false, 1, true)
end
end
end
function draw_tile_widget(x, y)
local mx, my = mouse()
local tile, wx, wy = get_world_cell(mx, my)
local sx, sy = get_screen_cell(x, y)
local type = tile.ore and ores[tile.ore].name or tile.is_land and 'Land' or 'Water'
local biome = tile.is_land and biomes[tile.biome].name or 'Ocean'
if tile.is_tree then
rectb(sx + tile.offset.x - 9, sy + tile.offset.y - 26, 24, 32, 4)
end
local info = {
'Sprite: ' .. (tile.ore and tostring(ores[tile.ore].tile_id) or tile.is_land and tostring(tile.sprite_id) or 224),
'Type: ' .. type,
'Biome: ' .. biome,
'Coords: ' .. tostring(wx) .. ',' .. tostring(wy),
}
if tile.is_tree then info[4] = 'Tree' end
draw_text_window(info, x, y)
end
function draw_text_window(data, x, y, fg, bg, text_color)
fg, bg, text = fg or 9, bg or 8, text_color or 4
local width = 0
local height = #data * 7 + 3
for i = 1, #data do
local string_width = print(data[i], 0, -10, 0, false, 1, true)
if string_width > width then width = string_width end
end
width = width + 4
x, y = clamp(x, 1, 240 - width - 1), clamp(y, 1, 136 - height - 1)
rectb(x, y, width, height, fg)
rect(x + 1, y + 1, width - 2, height - 2, bg)
for i = 1, #data do
print(data[i], x + 1, y - 5 + i*7, 0, false, 1, true)
print(data[i], x + 2, y - 5 + i*7, text, false, 1, true)
end
end
function save_map()
local tile1, wx, wy = get_world_cell(player.x, player.y)
local start_x, start_y = wx - 120, wy - 68
for y = 0, 135 do
for x = 0, 239 do
local tile = TileMan.tiles[start_y + y][start_x + x]
if not tile.visited and tile.is_land then AutoMap(start_x + x, start_y + y) end
end
end
for y = 0, 135 do
for x = 0, 239 do
local tile = TileMan.tiles[start_y + y][start_x + x]
mset(x, y, tile.sprite_id)
end
end
sync(4, 0, true)
end
function TIC()
local start_time = time()
cls(0)
if t % 2 == 0 then
update_water_effect(time())
end
t = t + 1
if t % 6 == 0 then
water_anim = water_anim + 1
if water_anim > 3 then water_anim = 0 end
end
--replace mouse cursor with ours
poke(0x3FFB, 341)
local x, y, left = mouse()
if key(23) or btn(0) then player.y = player.y - (show_map and 10 or 5) end
if key(19) or btn(1) then player.y = player.y + (show_map and 10 or 5) end
if key( 1) or btn(2) then player.x = player.x - (show_map and 10 or 5) end
if key( 4) or btn(3) then player.x = player.x + (show_map and 10 or 5) end
if keyp(49) then debug = not debug end
if keyp(13) then show_map = not show_map end
if keyp(37) then frequency = frequency - 0.01 end
if keyp(38) then frequency = frequency + 0.01 end
if keyp(8) then show_help = not show_help end
if show_map then
TileMan:draw_worldmap(player)
else
--Draw visible map
TileMan:draw_terrain(player, 31, 18)
TileMan:draw_clutter(player, 32, 21)
end
--Draw tile-grid highlight
local tile, wx, wy = get_world_cell(x, y)
local sx, sy = get_screen_cell(x, y)
if not show_map then
sspr(288, sx, sy, 0)
end
--Draw debug info
if debug then
local frame_time = floor(time() - start_time)
local total_frame_time = floor(time() - last_time)
draw_text_window({'Frame Time: ' .. frame_time .. 'ms', 'FPS: ' .. floor(1.0/total_frame_time * 1000)}, 2, 2)
sspr(320, 116 - 8, 64, 0, 1, 0, 0, 2, 1)
end
if key(64) then draw_tile_widget(x + 5, y + 8) end
if key(63) and keyp(20) then sync(0, 0, true) end
if show_help then draw_text_window(help, 1, 25) end
m.x, m.y, m.l = x, y, left
if keyp(16) then
save_map()
end
last_time = time()
end
--
-- 000:4444444443444444444444444444443444444444443444444444444444444444
-- 001:4444444444477446446777474477764744777777647677444777774444776744
-- 002:4445744444477444444775444447774444577444447774444447744444477444
-- 003:4647774444767774477737774767776747776777447777744447774644444444
-- 004:44444444444444444444444444444b444444bab444444b444444474444444444
-- 005:4647774444762764477232774767276746776777447777744447764644444444
-- 006:4444444445444444447444444474744444747444444444444444444444444444
-- 007:444444444444444444eddd444eddddd44ccdcdc444fcce444444444444444444
-- 008:44444444444444444444de444444cdc444444cd4444444444444444444444444
-- 009:4444444d44b444444bbd4444444bd4444444bd444d444bb444444b4444444444
-- 010:4444444444cccc444cccccc44c0c0cc44cceccc444cccc4444dede4444444444
-- 011:0000000000044000004444000444444004444440004444000004400000000000
-- 012:0000000044000404044444444444044444444444444444444444444444444444
-- 013:0000000000000044000004440000440400004444004444440404444404444444
-- 014:0000000000000000000000000000000000000000004444000444444044444444
-- 015:0404444004444440004444044044440000404400044444400044440404444440
-- 016:6666666666666666666666766666666666666666667666666666666666666666
-- 017:6666636666665666766456666767566565675676656756566666666666666666
-- 018:6666666666d666666d2d66d666d66d2d667666d6667666766666666666666666
-- 019:6666666666666666667666666675666666756656667567666666676666666666
-- 020:6676666667566666765666667664666676666766666665766666656766663667
-- 021:66666666666666666666666666666b666666bab666666b666666676666666666
-- 022:6669666666949666666866666667666666676666666766666666666666666666
-- 023:622666662c226666222266666cd666666cc66666666666666666666666666666
-- 024:66666666666cd66666edc66666dc666666666666666666666666666666666666
-- 025:66222c66622c22262c2222c2222ee22262ecce26666cc666666cc666666cc666
-- 026:666666666666666666cddd666eddddd66ccdcdc666ccce666666666666666666
-- 027:4444444444466444446666444666666446666664446666444446644444444444
-- 028:4444444466444646466666666666466666666666666666666666666666666666
-- 029:4444444444444444444446664444666644466666444666664466666644666666
-- 030:4444444444444444444444444444444444444444446666444666666466666666
-- 031:4646666446666664446666466466664444646644466666644466664646666664
-- 032:7777777776777777777777777777777777777777777777777777777777767777
-- 033:7777777777777777757777777757775775677657755775677557757775677777
-- 034:7777777777757777757757777767577677576767775757577757675777777777
-- 035:7777777776777777776777777765777677657767777775677777756777777777
-- 036:7726777772327777772647777774547777764777775677777776777777777777
-- 037:7777777777677777762677777767777777777777777776777777636777777677
-- 038:7777777777777777777777777777777777777777777777777777777777777777
-- 039:7777777777777777777777e7770770707e707f7777707f77777f7f7777777777
-- 040:777777777777777777eddd777eddddd77ccdcdc777fcce777777777777777777
-- 041:7777777777777777777777777777777777777777777777777777777777777777
-- 042:7777777777ddcdd77dcdddccddddcccdcddccdcefecceeef7ffffff777777777
-- 043:6666666666677666667777666777777667777776667777666667766666666666
-- 044:6666666677666767677777777777677777777777777777777777777777777777
-- 045:6666666666666676666667776666776766677777667677776677777767777777
-- 046:6666666666666666666666666666666666666666667777666777777677777777
-- 047:6777767667777776767777666677776766776766677777767677776667777776
-- 128:7ce7ce77cdd7edc7dec77cf7777777777ecd7de7edf77ece7ee7ecdc777777e7
-- 129:c2777727342f337733f744f772c742f7777777777437742ff323732f7d2f7f77
-- 130:7ce7cf778bd7fdb78ee778f777777777edcb7ff7fc8e78cf7ff7ffbc77777ef7
-- 131:7700700770fe70ef700f77f0770777777077770f000e70f00ef070e77f077777
-- 144:6ce6ce66cdd6edc6dec66cf6666666666ecd6de6edf66ece6ee6ecdc666666e6
-- 145:c2666626342f336633f644f662c642f6666666666436642ff323632f6d2f6f66
-- 146:6ce6cf668bd6fdb68ee668f666666666edcb6ff6fc8e68cf6ff6ffbc66666ef6
-- 147:6600600660fe60ef600f66f0660666666066660f000e60f00ef060e66f066666
-- 160:4ce4ce44cdd4edc4dec44cf4444444444ecd4de4edf44ece4ee4ecdc444444e4
-- 161:421112313c2f132133f112f112c11111111111111131112f132313231d2f1f34
-- 162:4ce4cf448bd4fdb48ee448f444444444edcb4ff4fc8e48cf4ff4ffbc44444ef4
-- 163:4400400440fe40ef400f44f0440444444044440f000e40f00ef040e44f044444
-- 193:0077777707556466746646567665656466677777677000007007777700746565
-- 194:0000000077000000657000076657007476650656776607567076755657576760
-- 195:0777700074746700565765706566666756777776677000070000000077770000
-- 196:1111111111111117111117551111155611117557111755611157575717567675
-- 197:77677777655656565575757557175676577567b765565bab571767b776761565
-- 198:1111111177111111667111115767111176767111676767117676767176176771
-- 199:1111111111111111111111111157575615656561575751566671676767677676
-- 200:1111111511111156111115755611676765617771565117776767717116756567
-- 201:7571111156561111157571116767611177177611775751717565656657575157
-- 209:0756665674665777766777007577700076670000676000000770000000700000
-- 210:6677777770733766002332700032230000333300000333300003333000023320
-- 211:6767700076756700776676700777657000077660000077600000067000000760
-- 212:55157756575757617676b676177b3b571177b7651111cc0611111c0511111bc1
-- 213:57576757656575717656567667617b7575776b57565657616165767611116c01
-- 214:6756576175656567565b57577576b67757b77771617777117bc7b111bb1b2b11
-- 215:6771717116777777116757571113211111113757117676761567177156567777
-- 216:7777561673276513113676316532673157365136765375577163656557573757
-- 217:717676766777b776166beb561777b66176325111573211111566561157577571
-- 226:0003223000033330000033300000333300002332000032230003333300033333
-- 227:0000070000000000000000000000000000000000000000000000000000000000
-- 228:11111c0c111111cb1111111c1111111b1111111b111111111111111111111111
-- 229:1111bb011111bc01b111cb0100110c010b11cbc1b0110c1c1bc1b0cb1b0c0cb1
-- 230:c011b111b0111111cc111111b0111111cc111111b11111111111111111111111
-- 231:67676765767176636777776116177711111711111171111111761111111b1111
-- 232:6515635626117367321733673217532613213321113233111133321111133211
-- 233:1676561675727575173767661567717613216661133211111321111133211111
-- 242:0003333000023320000322300003333000033330002333200032223000333300
-- 244:1111111111111111111111111111111111111111111111111111111111111111
-- 245:1cb0bb1111cc0c11111bc0111110bc11111b0b11111cb01111100c111110b011
-- 246:1111111111111111111111111111111111111111111111111111111111111111
-- 247:11b9b111111b1111111111111111111111111111111111111111111111111111
-- 248:1113321311133233111333321113332111133211111332111113321111333221
-- 249:3211111121111111111111111111111111111111111111111111111111111111
--
--
-- 032:0202020220000000000000022000000000000002200000000000000220202020
-- 064:bbf00000bf00000dbf000000bf000d00bf000d00bf000000bf00000dbbf00000
-- 065:00000fbbd00000fb000000fb00d000fb00d000fb000000fbd00000fb00000fbb
-- 085:bbb00000bd000000b0b00000000b000000000000000000000000000000000000
--
--
--
-- 000:00000000ffffffff00000000ffffffff
-- 001:0123456789abcdeffedcba9876543210
-- 002:0123456789abcdef0123456789abcdef
--
--
-- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000
--
--
-- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
--
--
-- 000:777777676766666666575757576767b776767676666666666666666666666bc666666c06bbc575757576767b77676767666575757576767b77676767666666666666676666666666666666666666676666666666666666666666676666666766657575756565777777757577777777777777777777757577
-- 001:7777777766666666675676757676656576676776666666666666666666666c0c6666bb06c07567675767665657667677667567675767665657667677666666666666666666666666666666666666666666666666666666666666666666666666666776767676777777565656677777777777777766565657
-- 002:77777776666666665565775657576757675657666666666666666666666666cb6666bc06b55657756575767576756576655657756575767576756576666666666666666666666666663666666666666666666666666666666666666666666666767677676767565675757575777777777777777775757575
-- 003:777777666666666657575766656575767565656766666666666666666676666cb666cb06c5757576665657576756565675757576665657576756565676666d666666666666666666666566666666666666666666666666666666667677666767767777777777756767776767677777677777776767676777
-- 004:77776766666667667676b67676565676565b575766666766667666666666666b00660c06b7676b67676565676565b57577676b67676565676565b5757d66d2d66666667666666766666546776676666666666676667666666666677767777777776777777732765736777b776777777777777777677b7776
-- 005:7777766666666666677b3b5767667b757576b67766666666666666666666666b0b66cbc6cc77b3b5767667b757576b677677b3b5767667b757576b6772d66d66666666666666666656657676666666666666666666666666666677677777677777767575777367636766beb5677777776777777765beb667
-- 006:76776666666666666677b76575776b5757b77776666666666666666666666666b0660c6cb6677b76575776b5757b777766677b76575776b5757b77776d6667666666666666666666676576566666666666666666666666666667777777777777777732767653267377777b667777777777777777766b7777
-- 007:77766666676666666666cc0656565766667777666766666666666666666667666bc6b0cb66760cc0656565766667777666766cc06565657666677776677667666676666667666666657576566666666666766666666666666676777777777777777773757573657367632577777777777777777777752367
-- 008:676666666666666666666c05666576767bc7b6666666666666666766666666666b0c0cb6666666c05666576767bc7b66666666c05666576767bc7b66666666666666666666666666666666666666676666666666666667666677777777777777767767676765375575732777777777777777777777772375
-- 009:666666666666666666666bc666666c06bb6b2b666666666666666666666666666cb0bb66666666bc666636c06bb6b2b6666666bc666666c06bb6b2b6666666666666666666666666666666666666666666666666666666666777777777777777775677777776365657566567777777777777777777656657
-- 010:666666666666666666666c0c6666bb06c066b66666666666666666666666666666cc0c66666666c0c6666bb06c066b66666666c0c6666bb06c066b66666666666666666666666666666666666666666666666666666666667700700770077777756567777575737575757757777777777777777777577575
-- 011:6666666666666666666666cb6666bc06b0666666666666666676666666d66666666bc0666676666cb6666bc06b0666666666666cb6666bc06b0666666666666666666666666666666666666666666666666666666666667670fe70effe007007767676765657563566676567677777777777777767656767
-- 012:66766666666666766666676cb666cb06cc76666666666676666666666d2d66d66660bc7666666666cb666cb06cc6676666766666cb666cb06cc6666666666676666667666666676666666676667666666666667666666777700f77f00f0700f00767e7663267773677572757577777777777777757572757
-- 013:66666666666666666666666b00660c06b0666666666666666666666666d66d2d666b0b6666666666b00660c06b06666666666666b00660c06b066666666666666666666666666666666666666666666666666666666677677707777770e77fe0f67777766327733677737676677777777777777766767377
-- 014:66666666666666666666666b0b66cbc6cc6666666666666666666666667666d6666cb06666666666b0b66cbc6cc6666666666666b0b66cbc6cc66666666666666666666666666666666666666666666666666666666777777077770f77777777776777777327753267567777677777767777777667777656
-- 015:666666666676666667666666b0760c6cb666666666766666666667666676667666700c66666667666b0660c6cb666666666666666b0660c6cb66676666766666676666666766666666766666666666666676666666767777000e70f0700777000f7770077732733277327666777777777777777776667237
-- 016:6666676666666666666666666bc6b0cb666667666666666666666666666666666660b0666666666666bc6b0cb66666666666676666bc6b0cb6666666666666666666666666666666666666666666676666666666667777770ef070e77ef07fe0fe07ef077773233777332777767777777677777776772337
-- 017:6666666666666666666666666b0c0cb666666666666666666666666666666666666666666666666666b0c0cb666666666666666666b0c0cb66666666666666666666666666666666666666666666666666666666677777777f077777770f70f7700760777773332777327777777777777777777777777237
-- 018:6776777776666666666666666cb0bb6666666666666666666666666666666666666666666666666666cb0bb6666666666666666666cb0bb66669666666666666666666666666666666666666666666666666666670077777777770f7770070077007b7777777332773327777777777777777777777776233
-- 019:76556565677666666666666666cc0c66667666666666666666766666667666666676666666666666666cc0c66666666666766666666cc0c666949666666666666666666666666666666666666666666666666676fe0070077e070fe070fe70effe0b9b077677332733277777767777777777777777777723
-- 020:555757575667666666666676666bc0766666666666666676666666666666666666666666667666666666bc0666766666666666666666bc06666866766676666666766666666667666676666666666676666667770f0700f00f07e000700f77f00f07b0f07777332332777777777777777777777777777772
-- 021:657675676576766666666b666660bc6666666666666666666666666666666666666666666666666666660bc6666666666666666666660bc66667666666666666666666666666666666666666666666666666776770e77fe0f07777077707777770e77fe07777333327777777777777777777777777777777
-- 022:7577567b776767666666bab6666b0b666666666666666666666666666666666666666666666666666666b0b666666666666666666666b0b66667666666666666666666666666666666666666666666666667777777777777777770777077770f777777777777333277777776777777777777777677777777
-- 023:665565bab676767666766b66667cb0666666676666766666666667666666676666666766666666666676cb0666666666666667666676cb0666776666666666666666666667666666666666666676666666767777700777000f77f007000e70f0700777007777332777777777777777777777777777777777
-- 024:7576767b776767676666676666600c66666666666666666666666666666666666666666666666766666600c66666676666666666666600c6666666666666676666666766666666666666676666666666667777777ef07fe0fe07ef070ef070e77ef07fe07777332776777777777777777677777777777767
-- 025:5767665657667677666666666660b06666666666666666666666666666666666666666666666666666660b06666666666666666666660b0666666666666666666666666666666666666666666666666667777777770f70f7700700777f077777770f70f77776332777777777777677777777777777777777
-- 026:657576757675657666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667666666666667777777777770f77f07f07770077777777770f77703332277777777777777777777677777777777
-- 027:6656575767565656766666666676666666666666666666666666666666666666667666666666666666666666666666666676666666666666667666666666666666666666666666666666657666666666667777777e070fe00ef70fe7fe0070077e070fe070fe70ef77777775757777777777777776777777
-- 028:676565676565b575766666766666666666666676667666666676666666766666666666666666676666766666666667666666666666666766666666666666667666666676666666766666657766666676677777770f07e000007770070f0700f00f07e000700f77f077777656565777777777777777777777
-- 029:767667b757576b6776666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666646676666666666767777f07777077777777770e77fe0f07777077707777767777575757577777777777777777777
-- 030:575776b5757b777766666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667666676666666666777777777770770ef77e0777777777777770777077770f77776767676767765657575777777777
-- 031:6565657666677776667666666666676666766666666666666666666666666666666667666766666666666666676666666666676667666666666667666676666666766666667666666756666666766666667777770f77f0070f0070f0700777000f77f007000e70f077767777777777656765656577777777
-- 032:5666576767bc7b6666666666666666666666666666666766666667666666676666666666666666666666676666666666666666666666666666666666666666666666666666666666765666666666666667777777fe07ef07700700ef7ef07fe0fe07ef070ef070e777775757777777565657575757777777
-- 033:666666c06bb6b2b6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667663666666666666676777777007007777777007770f70f7700700777f07777776656565777777676767677667767777
-- 034:c6666bb06c066b66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666966666666666777770f77f07f0777f07f0777f07f077777770f77f07f07777575757576565767676776767776777
-- 035:b6666bc06b0666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666766666667666666666666666694966666666767e070fe00ef70fe70ef70fe70ef70fe77e070fe00ef70fe776767677767657777d7c7d7767777777
-- 036:cb666cb06cc666666676666666dddc76666666766666667666666766666666766666667666766666667666666666667666666676667666666666667666666666666666666676666666668676666667770f07e0000077700700777007007770070f07e000007770077677b777637567237777777677777777
-- 037:b00660c06b066666666666666ddddde666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666766666667767f0777707777777777777777777777777f077770777777777765beb6677367637d757576d77777777
-- 038:b0b66cbc6cc66666666666666cdcdcc666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666766666677777777770770ef77e070ef77e070ef77e07777770770ef77e077766b777773762356cdc23dc77777777
-- 039:6b0660c6cb6667666666666666eccc66667666666676666667666666667666666676666666666666666666666676666666766666666666666676666666666766666667666666666666767666667677770f77f0070f0070f00f0070f00f0070f00f77f0070f0070f0777752367637563757573cef77777777
-- 040:66bc6b0cb6666666666667666666666666666666666666666666666666666666666666666666676666666766666666666666666666666766666666666666666666666666666667666666666666777777fe07ef07700700ef700700ef700700effe07ef07700700ef77777237575573567676767777777767
-- 041:66b0c0cb6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666777777770070077777770077777700777777007700700775757700777765665756563677777776577777777
-- 042:66cb0bb66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666777777777007007777770f770077777770070077f07f0756565677757577757575737575777765657777777
-- 043:666cc0c66666666666766666666666666676666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666677777770fe70ef7e070fe0fe00700770fe70ef0ef70f575657577565656565655365756567676767777767
-- 044:6666bc066676666666666666666667666666666666666676667666666666667666cddd766676666666766666666666766676666666666676666667666676666666666676667666666676666667777777700f77f00f07e0000f0700f070057575656776767676765755575755575377762366777677777777
-- 045:66660bc6666666666666666666666666666666666666666666666666666666666eddddd6666666666666666666666666666666666666666666666666666666666666666666666666666666666676777777077777f077770770e77fe077565656765575756567767676767676767637656575757767777777
-- 046:6666b0b6666666666666666666666666666666666666666666666666666666666ccdcdc666666666666666666666666666666666666666666666666666666666666666666666666666666666667777777077770f777770777777777775757505655656567656777777677777777756563656565677777777
-- 047:6676cb066666666666666766676666666666676666766666666666666676666666ccce666666666666666666667666666666666666766666676666666666666666766666666666666666666666777777000e70f00f77f0077007770006677676757575f56565567777757577777335656575757577777777
-- 048:666600c6666667666666666666666666666666666666666666666766666666666666666666666766666667666666666666666766666666666666666666666766666666666666676666666766677777770ef070e7fe07ef077ef07fe006767767666756767676777766565657677776767676777575777777
-- 049:66660b06666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666676777777f07777770070077770f70f776777777767677676767565675757575765657676767765656577777
-- 050:6666666666666666666666666666666666666666666666666666666666666666666667666666666666666666666666666666666677777677666666666666666666666666666666666666666667777777770070077f07f0777700700770677777767777573777756767676767676577777777757575757777
-- 051:666666666666666666666666666666666666666666666666666666666666666666666576666666666666666666666666666666776565655676666666666666666666666666666666666666666677777770fe70ef0ef70fe770fe70effe0675757e67777777327655677b7776335672377777676767676776
-- 052:6676666666666766666666766666676666766666666667666666666666666666666665776676666666766666666666766666676657575755557666766666676666666766666666766666676667777777700f77f000777007700f77f00f0732f0065675757773676365beb665636763777576777777777765
-- 053:666666666666666666666666666666666666666666666666666666666666666666664667666666666666666666666666666676756765767565566666666666666666666666666666666666666676777777077777777777777707777770e77375757332e366532673766b7776737623566772575777777756
-- 054:666666666666666666666666666666666666666666666666666466666664666666766667666666666666666666666666666767677b7657757557666666666666666666666666666666666666667777777077770f0ef77e077077770f77776767676533757573657367652367632563757665656577777767
-- 055:66666666676666666676666667666666666666666766666666666664666666646756666666666666666666666676666667767676bab56556665576666766666667666666667666666766666666777777000e70f00f0070f0000e70f070567777770767676765375575732375755735676757575757656576
-- 056:666667666666666666666666666666666666676666666666646444666464446676566666666667666666676666666666676767677b7677757575756666666666666666666666666666666666677777770ef070e7700700ef0ef070e775656777755673777776365657656657565636777676767776765777
-- 057:66666666666666666666666666666666666666666666666644444444444444447663666666666666666666666666666667767667565667675767657666666666666666666666666666666666676777777f077777777770077f07777776767676556567777575737577577575757375757677b77763756723
-- 058:66666666666666666666666666666666666666666666664444444444444444444466666666666666666666666666666666756576757675756577565566666366666666666666666666666666677777777007777770077777700777777767f76636767676565756356765676765365356565beb6677367637
-- 059:6676666666666666667666666666666666666666666666444444444444434444446666666666666666666666667666667656565767575656667575756666566666666666666666666666666666777777fe007007fe007007fe00700706777776776777663263773657572757763777623666b77777376235
-- 060:6666666666666676666666666666667666666666666664444444434444444444446666666676666666666676666666667575b56567656567676b676776645676666666766676666666666676677777770f0700f00f0700f00f0700f000677777767777766326733666767376763377237677523676375637
-- 061:666666666666666666666666666666666666666666666444444444444444444444466666666666666666666666666666776b675757b7667675b3b776676756656666666666666666666666666676777770e77fe070e77fe070e77fe077777777776277727322753267577657623577236777723757557356
-- 062:66666666666666666666666666666666666466666666444443444444444444444444666666666666666666666666666667777b7575b67757567b776665675676666666666666666666666666667777777777777777777777777777770ef77e07777373367732233276667236723372377776566575656366
-- 063:666667666676666666666766667666666666666466644444444444444444434444444466666666666676666666666766667777666675656560cc666665775656667666666666666666766666667777777007770070077700700777000f0760f0777733277733233777332337773323777775775757573757
-- 064:666666666666666666666666666666666464446644444444444444344344444444444444666667666666666666666666666b7cb76767566650c6676666666666666666666666676666666666677777777ef07fe07ef07fe07ef07fe07007b0ef767763277333332777327237772333777676567676536575
-- 065:66666666666666666666666666666666444444444444444444444444444444444444444466666666666666666666666666b2b6bb60c666666cb666666666666666666666666666666666666667677777770f70f7770f70f7770f70f7777b9b077777b3273326332773327233772337777575727577637776
-- 066:666666666666666666666666666666444444444444444444444444444444444444444444446666666666666666666666666b660c60bb6666c0c666666666666666666666666666666666666667777777700777777f07f077770070077700b007777b9b233277332733277723372337777667673777633772
-- 067:6666666666666666666666666666664444444444444444344344444444444444434444444466666666666666666666666666660b60cb6666bc6666666676666666666666666666666666666666777777fe0070070ef70fe770fe70ef70fe70ef7677b3332677332332777772332337777677776576235772
-- 068:666666766666667666766666666664444444434444344444444444444444434444444444446666666666676666766666666667cc60bc666bc666667666666666666666766666667666766666677777770f0700f000777007700f77f0700f77f0777733327777333327777777233337777766672377233723
-- 069:6666666666666666666666666666644444444444444444444444443444444444444444344446666666666666666666666666660b60c06600b6666666666666666666666666666666666666666676777770e77fe0777777777707777777077777777733277777333277777777723337776777723377733237
-- 070:666666666666666666666666666644444344444444444444444444444344444444444444444466666666666666666666666666cc6cbc66b0b66666666666666666666666666666666666666666777777777777770ef77e077077770f7077770f777733277777332777777777772337777777772377723337
-- 071:6676666666766666666666666664444444444444444444444434444444444444443444444444446667666666666666666766666bc6c0670b667666666666676666766666667666666666666666777777700777000f0070f0000e70f0000e70f0777733277777332777777777772337777777772337723377
-- 072:66666666666666666666676644444444444444344444344444444444444444344444444444444444666666666666676666666666bc0b6cb66666666666666666666666666666666666666766677777777ef07fe0700700ef0ef070e70ef070e7777333227777332777777777772337777777777233723377
-- 073:666666666666666666666666444444444444444444444444444444444444444444444444444444446666666666666666666666666bc0c0b6666666666666666666666666666666666666666667677777770f70f7777770077f0777777f077777777677777773332277767777722333777777777723323377
-- 074:6666666666666666666666444444444444444444444444444444444444444444444444444444444446666666666666666666666666bb0bc6666666666666666666666666666666666666666667777777777770f7777770f7777770f777777777777777777777677777777777777777777777777772333377
-- 075:66666d6666666666666666444444444444434444434444444444443444444434444444344444443444666666666666666666666666c0cc666676666666666666666666666666666666666666667777777e070fe07e070fe07e070fe076777777777777777777777777777777777777777677777776233377
-- 076:6d66d2d6666667666666644444444344444444444444444444344444443444444434444444344444466666666666667666766666660cb6766666666666766666667666666666667666666766677777770f07e0000f07e0000f07e00077777777777777777777777777777777777777777777777777723377
-- 077:d2d66d6666666666666664444444444444444444444444344444444444444444444444444444444444646666666666666666666666cb0666666666666666666666666666666666666666666666767777f0777707f0777707f077770777777777777777777777777777777777777777777777777777723377
-- 078:6d66676666666666666644444344444444444444444444444444444444444444444444444444444444666666666666666666666666b0b66666666666666666666666666666666666666666666677777777777077777770777777707777777777777777767777777777777776777777767777777777723377
-- 079:67766766676666666664444444444444444443444434444444444444444444444444444444444444446666666676666666666666660bc6666666676666666666666666666676666667666666667777770f77f0070f77f0070f77f00777777777777777777777777777777777777777777777777777223337
-- 080:6666666666666666444444444444443443444444444444444444344444443444444434444444344446666666666666666666676666c00666666666666666676666666766666666666666666667777777fe07ef07fe07ef07fe07ef0777777777767777777777776776777777767777777777777777777777
-- 081:66666666666666664444444444444444444444444444444444444444444444444444444444444444464666666666666666666666660b066666666666666666666666666666666666666666666767777770070077700700777007007777767777777777777777777777777777777777757576777777767777
-- 082:666666666666664444444444444444444444444444444444444444444444444444444444444444444666666666666666666966666666666666666666666666666666666666666666666666667f07f077700777777f07f0777777777777777777777777777777677777777777777776565657777777776777
-- 083:666666666666664444434444444344444444444443444444444444444443444443444444444444444466666677677777669496666666666666666666666666666676666666666666666666760ef70fe7fe0070070ef70fe77777777777777777777777677777777777777767777775757575777777777777
-- 084:66666676666664444444444444444444444443444444444444444344444444444444444444444344466666676556565677686676666667666666676666666766666666666666667666666777007770070f0700f0007770077777777777777777777777777777777777777777777767676767677656575757
-- 085:666666666666644444444444444444444444444444444434444444444444444444444434444444444464675555757575667766666666666666666666666666666666666666666666666677677777777770e77fe0777777777777777777777777677777777777777767777777677677777777776567656565
-- 086:666666666666444444444444444444444344444444444444434444444444444444444444434444444466655657675676576766666666666666666666666666666666666666666666666777770ef77e07777777770ef77e077777777677777776777777777777777777777777777757577777775656575757
-- 087:6676666666644444444443444444434444444444443444444444444444444344443444444444444444667557577567b7767676666766666667666666676666666666676666766666667677770f0070f0700777000f0070f07777777777777777777777777777777777777777766565657777776767676776
-- 088:666666664444444443444444434444444444443444444444444444344344444444444444444444344667556665565bab67676766666666666666666666666666666666666666666666777777700700ef7ef07fe0700700ef7677777776777777777777777777776777777777775757575765657676767767
-- 089:6666666644444444444444444444444444444444444444444444444444444444444444444444444446575757576767b77676767666666666666666666666666666666666666666666777777777777007770f70f7777770077777777777777777777777777777777777777777767676777676577777777777
-- 090:666666444444444444444444444444444444444444444444444444444444444444444444444444444756767576766565766767766666666666666666666666666666666666666666677777777f07f077777777777777777777777777777777777777777777777777777777777677b7776375672377777776
-- 091:666666444344444443444444444444344344444444444434444444344443444444444434444444445565775657576757675657666676666666666666666666666666666666666666667777770ef70fe777777777777777677677777776777777767777777777776776777777765beb667736763777575767
-- 092:6666644444444444444444444434444444444444443444444434444444444444443444444444434457575766656575767565656766666666666667666666676666cddd76667666666777777700777007777777777777777777777777777777777777777777777777777777777766b777773762356dcd23cc
-- 093:666664444444443444444434444444444444443444444444444444444444444444444444444444447676b67676565676565b57576666666666666666666666666eddddd666666666667677777777777777777777677777777777777777777777777777776777777777777777777752367637563757573ccd
-- 094:66664444444444444444444444444444444444444444444444444444444444444444444443444444477b3b5767667b757576b6776666666666666666666666666ccdcdc666666666667777770ef77e077777777677777777777777777777777777777777777777777777777777777237575573567676767e
-- 095:666444444434444444344444444444444434444444444444444444444444434444444444444444444477b76575776b5757b7777666666766676666666766666666ccce6666666666667777770f0070f07777777777777777777777777777777777777777777777777777777777765665756563677e77e765
-- 096:444444444444444444444444444434444444444444443444444434444344444444443444444444344666cc065656576666777766666666666666666666666666666666666666676667777777700700ef76777777777777777777777777777777777777777777777777777777777577575757375757777656
-- 097:4444444444444444444444444444444444444444444444444444444444444444444444444444444446466c05666576767bc7b6666666666666666666666666666666666666666666676777777777700777777777777777777776777777767777777677777777777777767777767656767653657565676767
-- 098:4444444444444444444444444444444444444444444444444444444444444444444444444444444466666bc666666c06bb6b2b666666666666666666666666666636666666666666677777777777777777777777777767777777777777776777777777777777777777777777757572757763777623667776
-- 099:4344444443444444444444444344444444434444444444344444443443444444444444444444444466666c0c6666bb06c066b6666666666666666666667666666665666666766666667777777677777777777777777777777777776777777777777777777677777777777777766767377763377237677777
-- 100:44444444444444444444434444444444444444444434444444344444444444444444434444444666666666cb6676bc06b06666766676666666766666666666666675466766666666677777777777777777777777777777777777777777777777777777777777777777777777767777657623577237777776
-- 101:444444344444443444444444444444344444444444444444444444444444443444444444444466666666666cb666cb06cc6666666666666666666666666666665665767666666666667677777777777777777777777777776777777777777777777777777777777777777777776667237723372367777777
-- 102:444444444444444443444444444444444444444444444444444444444444444443444444444666666666666b00660c06b06666666666666666666666666666666765765666666666667777777777777777777776777777777777777777777777777777767777777777777776777772337773323677777777
-- 103:443444444434444444444444443444444444434444444444444444444434444444444444444666666676666b0b66cbc6cc7666666666666666666666666667666565765666666766667777777777777777777777777777777777777777777777777777777777777777777777777777237772333777777677
-- 104:4444444444444444444444344444444443444444444434444444344444444444444444344466666666666666b0660c6cb66666666666676666666766666666666666676666666666677777777777777776777777777777677777777777777767767777777777777776777777777777233672337777777b77
-- 105:44444444444444444444444444444444444444444444444444444444444444444444444444666666666666666bc6b0cb66666666666666666666666666666666666666666666666667677777777677777777777777777777777777777777777777777777777677777777777777767772337233777777b9b7
-- 106:44444444444444444444444444444444444444444444444444444444444444444444444446666666666666666b0c0cb6666666666666666666666666666666666666666666666666777777777777677777776777777777777777777777776777777767777777677777777777777777772332337777777b77
-- 107:44444444444344444444443443444444444444444443444444444444444444344344444444666666667666666cb0bb66666666666676666666666666666666666666666666666676777777777777777777777777767777777777777777777777777777777777777776777777777777677233337777777777
-- 108:444443444444444444344444444444444444434444444444444443444434444444444444466666666666666666cc0c76667666666666666666766666666667666666676666666777777777777777777777777777777777777777777777777777777777777777777777777777777777777723337777777777
-- 109:4444444444444444444444444444443444444444444444444444444444444444444444344464666666666666666bc066666666666666666666666666666666666666666666667767777777777777777777777777777777777777777777777777777777777777777777777777677777777772337777777777
-- 110:43444444444444444444444444444444434444444444444443444444444444444444444444666666666666666660bc66666666666666666666666666666666666666666666677777777777767777777777777777777777777777777677777777777777777777777777777777777777777772337777777776
-- 111:4444444444444344444444444434444444444444444443444444444444444444443444444466666666666766667b0b66666666666666676666666666676666666766666666767777777777777777777777777777777777777777777777777777777777777777777777777777777777777772337777777777
-- 112:4444443443444444444434444444444444444434434444444444443444443444444444444666666666666666666cb066666667666666666666666766666666666666666666777777767777777777776777777767777777777677777777777767777777677777776777777777777777777722333776777777
-- 113:444444444444444444444444444444444444444444444444444444444444444444444444464666666666666666600c66666666666666666666666666666666666666666667777777777777777777777777777777777677777777777777777777777777777777777777767777777777777776777777777775
-- 114:44475444444444444444444444444444444444444444444444444444444444444444444466666666666666666660b066666666666666666666666666666666666666666667777777772677777777677777777777777777777777777777777777777777777777777777777777777777777777777777776656
-- 115:434774444443444443444444444444444444443444444434444444344443444444444444667666666666666666666666666666666666666666766666666666666676666666777777723277777777777777777777777777777777776776777777767777777777777777777777767777775757777777777575
-- 116:4457744444444444444444444444434444344444443444444434444444444444444446666666666666666676666666766666667666766666666666666666667666666666677777777726477777777777777777777777777777777777777777e7777777777777777777777777777777756565677777776767
-- 117:447774344444444444444434444444444444444444444444444444444444444444446666666666666666666666666666666666666666666666666666666666666666666666767777777454777777777777777777777777776777777777077070777777777777777777777777777777575757577777767777
-- 118:44477544444444444444444443444444444444444444444444444444444444444446666666666666666666666666666666666666666666666666666666666666666666666677777777764777777777777777777677777776777777777e707f77777777777777777677757575656776767676767677775757
-- 119:443777444444434444344444444444444444444444444444444444444444434444466666666667666676666666766666667666666666666666666766667666666666676666777777775677777777777777777777777777777777777777707f77777777777777777777565656765677777777776776656565
-- 120:4447744443444444444444444444443444443444444434444444344443444444446666666666666666666666666666666666666666666766666666666666666666666666677777777776777777777767767777777677777777777777777f7f77777777777677777775757575656577777775757777575757
-- 121:444774444444444444444444444444444444444444444444444444444444444444666666666666666666666666666666666666666666666666666666666666757566666667677777777677777777777777777777777777777777777777767777777677777777777776677676767677777756565666767677
-- 122:44444444444444444444444444444444444444444444444444444444444444446666666666666666666666666666666666696666666666666666666666666656565666667777777777777777777767777777777757577777777777777777777777777777777777777676776767675656757575757677b777
-- 123:4444443444444444444344444444444444444444444344444344444444444444666666666666666666666666666666666694966666666666667666666666757565756676777777777777776777777777767777756565676777777767777777777777777777777767767777777777756767776767665beb66
-- 124:44344444444443444444444444444344444443444444444444ddde4444444666666667666666667666666676666666766668667666666676666666666666676767676776565757577777777777777777777777575757577777777777777777777777777777777777776777777732765736777b776766b777
-- 125:4444444444444444444444444444444444444444444444444ddddde44444666666666666666666666666666666666666666766666666666666666666666677677677776567656565677777777775757565677676767676776777777777777777777777776777777777767575777367637766beb567775236
-- 126:4444444443444444444444444344444443444444444444444cdcdcc444466666666666666666666666666666666666666667666666666666666666666676575777777756565757575777777777565656765677777777776777777777777777767777777677777777777732777653267377777b6677777237
-- 127:44444444444444444444434444444444444444444444434444eccf444446666667666666667666666676666666766666667766666676666666666766666565657676776767676776677777777575757565657777777575777777777777777777777777777777777777777375757365736763257777765665
-- 128:444434444444443443444444444444344444443443444444444444444466666666666666666666666666666666666666666666666666666666666666675657575765657676767767677777777667767676767777775656566777777776777777767777777777777777776767676537557573276777757757
-- 129:444444444444444444444444444444444444444444444444444444444466666666666666666666666666666666666666666666666666666666666666667676767676577777777777677777777676776767675656757575757777777777777777777777777777777777567777777636565756656776765676
-- 130:4444444444444444444444444444444444444444444444444444444466666666666666666666666666666666666666666666666666666666666666666677b7776375672377777776777777777677777777777567677767676777777777776777777767777777777775656777757573757575775775757275
-- 131:434444444444443444444434444444444444443444444434444444446676666666666666666666666676666666666666667666666666666666666666665beb66773676377757576777777767766777777732765736777b776777777777777777777777777677777776767676565756356767656766676737
-- 132:4444444444344444443444444444434444344444443444444444466666666666667666666676666666666666667666666666666666666766667666666666b77777376235677723777777777777767575777367637766beb56777777777777777777777777777777777677766326777367757275756777765
-- 133:44444434444444444444444444444444444444444444444444446666666666666666666666666666666666666666666666666666666666666666666666665236763756375757377767777777777732777653267377777b667777777777777777777777777777777776777776732773367773767667666723
-- 134:444444444444444444444444434444444444444444444444444666666666666666666666666666666666666666666666666666666666666666666666666772375755735676767677777777777777737575736573676325777777777677777777777777777777777777677777732775326756777767777233
-- 135:443444444444444444444444444444444444444444444444444666666666676666666666666666666666676666666666666667666766666666666666667656657565636777777765777777777767676767653755757327777777777777777777777777777777777777777777773273327732766677777723
--
--
-- 000:1010105d245db13e50ef9157ffff6daee65061be3c047f5005344c185dc95999f6e6eaf2b6baba8d8d9d444460282038
--