1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-01-22 03:39:09 +02:00

Add inception scenario (#1445)

This commit is contained in:
RedRafe 2024-11-15 18:39:09 +01:00 committed by GitHub
parent 8871c4c257
commit 8c559cfafd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 526 additions and 0 deletions

View File

@ -0,0 +1,36 @@
return {
maze = {
enabled = true,
size = 50, -- in chunks
wall_thickness = 1, -- in chunks
cell_size = 5, -- must be an odd number
},
terrain = {
enabled = true,
boundary = 11, -- in chunks
noise_threshold = 0.77, -- must be (0, 1)
ore_base_quantity = 11, -- base richness
ore_chunk_scale = 30, -- in chunks
mixed_ores = {
'iron-ore',
'copper-ore',
'iron-ore',
'stone',
'copper-ore',
'iron-ore',
'copper-ore',
'iron-ore',
'coal',
'iron-ore',
'copper-ore',
'iron-ore',
'stone',
'copper-ore',
'coal',
},
blacklisted_resources = {
['uranium-ore'] = true,
['crude-oil'] = true,
},
}
}

View File

@ -0,0 +1,245 @@
local Global = require 'utils.global'
local math = require 'utils.math'
local table = require 'utils.table'
local configuration = require 'map_gen.maps.inception.configuration'.maze
local insert = table.insert
local shuffle = table.shuffle_table
local math_max = math.max
local math_floor = math.floor
local math_random = math.random
local MAZE_SIZE = configuration.size
local WALL_THICKNESS = configuration.wall_thickness
local CELL_SIZE = configuration.cell_size
local WALL_DELTA = math_floor((CELL_SIZE - WALL_THICKNESS) / 2)
local DIRECTIONS = {
{ x = 0, y = -2 }, -- north
{ x = 2, y = 0 }, -- east
{ x = -2, y = 0 }, -- west
{ x = 0, y = 2 }, -- south
}
local pixels = {}
local cells = {}
local maze_walls = {}
local primitives = {
max = 0,
walk_seed_w = 0,
walk_seed_h = 0,
}
Global.register({
maze_walls = maze_walls,
primitives = primitives,
},
function(tbl)
maze_walls = tbl.maze_walls
primitives = tbl.primitives
end
)
local Maze = {}
local function add_tile(x, y, width, height, add_cell)
if add_cell then
if cells[x] == nil then
cells[x] = {}
end
cells[x][y] = 1
end
for x_pos = x, x + width - 1 do
for y_pos = y, y + height - 1 do
if pixels[x_pos] == nil then
pixels[x_pos] = {}
end
pixels[x_pos][y_pos] = 1
end
end
end
local function render()
local y_max = 0
for x, _ in pairs(pixels) do
for y, _ in pairs(pixels[x]) do
if y * 32 > primitives.max and y % 2 == 0 then
y_max = math_max(y_max, y)
end
end
end
primitives.max = y_max * 32
for x = 1, y_max do
for y = 1, WALL_DELTA do
if not pixels[x] then
pixels[x] = {}
end
pixels[x][y] = 1
end
end
for x = 1, WALL_DELTA do
for y = 1, y_max do
if not pixels[x] then
pixels[x] = {}
end
pixels[x][y] = 1
end
end
for x = 1, y_max do
for y = 1, y_max do
if not (pixels[x] and pixels[x][y]) then
maze_walls[x * 32 .. '/' .. y * 32] = true
end
end
end
end
-- builds a width-by-height grid
local function initialize_grid(w, h)
local a = {}
for i = 1, h do
insert(a, {})
for j = 1, w do
insert(a[i], true)
end
end
return a
end
-- average of a and b
local function avg(a, b)
return (a + b) / 2
end
local function make_maze(w, h)
local map = initialize_grid(w * 2 + 1, h * 2 + 1)
local walk
walk = function(x, y)
map[y][x] = false
local d = { 1, 2, 3, 4 }
shuffle(d)
for i, dir_num in pairs(d) do
local xx = x + DIRECTIONS[dir_num].x
local yy = y + DIRECTIONS[dir_num].y
if map[yy] and map[yy][xx] then
map[avg(y, yy)][avg(x, xx)] = false
walk(xx, yy)
end
end
end
walk(primitives.walk_seed_w, primitives.walk_seed_h)
for i = 1, h * 2 + 1 do
for j = 1, w * 2 + 1 do
if map[i][j] then
add_tile(i * CELL_SIZE, j * CELL_SIZE, CELL_SIZE, CELL_SIZE, true)
end
end
end
end
local function is_map(x, y)
return cells[x] and cells[x][y] == 1
end
local function is_wall(x, y)
return not is_map(x, y)
end
local function reduce_walls()
for x, _ in pairs(cells) do
for y, _ in pairs(cells[x]) do
-- Left
if is_wall(x - CELL_SIZE, y) then
add_tile(x - WALL_DELTA, y, WALL_DELTA, CELL_SIZE, false)
end
-- Right
if is_wall(x + CELL_SIZE, y) then
add_tile(x + CELL_SIZE, y, WALL_DELTA, CELL_SIZE, false)
end
-- Above
if is_wall(x, y - CELL_SIZE) then
add_tile(x - WALL_DELTA, y - WALL_DELTA, CELL_SIZE + 2 * WALL_DELTA, WALL_DELTA, false)
end
-- Below
if is_wall(x, y + CELL_SIZE) then
add_tile(x - WALL_DELTA, y + CELL_SIZE, CELL_SIZE + 2 * WALL_DELTA, WALL_DELTA, false)
end
end
end
end
local function remove_chunk(surface, area)
local tiles = {}
for x = area.left_top.x, area.right_bottom.x - 1 do
for y = area.left_top.y, area.right_bottom.y - 1 do
insert(tiles, { name = 'out-of-map', position = { x = x, y = y } })
end
end
surface.set_tiles(tiles)
end
Maze.on_init = function()
if not configuration.enabled then
return
end
primitives.walk_seed_w = math_random(1, MAZE_SIZE) * 2
primitives.walk_seed_h = math_random(1, MAZE_SIZE) * 2
make_maze(MAZE_SIZE, MAZE_SIZE)
reduce_walls()
render()
end
Maze.set_wall_tiles = function(surface, area)
if not configuration.enabled then
return
end
local pos = area.left_top
if maze_walls[pos.x + primitives.max / 2 .. '/' .. pos.y + primitives.max / 2] then
remove_chunk(surface, area)
return true
end
return
end
Maze.debug_maze = function(surface, show_tile_renders)
local _max = primitives.max
local draw_text = rendering.draw_text
local tiles, spawn = {}, { x = 0, y = 0 }
surface.request_to_generate_chunks({0,0}, math.ceil(_max/32/32))
surface.force_generate_chunk_requests()
local params = {
text = 'Max: '.. _max,
surface = surface,
color = { b = 1 },
draw_on_ground = true,
scale_with_zoom = false,
target = spawn,
scale = 0.6
}
draw_text(params)
tiles[#tiles +1] = { name = 'lab-white', position = spawn}
params.color = { r = 1 }
params.scale = 0.5
for x = 1, _max/32 do
for y = 1, _max/32 do
if show_tile_renders and math_max(x, y) < 128 then
params.text = x .. '/' .. y
params.target = { x = x + 0.30, y = y + 0.30 }
draw_text(params)
end
tiles[#tiles +1] = { name = pixels[x] and pixels[x][y] and 'lab-white' or 'lab-dark-1', position = { x = x, y = y }}
end
end
surface.set_tiles(tiles)
end
return Maze

View File

@ -0,0 +1,186 @@
local math = require 'utils.math'
local configuration = require 'map_gen.maps.inception.configuration'.terrain
local Noise = require 'map_gen.shared.simplex_noise'
local simplex = Noise.d2
local math_abs = math.abs
local math_max = math.max
local math_min = math.min
local math_floor = math.floor
local math_random = math.random
local math_clamp = math.clamp
local BLACKLISTED_RESOURCES = configuration.blacklisted_resources
local BOUNDARY = 32 * configuration.boundary
local MIXED_ORES = configuration.mixed_ores
local NOISE_THRESHOLD = configuration.noise_threshold
local ORE_BASE_QUANTITY = configuration.ore_base_quantity
local ORE_CHUNK_SCALE = 32 * configuration.ore_chunk_scale
local NOISES = {
['dungeon_sewer'] = {{ modifier = 0.00055, weight = 1.05 }, { modifier = 0.0062, weight = 0.024 }, { modifier = 0.0275, weight = 0.00135 }},
['cave_miner_01'] = {{ modifier = 0.002, weight = 1 }, { modifier = 0.003, weight = 0.5 }, { modifier = 0.01, weight = 0.01 }, { modifier = 0.1, weight = 0.015 }},
['oasis'] = {{ modifier = 0.00165, weight = 1.1 }, { modifier = 0.00275, weight = 0.55 }, { modifier = 0.011, weight = 0.165 }, { modifier = 0.11, weight = 0.0187 }},
['dungeons'] = {{ modifier = 0.0028, weight = 0.99 }, { modifier = 0.0059, weight = 0.21 }},
['cave_rivers_2'] = {{ modifier = 0.0035, weight = 0.90 }, { modifier = 0.0088, weight = 0.15 }, { modifier = 0.051, weight = 0.011 }},
['cave_miner_02'] = {{ modifier = 0.006, weight = 1 }, { modifier = 0.02, weight = 0.15 }, { modifier = 0.25, weight = 0.025 }},
['large_caves'] = {{ modifier = 0.055, weight = 0.045 }, { modifier = 0.11, weight = 0.042 }, { modifier = 0.00363, weight = 1.05 }, { modifier = 0.01, weight = 0.23 }},
['no_rocks'] = {{ modifier = 0.00495, weight = 0.945 }, { modifier = 0.01665, weight = 0.2475 }, { modifier = 0.0435, weight = 0.0435 }, { modifier = 0.07968, weight = 0.0315 }},
['scrapyard'] = {{ modifier = 0.0055, weight = 1.1 }, { modifier = 0.011, weight = 0.385 }, { modifier = 0.055, weight = 0.253 }, { modifier = 0.11, weight = 0.121 }},
['scrapyard_2'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.044, weight = 0.165 }, { modifier = 0.242, weight = 0.055 }, { modifier = 0.055, weight = 0.352 }},
['smol_areas'] = {{ modifier = 0.0052, weight = 0.83 }, { modifier = 0.139, weight = 0.144 }, { modifier = 0.129, weight = 0.072 }, { modifier = 0.111, weight = 0.01 }},
['cave_rivers'] = {{ modifier = 0.0053, weight = 0.71 }, { modifier = 0.0086, weight = 0.24 }, { modifier = 0.070, weight = 0.025 }},
['small_caves'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.044, weight = 0.165 }, { modifier = 0.242, weight = 0.055 }},
['forest_location'] = {{ modifier = 0.0066, weight = 1.1 }, { modifier = 0.011, weight = 0.275 }, { modifier = 0.055, weight = 0.165 }, { modifier = 0.11, weight = 0.0825 }},
['small_caves_2'] = {{ modifier = 0.0099, weight = 1.1 }, { modifier = 0.055, weight = 0.275 }, { modifier = 0.275, weight = 0.055 }},
['forest_density'] = {{ modifier = 0.01, weight = 1 }, { modifier = 0.05, weight = 0.5 }, { modifier = 0.1, weight = 0.025 }},
['cave_ponds'] = {{ modifier = 0.014, weight = 0.77 }, { modifier = 0.18, weight = 0.085 }},
['no_rocks_2'] = {{ modifier = 0.0184, weight = 1.265 }, { modifier = 0.143, weight = 0.1045 }},
['mixed_ore'] = {{ modifier = 0.0042, weight = 1.000 }, { modifier = 0.0310, weight = 0.080 }, { modifier = 0.1000, weight = 0.025 }},
}
local Terrain = {}
local noise_pattern = function(feature, position, seed)
local noise, d = 0, 0
local noise_weights = NOISES[feature]
for i = 1, #noise_weights do
local nw = noise_weights[i]
noise = noise + simplex(position.x * nw.modifier, position.y * nw.modifier, seed) * nw.weight
d = d + nw.weight
seed = seed + 10000
end
noise = noise / d
return noise
end
Terrain.reshape_land = function(surface, area)
if not configuration.enabled then
return
end
local left_top = area.left_top
local right_bottom = area.right_bottom
local seed = surface.map_gen_settings.seed
local count_entities = surface.count_entities_filtered
local function is_ore(position)
return count_entities { position = { x = position.x + 0.5, y = position.y + 0.5 }, type = 'resource', limit = 1 } > 0
end
local function do_tile(x, y)
local p = { x = x, y = y }
local cave_rivers = noise_pattern('cave_rivers', p, seed)
local no_rocks = noise_pattern('no_rocks', p, seed)
local cave_ponds = noise_pattern('cave_ponds', p, 2 * seed)
local small_caves = noise_pattern('dungeons', p, 2 * seed)
-- Chasms
if cave_ponds < 0.110 and cave_ponds > 0.112 then
if small_caves > 0.5 or small_caves < -0.5 then
return { name = 'out-of-map', position = p }
end
end
-- Rivers
if cave_rivers < 0.044 and cave_rivers > -0.072 then
if cave_ponds > 0.1 then
if not is_ore(p) then
return { name = 'water-shallow', position = p }
else
return { name = 'cyan-refined-concrete', position = p }
end
end
end
-- Water Ponds
if cave_ponds > 0.6 then
if cave_ponds > 0.74 then
return { name = 'acid-refined-concrete', position = p }
end
if not is_ore(p) then
return { name = 'green-refined-concrete', position = p }
else
return { name = 'cyan-refined-concrete', position = p }
end
end
if cave_ponds > 0.622 then
if cave_ponds > 0.542 then
if cave_rivers > -0.302 then
return { name = 'refined-hazard-concrete-right', position = p }
end
end
end
-- Worm oil
if no_rocks < 0.029 and no_rocks > -0.245 then
if small_caves > 0.081 then
return { name = 'brown-refined-concrete', position = p }
end
end
-- Chasms2
if small_caves < -0.54 and cave_ponds < -0.5 then
if not is_ore(p) then
return { name = 'black-refined-concrete', position = p }
end
end
end
local tiles = {}
for x = 0, math_min(right_bottom.x - left_top.x, 31) do
for y = 0, 31 do
local tile = do_tile(left_top.x + x, left_top.y + y)
if tile then
tiles[#tiles + 1] = tile
end
end
end
surface.set_tiles(tiles, true)
end
Terrain.mixed_resources = function(surface, area)
if not configuration.enabled then
return
end
local left_top = area.left_top
local right_bottom = area.right_bottom
local seed = surface.map_gen_settings.seed
local create_entity = surface.create_entity
local can_place_entity = surface.can_place_entity
local find_entities_filtered = surface.find_entities_filtered
local function clear_ore(position)
for _, resource in pairs(find_entities_filtered { position = position, type = 'resource' }) do
if BLACKLISTED_RESOURCES[resource.name] then
return false
end
resource.destroy()
end
return true
end
local distance = math_max(math_abs(left_top.y), math_abs(right_bottom.y), math_abs(left_top.x), math_abs(right_bottom.x))
local chunks = math_clamp(math_abs((distance - BOUNDARY) / ORE_CHUNK_SCALE), 1, 100)
chunks = math_random(chunks, chunks + 4)
for x = 0, 31 do
for y = 0, 31 do
local position = { x = left_top.x + x, y = left_top.y + y }
if can_place_entity({ name = 'iron-ore', position = position }) then
local noise = noise_pattern('mixed_ore', position, seed)
if math_abs(noise) > NOISE_THRESHOLD then
local idx = math_floor(noise * 25 + math_abs(position.x) * 0.05) % #MIXED_ORES + 1
local amount = ORE_BASE_QUANTITY * chunks * 35 + math_random(100)
if clear_ore(position) then
create_entity({ name = MIXED_ORES[idx], position = position, amount = amount })
end
end
end
end
end
end
return Terrain

View File

@ -0,0 +1,58 @@
local Config = require 'config'
local Event = require 'utils.event'
local RS = require 'map_gen.shared.redmew_surface'
local ScenarioInfo = require 'features.gui.info'
local Maze = require 'map_gen.maps.inception.modules.maze'
local Terrain = require 'map_gen.maps.inception.modules.terrain'
-- == MAP CONFIG ==============================================================
Config.redmew_surface.enabled = false
Config.market.enabled = false
Config.player_rewards.enabled = false
Config.player_shortcuts.enabled = true
Config.dump_offline_inventories.enabled = true
-- == MAP INFO ================================================================
ScenarioInfo.set_map_name('Inception')
ScenarioInfo.set_map_description([[
An idea is like a virus. Resilient. Highly contagious. And even the smallest seed of an idea can grow. It can grow to define or destroy you.
]])
ScenarioInfo.set_map_extra_info([[
Prepare to embark on a mind-bending journey through the vast possibilities of automation and ingenuity! In this unique scenario, you awaken in the heart of an intricate labyrinth that twists and turns in a dreamlike reality. With indestructible walls, every corner seemingly leads to new surprises and challenges.
Your mission is to navigate this complex maze, unlocking the secrets hidden within its depths, and ultimately find your way to freedom. Collect resources, construct powerful factories, and harness advanced technologies as you unravel the mysteries of this dreamlike world. However, bewarethe maze is alive with distractions and traps created by the very fabric of the environment.
Every decision you make will ripple through the labyrinth, shaping your path and determining your fate. Will you conquer the challenges and forge a thriving factory in this maze, or will you become lost in the dreams of Nauvis? The journey begins nowawaken your potential, and let the adventure unfold!
The [color=red]RedMew[/color] team
]])
ScenarioInfo.set_new_info([[
2024-11-12:
- Added inception maze scenario
]])
-- == EVENTS ==================================================================
Event.on_init(function()
Maze.on_init()
--Maze.debug_maze(game.surfaces.nauvis, true)
end)
Event.add(defines.events.on_chunk_generated, function(event)
local surface, area = event.surface, event.area
if surface ~= RS.get_surface() then
return
end
-- Make maze walls
if Maze.set_wall_tiles(surface, area) then
return
end
-- Add mixed patches
Terrain.mixed_resources(surface, area)
-- Add special tiles
Terrain.reshape_land(surface, area)
end)
-- ============================================================================

View File

@ -0,0 +1 @@
return require 'map_gen.maps.inception.scenario'