diff --git a/worldgen-c/bin/worldgen b/worldgen-c/bin/worldgen index e2a4ac7..8adb09c 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 e3288a0..f69c0a6 100644 --- a/worldgen-c/src/worldgen.c +++ b/worldgen-c/src/worldgen.c @@ -131,6 +131,7 @@ static inline double smoothstep01(double v) { } static int ground_slope(worldgen_ctx *ctx, int x, int z); +static int is_dry_beach_sand_patch(worldgen_ctx *ctx, const column_data *data, int world_x, int world_z); static uint16_t select_surface_block(worldgen_ctx *ctx, const column_data *data, int world_x, int world_z); static void generate_chunk_trails(worldgen_ctx *ctx, int chunk_x, int chunk_z, column_data columns[CHUNK_SIZE][CHUNK_SIZE], chunk_data *out); static void generate_chunk_redwood_floor(worldgen_ctx *ctx, int chunk_x, int chunk_z, @@ -937,6 +938,36 @@ static int generate_coal(worldgen_ctx *ctx, int x, int y, int z, int column_heig // --------------------------------------------------------------------------- // Terrain block generation // --------------------------------------------------------------------------- +static int is_dry_beach_sand_patch(worldgen_ctx *ctx, const column_data *data, int world_x, int world_z) { + if (data->has_water && data->water_surface >= data->height) return 0; + if (ground_slope(ctx, world_x, world_z) > 2) return 0; + + int nearest_water_dist2 = 9999; + int shore_level = ctx->sea_level; + for (int dx = -7; dx <= 7; ++dx) { + for (int dz = -7; dz <= 7; ++dz) { + int dist2 = dx * dx + dz * dz; + if (dist2 == 0 || dist2 > 49) continue; + column_data neighbor = get_column_data(ctx, world_x + dx, world_z + dz); + if (!neighbor.has_water || neighbor.water_surface < neighbor.height) continue; + if (data->height < neighbor.water_surface - 1 || data->height > neighbor.water_surface + 4) continue; + if (dist2 < nearest_water_dist2) { + nearest_water_dist2 = dist2; + shore_level = neighbor.water_surface; + } + } + } + if (nearest_water_dist2 == 9999) return 0; + if (data->height > shore_level + 4) return 0; + + double broad = simplex_noise2(&ctx->noise, (world_x + 72000) * 0.045, (world_z - 72000) * 0.045) * 0.5 + 0.5; + double ragged = simplex_noise2(&ctx->noise, (world_x - 81000) * 0.16, (world_z + 81000) * 0.16) * 0.5 + 0.5; + double patch = broad * 0.7 + ragged * 0.3; + double near_bonus = clamp01((18.0 - (double)nearest_water_dist2) / 18.0) * 0.18; + double height_penalty = clamp01((double)(data->height - shore_level) / 4.0) * 0.16; + return patch + near_bonus - height_penalty > 0.56; +} + static uint16_t select_surface_block(worldgen_ctx *ctx, const column_data *data, int world_x, int world_z) { if (data->has_water && data->water_surface >= data->height) { int slope = ground_slope(ctx, world_x, world_z); @@ -964,6 +995,9 @@ static uint16_t select_surface_block(worldgen_ctx *ctx, const column_data *data, double noise = simplex_noise2(&ctx->noise, world_x * 0.02, world_z * 0.02) * 0.5 + 0.5; if (noise < t) return BLOCK_SNOW; } + if (is_dry_beach_sand_patch(ctx, data, world_x, world_z)) { + return BLOCK_SAND; + } if (data->biome == BIOME_REDWOOD_FOREST) { int slope = ground_slope(ctx, world_x, world_z); if (slope >= 5) return BLOCK_STONE; @@ -3973,7 +4007,15 @@ void worldgen_generate_chunk(worldgen_ctx *ctx, int chunk_x, int chunk_z, chunk_ out->blocks[y][dx][dz] = BLOCK_DIRT; } if (cd.height >= 0 && cd.height < CHUNK_HEIGHT) { - out->blocks[cd.height][dx][dz] = select_surface_block(ctx, &cd, world_x, world_z); + uint16_t surface = select_surface_block(ctx, &cd, world_x, world_z); + if (surface == BLOCK_SAND) { + int sand_bottom = cd.height - 2; + if (sand_bottom < dirt_start) sand_bottom = dirt_start; + for (int y = sand_bottom; y < cd.height; ++y) { + if (y > 0 && y < CHUNK_HEIGHT) out->blocks[y][dx][dz] = BLOCK_SAND; + } + } + out->blocks[cd.height][dx][dz] = surface; } if (cd.has_water) { int water_top = cd.water_surface;