RedMew
RedMew copied to clipboard
Create dragon.lua
Initial version of dragon fractal map.
Has slow map generation. Probably due to the size of shapes used in the builder functions?
Looks good. In my opinion it needs some notes on how best to configure ore. Since you don't remove the vanilla ore generation I am guessing you expect players to configure that from the scenario startup page or use a mod like you did for the recent play test.
A screenshot of n=5 iterations would be good to add to map_gen/data/.map_previews/ as well as linking to it from some way at the start of the file to make it clear that it's a dragon fractal pattern? OR link to a wikipedia page describing the algorithm? Just so people are clear what it will look like without having to explore it themselves.
@R-Nukem I had a go at optimising the map. Can you check this for correctness? I'm tired so this is a bit messy, but if it's correct either you or I can tidy it up.
The basic idea is to pre render the first 5 iterations to a 2d array then use that as the starting point for the next 5 iterations.
local b = require 'map_gen.shared.builders'
local math = require 'utils.math'
-- Dragon Fractal Map by R. Nukem
local scale = 64
local block = 1
local h = 4 * block
local w = block
-- Level 0
local map1 = b.translate(b.rectangle(w, h), w / 2, -h / 2)
local map2
local a1 = w
local b1 = h
local a2
-- How many iterations of "unfolding" the fractal?
--Note each iteration on the order of doubles the map size each iteration
local FractalOrder = 5
-- Loop to unfold the fractal
for _ = 1, 5 do
map1 = b.translate(map1, -a1, b1)
map2 = b.rotate(map1, math.pi / 2)
map1 = b.add(map1, map2)
map1 = b.translate(map1, a1, -b1)
a2 = a1
a1 = a1 + b1
b1 = b1 - a2
end
local data = {}
for y = -31, 31 do
local row = {}
data[#data + 1] = row
for x = -31, 31 do
row[#row + 1] = map1(x + 0.5, y + 0.5)
end
end
local pic = {width = 63, height = 63, data = data}
map1 = b.picture(pic)
for i = 1, FractalOrder do
map1 = b.translate(map1, -a1, b1)
map2 = b.rotate(map1, math.pi / 2)
map2 = b.translate(map2, 0, -block) -- No idea why this is needed :(
map1 = b.add(map1, map2)
map1 = b.translate(map1, a1, -b1)
a2 = a1
a1 = a1 + b1
b1 = b1 - a2
end
map1 = b.translate(map1, -block / 2, block / 2)
map1 = b.scale(map1, scale, scale)
block = block * scale
-- make starting area
local start_region = b.rectangle(block, block)
map1 = b.subtract(map1, start_region)
start_region = b.change_tile(start_region, true, 'grass-1')
start_region = b.remove_map_gen_resources(start_region)
local start_water = b.change_tile(b.circle(5), true, 'water')
map1 = b.any {start_water, start_region, map1}
--make starting ores
local value = b.manhattan_value
local ore_shape = b.scale(b.circle(30), 0.15)
local start_ore = b.circle(30)
local start_iron = b.resource(start_ore, 'iron-ore', value(1000, 0))
local start_copper = b.resource(start_ore, 'copper-ore', value(750, 0))
local start_coal = b.resource(start_ore, 'coal', value(500, 0))
local start_stone = b.resource(start_ore, 'stone', value(500, 0))
start_ore = b.segment_pattern({start_coal, start_stone, start_copper, start_iron})
ore_shape = b.choose(b.circle(30), start_ore, ore_shape)
--apply starting ores to map
map1 = b.apply_entity(map1, ore_shape)
--shift spawn so player doesn't die to start water
map1 = b.translate(map1, 0, block / 2)
return map1