diff --git a/worldgen-c/bin/worldgen b/worldgen-c/bin/worldgen index a705f9a..26ca610 100755 Binary files a/worldgen-c/bin/worldgen and b/worldgen-c/bin/worldgen differ diff --git a/worldgen-c/src/worldgen.c b/worldgen-c/src/worldgen.c index dd9c8f8..6f2fe21 100644 --- a/worldgen-c/src/worldgen.c +++ b/worldgen-c/src/worldgen.c @@ -2000,7 +2000,9 @@ static void generate_tree(worldgen_ctx *ctx, const tree_archetype *arch, int x, double maturity, rng_state *rng, block_list *out) { if (!arch) return; int height = rng_range_inclusive(rng, arch->min_height, arch->max_height); - double height_scale = 0.62 + clamp01(maturity) * 0.38; + /* Preserve the proportions expected by each canopy builder; maturity now + * adds subtle height variation without reducing young trees to bare poles. */ + double height_scale = 0.86 + clamp01(maturity) * 0.14; height = (int)llround((double)height * height_scale); if (height < 4) height = 4; if (!can_place_tree(ctx, x, y, z, height, arch->space_radius, arch->canopy_extra)) { @@ -2972,10 +2974,10 @@ static void generate_chunk_cabins(worldgen_ctx *ctx, int chunk_x, int chunk_z, c double dist2 = nearest_trail_distance2(ctx, world_cx, world_cz, 1.0e12); double bonus = 0.0; double dist = sqrt(dist2); - if (dist < 640.0) { - double t = clamp01(1.0 - dist / 640.0); - bonus += 0.45 * t; - } + /* Favor a wooded setback instead of putting the building footprint + * directly on the centerline. The spur still handles the connection. */ + if (dist < 8.0) bonus -= (8.0 - dist) * 0.9; + else if (dist < 96.0) bonus += 0.45 * clamp01(1.0 - fabs(dist - 20.0) / 76.0); score += bonus; } if (score > best_score) { @@ -3304,14 +3306,14 @@ static void generate_chunk_trees(worldgen_ctx *ctx, int chunk_x, int chunk_z, ch } /* Openings retain a few isolated field trees, while forest interiors * become substantially denser than their regenerating edges. */ - spawn_prob = (0.035 + density * 0.78) * altitude_factor; + spawn_prob = (0.08 + density * 0.9) * altitude_factor; if (is_old_growth) { spawn_prob = clamp01(0.25 + grove_mask * 0.7) * altitude_factor; } } if (rng_next_f64(&rng) > spawn_prob) continue; - double spacing = is_redwood ? (10.0 + (1.0 - stand_density) * 4.0) - : (4.5 + (1.0 - cover) * 4.5 + maturity * 1.5); + double spacing = is_redwood ? (8.0 + (1.0 - stand_density) * 3.0) + : (3.5 + (1.0 - cover) * 2.5 + maturity * 0.75); if (!tree_wins_spacing(ctx, gx, gz, grid, candidate_x, candidate_z, spacing)) continue; block_list tmp; @@ -3582,11 +3584,15 @@ static double nearest_trail_distance2(worldgen_ctx *ctx, int x, int z, double fa for (size_t i = 0; i < ctx->trail_segment_count; ++i) { trail_segment *seg = &ctx->trail_segments[i]; if (!seg || seg->count < 1 || !seg->points) continue; - for (int p = 0; p < seg->count; ++p) { - int tx = seg->points[p * 2]; - int tz = seg->points[p * 2 + 1]; - double dx = (double)(tx - x); - double dz = (double)(tz - z); + for (int p = 0; p < seg->count - 1; ++p) { + double d2 = point_segment_distance2((double)x, (double)z, + (double)seg->points[p * 2], (double)seg->points[p * 2 + 1], + (double)seg->points[(p + 1) * 2], (double)seg->points[(p + 1) * 2 + 1]); + if (d2 < best) best = d2; + } + if (seg->count == 1) { + double dx = (double)(seg->points[0] - x); + double dz = (double)(seg->points[1] - z); double d2 = dx * dx + dz * dz; if (d2 < best) best = d2; }