RedMew icon indicating copy to clipboard operation
RedMew copied to clipboard

Create dragon.lua

Open R-Nukem opened this issue 4 years ago • 2 comments

Initial version of dragon fractal map.

Has slow map generation. Probably due to the size of shapes used in the builder functions?

R-Nukem avatar Sep 29 '20 21:09 R-Nukem

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.

Jayefuu avatar Sep 30 '20 06:09 Jayefuu

@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

grilledham avatar Sep 30 '20 19:09 grilledham