#include "game/levelgen.h"
#include "engine/parallax.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* ═══════════════════════════════════════════════════
 *  RNG — simple xorshift32 for deterministic generation
 * ═══════════════════════════════════════════════════ */

static uint32_t s_rng_state;

static void rng_seed(uint32_t seed) {
    s_rng_state = seed ? seed : (uint32_t)time(NULL);
    if (s_rng_state == 0) s_rng_state = 1;
}

static uint32_t rng_next(void) {
    uint32_t x = s_rng_state;
    x ^= x << 13;
    x ^= x >> 17;
    x ^= x << 5;
    s_rng_state = x;
    return x;
}

/* Random int in [min, max] inclusive */
static int rng_range(int min, int max) {
    if (min >= max) return min;
    return min + (int)(rng_next() % (uint32_t)(max - min + 1));
}

/* Random float in [0, 1) */
static float rng_float(void) {
    return (float)(rng_next() & 0xFFFF) / 65536.0f;
}

/* ═══════════════════════════════════════════════════
 *  Tile IDs used in generation
 *  (must match TILEDEF entries we set up)
 * ═══════════════════════════════════════════════════ */

#define TILE_EMPTY    0
#define TILE_SOLID_1  1   /* main ground/wall tile      */
#define TILE_SOLID_2  2   /* variant solid tile          */
#define TILE_SOLID_3  3   /* variant solid tile          */
#define TILE_PLAT     4   /* one-way platform            */

/* ═══════════════════════════════════════════════════
 *  Segment types and templates
 *
 *  Each segment is a rectangular section of tiles
 *  with a fixed height (the full level height) and
 *  a variable width. Segments are stitched left-to-right.
 *
 *  The level has a standard height of 23 tiles
 *  (matching level01 — fits ~1.0 screen vertically).
 *  Ground is at row 20-22 (3 tiles thick).
 * ═══════════════════════════════════════════════════ */

#define SEG_HEIGHT   23
#define GROUND_ROW   20    /* first ground row (single-screen levels)  */
#define FLOOR_ROWS   3     /* rows 20, 21, 22 */

/* ── Height zones for tall levels ─────────────────── */
#define TALL_HEIGHT  46    /* two screens tall */
#define ZONE_HIGH_GROUND  17   /* ground row for HIGH zone (upper area) */
#define ZONE_LOW_GROUND   43   /* ground row for LOW zone (lower area)  */

typedef enum SegmentType {
    SEG_FLAT,           /* flat ground, maybe some platforms above   */
    SEG_PIT,            /* gap in the ground — must jump across      */
    SEG_PLATFORMS,      /* vertical platforming section              */
    SEG_CORRIDOR,       /* walled corridor with ceiling              */
    SEG_ARENA,          /* open area, wider, good for combat         */
    SEG_SHAFT,          /* vertical shaft with platforms inside      */
    SEG_TRANSITION,     /* doorway/airlock between themes            */
    SEG_CLIMB,          /* vertical connector between height zones   */
    SEG_TYPE_COUNT
} SegmentType;

/* ═══════════════════════════════════════════════════
 *  Tile placement helpers
 * ═══════════════════════════════════════════════════ */

static void set_tile(uint16_t *layer, int map_w, int map_h,
                     int x, int y, uint16_t id) {
    if (x >= 0 && x < map_w && y >= 0 && y < map_h) {
        layer[y * map_w + x] = id;
    }
}

static void fill_rect(uint16_t *layer, int map_w, int map_h,
                       int x0, int y0, int x1, int y1, uint16_t id) {
    for (int y = y0; y <= y1; y++) {
        for (int x = x0; x <= x1; x++) {
            set_tile(layer, map_w, map_h, x, y, id);
        }
    }
}

static void fill_ground(uint16_t *layer, int map_w, int map_h,
                         int x0, int x1, int ground_row) {
    fill_rect(layer, map_w, map_h, x0, ground_row, x1, map_h - 1, TILE_SOLID_1);
}

/* Add a random solid variant tile to break up visual monotony */
static uint16_t random_solid(void) {
    int r = rng_range(0, 5);
    if (r == 0) return TILE_SOLID_2;
    if (r == 1) return TILE_SOLID_3;
    return TILE_SOLID_1;
}

/* ═══════════════════════════════════════════════════
 *  Entity spawn helpers
 * ═══════════════════════════════════════════════════ */

static void add_entity(Tilemap *map, const char *type, int tile_x, int tile_y) {
    if (map->entity_spawn_count >= MAX_ENTITY_SPAWNS) return;
    EntitySpawn *es = &map->entity_spawns[map->entity_spawn_count];
    strncpy(es->type_name, type, 31);
    es->type_name[31] = '\0';
    es->x = (float)(tile_x * TILE_SIZE);
    es->y = (float)(tile_y * TILE_SIZE);
    map->entity_spawn_count++;
}

/* ═══════════════════════════════════════════════════
 *  Segment generators
 *
 *  Each writes tiles into the collision layer starting
 *  at column offset `x0` for `width` columns.
 *  Returns the effective ground connectivity at the
 *  right edge (row of the topmost ground tile, or -1
 *  for no ground at the edge).
 * ═══════════════════════════════════════════════════ */

/* SEG_FLAT: solid ground, optionally with platforms and enemies */
static void gen_flat(Tilemap *map, int x0, int w, int ground_row,
                     float difficulty, LevelTheme theme) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    fill_ground(col, mw, mh, x0, x0 + w - 1, ground_row);

    /* Random platforms above */
    int num_plats = rng_range(0, 2);
    for (int i = 0; i < num_plats; i++) {
        int px = x0 + rng_range(1, w - 5);
        int py = ground_row - rng_range(3, 7);
        int pw = rng_range(3, 5);
        for (int j = 0; j < pw && px + j < x0 + w; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }

        /* Maybe a grunt on the platform */
        if (difficulty > 0.3f && rng_float() < difficulty * 0.5f) {
            add_entity(map, "grunt", px + pw / 2, py - 1);
        }
    }

    /* Ground enemies — Mars themes get chargers */
    if (rng_float() < 0.4f + difficulty * 0.4f) {
        if (theme == THEME_MARS_BASE || theme == THEME_MARS_SURFACE) {
            add_entity(map, "charger", x0 + rng_range(2, w - 3), ground_row - 1);
        } else {
            add_entity(map, "grunt", x0 + rng_range(2, w - 3), ground_row - 1);
        }
    }

    /* Mars Base: laser turret on a platform */
    if (theme == THEME_MARS_BASE && difficulty > 0.3f && rng_float() < 0.5f) {
        add_entity(map, "laser_turret", x0 + rng_range(2, w - 3), ground_row - 5);
    }
}

/* SEG_PIT: gap in the ground the player must jump */
static void gen_pit(Tilemap *map, int x0, int w, int ground_row,
                    float difficulty, LevelTheme theme) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    int pit_start = rng_range(3, 5);
    int pit_width = rng_range(3, 5 + (int)(difficulty * 3));
    if (pit_width > w - 4) pit_width = w - 4;
    int pit_end = pit_start + pit_width;

    /* Ground before pit */
    fill_ground(col, mw, mh, x0, x0 + pit_start - 1, ground_row);
    /* Ground after pit */
    if (x0 + pit_end < x0 + w) {
        fill_ground(col, mw, mh, x0 + pit_end, x0 + w - 1, ground_row);
    }

    /* Hazard at pit bottom — theme dependent */
    if (difficulty > 0.2f && rng_float() < 0.5f) {
        int fx = x0 + pit_start + pit_width / 2;
        if (theme == THEME_PLANET_SURFACE || theme == THEME_PLANET_BASE ||
            theme == THEME_MARS_SURFACE) {
            /* Flame vents: natural hazard (surface) or industrial (base).
             * Pedestal at the bottom of the ground layer, not map bottom. */
            add_entity(map, "flame_vent", fx, ground_row);
            int ped_top = ground_row + FLOOR_ROWS - 2;
            int ped_bot = ground_row + FLOOR_ROWS - 1;
            fill_rect(col, mw, mh, fx - 1, ped_top, fx + 1, ped_bot, TILE_SOLID_1);
        } else if (theme == THEME_MARS_BASE) {
            /* Mars Base: force field + laser turret overlooking pit */
            add_entity(map, "force_field", fx, ground_row - 2);
            if (difficulty > 0.4f) {
                add_entity(map, "laser_turret", fx - 3, ground_row - 4);
            }
        } else {
            /* Space station: force field across the pit */
            add_entity(map, "force_field", fx, ground_row - 2);
        }
    }

    /* Stepping stones in wider pits */
    if (pit_width >= 5) {
        int sx = x0 + pit_start + pit_width / 2;
        if (theme == THEME_SPACE_STATION && rng_float() < 0.6f) {
            /* Moving platform instead of static stepping stones */
            add_entity(map, "platform", sx, ground_row - 2);
        } else {
            set_tile(col, mw, mh, sx, ground_row - 1, TILE_PLAT);
            set_tile(col, mw, mh, sx + 1, ground_row - 1, TILE_PLAT);
        }
    }
}

/* SEG_PLATFORMS: vertical platforming section */
static void gen_platforms(Tilemap *map, int x0, int w, int ground_row,
                          float difficulty, LevelTheme theme) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    /* Ground at bottom */
    fill_ground(col, mw, mh, x0, x0 + w - 1, ground_row);

    /* Stack of platforms ascending */
    int num_plats = rng_range(3, 5);
    /* Space station: more platforms, low gravity makes climbing easier */
    if (theme == THEME_SPACE_STATION) num_plats += 1;

    /* Ceiling row: platforms should not go above this */
    int ceil_row = ground_row - 17;
    if (ceil_row < 3) ceil_row = 3;

    for (int i = 0; i < num_plats; i++) {
        int py = ground_row - 3 - i * 3;
        if (py < ceil_row) break;
        int px = x0 + rng_range(1, w - 4);
        int pw = rng_range(2, 4);
        for (int j = 0; j < pw && px + j < x0 + w; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }
    }

    /* Moving platform — more common on stations, less on surface */
    float plat_chance = (theme == THEME_SPACE_STATION) ? 0.8f :
                        (theme == THEME_PLANET_SURFACE) ? 0.3f : 0.5f;
    if (rng_float() < plat_chance) {
        int py = ground_row - rng_range(5, 10);
        bool vertical = (theme == THEME_SPACE_STATION && rng_float() < 0.5f);
        add_entity(map, vertical ? "platform_v" : "platform", x0 + w / 2, py);
    }

    /* Aerial threat */
    if (difficulty > 0.3f && rng_float() < difficulty) {
        int fly_lo = ground_row - 15;
        int fly_hi = ground_row - 10;
        if (fly_lo < ceil_row) fly_lo = ceil_row;
        if (theme == THEME_PLANET_SURFACE || theme == THEME_MARS_SURFACE) {
            add_entity(map, "flyer", x0 + rng_range(2, w - 3), rng_range(fly_lo, fly_hi));
        } else if (theme == THEME_SPACE_STATION) {
            if (rng_float() < 0.5f) {
                add_entity(map, "turret", x0 + rng_range(2, w - 3), rng_range(fly_lo, fly_lo + 4));
            } else {
                add_entity(map, "flyer", x0 + rng_range(2, w - 3), rng_range(fly_lo, fly_hi));
            }
        } else if (theme == THEME_MARS_BASE) {
            /* Mars Base: turrets and laser turrets dominate */
            if (rng_float() < 0.6f) {
                add_entity(map, "laser_turret", x0 + rng_range(2, w - 3), rng_range(fly_lo, fly_lo + 4));
            } else {
                add_entity(map, "turret", x0 + rng_range(2, w - 3), rng_range(fly_lo, fly_lo + 4));
            }
        } else {
            add_entity(map, "flyer", x0 + rng_range(2, w - 3), rng_range(fly_lo, fly_hi));
        }
    }

    /* Fuel pickup on a high platform — reward for climbing */
    if (rng_float() < 0.45f) {
        int top_py = ground_row - 3 - (num_plats - 1) * 3;
        if (top_py >= ceil_row) {
            add_entity(map, "powerup_fuel", x0 + rng_range(2, w - 3), top_py - 1);
        }
    }
}

