diff --git a/map_gen/shared/builders.lua b/map_gen/shared/builders.lua index 6970930b..a282572d 100644 --- a/map_gen/shared/builders.lua +++ b/map_gen/shared/builders.lua @@ -1,5 +1,4 @@ -- helpers - tau = 2 * math.pi deg_to_rad = tau / 360 function degrees(angle) @@ -7,7 +6,6 @@ function degrees(angle) end -- shape builders - function empty_builder(x, y) return false end @@ -124,9 +122,9 @@ function decompress(pic) local data = pic.data local width = pic.width local height = pic.height - + local uncompressed = {} - + for y = 1, height do local row = data[y] local u_row = {} @@ -135,14 +133,14 @@ function decompress(pic) for index = 1, #row, 2 do local pixel = tile_map[row[index]] local count = row[index + 1] - + for i = 1, count do u_row[x] = pixel x = x + 1 end end end - + return {width = width, height = height, data = uncompressed} end @@ -150,7 +148,7 @@ function picture_builder(pic) local data = pic.data local width = pic.width local height = pic.height - + -- the plus one is because lua tables are one based. local half_width = math.floor(width / 2) + 1 local half_height = math.floor(height / 2) + 1 @@ -159,7 +157,7 @@ function picture_builder(pic) y = math.floor(y) local x2 = x + half_width local y2 = y + half_height - + if y2 > 0 and y2 <= height and x2 > 0 and x2 <= width then local pixel = data[y2][x2] return pixel @@ -170,7 +168,6 @@ function picture_builder(pic) end -- transforms and shape helpers - function translate(builder, x_offset, y_offset) return function(x, y, world_x, world_y, surface) return builder(x - x_offset, y - y_offset, world_x, world_y, surface) @@ -312,6 +309,17 @@ function choose(condition, true_shape, false_shape) end end +function shape_or_else(shape, else_shape) + return function(local_x, local_y, world_x, world_y, surface) + local tile, entity = shape(local_x, local_y, world_x, world_y, surface) + if (tile) then + return tile, entity + else + return else_shape(local_x, local_y, world_x, world_y, surface) + end + end +end + function linear_grow(shape, size) local half_size = size / 2 return function(local_x, local_y, world_x, world_y, surface) @@ -319,10 +327,10 @@ function linear_grow(shape, size) local n = math.ceil((math.sqrt(8 * t + 1) - 1) / 2) local t_upper = n * (n + 1) * 0.5 local t_lower = t_upper - n - + local y = (local_y - size * (t_lower + n / 2 - 0.5)) / n local x = local_x / n - + return shape(x, y, world_x, world_y, surface) end end @@ -333,24 +341,24 @@ function grow(in_shape, out_shape, size, offset) local tx = math.ceil(math.abs(local_x) / half_size) local ty = math.ceil(math.abs(local_y) / half_size) local t = math.max(tx, ty) - + local tile, entity - + for i = t, 2.5 * t, 1 do local out_t = 1 / (i - offset) local in_t = 1 / i - + tile = out_shape(out_t * local_x, out_t * local_y, world_x, world_y, surface) if tile then return false end - + tile, entity = in_shape(in_t * local_x, in_t * local_y, world_x, world_y, surface) if tile then return tile, entity end end - + return false end end @@ -359,20 +367,20 @@ function project(shape, size, r) local ln_r = math.log(r) local r2 = 1 / (r - 1) local a = 1 / size - + return function(local_x, local_y, world_x, world_y, surface) local offset = 0.5 * size local sn = math.ceil(local_y + offset) - + local n = math.ceil(math.log((r - 1) * sn * a + 1) / ln_r - 1) local rn = r ^ n local rn2 = 1 / rn local c = size * rn - + local sn_upper = size * (r ^ (n + 1) - 1) * r2 local x = local_x * rn2 local y = (local_y - (sn_upper - 0.5 * c) + offset) * rn2 - + return shape(x, y, world_x, world_y, surface) end end @@ -382,61 +390,60 @@ function project_overlap(shape, size, r) local r2 = 1 / (r - 1) local a = 1 / size local offset = 0.5 * size - + return function(local_x, local_y, world_x, world_y, surface) local sn = math.ceil(local_y + offset) - + local n = math.ceil(math.log((r - 1) * sn * a + 1) / ln_r - 1) local rn = r ^ n local rn2 = 1 / rn local c = size * rn - + local sn_upper = size * (r ^ (n + 1) - 1) * r2 local x = local_x * rn2 local y = (local_y - (sn_upper - 0.5 * c) + offset) * rn2 - + local tile local entity - + tile, entity = shape(x, y, world_x, world_y, surface) if tile then return tile, entity end - + local n_above = n - 1 local rn_above = rn / r local rn2_above = 1 / rn_above local c_above = size * rn_above - + local sn_upper_above = sn_upper - c local x_above = local_x * rn2_above local y_above = (local_y - (sn_upper_above - 0.5 * c_above) + offset) * rn2_above - + tile, entity = shape(x_above, y_above, world_x, world_y, surface) if tile then return tile, entity end - + local n_below = n + 1 local rn_below = rn * r local rn2_below = 1 / rn_below local c_below = size * rn_below - + local sn_upper_below = sn_upper + c_below local x_below = local_x * rn2_below local y_below = (local_y - (sn_upper_below - 0.5 * c_below) + offset) * rn2_below - + return shape(x_below, y_below, world_x, world_y, surface) end end -- ore generation. - -- builder is the shape of the ore patch. function resource_module_builder(builder, resource_type, amount_function) amount_function = amount_function or function(a, b) - return 603 - end + return 603 + end return function(x, y, world_x, world_y, surface) if builder(x, y, world_x, world_y, surface) then return { @@ -463,7 +470,6 @@ function builder_with_resource(land_builder, resource_module) end -- pattern builders. - function single_pattern_builder(shape, width, height) shape = shape or empty_builder local half_width = width / 2 @@ -473,11 +479,11 @@ function single_pattern_builder(shape, width, height) else half_height = half_width end - + return function(local_x, local_y, world_x, world_y, surface) local_y = ((local_y + half_height) % height) - half_height local_x = ((local_x + half_width) % width) - half_width - + return shape(local_x, local_y, world_x, world_y, surface) end end @@ -491,11 +497,11 @@ function single_pattern_overlap_builder(shape, width, height) else half_height = half_width end - + return function(local_x, local_y, world_x, world_y, surface) local_y = ((local_y + half_height) % height) - half_height local_x = ((local_x + half_width) % width) - half_width - + return shape(local_x, local_y, world_x, world_y, surface) or shape(local_x + width, local_y, world_x, world_y, surface) or shape(local_x - width, local_y, world_x, world_y, surface) or @@ -507,10 +513,10 @@ end function single_x_pattern_builder(shape, width) shape = shape or empty_builder local half_width = width / 2 - + return function(local_x, local_y, world_x, world_y, surface) local_x = ((local_x + half_width) % width) - half_width - + return shape(local_x, local_y, world_x, world_y, surface) end end @@ -518,10 +524,10 @@ end function single_y_pattern_builder(shape, height) shape = shape or empty_builder local half_height = height / 2 - + return function(local_x, local_y, world_x, world_y, surface) local_y = ((local_y + half_height) % height) - half_height - + return shape(local_x, local_y, world_x, world_y, surface) end end @@ -529,25 +535,68 @@ end function grid_pattern_builder(pattern, columns, rows, width, height) local half_width = width / 2 local half_height = height / 2 - + return function(local_x, local_y, world_x, world_y, surface) local local_y2 = ((local_y + half_height) % height) - half_height local row_pos = math.floor(local_y / height + 0.5) local row_i = row_pos % rows + 1 local row = pattern[row_i] or {} - + local local_x2 = ((local_x + half_width) % width) - half_width local col_pos = math.floor(local_x / width + 0.5) local col_i = col_pos % columns + 1 - + local shape = row[col_i] or empty_builder return shape(local_x2, local_y2, world_x, world_y, surface) end end +function grid_pattern_overlap_builder(pattern, columns, rows, width, height) + local half_width = width / 2 + local half_height = height / 2 + + return function(local_x, local_y, world_x, world_y, surface) + local local_y2 = ((local_y + half_height) % height) - half_height + local row_pos = math.floor(local_y / height + 0.5) + local row_i = row_pos % rows + 1 + local row = pattern[row_i] or {} + + local local_x2 = ((local_x + half_width) % width) - half_width + local col_pos = math.floor(local_x / width + 0.5) + local col_i = col_pos % columns + 1 + + local shape = row[col_i] or empty_builder + + local tile, entity = shape(local_x2, local_y2, world_x, world_y, surface) + if tile then return tile, entity end + + local col_i_left = (col_pos - 1) % columns + 1 + shape = row[col_i_left] or empty_builder + tile, entity = shape(local_x2 + width, local_y2, world_x, world_y, surface) + if tile then return tile, entity end + + local col_i_right = (col_pos + 1) % columns + 1 + shape = row[col_i_right] or empty_builder + tile, entity = shape(local_x2 - width, local_y2, world_x, world_y, surface) + if tile then return tile, entity end + + local row_i_up = (row_pos - 1) % rows + 1 + local row_up = pattern[row_i_up] or {} + shape = row_up[col_i] + tile, entity = shape(local_x2, local_y2 + height, world_x, world_y, surface) + if tile then return tile, entity end + + local row_i_down = (row_pos + 1) % rows + 1 + local row_down = pattern[row_i_down] or {} + shape = row_down[col_i] + tile, entity = shape(local_x2, local_y2 - height, world_x, world_y, surface) + if tile then return tile, entity end + end +end + function segment_pattern_builder(pattern) local count = #pattern - + return function(local_x, local_y, world_x, world_y, surface) local angle = math.atan2(-local_y, local_x) local index = math.floor(angle / tau * count) % count + 1 @@ -557,7 +606,6 @@ function segment_pattern_builder(pattern) end -- tile converters - function change_tile(builder, old_tile, new_tile) return function(local_x, local_y, world_x, world_y, surface) local tile, entity = builder(local_x, local_y, world_x, world_y, surface) @@ -624,6 +672,16 @@ function spawn_fish(builder, spawn_rate) end end +function spawn_entity(builder, name) + return function(local_x, local_y, world_x, world_y, surface) + if builder(local_x, local_y, world_x, world_y, surface) then + return {name = name, position = {world_x, world_y}} + else + return nil + end + end +end + function apply_effect(builder, func) return function(local_x, local_y, world_x, world_y, surface) local tile, entity = builder(local_x, local_y, world_x, world_y, surface)