/* SEG_CORRIDOR: walled section with ceiling */
static void gen_corridor(Tilemap *map, int x0, int w, int ground_row,
                         float difficulty, LevelTheme theme) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    int ceil_row = ground_row - rng_range(5, 8);

    /* Ground */
    fill_ground(col, mw, mh, x0, x0 + w - 1, ground_row);

    /* Ceiling */
    fill_rect(col, mw, mh, x0, ceil_row - 2, x0 + w - 1, ceil_row, TILE_SOLID_1);

    /* Walls at edges (short, just to frame) */
    fill_rect(col, mw, mh, x0, ceil_row, x0, ground_row - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, ceil_row, x0 + w - 1, ground_row - 1, TILE_SOLID_1);

    /* Opening in left wall (1 tile above ground to enter) */
    set_tile(col, mw, mh, x0, ground_row - 1, TILE_EMPTY);
    set_tile(col, mw, mh, x0, ground_row - 2, TILE_EMPTY);
    set_tile(col, mw, mh, x0, ground_row - 3, TILE_EMPTY);

    /* Opening in right wall */
    set_tile(col, mw, mh, x0 + w - 1, ground_row - 1, TILE_EMPTY);
    set_tile(col, mw, mh, x0 + w - 1, ground_row - 2, TILE_EMPTY);
    set_tile(col, mw, mh, x0 + w - 1, ground_row - 3, TILE_EMPTY);

    /* Theme-dependent corridor hazards */
    if (theme == THEME_MARS_BASE) {
        /* Mars Base: laser turrets, turrets, and spawners */
        if (difficulty > 0.2f && rng_float() < 0.7f) {
            add_entity(map, "laser_turret", x0 + w / 2, ceil_row + 1);
        }
        if (difficulty > 0.4f && rng_float() < 0.5f) {
            add_entity(map, "turret", x0 + rng_range(2, w - 3), ceil_row + 1);
        }
        if (difficulty > 0.5f && rng_float() < 0.4f) {
            add_entity(map, "spawner", x0 + w / 2, ceil_row + 2);
        }
    } else if (theme == THEME_PLANET_BASE || theme == THEME_SPACE_STATION) {
        /* Tech environments: turrets and force fields */
        if (difficulty > 0.2f && rng_float() < 0.7f) {
            add_entity(map, "turret", x0 + w / 2, ceil_row + 1);
        }
        if (difficulty > 0.4f && rng_float() < 0.5f) {
            add_entity(map, "force_field", x0 + w / 2, ground_row - 1);
        }
    } else {
        /* Planet/Mars surface: flame vents leak through the floor */
        if (difficulty > 0.3f && rng_float() < 0.5f) {
            add_entity(map, "flame_vent", x0 + rng_range(2, w - 3), ground_row - 1);
        }
        /* Rare turret even on surface (crashed tech, scavenged) */
        if (difficulty > 0.5f && rng_float() < 0.3f) {
            add_entity(map, "turret", x0 + w / 2, ceil_row + 1);
        }
    }

    /* Patrol inside — Mars themes prefer chargers */
    if (rng_float() < 0.5f + difficulty * 0.3f) {
        if (theme == THEME_MARS_BASE || theme == THEME_MARS_SURFACE) {
            add_entity(map, "charger", x0 + rng_range(2, w - 3), ground_row - 1);
        } else {
            add_entity(map, "grunt", x0 + rng_range(2, w - 3), ground_row - 1);
        }
    }

    /* Health pickup near the exit — reward for surviving the corridor */
    if (difficulty > 0.3f && rng_float() < 0.35f) {
        add_entity(map, "powerup_hp", x0 + w - 3, ground_row - 1);
    }

    /* Fuel pickup hidden in the corridor */
    if (rng_float() < 0.3f) {
        add_entity(map, "powerup_fuel", x0 + rng_range(2, w - 3), ceil_row + 2);
    }
}

/* SEG_ARENA: wide open area, multiple enemies */
static void gen_arena(Tilemap *map, int x0, int w, int ground_row,
                      float difficulty, LevelTheme theme) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    fill_ground(col, mw, mh, x0, x0 + w - 1, ground_row);

    /* Raised platforms on sides */
    int plat_h = ground_row - rng_range(2, 4);
    fill_rect(col, mw, mh, x0, plat_h, x0 + 2, ground_row - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 3, plat_h, x0 + w - 1, ground_row - 1, TILE_SOLID_1);

    /* Central platform */
    int cp_y = ground_row - rng_range(4, 6);
    int cp_x = x0 + w / 2 - 2;
    for (int j = 0; j < 4; j++) {
        set_tile(col, mw, mh, cp_x + j, cp_y, TILE_PLAT);
    }

    /* Fly zone for aerial enemies */
    int fly_lo = ground_row - 12;
    int fly_hi = ground_row - 6;
    if (fly_lo < 3) fly_lo = 3;

    /* Multiple enemies — composition depends on theme */
    int num_enemies = 1 + (int)(difficulty * 3);
    for (int i = 0; i < num_enemies; i++) {
        float r = rng_float();
        if (theme == THEME_PLANET_SURFACE || theme == THEME_MARS_SURFACE) {
            /* Surface: mostly ground enemies, some chargers on Mars */
            if (r < 0.50f)
                add_entity(map, "grunt", x0 + rng_range(3, w - 4), ground_row - 1);
            else if (r < 0.75f && theme == THEME_MARS_SURFACE)
                add_entity(map, "charger", x0 + rng_range(3, w - 4), ground_row - 1);
            else
                add_entity(map, "flyer", x0 + rng_range(3, w - 4), rng_range(fly_lo, fly_hi));
        } else if (theme == THEME_MARS_BASE) {
            /* Mars Base: chargers, grunts, and flyers */
            if (r < 0.35f)
                add_entity(map, "charger", x0 + rng_range(3, w - 4), ground_row - 1);
            else if (r < 0.60f)
                add_entity(map, "grunt", x0 + rng_range(3, w - 4), ground_row - 1);
            else
                add_entity(map, "flyer", x0 + rng_range(3, w - 4), rng_range(fly_lo, fly_hi));
        } else if (theme == THEME_SPACE_STATION) {
            if (r < 0.35f)
                add_entity(map, "grunt", x0 + rng_range(3, w - 4), ground_row - 1);
            else
                add_entity(map, "flyer", x0 + rng_range(3, w - 4), rng_range(fly_lo, fly_hi));
        } else {
            if (r < 0.5f)
                add_entity(map, "grunt", x0 + rng_range(3, w - 4), ground_row - 1);
            else
                add_entity(map, "flyer", x0 + rng_range(3, w - 4), rng_range(fly_lo, fly_hi));
        }
    }

    /* Theme-dependent arena hazard */
    if (difficulty > 0.5f && rng_float() < 0.7f) {
        int side = rng_range(0, 1);
        int tx = side ? x0 + w - 2 : x0 + 1;
        if (theme == THEME_PLANET_SURFACE || theme == THEME_MARS_SURFACE) {
            add_entity(map, "flame_vent", x0 + w / 2, ground_row - 1);
        } else if (theme == THEME_MARS_BASE) {
            /* Mars Base: laser turret + spawner in arenas */
            add_entity(map, "laser_turret_track", tx, plat_h - 1);
            if (difficulty > 0.6f) {
                add_entity(map, "spawner", x0 + w / 2, plat_h - 1);
            }
        } else {
            add_entity(map, "turret", tx, plat_h - 1);
        }
    }

    /* Powerup reward on the central platform (earned by clearing the arena) */
    if (rng_float() < 0.5f) {
        if (difficulty > 0.6f && rng_float() < 0.25f) {
            add_entity(map, "powerup_drone", cp_x + 2, cp_y - 1);
        } else if (rng_float() < 0.35f) {
            add_entity(map, "powerup_fuel", cp_x + 2, cp_y - 1);
        } else {
            add_entity(map, "powerup_hp", cp_x + 2, cp_y - 1);
        }
    }
}

/* SEG_SHAFT: vertical shaft with platforms to climb */
static void gen_shaft(Tilemap *map, int x0, int w, int ground_row,
                      float difficulty, LevelTheme theme) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    /* Ground at bottom */
    fill_ground(col, mw, mh, x0, x0 + w - 1, ground_row);

    /* Ceiling row for the shaft */
    int ceil_row = ground_row - 17;
    if (ceil_row < 3) ceil_row = 3;

    /* Walls on both sides forming a shaft */
    int shaft_left = x0 + 1;
    int shaft_right = x0 + w - 2;
    fill_rect(col, mw, mh, x0, ceil_row, x0, ground_row - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, ceil_row, x0 + w - 1, ground_row - 1, TILE_SOLID_1);

    /* Opening at top */
    set_tile(col, mw, mh, x0, ceil_row, TILE_EMPTY);
    set_tile(col, mw, mh, x0 + w - 1, ceil_row, TILE_EMPTY);

    /* Openings at bottom to enter */
    for (int r = ground_row - 3; r < ground_row; r++) {
        set_tile(col, mw, mh, x0, r, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, r, TILE_EMPTY);
    }

    /* Alternating platforms up the shaft */
    int inner_w = shaft_right - shaft_left + 1;
    for (int i = 0; i < 5; i++) {
        int py = ground_row - 3 - i * 3;
        if (py < ceil_row + 1) break;
        bool left_side = (i % 2 == 0);
        int px = left_side ? shaft_left : shaft_right - 2;
        int pw = (inner_w > 4) ? 3 : 2;
        for (int j = 0; j < pw; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }
    }

    /* Vertical moving platform — very common in stations */
    float vplat_chance = (theme == THEME_SPACE_STATION) ? 0.8f : 0.4f;
    if (rng_float() < vplat_chance) {
        int mid_y = (ceil_row + ground_row) / 2;
        add_entity(map, "platform_v", x0 + w / 2, mid_y);
    }

    /* Bottom hazard — theme dependent */
    if (difficulty > 0.3f && rng_float() < 0.5f) {
        if (theme == THEME_PLANET_SURFACE || theme == THEME_PLANET_BASE ||
            theme == THEME_MARS_SURFACE) {
            add_entity(map, "flame_vent", x0 + w / 2, ground_row - 1);
        } else if (theme == THEME_MARS_BASE) {
            /* Mars Base: force field + optional laser turret */
            add_entity(map, "force_field", x0 + w / 2, ground_row - 2);
            if (difficulty > 0.5f) {
                int side = rng_range(0, 1);
                add_entity(map, "laser_turret", side ? x0 + 1 : x0 + w - 2,
                           ground_row - 5);
            }
        } else {
            add_entity(map, "force_field", x0 + w / 2, ground_row - 2);
        }
    }

    /* Aerial threat in shaft */
    if (difficulty > 0.4f && rng_float() < difficulty) {
        int mid_y = (ceil_row + ground_row) / 2;
        if (theme == THEME_MARS_BASE) {
            /* Mars Base: laser turrets on walls dominate shafts */
            int side = rng_range(0, 1);
            int turret_x = side ? x0 + 1 : x0 + w - 2;
            if (rng_float() < 0.6f) {
                add_entity(map, "laser_turret_track", turret_x, rng_range(ceil_row + 2, mid_y));
            } else {
                add_entity(map, "turret", turret_x, rng_range(ceil_row + 2, mid_y));
            }
        } else if (theme == THEME_SPACE_STATION && rng_float() < 0.4f) {
            int side = rng_range(0, 1);
            int turret_x = side ? x0 + 1 : x0 + w - 2;
            add_entity(map, "turret", turret_x, rng_range(ceil_row + 2, mid_y));
        } else {
            add_entity(map, "flyer", x0 + w / 2, rng_range(ceil_row + 3, mid_y));
        }
    }

    /* Fuel pickup near the top — reward for climbing */
    if (rng_float() < 0.5f) {
        add_entity(map, "powerup_fuel", x0 + w / 2, ceil_row + 3);
    }
}

/* ═══════════════════════════════════════════════════
 *  Segment type selection based on theme
 * ═══════════════════════════════════════════════════ */

static SegmentType pick_segment_type(LevelTheme theme, int index, int total) {
    /* First segment is always flat (safe start) */
    if (index == 0) return SEG_FLAT;

    /* Last segment tends to be an arena (climactic) */
    if (index == total - 1 && rng_float() < 0.6f) return SEG_ARENA;

    /* Theme biases */
    float r = rng_float();
    switch (theme) {
        case THEME_PLANET_SURFACE:
            /* Open terrain: lots of flat ground, pits, arenas.
               Harsh alien landscape — wide and horizontal. */
            if (r < 0.25f) return SEG_FLAT;
            if (r < 0.50f) return SEG_PIT;
            if (r < 0.70f) return SEG_ARENA;
            if (r < 0.85f) return SEG_PLATFORMS;
            return SEG_SHAFT;

        case THEME_PLANET_BASE:
            /* Research outpost: corridors, shafts, structured.
               Indoor military feel — walled and enclosed. */
            if (r < 0.30f) return SEG_CORRIDOR;
            if (r < 0.50f) return SEG_SHAFT;
            if (r < 0.65f) return SEG_ARENA;
            if (r < 0.80f) return SEG_FLAT;
            if (r < 0.90f) return SEG_PLATFORMS;
            return SEG_PIT;

        case THEME_SPACE_STATION:
            /* Orbital station: shafts, platforms, corridors.
               Vertical design, low gravity — lots of verticality. */
            if (r < 0.25f) return SEG_SHAFT;
            if (r < 0.45f) return SEG_PLATFORMS;
            if (r < 0.60f) return SEG_CORRIDOR;
            if (r < 0.75f) return SEG_ARENA;
            if (r < 0.90f) return SEG_FLAT;
            return SEG_PIT;

        case THEME_MARS_SURFACE:
            /* Red dusty exterior: spacey, wide-open, few obstacles.
               Charger enemies, occasional pits, wind gusts. */
            if (r < 0.35f) return SEG_FLAT;
            if (r < 0.55f) return SEG_PIT;
            if (r < 0.75f) return SEG_ARENA;
            if (r < 0.90f) return SEG_PLATFORMS;
            return SEG_SHAFT;

        case THEME_MARS_BASE:
            /* Indoor Mars facility: very vertical, narrow corridors,
               90-degree turns, heavy turret/spawner presence. */
            if (r < 0.30f) return SEG_CORRIDOR;
            if (r < 0.55f) return SEG_SHAFT;
            if (r < 0.70f) return SEG_ARENA;
            if (r < 0.85f) return SEG_PLATFORMS;
            return SEG_FLAT;

        default:
            /* Only pick content types (exclude TRANSITION and CLIMB connectors) */
            return (SegmentType)rng_range(0, SEG_SHAFT);
    }
}

/* Width for each segment type */
static int segment_width(SegmentType type) {
    switch (type) {
        case SEG_FLAT:       return rng_range(8, 14);
        case SEG_PIT:        return rng_range(10, 14);
        case SEG_PLATFORMS:  return rng_range(10, 14);
        case SEG_CORRIDOR:   return rng_range(10, 16);
        case SEG_ARENA:      return rng_range(14, 20);
        case SEG_SHAFT:      return rng_range(6, 10);
        case SEG_TRANSITION: return 6;   /* fixed: doorway/airlock */
        case SEG_CLIMB:      return 10;  /* fixed: vertical connector */
        default:             return 10;
    }
}

/* ═══════════════════════════════════════════════════
 *  SEG_TRANSITION — doorway/airlock between themes
 *
 *  A narrow walled passage with a doorway frame.
 *  Visually signals the environment change.
 * ═══════════════════════════════════════════════════ */

static void gen_transition(Tilemap *map, int x0, int w, int ground_row,
                           float difficulty, LevelTheme from, LevelTheme to) {
    (void)difficulty;
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    /* ── Ground: solid floor across the whole transition ── */
    fill_ground(col, mw, mh, x0, x0 + w - 1, ground_row);

    /* ── Airlock structure ──
     * Layout (6 tiles wide):
     *   col 0: outer wall (left bulkhead)
     *   col 1: inner left frame
     *   col 2-3: airlock chamber (open space)
     *   col 4: inner right frame
     *   col 5: outer wall (right bulkhead)
     *
     * Vertical layout is relative to ground_row:
     *   header: ground_row-16 to ground_row-13
     *   inner frame: ground_row-12 to ground_row-1
     *   open passageway in between
     */

    int left  = x0;
    int right = x0 + w - 1;

    int header_top = ground_row - 16;
    if (header_top < 0) header_top = 0;
    int header_bot = ground_row - 13;
    int frame_top  = ground_row - 12;

    /* Outer bulkhead walls — full height from header to ground */
    fill_rect(col, mw, mh, left,  header_top, left,  ground_row - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, right, header_top, right, ground_row - 1, TILE_SOLID_1);

    /* Thick ceiling header (airlock hull) */
    fill_rect(col, mw, mh, left, header_top, right, header_bot, TILE_SOLID_2);

    /* Inner frame columns — pillars flanking the doorway */
    fill_rect(col, mw, mh, left + 1,  frame_top, left + 1,  ground_row - 1, TILE_SOLID_2);
    fill_rect(col, mw, mh, right - 1, frame_top, right - 1, ground_row - 1, TILE_SOLID_2);

    /* Clear the inner chamber (passable area between pillars) */
    for (int y = frame_top; y < ground_row; y++) {
        for (int x = left + 2; x <= right - 2; x++) {
            set_tile(col, mw, mh, x, y, TILE_EMPTY);
        }
    }

    /* Door openings in the outer walls (player entry/exit) */
    for (int y = ground_row - 4; y < ground_row; y++) {
        set_tile(col, mw, mh, left,  y, TILE_EMPTY);
        set_tile(col, mw, mh, right, y, TILE_EMPTY);
    }

    /* Floor plating inside the airlock — one-way platform */
    for (int x = left + 2; x <= right - 2; x++) {
        set_tile(col, mw, mh, x, ground_row - 1, TILE_PLAT);
    }

    /* ── Hazards inside the airlock ── */
    int hazard_y = (frame_top + ground_row) / 2;

    /* Force field barrier in the doorway when entering a tech zone */
    if ((to == THEME_PLANET_BASE || to == THEME_SPACE_STATION) &&
        from == THEME_PLANET_SURFACE) {
        add_entity(map, "force_field", x0 + w / 2, hazard_y);
    }

    /* Force field when transitioning between base and station too */
    if ((from == THEME_PLANET_BASE && to == THEME_SPACE_STATION) ||
        (from == THEME_SPACE_STATION && to == THEME_PLANET_BASE)) {
        add_entity(map, "force_field", x0 + w / 2, hazard_y - 1);
    }

    /* Mars transitions: force field entering the base from surface */
    if (to == THEME_MARS_BASE && from == THEME_MARS_SURFACE) {
        add_entity(map, "force_field", x0 + w / 2, hazard_y);
    }
}

/* ═══════════════════════════════════════════════════
 *  SEG_CLIMB — vertical connector between height zones
 *
 *  Bridges two different ground levels using a shaft
 *  with alternating platforms. When descending (high→low)
 *  the shaft goes from ground_from down to ground_to.
 *  The segment width is fixed at 10 tiles.
 * ═══════════════════════════════════════════════════ */

static void gen_climb(Tilemap *map, int x0, int w,
                      int ground_from, int ground_to,
                      float difficulty, LevelTheme theme) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    /* Determine the top and bottom of the shaft */
    int top_ground = (ground_from < ground_to) ? ground_from : ground_to;
    int bot_ground = (ground_from < ground_to) ? ground_to   : ground_from;

    /* Respect traversal direction: left side is ground_from, right is ground_to.
     * Ascending (from > to): left is LOW (bottom), right is HIGH (top)
     * Descending (from < to): left is HIGH (top), right is LOW (bottom) */
    int left_ground  = ground_from;
    int right_ground = ground_to;

    /* Fill ground on both levels at the edges of the segment */
    fill_rect(col, mw, mh, x0, left_ground, x0 + 2, mh - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 3, right_ground, x0 + w - 1, mh - 1, TILE_SOLID_1);

    /* Shaft walls span the full height range between the two zones */
    int shaft_left  = x0 + 2;
    int shaft_right = x0 + w - 3;
    fill_rect(col, mw, mh, shaft_left,  top_ground, shaft_left,  bot_ground - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, shaft_right, top_ground, shaft_right, bot_ground - 1, TILE_SOLID_1);

    /* Connect left ground to shaft entrance */
    fill_rect(col, mw, mh, x0, left_ground, shaft_left, left_ground + FLOOR_ROWS - 1, TILE_SOLID_1);

    /* Connect right ground to shaft exit */
    fill_rect(col, mw, mh, shaft_right, right_ground, x0 + w - 1, right_ground + FLOOR_ROWS - 1, TILE_SOLID_1);

    /* Opening at left side of shaft — player enters from ground_from level */
    for (int r = left_ground - 3; r < left_ground; r++) {
        set_tile(col, mw, mh, shaft_left, r, TILE_EMPTY);
    }

    /* Opening at right side of shaft — player exits to ground_to level */
    for (int r = right_ground - 3; r < right_ground; r++) {
        set_tile(col, mw, mh, shaft_right, r, TILE_EMPTY);
    }

    /* Alternating platforms inside the shaft */
    int shaft_inner_w = shaft_right - shaft_left - 1;
    int shaft_depth = bot_ground - top_ground;
    int num_plats = shaft_depth / 4;
    if (num_plats < 3) num_plats = 3;
    if (num_plats > 8) num_plats = 8;

    for (int i = 0; i < num_plats; i++) {
        int py = top_ground + 2 + i * (shaft_depth - 4) / num_plats;
        if (py >= bot_ground - 1) break;
        bool left_side = (i % 2 == 0);
        int px = left_side ? shaft_left + 1 : shaft_right - 3;
        int pw = (shaft_inner_w > 4) ? 3 : 2;
        for (int j = 0; j < pw; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }
    }

    /* Vertical moving platform in the shaft center */
    if (rng_float() < 0.5f) {
        int mid_x = (shaft_left + shaft_right) / 2;
        int mid_y = (top_ground + bot_ground) / 2;
        add_entity(map, "platform_v", mid_x, mid_y);
    }

    /* Aerial threat inside the shaft */
    if (difficulty > 0.3f && rng_float() < difficulty) {
        int mid_y = (top_ground + bot_ground) / 2;
        if (theme == THEME_SPACE_STATION && rng_float() < 0.4f) {
            int turret_x = (rng_range(0, 1)) ? shaft_left + 1 : shaft_right - 1;
            add_entity(map, "turret", turret_x, mid_y);
        } else {
            add_entity(map, "flyer", (shaft_left + shaft_right) / 2, mid_y);
        }
    }

    /* Fuel pickup midway through the climb */
    if (rng_float() < 0.5f) {
        int mid_y = (top_ground + bot_ground) / 2;
        add_entity(map, "powerup_fuel", (shaft_left + shaft_right) / 2, mid_y - 2);
    }
}

/* ═══════════════════════════════════════════════════
 *  Theme sequence helpers
 * ═══════════════════════════════════════════════════ */

/* Get the theme for a given segment index from the config */
static LevelTheme theme_for_segment(const LevelGenConfig *config, int seg_idx) {
    if (config->theme_count <= 0) return THEME_PLANET_SURFACE;
    if (seg_idx >= config->theme_count) return config->themes[config->theme_count - 1];
    return config->themes[seg_idx];
}

/* Get gravity for a theme.
 * Surface: low gravity alien world — floaty jumps.
 * Base: normal Earth-like artificial gravity.
 * Station: heavy centrifugal / mag-lock gravity. */
static float gravity_for_theme(LevelTheme theme) {
    switch (theme) {
        case THEME_PLANET_SURFACE: return 400.0f;
        case THEME_PLANET_BASE:    return 600.0f;
        case THEME_SPACE_STATION:  return 750.0f;
        case THEME_MARS_SURFACE:   return 370.0f; /* Mars: ~0.38g */
        case THEME_MARS_BASE:      return 700.0f; /* artificial gravity */
        default:                   return 600.0f;
    }
}

/* Get background color for a theme */
static SDL_Color bg_color_for_theme(LevelTheme theme) {
    switch (theme) {
        case THEME_PLANET_SURFACE: return (SDL_Color){12, 8, 20, 255};
        case THEME_PLANET_BASE:    return (SDL_Color){10, 14, 22, 255};
        case THEME_SPACE_STATION:  return (SDL_Color){5, 5, 18, 255};
        case THEME_MARS_SURFACE:   return (SDL_Color){30, 12, 8, 255};
        case THEME_MARS_BASE:      return (SDL_Color){18, 10, 8, 255};
        default:                   return (SDL_Color){15, 15, 30, 255};
    }
}

/* Map theme to parallax visual style */
static ParallaxStyle parallax_style_for_theme(LevelTheme theme) {
    switch (theme) {
        case THEME_PLANET_SURFACE: return PARALLAX_STYLE_ALIEN_SKY;
        case THEME_PLANET_BASE:    return PARALLAX_STYLE_INTERIOR;
        case THEME_SPACE_STATION:  return PARALLAX_STYLE_DEEP_SPACE;
        case THEME_MARS_SURFACE:   return PARALLAX_STYLE_MARS;
        case THEME_MARS_BASE:      return PARALLAX_STYLE_INTERIOR;
        default:                   return PARALLAX_STYLE_DEFAULT;
    }
}

static const char *theme_label(LevelTheme t) {
    switch (t) {
        case THEME_PLANET_SURFACE: return "surface";
        case THEME_PLANET_BASE:    return "base";
        case THEME_SPACE_STATION:  return "station";
        case THEME_MARS_SURFACE:   return "mars_surf";
        case THEME_MARS_BASE:      return "mars_base";
        default:                   return "?";
    }
}

/* ═══════════════════════════════════════════════════
 *  Background decoration (bg_layer)
 * ═══════════════════════════════════════════════════ */

static void gen_bg_decoration(Tilemap *map) {
    /* Scatter some background tiles for visual depth */
    uint16_t *bg = map->bg_layer;
    int mw = map->width;

    for (int y = 0; y < map->height - FLOOR_ROWS; y++) {
        for (int x = 0; x < mw; x++) {
            /* Only place bg tiles where collision is empty */
            if (map->collision_layer[y * mw + x] != TILE_EMPTY) continue;

            /* Sparse random decoration */
            if (rng_float() < 0.02f) {
                bg[y * mw + x] = (uint16_t)rng_range(2, 3);
            }
        }
    }
}

/* ═══════════════════════════════════════════════════
 *  Main generator
 * ═══════════════════════════════════════════════════ */

LevelGenConfig levelgen_default_config(void) {
    LevelGenConfig config = {
        .seed         = 0,
        .num_segments = 5,
        .difficulty   = 0.5f,
        .gravity      = 0,   /* 0 = let theme decide */
        .theme_count  = 1,
    };
    config.themes[0] = THEME_SPACE_STATION;
    return config;
}

bool levelgen_generate(Tilemap *map, const LevelGenConfig *config) {
    if (!map || !config) return false;

    rng_seed(config->seed);

    int num_segs = config->num_segments;
    if (num_segs < 2) num_segs = 2;
    if (num_segs > 10) num_segs = 10;

    /* ── Phase 1: decide segment types, widths, and height zones ── */
    /* We may insert transition/climb segments between boundaries,
     * so the final count can be larger than num_segs.
     * Max: num_segs content + (num_segs-1) connectors*2 = ~3*num_segs */
    #define MAX_FINAL_SEGS 32
    SegmentType seg_types[MAX_FINAL_SEGS];
    int         seg_widths[MAX_FINAL_SEGS];
    LevelTheme  seg_themes[MAX_FINAL_SEGS];   /* per-segment theme     */
    LevelTheme  seg_from[MAX_FINAL_SEGS];      /* for transitions       */
    int         seg_ground[MAX_FINAL_SEGS];    /* ground row per segment */
    int         final_seg_count = 0;
    int         total_width = 0;
    bool        uses_tall = false;  /* track if any zone change occurs */

    /* Determine zone preference per theme:
     * Surface: stays LOW (bottom of tall map, or normal if single-screen)
     * Base:    uses HIGH (upper area of tall map)
     * Station: alternates between HIGH and LOW */
    for (int i = 0; i < num_segs; i++) {
        LevelTheme t = theme_for_segment(config, i);

        /* Insert a transition segment at theme boundaries */
        if (i > 0) {
            LevelTheme prev_t = theme_for_segment(config, i - 1);
            if (t != prev_t && final_seg_count < MAX_FINAL_SEGS) {
                seg_types[final_seg_count]  = SEG_TRANSITION;
                seg_widths[final_seg_count] = segment_width(SEG_TRANSITION);
                seg_themes[final_seg_count] = t;
                seg_from[final_seg_count]   = prev_t;
                seg_ground[final_seg_count] = 0; /* filled in later */
                total_width += seg_widths[final_seg_count];
                final_seg_count++;
            }
        }

        if (final_seg_count >= MAX_FINAL_SEGS) break;

        seg_types[final_seg_count]  = pick_segment_type(t, i, num_segs);
        seg_widths[final_seg_count] = segment_width(seg_types[final_seg_count]);
        seg_themes[final_seg_count] = t;
        seg_from[final_seg_count]   = t;
        seg_ground[final_seg_count] = 0; /* filled in later */
        total_width += seg_widths[final_seg_count];
        final_seg_count++;
    }
    num_segs = final_seg_count;

    /* ── Phase 1b: assign height zones per segment ── */
    /* Decide if this level should be tall based on theme variety.
     * A level with both Surface and Base/Station themes gets tall
     * to give each theme its own vertical zone. Single-theme levels
     * stay at the standard 23-tile height. */
    bool has_surface = false, has_base = false, has_station = false;
    bool has_mars_surf = false, has_mars_base = false;
    for (int i = 0; i < num_segs; i++) {
        if (seg_themes[i] == THEME_PLANET_SURFACE) has_surface = true;
        if (seg_themes[i] == THEME_PLANET_BASE)    has_base = true;
        if (seg_themes[i] == THEME_SPACE_STATION)  has_station = true;
        if (seg_themes[i] == THEME_MARS_SURFACE)   has_mars_surf = true;
        if (seg_themes[i] == THEME_MARS_BASE)      has_mars_base = true;
    }

    /* Go tall if we have theme variety that benefits from verticality */
    uses_tall = (has_surface && (has_base || has_station)) ||
                (has_mars_surf && has_mars_base) ||
                (has_station && num_segs >= 5);

    if (uses_tall) {
        /* Assign ground rows based on theme:
         * Surface → LOW zone (ground at row 43, near bottom)
         * Base → HIGH zone (ground at row 17, near top)
         * Station → alternates, preferring HIGH */
        int station_zone_counter = 0;
        for (int i = 0; i < num_segs; i++) {
            if (seg_types[i] == SEG_TRANSITION) {
                /* Skip: ground row filled in from predecessor below */
                continue;
            }
            switch (seg_themes[i]) {
                case THEME_PLANET_SURFACE:
                case THEME_MARS_SURFACE:
                    seg_ground[i] = ZONE_LOW_GROUND;
                    break;
                case THEME_PLANET_BASE:
                case THEME_MARS_BASE:
                    seg_ground[i] = ZONE_HIGH_GROUND;
                    break;
                case THEME_SPACE_STATION:
                    /* Alternate every 2 segments */
                    seg_ground[i] = (station_zone_counter / 2 % 2 == 0)
                        ? ZONE_HIGH_GROUND : ZONE_LOW_GROUND;
                    station_zone_counter++;
                    break;
                default:
                    seg_ground[i] = ZONE_LOW_GROUND;
                    break;
            }
        }

        /* Fill in transition segment ground rows from their predecessor.
         * Transitions must be walkable from the previous segment; if the
         * zone also changes, a SEG_CLIMB is inserted *after* the transition
         * to bridge to the new elevation. */
        for (int i = 0; i < num_segs; i++) {
            if (seg_types[i] == SEG_TRANSITION) {
                /* Find predecessor ground row */
                int prev_gr = ZONE_LOW_GROUND;
                for (int j = i - 1; j >= 0; j--) {
                    if (seg_ground[j] != 0) { prev_gr = seg_ground[j]; break; }
                }
                seg_ground[i] = prev_gr;
            }
        }

        /* Insert SEG_CLIMB segments where the ground level changes.
         * Climbs are inserted between any two adjacent segments whose
         * ground rows differ, including after transitions that stayed
         * at the old elevation while the next segment needs a new one. */
        SegmentType tmp_types[MAX_FINAL_SEGS];
        int         tmp_widths[MAX_FINAL_SEGS];
        LevelTheme  tmp_themes[MAX_FINAL_SEGS];
        LevelTheme  tmp_from[MAX_FINAL_SEGS];
        int         tmp_ground[MAX_FINAL_SEGS];
        int         new_count = 0;
        int         climb_width_total = 0;

        for (int i = 0; i < num_segs; i++) {
            /* Check if we need a climb before this segment */
            if (i > 0 && new_count > 0 && seg_ground[i] != 0 &&
                tmp_ground[new_count - 1] != seg_ground[i] &&
                new_count < MAX_FINAL_SEGS) {
                /* Insert climb connector */
                tmp_types[new_count]  = SEG_CLIMB;
                tmp_widths[new_count] = segment_width(SEG_CLIMB);
                tmp_themes[new_count] = seg_themes[i];
                tmp_from[new_count]   = seg_themes[i > 0 ? i - 1 : i];
                tmp_ground[new_count] = seg_ground[i]; /* target zone */
                climb_width_total    += tmp_widths[new_count];
                new_count++;
            }
            if (new_count < MAX_FINAL_SEGS) {
                tmp_types[new_count]  = seg_types[i];
                tmp_widths[new_count] = seg_widths[i];
                tmp_themes[new_count] = seg_themes[i];
                tmp_from[new_count]   = seg_from[i];
                tmp_ground[new_count] = seg_ground[i];
                new_count++;
            }
        }

        /* Copy back */
        num_segs = new_count;
        total_width += climb_width_total;
        for (int i = 0; i < num_segs; i++) {
            seg_types[i]  = tmp_types[i];
            seg_widths[i] = tmp_widths[i];
            seg_themes[i] = tmp_themes[i];
            seg_from[i]   = tmp_from[i];
            seg_ground[i] = tmp_ground[i];
        }
    } else {
        /* Standard single-screen height: all segments use GROUND_ROW */
        for (int i = 0; i < num_segs; i++) {
            seg_ground[i] = GROUND_ROW;
        }
    }

    /* Add 2-tile buffer on each side */
    total_width += 4;

    /* ── Phase 2: allocate tilemap ── */
    int level_height = uses_tall ? TALL_HEIGHT : SEG_HEIGHT;
    memset(map, 0, sizeof(Tilemap));
    map->width = total_width;
    map->height = level_height;

    int total_tiles = map->width * map->height;
    map->collision_layer = calloc(total_tiles, sizeof(uint16_t));
    map->bg_layer        = calloc(total_tiles, sizeof(uint16_t));
    map->fg_layer        = calloc(total_tiles, sizeof(uint16_t));

    if (!map->collision_layer || !map->bg_layer || !map->fg_layer) {
        fprintf(stderr, "levelgen: failed to allocate layers\n");
        return false;
    }

    /* ── Phase 3: set tile definitions ── */
    map->tile_defs[1] = (TileDef){0, 0, TILE_SOLID};    /* main solid */
    map->tile_defs[2] = (TileDef){1, 0, TILE_SOLID};    /* solid variant */
    map->tile_defs[3] = (TileDef){2, 0, TILE_SOLID};    /* solid variant */
    map->tile_defs[4] = (TileDef){0, 1, TILE_PLATFORM}; /* one-way */
    map->tile_def_count = 5;

    /* ── Phase 4: generate segments ── */
    int cursor = 2;  /* start after left buffer */
    int mh = map->height;

    /* Left border wall */
    fill_rect(map->collision_layer, map->width, mh, 0, 0, 1, mh - 1, TILE_SOLID_1);

    for (int i = 0; i < num_segs; i++) {
        int w = seg_widths[i];
        LevelTheme theme = seg_themes[i];
        int gr = seg_ground[i];

        switch (seg_types[i]) {
            case SEG_FLAT:      gen_flat(map, cursor, w, gr, config->difficulty, theme);      break;
            case SEG_PIT:       gen_pit(map, cursor, w, gr, config->difficulty, theme);       break;
            case SEG_PLATFORMS: gen_platforms(map, cursor, w, gr, config->difficulty, theme);  break;
            case SEG_CORRIDOR:  gen_corridor(map, cursor, w, gr, config->difficulty, theme);  break;
            case SEG_ARENA:     gen_arena(map, cursor, w, gr, config->difficulty, theme);     break;
            case SEG_SHAFT:     gen_shaft(map, cursor, w, gr, config->difficulty, theme);     break;
            case SEG_TRANSITION:
                gen_transition(map, cursor, w, gr, config->difficulty, seg_from[i], theme);
                break;
            case SEG_CLIMB: {
                /* Find the previous segment's ground row */
                int prev_gr = (i > 0) ? seg_ground[i - 1] : gr;
                gen_climb(map, cursor, w, prev_gr, gr, config->difficulty, theme);
                break;
            }
            default:            gen_flat(map, cursor, w, gr, config->difficulty, theme);      break;
        }

        cursor += w;
    }

    /* Right border wall */
    fill_rect(map->collision_layer, map->width, mh,
              map->width - 2, 0, map->width - 1, mh - 1, TILE_SOLID_1);

    /* ── Phase 5: add visual variety to solid tiles ── */
    for (int y = 0; y < map->height; y++) {
        for (int x = 0; x < map->width; x++) {
            int idx = y * map->width + x;
            if (map->collision_layer[idx] == TILE_SOLID_1) {
                /* Only vary interior tiles (not edge tiles) */
                bool has_air_neighbor = false;
                if (y > 0 && map->collision_layer[(y-1)*map->width+x] == 0) has_air_neighbor = true;
                if (!has_air_neighbor) {
                    map->collision_layer[idx] = random_solid();
                }
            }
        }
    }

    /* ── Phase 6: background decoration ── */
    gen_bg_decoration(map);

    /* ── Phase 7: metadata ── */
    int first_ground = seg_ground[0];
    map->player_spawn = vec2(3.0f * TILE_SIZE, (first_ground - 2) * TILE_SIZE);

    /* Theme-based gravity and atmosphere (uses first theme in sequence) */
    LevelTheme primary_theme = config->themes[0];
    map->gravity  = config->gravity > 0 ? config->gravity : gravity_for_theme(primary_theme);
    map->bg_color = bg_color_for_theme(primary_theme);
    map->has_bg_color = true;
    map->parallax_style = (int)parallax_style_for_theme(primary_theme);

    /* Select tileset based on theme. Mars themes use a dedicated tileset;
     * all others use the default. level_load_generated() loads the texture. */
    if (primary_theme == THEME_MARS_SURFACE || primary_theme == THEME_MARS_BASE) {
        snprintf(map->tileset_path, sizeof(map->tileset_path),
                 "%s", "assets/tiles/mars_tileset.png");
    }

    /* Exit zone at the far-right end of the level.
     * Placed just inside the right border wall, 2 tiles wide, 3 tiles tall
     * sitting on the ground row. Target "generate" chains to another
     * procedurally generated level. */
    if (map->exit_zone_count < MAX_EXIT_ZONES) {
        ExitZone *ez = &map->exit_zones[map->exit_zone_count++];
        int last_ground = seg_ground[num_segs - 1];
        int exit_x = map->width - 5; /* a few tiles from the right wall */
        int exit_y = last_ground - 3; /* 3 tiles above ground */
        ez->x = (float)(exit_x * TILE_SIZE);
        ez->y = (float)(exit_y * TILE_SIZE);
        ez->w = 2.0f * TILE_SIZE;
        ez->h = 3.0f * TILE_SIZE;
        snprintf(ez->target, sizeof(ez->target), "generate");

        /* Clear any solid tiles in the exit zone area so the player can walk into it */
        for (int y = exit_y; y < exit_y + 3 && y < map->height; y++) {
            for (int x = exit_x; x < exit_x + 2 && x < map->width; x++) {
                map->collision_layer[y * map->width + x] = 0;
            }
        }
    }

    /* Music — Mars themes get their own track */
    if (primary_theme == THEME_MARS_SURFACE || primary_theme == THEME_MARS_BASE) {
        snprintf(map->music_path, sizeof(map->music_path), "assets/sounds/kaffe_og_kage.ogg");
    } else {
        snprintf(map->music_path, sizeof(map->music_path), "assets/sounds/algardalgar.ogg");
    }

    /* Tileset */
    /* NOTE: tileset texture will be loaded by level_load_generated */

    /* Segment type names for debug output */
    static const char *seg_names[] = {
        "flat", "pit", "plat", "corr", "arena", "shaft", "trans", "climb"
    };
    printf("levelgen: generated %dx%d level (%d segments, seed=%u%s)\n",
           map->width, map->height, num_segs, s_rng_state,
           uses_tall ? ", tall" : "");
    printf("  segments:");
    for (int i = 0; i < num_segs; i++) {
        printf(" %s[%s@%d]", seg_names[seg_types[i]],
               theme_label(seg_themes[i]), seg_ground[i]);
    }
    printf("\n");

    return true;
}

/* ═══════════════════════════════════════════════════
 *  Space Station Generator
 *
 *  A dedicated generator for long, narrow, low-gravity
 *  space station levels. Uses the standard 23-tile height
 *  but fills ceiling and floor to create a narrower
 *  playable corridor (roughly 10 tiles of vertical space).
 *
 *  Segment types are biased toward horizontal layouts:
 *  corridors, flat sections, arenas. Shafts are replaced
 *  by wider horizontal variants.
 * ═══════════════════════════════════════════════════ */

/* Station layout constants */
#define STATION_CEIL_ROW    4   /* ceiling bottom edge (rows 0-4 solid)  */
#define STATION_FLOOR_ROW  17   /* floor top edge (rows 17-22 solid)     */
#define STATION_PLAY_H     12   /* playable rows: 5-16 inclusive         */

static void station_fill_envelope(uint16_t *col, int mw, int mh, int x0, int x1) {
    /* Ceiling: rows 0 through STATION_CEIL_ROW */
    fill_rect(col, mw, mh, x0, 0, x1, STATION_CEIL_ROW, TILE_SOLID_1);
    /* Floor: rows STATION_FLOOR_ROW through bottom */
    fill_rect(col, mw, mh, x0, STATION_FLOOR_ROW, x1, SEG_HEIGHT - 1, TILE_SOLID_1);
}

/* ── Station segment: long flat corridor ── */
static void gen_station_corridor(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    station_fill_envelope(col, mw, mh, x0, x0 + w - 1);

    /* Random platforms floating in the corridor */
    int num_plats = rng_range(1, 3);
    for (int i = 0; i < num_plats; i++) {
        int px = x0 + rng_range(2, w - 5);
        int py = rng_range(STATION_CEIL_ROW + 3, STATION_FLOOR_ROW - 3);
        int pw = rng_range(2, 4);
        for (int j = 0; j < pw && px + j < x0 + w; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }
    }

    /* Ground patrols — always at least 1, scales with difficulty */
    int num_grunts = 1 + (int)(difficulty * 2);
    for (int i = 0; i < num_grunts; i++) {
        add_entity(map, "grunt", x0 + rng_range(3, w - 4), STATION_FLOOR_ROW - 1);
    }

    /* Flyers in the corridor */
    int num_flyers = (int)(difficulty * 2);
    for (int i = 0; i < num_flyers; i++) {
        add_entity(map, "flyer", x0 + rng_range(3, w - 4),
                   rng_range(STATION_CEIL_ROW + 2, STATION_FLOOR_ROW - 3));
    }

    /* Turret at high difficulty */
    if (difficulty > 0.6f && rng_float() < 0.5f) {
        add_entity(map, "turret", x0 + rng_range(3, w - 4), STATION_CEIL_ROW + 1);
    }
}

/* ── Station segment: bulkhead (walls with doorway) ── */
static void gen_station_bulkhead(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    station_fill_envelope(col, mw, mh, x0, x0 + w - 1);

    /* Central bulkhead wall with a doorway */
    int wall_x = x0 + w / 2;
    fill_rect(col, mw, mh, wall_x, STATION_CEIL_ROW + 1, wall_x, STATION_FLOOR_ROW - 1, TILE_SOLID_2);

    /* Doorway opening (3 tiles tall) */
    int door_y = rng_range(STATION_CEIL_ROW + 3, STATION_FLOOR_ROW - 4);
    for (int y = door_y; y < door_y + 3; y++) {
        set_tile(col, mw, mh, wall_x, y, TILE_EMPTY);
    }

    /* Turret guarding the doorway — always present */
    add_entity(map, "turret", wall_x - 2, door_y - 1);

    /* Second turret on the other side at higher difficulty */
    if (difficulty > 0.6f) {
        add_entity(map, "turret", wall_x + 2, door_y - 1);
    }

    /* Force field in the doorway */
    if (difficulty > 0.4f && rng_float() < 0.6f) {
        add_entity(map, "force_field", wall_x, door_y + 1);
    }

    /* Grunts on both sides of the bulkhead */
    add_entity(map, "grunt", x0 + rng_range(2, w / 2 - 2), STATION_FLOOR_ROW - 1);
    if (rng_float() < 0.5f + difficulty * 0.5f) {
        add_entity(map, "grunt", x0 + rng_range(w / 2 + 2, w - 3), STATION_FLOOR_ROW - 1);
    }

    /* Flyer patrol */
    if (difficulty > 0.4f) {
        add_entity(map, "flyer", x0 + rng_range(3, w - 4),
                   rng_range(STATION_CEIL_ROW + 2, STATION_FLOOR_ROW - 3));
    }
}

/* ── Station segment: platform gauntlet ── */
static void gen_station_platforms(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    station_fill_envelope(col, mw, mh, x0, x0 + w - 1);

    /* Remove some floor sections to create pits (lethal in a station) */
    int pit_start = x0 + rng_range(3, 6);
    int pit_end   = x0 + w - rng_range(3, 6);
    for (int x = pit_start; x < pit_end && x < x0 + w; x++) {
        for (int y = STATION_FLOOR_ROW; y < STATION_FLOOR_ROW + 2; y++) {
            set_tile(col, mw, mh, x, y, TILE_EMPTY);
        }
    }

    /* Floating platforms across the gap */
    int num_plats = rng_range(3, 5);
    int spacing = (pit_end - pit_start) / (num_plats + 1);
    if (spacing < 2) spacing = 2;
    for (int i = 0; i < num_plats; i++) {
        int px = pit_start + (i + 1) * spacing - 1;
        int py = rng_range(STATION_CEIL_ROW + 4, STATION_FLOOR_ROW - 2);
        int pw = rng_range(2, 3);
        for (int j = 0; j < pw && px + j < x0 + w; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }
    }

    /* Moving platform */
    if (rng_float() < 0.7f) {
        bool vertical = rng_float() < 0.4f;
        int mx = pit_start + (pit_end - pit_start) / 2;
        int my = rng_range(STATION_CEIL_ROW + 4, STATION_FLOOR_ROW - 3);
        add_entity(map, vertical ? "platform_v" : "platform", mx, my);
    }

    /* Flyers guarding the gap — always at least 1 */
    int num_flyers = 1 + (int)(difficulty * 2);
    for (int i = 0; i < num_flyers; i++) {
        add_entity(map, "flyer", x0 + rng_range(3, w - 4),
                   rng_range(STATION_CEIL_ROW + 2, STATION_FLOOR_ROW - 4));
    }

    /* Turret overlooking the pit */
    if (difficulty > 0.5f) {
        add_entity(map, "turret", x0 + rng_range(2, 4), STATION_CEIL_ROW + 1);
    }
}

/* ── Station segment: combat bay (wider arena) ── */
static void gen_station_bay(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    station_fill_envelope(col, mw, mh, x0, x0 + w - 1);

    /* Open up a taller space by raising the ceiling locally */
    int bay_x0 = x0 + 2;
    int bay_x1 = x0 + w - 3;
    for (int x = bay_x0; x <= bay_x1; x++) {
        set_tile(col, mw, mh, x, STATION_CEIL_ROW, TILE_EMPTY);
        set_tile(col, mw, mh, x, STATION_CEIL_ROW - 1, TILE_EMPTY);
    }

    /* Central floating platform */
    int cp_x = x0 + w / 2 - 2;
    int cp_y = rng_range(STATION_CEIL_ROW + 2, STATION_FLOOR_ROW - 5);
    for (int j = 0; j < 4; j++) {
        set_tile(col, mw, mh, cp_x + j, cp_y, TILE_PLAT);
    }

    /* Ledges on the sides */
    fill_rect(col, mw, mh, x0, STATION_FLOOR_ROW - 3, x0 + 1, STATION_FLOOR_ROW - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 2, STATION_FLOOR_ROW - 3, x0 + w - 1, STATION_FLOOR_ROW - 1, TILE_SOLID_1);

    /* Swarm of enemies — bays are the big combat encounters */
    int num_enemies = 3 + (int)(difficulty * 4);
    for (int i = 0; i < num_enemies; i++) {
        float r = rng_float();
        if (r < 0.30f) {
            add_entity(map, "grunt", x0 + rng_range(3, w - 4), STATION_FLOOR_ROW - 1);
        } else {
            add_entity(map, "flyer", x0 + rng_range(3, w - 4),
                       rng_range(STATION_CEIL_ROW + 1, STATION_FLOOR_ROW - 4));
        }
    }

    /* Turrets on both side ledges */
    add_entity(map, "turret", x0 + 1, STATION_FLOOR_ROW - 4);
    if (difficulty > 0.5f) {
        add_entity(map, "turret", x0 + w - 2, STATION_FLOOR_ROW - 4);
    }

    /* Powerup on the central platform — reward for surviving */
    if (rng_float() < 0.6f) {
        if (difficulty > 0.5f && rng_float() < 0.3f) {
            add_entity(map, "powerup_drone", cp_x + 2, cp_y - 1);
        } else {
            add_entity(map, "powerup_hp", cp_x + 2, cp_y - 1);
        }
    }
}

/* ── Station segment: vent / crawlspace ── */
static void gen_station_vent(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    station_fill_envelope(col, mw, mh, x0, x0 + w - 1);

    /* Lower the ceiling even more for a tight crawlspace */
    int vent_ceil = STATION_CEIL_ROW + 3;
    fill_rect(col, mw, mh, x0, STATION_CEIL_ROW + 1, x0 + w - 1, vent_ceil, TILE_SOLID_2);

    /* Opening at left */
    for (int y = vent_ceil - 1; y <= vent_ceil + 2 && y < STATION_FLOOR_ROW; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
    }
    /* Opening at right */
    for (int y = vent_ceil - 1; y <= vent_ceil + 2 && y < STATION_FLOOR_ROW; y++) {
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }

    /* Flame vents along the floor — always present, more at higher difficulty */
    int num_vents = 1 + (int)(difficulty * 2);
    for (int i = 0; i < num_vents; i++) {
        add_entity(map, "flame_vent", x0 + rng_range(2, w - 3), STATION_FLOOR_ROW - 1);
    }

    /* Force field obstacle */
    if (difficulty > 0.3f && rng_float() < 0.6f) {
        add_entity(map, "force_field", x0 + w / 2, vent_ceil + 2);
    }

    /* Grunt lurking in the vent */
    if (rng_float() < 0.4f + difficulty * 0.4f) {
        add_entity(map, "grunt", x0 + rng_range(2, w - 3), STATION_FLOOR_ROW - 1);
    }

    /* Fuel pickup reward (useful in low gravity) */
    if (rng_float() < 0.4f) {
        add_entity(map, "powerup_fuel", x0 + rng_range(2, w - 3), vent_ceil + 1);
    }
}

/* ── Station segment: airlock entry (first segment) ── */
static void gen_station_entry(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;
    (void)col; (void)mw; (void)mh; /* used by station_fill_envelope */

    station_fill_envelope(col, mw, mh, x0, x0 + w - 1);

    /* Health pickup to start — always present */
    add_entity(map, "powerup_hp", x0 + w / 2, STATION_FLOOR_ROW - 1);

    /* At higher difficulty, even the entry isn't safe */
    if (difficulty > 0.6f) {
        add_entity(map, "grunt", x0 + rng_range(w / 2 + 2, w - 3), STATION_FLOOR_ROW - 1);
    }
    if (difficulty > 0.8f) {
        add_entity(map, "flyer", x0 + rng_range(3, w - 4),
                   rng_range(STATION_CEIL_ROW + 2, STATION_FLOOR_ROW - 3));
    }
}

/* Segment type selection for station */
typedef enum StationSegType {
    SSEG_ENTRY,
    SSEG_CORRIDOR,
    SSEG_BULKHEAD,
    SSEG_PLATFORMS,
    SSEG_BAY,
    SSEG_VENT,
    SSEG_TYPE_COUNT
} StationSegType;

static StationSegType pick_station_segment(int index, int total) {
    if (index == 0) return SSEG_ENTRY;
    if (index == total - 1 && rng_float() < 0.6f) return SSEG_BAY;

    float r = rng_float();
    if (r < 0.25f) return SSEG_CORRIDOR;
    if (r < 0.45f) return SSEG_BULKHEAD;
    if (r < 0.65f) return SSEG_PLATFORMS;
    if (r < 0.80f) return SSEG_BAY;
    return SSEG_VENT;
}

static int station_segment_width(StationSegType type) {
    switch (type) {
        case SSEG_ENTRY:     return rng_range(12, 16);
        case SSEG_CORRIDOR:  return rng_range(18, 28);
        case SSEG_BULKHEAD:  return rng_range(16, 22);
        case SSEG_PLATFORMS: return rng_range(20, 30);
        case SSEG_BAY:       return rng_range(24, 34);
        case SSEG_VENT:      return rng_range(14, 20);
        default:             return 18;
    }
}

LevelGenConfig levelgen_station_config(uint32_t seed, int depth) {
    if (depth < 0) depth = 0;

    /* Segments grow with depth: 10 -> 11 -> 12 -> 13 -> 14 (capped) */
    int segments = 10 + depth;
    if (segments > 14) segments = 14;

    /* Difficulty ramps up: 0.5 -> 0.65 -> 0.8 -> 0.9 -> 1.0 (capped) */
    float diff = 0.5f + depth * 0.15f;
    if (diff > 1.0f) diff = 1.0f;

    LevelGenConfig config = {
        .seed         = seed,
        .num_segments = segments,
        .difficulty   = diff,
        .gravity      = 150.0f,    /* near-zero: floaty space station */
        .theme_count  = 1,
    };
    config.themes[0] = THEME_SPACE_STATION;
    return config;
}

bool levelgen_generate_station(Tilemap *map, const LevelGenConfig *config) {
    if (!map || !config) return false;

    rng_seed(config->seed);

    int num_segs = config->num_segments;
    if (num_segs < 3)  num_segs = 3;
    if (num_segs > 14) num_segs = 14;

    /* ── Phase 1: decide segment types and widths ── */
    StationSegType seg_types[20];
    int            seg_widths[20];
    int            total_width = 0;

    for (int i = 0; i < num_segs && i < 20; i++) {
        seg_types[i]  = pick_station_segment(i, num_segs);
        seg_widths[i] = station_segment_width(seg_types[i]);
        total_width  += seg_widths[i];
    }

    /* Add 2-tile buffer on each side */
    total_width += 4;

    /* ── Phase 2: allocate tilemap ── */
    memset(map, 0, sizeof(Tilemap));
    map->width  = total_width;
    map->height = SEG_HEIGHT;

    int total_tiles = map->width * map->height;
    map->collision_layer = calloc(total_tiles, sizeof(uint16_t));
    map->bg_layer        = calloc(total_tiles, sizeof(uint16_t));
    map->fg_layer        = calloc(total_tiles, sizeof(uint16_t));

    if (!map->collision_layer || !map->bg_layer || !map->fg_layer) {
        fprintf(stderr, "levelgen_station: failed to allocate layers\n");
        return false;
    }

    /* ── Phase 3: tile definitions ── */
    map->tile_defs[1] = (TileDef){0, 0, TILE_SOLID};
    map->tile_defs[2] = (TileDef){1, 0, TILE_SOLID};
    map->tile_defs[3] = (TileDef){2, 0, TILE_SOLID};
    map->tile_defs[4] = (TileDef){0, 1, TILE_PLATFORM};
    map->tile_def_count = 5;

    /* ── Phase 4: generate segments ── */
    int cursor = 2;
    int smh = map->height;

    /* Left border wall */
    fill_rect(map->collision_layer, map->width, smh, 0, 0, 1, smh - 1, TILE_SOLID_1);

    static const char *sseg_names[] = {
        "entry", "corr", "bulk", "plat", "bay", "vent"
    };

    for (int i = 0; i < num_segs; i++) {
        int w = seg_widths[i];
        float diff = config->difficulty;

        switch (seg_types[i]) {
            case SSEG_ENTRY:     gen_station_entry(map, cursor, w, diff);     break;
            case SSEG_CORRIDOR:  gen_station_corridor(map, cursor, w, diff);  break;
            case SSEG_BULKHEAD:  gen_station_bulkhead(map, cursor, w, diff);  break;
            case SSEG_PLATFORMS: gen_station_platforms(map, cursor, w, diff);  break;
            case SSEG_BAY:       gen_station_bay(map, cursor, w, diff);       break;
            case SSEG_VENT:      gen_station_vent(map, cursor, w, diff);      break;
            default:             gen_station_corridor(map, cursor, w, diff);  break;
        }

        cursor += w;
    }

    /* Right border wall */
    fill_rect(map->collision_layer, map->width, smh,
              map->width - 2, 0, map->width - 1, smh - 1, TILE_SOLID_1);

    /* ── Phase 5: visual variety ── */
    for (int y = 0; y < map->height; y++) {
        for (int x = 0; x < map->width; x++) {
            int idx = y * map->width + x;
            if (map->collision_layer[idx] == TILE_SOLID_1) {
                bool has_air_neighbor = false;
                if (y > 0 && map->collision_layer[(y-1)*map->width+x] == 0)
                    has_air_neighbor = true;
                if (!has_air_neighbor) {
                    map->collision_layer[idx] = random_solid();
                }
            }
        }
    }

    /* ── Phase 6: background decoration ── */
    gen_bg_decoration(map);

    /* ── Phase 7: metadata ── */
    map->player_spawn = vec2(4.0f * TILE_SIZE,
                             (STATION_FLOOR_ROW - 2) * TILE_SIZE);

    map->gravity  = config->gravity > 0 ? config->gravity : 150.0f;
    map->bg_color = (SDL_Color){3, 3, 14, 255};  /* very dark blue-black */
    map->has_bg_color = true;
    map->parallax_style = (int)PARALLAX_STYLE_DEEP_SPACE;

    /* Exit zone at far right */
    if (map->exit_zone_count < MAX_EXIT_ZONES) {
        ExitZone *ez = &map->exit_zones[map->exit_zone_count++];
        int exit_x = map->width - 5;
        int exit_y = STATION_FLOOR_ROW - 3;
        ez->x = (float)(exit_x * TILE_SIZE);
        ez->y = (float)(exit_y * TILE_SIZE);
        ez->w = 2.0f * TILE_SIZE;
        ez->h = 3.0f * TILE_SIZE;
        snprintf(ez->target, sizeof(ez->target), "generate:station");

        /* Clear exit zone area */
        for (int y = exit_y; y < exit_y + 3 && y < map->height; y++) {
            for (int x = exit_x; x < exit_x + 2 && x < map->width; x++) {
                map->collision_layer[y * map->width + x] = 0;
            }
        }
    }

    /* Music */
    snprintf(map->music_path, sizeof(map->music_path), "assets/sounds/algardalgar.ogg");

    printf("levelgen_station: generated %dx%d level (%d segments, seed=%u, gravity=%.0f)\n",
           map->width, map->height, num_segs, s_rng_state, map->gravity);
    printf("  segments:");
    for (int i = 0; i < num_segs; i++) {
        printf(" %s", sseg_names[seg_types[i]]);
    }
    printf("\n");

    return true;
}

/* ═══════════════════════════════════════════════════
 *  Mars Base Generator
 *
 *  A dedicated generator for vertical, claustrophobic
 *  Mars underground base levels. Uses the tall 46-tile
 *  height to create multi-level structures connected by
 *  shafts. Heavy laser turret, spawner, and charger
 *  presence. The base digs underground because the
 *  surface is hazardous.
 *
 *  Layout: narrow vertical shafts connect wider rooms.
 *  Ceiling and floor are solid rock. Playable area is
 *  roughly 38 tiles tall (rows 3-41) with internal
 *  floors dividing it into 3 levels.
 * ═══════════════════════════════════════════════════ */

/* Mars Base layout constants */
#define MB_HEIGHT      46    /* full level height (tall)          */
#define MB_CEIL_ROW     2    /* top rock ceiling bottom           */
#define MB_FLOOR_ROW   43    /* bottom rock floor top             */
#define MB_MID_UPPER   15    /* upper internal floor              */
#define MB_MID_LOWER   29    /* lower internal floor              */

static void mb_fill_shell(uint16_t *col, int mw, int mh, int x0, int x1) {
    /* Top rock: rows 0 through MB_CEIL_ROW */
    fill_rect(col, mw, mh, x0, 0, x1, MB_CEIL_ROW, TILE_SOLID_1);
    /* Bottom rock: rows MB_FLOOR_ROW through bottom */
    fill_rect(col, mw, mh, x0, MB_FLOOR_ROW, x1, mh - 1, TILE_SOLID_1);
}

/* Mars Base segment types */
typedef enum MarsBaseSegType {
    MBSEG_ENTRY,       /* safe entry room at the top              */
    MBSEG_SHAFT,       /* vertical shaft spanning multiple levels */
    MBSEG_CORRIDOR,    /* narrow horizontal corridor on one level */
    MBSEG_TURRET_HALL, /* long hall with laser turrets on walls   */
    MBSEG_HIVE,        /* spawner room with grunt waves          */
    MBSEG_ARENA,       /* tall multi-level combat arena           */
    MBSEG_TYPE_COUNT
} MarsBaseSegType;

/* ── Mars Base segment: entry room (top level) ── */
static void gen_mb_entry(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    mb_fill_shell(col, mw, mh, x0, x0 + w - 1);

    /* Internal floors at upper and lower mid-levels */
    fill_rect(col, mw, mh, x0, MB_MID_UPPER, x0 + w - 1, MB_MID_UPPER + 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0, MB_MID_LOWER, x0 + w - 1, MB_MID_LOWER + 1, TILE_SOLID_1);

    /* Open space on the top level only (rows CEIL+1 to MID_UPPER-1) */
    /* Side walls */
    fill_rect(col, mw, mh, x0, MB_CEIL_ROW + 1, x0, MB_MID_UPPER - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, MB_CEIL_ROW + 1, x0 + w - 1, MB_MID_UPPER - 1, TILE_SOLID_1);

    /* Opening on the right wall to exit to the next segment */
    for (int y = MB_MID_UPPER - 4; y < MB_MID_UPPER; y++) {
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }

    /* Health pickup */
    add_entity(map, "powerup_hp", x0 + w / 2, MB_MID_UPPER - 1);

    /* Charger at higher difficulty */
    if (difficulty > 0.5f) {
        add_entity(map, "charger", x0 + rng_range(3, w - 4), MB_MID_UPPER - 1);
    }
}

/* ── Mars Base segment: vertical shaft ── */
static void gen_mb_shaft(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    mb_fill_shell(col, mw, mh, x0, x0 + w - 1);

    /* Walls on both sides spanning the full playable height */
    fill_rect(col, mw, mh, x0, MB_CEIL_ROW + 1, x0, MB_FLOOR_ROW - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, MB_CEIL_ROW + 1, x0 + w - 1, MB_FLOOR_ROW - 1, TILE_SOLID_1);

    /* Openings at top and bottom of walls for connectivity */
    for (int y = MB_CEIL_ROW + 1; y < MB_CEIL_ROW + 5; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }
    for (int y = MB_FLOOR_ROW - 4; y < MB_FLOOR_ROW; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }

    /* Alternating platforms climbing up the shaft */
    int shaft_depth = MB_FLOOR_ROW - MB_CEIL_ROW - 2;
    int num_plats = shaft_depth / 4;
    if (num_plats > 9) num_plats = 9;
    int inner_w = w - 2;

    for (int i = 0; i < num_plats; i++) {
        int py = MB_FLOOR_ROW - 3 - i * 4;
        if (py < MB_CEIL_ROW + 2) break;
        bool left_side = (i % 2 == 0);
        int px = left_side ? x0 + 1 : x0 + w - 1 - (inner_w > 4 ? 3 : 2);
        int pw = (inner_w > 4) ? 3 : 2;
        for (int j = 0; j < pw; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }
    }

    /* Vertical moving platform */
    if (rng_float() < 0.5f) {
        int mid_y = (MB_CEIL_ROW + MB_FLOOR_ROW) / 2;
        add_entity(map, "platform_v", x0 + w / 2, mid_y);
    }

    /* Laser turret on one wall — fires across the shaft */
    if (difficulty > 0.2f) {
        int side = rng_range(0, 1);
        int turret_x = side ? x0 + 1 : x0 + w - 2;
        int turret_y = rng_range(MB_CEIL_ROW + 6, MB_MID_LOWER);
        add_entity(map, "laser_turret", turret_x, turret_y);
    }

    /* Second laser turret (tracking) at higher difficulty */
    if (difficulty > 0.6f && rng_float() < 0.6f) {
        int side = rng_range(0, 1);
        int turret_x = side ? x0 + 1 : x0 + w - 2;
        int turret_y = rng_range(MB_MID_UPPER, MB_MID_LOWER - 4);
        add_entity(map, "laser_turret_track", turret_x, turret_y);
    }

    /* Flyer in the shaft */
    if (difficulty > 0.3f && rng_float() < difficulty) {
        int mid_y = (MB_CEIL_ROW + MB_FLOOR_ROW) / 2;
        add_entity(map, "flyer", x0 + w / 2, rng_range(mid_y - 6, mid_y + 6));
    }

    /* Fuel pickup near the top */
    if (rng_float() < 0.5f) {
        add_entity(map, "powerup_fuel", x0 + w / 2, MB_CEIL_ROW + 4);
    }
}

/* ── Mars Base segment: narrow corridor (one level) ── */
static void gen_mb_corridor(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    mb_fill_shell(col, mw, mh, x0, x0 + w - 1);

    /* Pick which level this corridor is on (upper, mid, or lower) */
    int level = rng_range(0, 2);
    int floor_row, ceil_row;
    switch (level) {
        case 0: /* upper */
            ceil_row  = MB_CEIL_ROW;
            floor_row = MB_MID_UPPER;
            break;
        case 1: /* middle */
            ceil_row  = MB_MID_UPPER + 2;
            floor_row = MB_MID_LOWER;
            break;
        default: /* lower */
            ceil_row  = MB_MID_LOWER + 2;
            floor_row = MB_FLOOR_ROW;
            break;
    }

    /* Floor and ceiling for this level */
    fill_rect(col, mw, mh, x0, ceil_row, x0 + w - 1, ceil_row + 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0, floor_row, x0 + w - 1, floor_row + 1, TILE_SOLID_1);

    /* Fill rest with rock (above and below the corridor) */
    if (ceil_row > MB_CEIL_ROW + 1) {
        fill_rect(col, mw, mh, x0, MB_CEIL_ROW + 1, x0 + w - 1, ceil_row - 1, TILE_SOLID_1);
    }
    if (floor_row + 2 < MB_FLOOR_ROW) {
        fill_rect(col, mw, mh, x0, floor_row + 2, x0 + w - 1, MB_FLOOR_ROW - 1, TILE_SOLID_1);
    }

    /* Side walls with openings */
    fill_rect(col, mw, mh, x0, ceil_row + 2, x0, floor_row - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, ceil_row + 2, x0 + w - 1, floor_row - 1, TILE_SOLID_1);
    /* Door openings */
    for (int y = floor_row - 4; y < floor_row; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }

    /* Charger patrol */
    if (rng_float() < 0.5f + difficulty * 0.3f) {
        add_entity(map, "charger", x0 + rng_range(2, w - 3), floor_row - 1);
    }

    /* Grunt */
    if (rng_float() < 0.4f + difficulty * 0.3f) {
        add_entity(map, "grunt", x0 + rng_range(2, w - 3), floor_row - 1);
    }

    /* Turret on ceiling */
    if (difficulty > 0.3f && rng_float() < 0.6f) {
        add_entity(map, "turret", x0 + w / 2, ceil_row + 2);
    }

    /* Health pickup */
    if (rng_float() < 0.3f) {
        add_entity(map, "powerup_hp", x0 + rng_range(2, w - 3), floor_row - 1);
    }
}

/* ── Mars Base segment: turret hall (laser gauntlet) ── */
static void gen_mb_turret_hall(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    mb_fill_shell(col, mw, mh, x0, x0 + w - 1);

    /* Walls spanning full height */
    fill_rect(col, mw, mh, x0, MB_CEIL_ROW + 1, x0, MB_FLOOR_ROW - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, MB_CEIL_ROW + 1, x0 + w - 1, MB_FLOOR_ROW - 1, TILE_SOLID_1);

    /* Internal floors dividing into 3 levels */
    fill_rect(col, mw, mh, x0 + 1, MB_MID_UPPER, x0 + w - 2, MB_MID_UPPER + 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + 1, MB_MID_LOWER, x0 + w - 2, MB_MID_LOWER + 1, TILE_SOLID_1);

    /* Openings between levels: holes in the floors to drop through */
    int hole1_x = x0 + rng_range(2, w / 2 - 1);
    int hole2_x = x0 + rng_range(w / 2 + 1, w - 3);
    for (int j = 0; j < 3 && hole1_x + j < x0 + w - 1; j++) {
        set_tile(col, mw, mh, hole1_x + j, MB_MID_UPPER, TILE_EMPTY);
        set_tile(col, mw, mh, hole1_x + j, MB_MID_UPPER + 1, TILE_EMPTY);
    }
    for (int j = 0; j < 3 && hole2_x + j < x0 + w - 1; j++) {
        set_tile(col, mw, mh, hole2_x + j, MB_MID_LOWER, TILE_EMPTY);
        set_tile(col, mw, mh, hole2_x + j, MB_MID_LOWER + 1, TILE_EMPTY);
    }

    /* Door openings on sides at each level */
    for (int y = MB_MID_UPPER - 4; y < MB_MID_UPPER; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }
    for (int y = MB_MID_LOWER - 4; y < MB_MID_LOWER; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }
    for (int y = MB_FLOOR_ROW - 4; y < MB_FLOOR_ROW; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }

    /* Laser turrets on walls at each level — the gauntlet */
    /* Upper level */
    add_entity(map, "laser_turret", x0 + 1, MB_CEIL_ROW + 5);

    /* Middle level */
    add_entity(map, "laser_turret", x0 + w - 2, MB_MID_UPPER + 5);

    /* Lower level — tracking at higher difficulty */
    if (difficulty > 0.4f) {
        add_entity(map, "laser_turret_track", x0 + 1, MB_MID_LOWER + 5);
    } else {
        add_entity(map, "laser_turret", x0 + 1, MB_MID_LOWER + 5);
    }

    /* Extra turret at high difficulty */
    if (difficulty > 0.7f) {
        add_entity(map, "turret", x0 + w / 2, MB_CEIL_ROW + 2);
    }

    /* One-way platforms for navigation between holes */
    int plat_y1 = MB_MID_UPPER - 4;
    int plat_y2 = MB_MID_LOWER - 4;
    for (int j = 0; j < 3; j++) {
        set_tile(col, mw, mh, x0 + w / 2 - 1 + j, plat_y1, TILE_PLAT);
        set_tile(col, mw, mh, x0 + w / 2 - 1 + j, plat_y2, TILE_PLAT);
    }

    /* Fuel pickup as reward for surviving the gauntlet */
    if (rng_float() < 0.5f) {
        add_entity(map, "powerup_fuel", x0 + w / 2, MB_FLOOR_ROW - 1);
    }
}

/* ── Mars Base segment: hive / spawner room ── */
static void gen_mb_hive(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    mb_fill_shell(col, mw, mh, x0, x0 + w - 1);

    /* Walls */
    fill_rect(col, mw, mh, x0, MB_CEIL_ROW + 1, x0, MB_FLOOR_ROW - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, MB_CEIL_ROW + 1, x0 + w - 1, MB_FLOOR_ROW - 1, TILE_SOLID_1);

    /* Internal floor at lower mid-level only — open upper area */
    fill_rect(col, mw, mh, x0 + 1, MB_MID_LOWER, x0 + w - 2, MB_MID_LOWER + 1, TILE_SOLID_1);

    /* Hole in lower floor for vertical connectivity */
    int hole_x = x0 + rng_range(2, w - 4);
    for (int j = 0; j < 3 && hole_x + j < x0 + w - 1; j++) {
        set_tile(col, mw, mh, hole_x + j, MB_MID_LOWER, TILE_EMPTY);
        set_tile(col, mw, mh, hole_x + j, MB_MID_LOWER + 1, TILE_EMPTY);
    }

    /* Door openings on sides */
    for (int y = MB_MID_LOWER - 4; y < MB_MID_LOWER; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }
    for (int y = MB_FLOOR_ROW - 4; y < MB_FLOOR_ROW; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }

    /* Spawner in the upper area — the hive */
    add_entity(map, "spawner", x0 + w / 2, MB_CEIL_ROW + 4);

    /* Second spawner at high difficulty */
    if (difficulty > 0.6f) {
        add_entity(map, "spawner", x0 + w / 2, MB_MID_LOWER + 5);
    }

    /* Platforms for vertical navigation in the upper area */
    for (int i = 0; i < 3; i++) {
        int py = MB_MID_LOWER - 3 - i * 5;
        if (py < MB_CEIL_ROW + 3) break;
        int px = (i % 2 == 0) ? x0 + 2 : x0 + w - 5;
        for (int j = 0; j < 3; j++) {
            set_tile(col, mw, mh, px + j, py, TILE_PLAT);
        }
    }

    /* Turret guarding the spawner */
    if (difficulty > 0.3f) {
        add_entity(map, "turret", x0 + rng_range(2, w - 3), MB_CEIL_ROW + 2);
    }

    /* Health and fuel pickups — earned by destroying the hive */
    add_entity(map, "powerup_hp", x0 + w / 2 - 2, MB_FLOOR_ROW - 1);
    if (rng_float() < 0.4f) {
        add_entity(map, "powerup_fuel", x0 + w / 2 + 2, MB_MID_LOWER - 1);
    }
}

/* ── Mars Base segment: tall multi-level arena ── */
static void gen_mb_arena(Tilemap *map, int x0, int w, float difficulty) {
    uint16_t *col = map->collision_layer;
    int mw = map->width;
    int mh = map->height;

    mb_fill_shell(col, mw, mh, x0, x0 + w - 1);

    /* Walls */
    fill_rect(col, mw, mh, x0, MB_CEIL_ROW + 1, x0, MB_FLOOR_ROW - 1, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1, MB_CEIL_ROW + 1, x0 + w - 1, MB_FLOOR_ROW - 1, TILE_SOLID_1);

    /* Side ledges at three heights — creates a vertical arena */
    int ledge_w = 3;
    /* Upper ledges */
    fill_rect(col, mw, mh, x0 + 1, MB_CEIL_ROW + 8, x0 + ledge_w, MB_CEIL_ROW + 8, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1 - ledge_w, MB_CEIL_ROW + 8, x0 + w - 2, MB_CEIL_ROW + 8, TILE_SOLID_1);
    /* Mid ledges */
    fill_rect(col, mw, mh, x0 + 1, MB_MID_UPPER + 6, x0 + ledge_w, MB_MID_UPPER + 6, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1 - ledge_w, MB_MID_UPPER + 6, x0 + w - 2, MB_MID_UPPER + 6, TILE_SOLID_1);
    /* Lower ledges */
    fill_rect(col, mw, mh, x0 + 1, MB_MID_LOWER + 6, x0 + ledge_w, MB_MID_LOWER + 6, TILE_SOLID_1);
    fill_rect(col, mw, mh, x0 + w - 1 - ledge_w, MB_MID_LOWER + 6, x0 + w - 2, MB_MID_LOWER + 6, TILE_SOLID_1);

    /* Central floating platforms at different heights */
    int cp_x = x0 + w / 2 - 2;
    for (int j = 0; j < 4; j++) {
        set_tile(col, mw, mh, cp_x + j, MB_CEIL_ROW + 12, TILE_PLAT);
        set_tile(col, mw, mh, cp_x + j, MB_MID_LOWER - 2, TILE_PLAT);
    }

    /* Ground floor for walking */
    fill_rect(col, mw, mh, x0 + 1, MB_FLOOR_ROW - 1, x0 + w - 2, MB_FLOOR_ROW - 1, TILE_SOLID_1);

    /* Door openings on sides */
    for (int y = MB_FLOOR_ROW - 5; y < MB_FLOOR_ROW - 1; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }
    for (int y = MB_CEIL_ROW + 1; y < MB_CEIL_ROW + 5; y++) {
        set_tile(col, mw, mh, x0, y, TILE_EMPTY);
        set_tile(col, mw, mh, x0 + w - 1, y, TILE_EMPTY);
    }

    /* Enemies — mixed chargers, grunts, flyers across levels */
    int num_enemies = 2 + (int)(difficulty * 3);
    for (int i = 0; i < num_enemies; i++) {
        float r = rng_float();
        if (r < 0.30f) {
            add_entity(map, "charger", x0 + rng_range(3, w - 4), MB_FLOOR_ROW - 2);
        } else if (r < 0.55f) {
            add_entity(map, "grunt", x0 + rng_range(3, w - 4), MB_FLOOR_ROW - 2);
        } else {
            int fly_y = rng_range(MB_CEIL_ROW + 5, MB_FLOOR_ROW - 6);
            add_entity(map, "flyer", x0 + rng_range(3, w - 4), fly_y);
        }
    }

    /* Turrets on ledges */
    if (difficulty > 0.3f) {
        add_entity(map, "turret", x0 + 2, MB_CEIL_ROW + 7);
    }
    if (difficulty > 0.6f) {
        add_entity(map, "turret", x0 + w - 3, MB_MID_UPPER + 5);
    }

    /* Laser turret for extra threat */
    if (difficulty > 0.5f && rng_float() < 0.6f) {
        add_entity(map, "laser_turret_track", x0 + 1, MB_MID_LOWER + 3);
    }

    /* Powerup on central platform */
    if (rng_float() < 0.5f) {
        if (difficulty > 0.5f && rng_float() < 0.3f) {
            add_entity(map, "powerup_drone", cp_x + 2, MB_CEIL_ROW + 11);
        } else {
            add_entity(map, "powerup_hp", cp_x + 2, MB_MID_LOWER - 3);
        }
    }
}

/* ── Mars Base segment selection ── */

static MarsBaseSegType pick_mb_segment(int index, int total) {
    if (index == 0) return MBSEG_ENTRY;
    if (index == total - 1 && rng_float() < 0.6f) return MBSEG_ARENA;

    float r = rng_float();
    /* Heavy shaft + turret hall bias for that vertical feel */
    if (r < 0.25f) return MBSEG_SHAFT;
    if (r < 0.45f) return MBSEG_TURRET_HALL;
    if (r < 0.60f) return MBSEG_CORRIDOR;
    if (r < 0.75f) return MBSEG_HIVE;
    if (r < 0.90f) return MBSEG_ARENA;
    return MBSEG_CORRIDOR;
}

static int mb_segment_width(MarsBaseSegType type) {
    switch (type) {
        case MBSEG_ENTRY:      return rng_range(10, 14);
        case MBSEG_SHAFT:      return rng_range(8, 12);
        case MBSEG_CORRIDOR:   return rng_range(12, 18);
        case MBSEG_TURRET_HALL:return rng_range(12, 16);
        case MBSEG_HIVE:       return rng_range(14, 18);
        case MBSEG_ARENA:      return rng_range(16, 22);
        default:               return 12;
    }
}

/* ── Config preset for Mars Base ── */

LevelGenConfig levelgen_mars_base_config(uint32_t seed, int depth) {
    if (depth < 0) depth = 0;

    /* Segments grow with depth: 6 -> 7 -> 8 (capped) */
    int segments = 6 + depth;
    if (segments > 8) segments = 8;

    /* Difficulty ramps: 0.5 -> 0.7 -> 0.9 (capped) */
    float diff = 0.5f + depth * 0.2f;
    if (diff > 1.0f) diff = 1.0f;

    LevelGenConfig config = {
        .seed         = seed,
        .num_segments = segments,
        .difficulty   = diff,
        .gravity      = 700.0f,    /* artificial gravity in the base */
        .theme_count  = 1,
    };
    config.themes[0] = THEME_MARS_BASE;
    return config;
}

/* ── Generate a Mars Base level ── */

bool levelgen_generate_mars_base(Tilemap *map, const LevelGenConfig *config) {
    if (!map || !config) return false;

    rng_seed(config->seed);

    int num_segs = config->num_segments;
    if (num_segs < 3)  num_segs = 3;
    if (num_segs > 10) num_segs = 10;

    /* ── Phase 1: decide segment types and widths ── */
    MarsBaseSegType seg_types[12];
    int             seg_widths[12];
    int             total_width = 0;

    for (int i = 0; i < num_segs && i < 12; i++) {
        seg_types[i]  = pick_mb_segment(i, num_segs);
        seg_widths[i] = mb_segment_width(seg_types[i]);
        total_width  += seg_widths[i];
    }

    /* 2-tile buffer on each side */
    total_width += 4;

    /* ── Phase 2: allocate tilemap ── */
    memset(map, 0, sizeof(Tilemap));
    map->width  = total_width;
    map->height = MB_HEIGHT;

    int total_tiles = map->width * map->height;
    map->collision_layer = calloc(total_tiles, sizeof(uint16_t));
    map->bg_layer        = calloc(total_tiles, sizeof(uint16_t));
    map->fg_layer        = calloc(total_tiles, sizeof(uint16_t));

    if (!map->collision_layer || !map->bg_layer || !map->fg_layer) {
        fprintf(stderr, "levelgen_mars_base: failed to allocate layers\n");
        return false;
    }

    /* ── Phase 3: tile definitions ── */
    map->tile_defs[1] = (TileDef){0, 0, TILE_SOLID};
    map->tile_defs[2] = (TileDef){1, 0, TILE_SOLID};
    map->tile_defs[3] = (TileDef){2, 0, TILE_SOLID};
    map->tile_defs[4] = (TileDef){0, 1, TILE_PLATFORM};
    map->tile_def_count = 5;

    /* ── Phase 4: generate segments ── */
    int cursor = 2;

    /* Left border wall */
    fill_rect(map->collision_layer, map->width, map->height,
              0, 0, 1, map->height - 1, TILE_SOLID_1);

    static const char *mb_seg_names[] = {
        "entry", "shaft", "corr", "turret", "hive", "arena"
    };

    for (int i = 0; i < num_segs; i++) {
        int w = seg_widths[i];
        float diff = config->difficulty;

        switch (seg_types[i]) {
            case MBSEG_ENTRY:       gen_mb_entry(map, cursor, w, diff);       break;
            case MBSEG_SHAFT:       gen_mb_shaft(map, cursor, w, diff);       break;
            case MBSEG_CORRIDOR:    gen_mb_corridor(map, cursor, w, diff);    break;
            case MBSEG_TURRET_HALL: gen_mb_turret_hall(map, cursor, w, diff); break;
            case MBSEG_HIVE:        gen_mb_hive(map, cursor, w, diff);        break;
            case MBSEG_ARENA:       gen_mb_arena(map, cursor, w, diff);       break;
            default:                gen_mb_corridor(map, cursor, w, diff);    break;
        }

        cursor += w;
    }

    /* Right border wall */
    fill_rect(map->collision_layer, map->width, map->height,
              map->width - 2, 0, map->width - 1, map->height - 1, TILE_SOLID_1);

    /* ── Phase 5: visual variety (random solid variants for interior tiles) ── */
    for (int y = 0; y < map->height; y++) {
        for (int x = 0; x < map->width; x++) {
            int idx = y * map->width + x;
            if (map->collision_layer[idx] == TILE_SOLID_1) {
                bool has_air_neighbor = false;
                if (y > 0 && map->collision_layer[(y - 1) * map->width + x] == 0)
                    has_air_neighbor = true;
                if (!has_air_neighbor) {
                    map->collision_layer[idx] = random_solid();
                }
            }
        }
    }

    /* ── Phase 5b: background decoration ── */
    gen_bg_decoration(map);

    /* ── Phase 6: metadata ── */
    map->player_spawn = vec2(4.0f * TILE_SIZE,
                             (MB_MID_UPPER - 2) * TILE_SIZE);

    map->gravity  = config->gravity > 0 ? config->gravity : 700.0f;
    map->bg_color = (SDL_Color){18, 10, 8, 255};
    map->has_bg_color = true;
    map->parallax_style = (int)PARALLAX_STYLE_INTERIOR;

    /* Mars tileset */
    snprintf(map->tileset_path, sizeof(map->tileset_path),
             "%s", "assets/tiles/mars_tileset.png");

    /* Exit zone at the bottom-right of the level */
    if (map->exit_zone_count < MAX_EXIT_ZONES) {
        ExitZone *ez = &map->exit_zones[map->exit_zone_count++];
        int exit_x = map->width - 5;
        int exit_y = MB_FLOOR_ROW - 3;
        ez->x = (float)(exit_x * TILE_SIZE);
        ez->y = (float)(exit_y * TILE_SIZE);
        ez->w = 2.0f * TILE_SIZE;
        ez->h = 3.0f * TILE_SIZE;
        snprintf(ez->target, sizeof(ez->target), "generate:mars_base");

        /* Clear exit zone area */
        for (int y = exit_y; y < exit_y + 3 && y < map->height; y++) {
            for (int x = exit_x; x < exit_x + 2 && x < map->width; x++) {
                map->collision_layer[y * map->width + x] = 0;
            }
        }
    }

    /* Music */
    snprintf(map->music_path, sizeof(map->music_path), "assets/sounds/kaffe_og_kage.ogg");

    printf("levelgen_mars_base: generated %dx%d level (%d segments, seed=%u)\n",
           map->width, map->height, num_segs, s_rng_state);
    printf("  segments:");
    for (int i = 0; i < num_segs; i++) {
        printf(" %s", mb_seg_names[seg_types[i]]);
    }
    printf("\n");

    return true;
}

/* ═══════════════════════════════════════════════════
 *  Dump to .lvl file format
 * ═══════════════════════════════════════════════════ */

bool levelgen_dump_lvl(const Tilemap *map, const char *path) {
    if (!map || !path) return false;

    FILE *f = fopen(path, "w");
    if (!f) {
        fprintf(stderr, "levelgen: failed to open %s for writing\n", path);
        return false;
    }

    fprintf(f, "# Procedurally generated level\n");
    fprintf(f, "# Seed state: %u\n\n", s_rng_state);

    fprintf(f, "TILESET assets/tiles/tileset.png\n");
    fprintf(f, "SIZE %d %d\n", map->width, map->height);

    /* Player spawn in tile coords */
    int spawn_tx = (int)(map->player_spawn.x / TILE_SIZE);
    int spawn_ty = (int)(map->player_spawn.y / TILE_SIZE);
    fprintf(f, "SPAWN %d %d\n", spawn_tx, spawn_ty);

    if (map->gravity > 0) {
        fprintf(f, "GRAVITY %.0f\n", map->gravity);
    }

    if (map->wind != 0.0f) {
        fprintf(f, "WIND %.0f\n", map->wind);
    }

    if (map->has_bg_color) {
        fprintf(f, "BG_COLOR %d %d %d\n",
                map->bg_color.r, map->bg_color.g, map->bg_color.b);
    }

    if (map->music_path[0]) {
        fprintf(f, "MUSIC %s\n", map->music_path);
    }

    if (map->player_unarmed) {
        fprintf(f, "PLAYER_UNARMED\n");
    }

    fprintf(f, "\n");

    /* Entity spawns */
    for (int i = 0; i < map->entity_spawn_count; i++) {
        const EntitySpawn *es = &map->entity_spawns[i];
        int tx = (int)(es->x / TILE_SIZE);
        int ty = (int)(es->y / TILE_SIZE);
        fprintf(f, "ENTITY %s %d %d\n", es->type_name, tx, ty);
    }

    fprintf(f, "\n");

    /* Exit zones */
    for (int i = 0; i < map->exit_zone_count; i++) {
        const ExitZone *ez = &map->exit_zones[i];
        int tx = (int)(ez->x / TILE_SIZE);
        int ty = (int)(ez->y / TILE_SIZE);
        int tw = (int)(ez->w / TILE_SIZE);
        int th = (int)(ez->h / TILE_SIZE);
        if (ez->target[0]) {
            fprintf(f, "EXIT %d %d %d %d %s\n", tx, ty, tw, th, ez->target);
        } else {
            fprintf(f, "EXIT %d %d %d %d\n", tx, ty, tw, th);
        }
    }
    if (map->exit_zone_count > 0) fprintf(f, "\n");

    /* Tile definitions */
    for (int id = 1; id < map->tile_def_count; id++) {
        const TileDef *td = &map->tile_defs[id];
        if (td->flags != 0 || td->tex_x != 0 || td->tex_y != 0) {
            fprintf(f, "TILEDEF %d %d %d %u\n", id, td->tex_x, td->tex_y, td->flags);
        }
    }

    fprintf(f, "\n");

    /* Collision layer */
    fprintf(f, "LAYER collision\n");
    for (int y = 0; y < map->height; y++) {
        for (int x = 0; x < map->width; x++) {
            if (x > 0) fprintf(f, " ");
            fprintf(f, "%d", map->collision_layer[y * map->width + x]);
        }
        fprintf(f, "\n");
    }

    /* Background layer */
    bool has_bg = false;
    for (int i = 0; i < map->width * map->height; i++) {
        if (map->bg_layer[i] != 0) { has_bg = true; break; }
    }
    if (has_bg) {
        fprintf(f, "\nLAYER bg\n");
        for (int y = 0; y < map->height; y++) {
            for (int x = 0; x < map->width; x++) {
                if (x > 0) fprintf(f, " ");
                fprintf(f, "%d", map->bg_layer[y * map->width + x]);
            }
            fprintf(f, "\n");
        }
    }

    fclose(f);
    printf("levelgen: dumped level to %s\n", path);
    return true;
}
