"""Stage definitions and defaults."""

from __future__ import annotations

from .entities_constants import ZOMBIE_DECAY_DURATION_FRAMES
from .gameplay_constants import SURVIVOR_SPAWN_RATE
from .level_constants import DEFAULT_GRID_COLS, DEFAULT_GRID_ROWS
from .models import FuelMode, Stage


def _build_stage18_reinforced_wall_zones(
    *,
    grid_cols: int,
    grid_rows: int,
    rooms_per_side: int,
    room_size: int,
    gap_width: int,
) -> list[tuple[int, int, int, int]]:
    reinforced_cells: set[tuple[int, int]] = set()

    # Inter-panel gap bands.
    inner_start = 2
    gap_cols: list[int] = []
    gap_rows: list[int] = []
    step = room_size + gap_width
    for idx in range(1, rooms_per_side):
        gap_start = inner_start + idx * step - gap_width
        gap_cols.extend(range(gap_start, gap_start + gap_width))
        gap_rows.extend(range(gap_start, gap_start + gap_width))
    for x in gap_cols:
        for y in range(inner_start, grid_rows - inner_start):
            reinforced_cells.add((x, y))
    for y in gap_rows:
        for x in range(inner_start, grid_cols - inner_start):
            reinforced_cells.add((x, y))

    # Corridor openings (width 1) through the gap bands.
    room_centers = [
        inner_start + (room_size // 2) + idx * step for idx in range(rooms_per_side)
    ]
    for y in room_centers:
        for x in gap_cols:
            reinforced_cells.discard((x, y))
    for x in room_centers:
        for y in gap_rows:
            reinforced_cells.discard((x, y))

    return [(x, y, 1, 1) for x, y in sorted(reinforced_cells)]


def _build_stage18_pitfall_zones(
    *,
    grid_cols: int,
    grid_rows: int,
    rooms_per_side: int,
    room_size: int,
    gap_width: int,
) -> list[tuple[int, int, int, int]]:
    pitfall_cells: set[tuple[int, int]] = set()
    inner_start = 2

    # Panel-edge notches: keep only the jagged concave parts as pitfalls.
    for row in range(rooms_per_side):
        for col in range(rooms_per_side):
            start_x = inner_start + col * (room_size + gap_width)
            start_y = inner_start + row * (room_size + gap_width)
            end_x = start_x + room_size - 1
            end_y = start_y + room_size - 1
            for offset in range(0, room_size, 2):
                x = start_x + offset
                y = start_y + offset
                pitfall_cells.add((x, start_y))
                pitfall_cells.add((x, end_y))
                pitfall_cells.add((start_x, y))
                pitfall_cells.add((end_x, y))

    # Keep pitfalls and reinforced walls disjoint.
    reinforced_cells = {
        (cell_x, cell_y)
        for zone_x, zone_y, zone_w, zone_h in _build_stage18_reinforced_wall_zones(
            grid_cols=grid_cols,
            grid_rows=grid_rows,
            rooms_per_side=rooms_per_side,
            room_size=room_size,
            gap_width=gap_width,
        )
        for cell_y in range(zone_y, zone_y + zone_h)
        for cell_x in range(zone_x, zone_x + zone_w)
    }
    pitfall_cells -= reinforced_cells
    pitfall_cells = {
        (x, y)
        for x, y in pitfall_cells
        if 1 <= x < grid_cols - 1 and 1 <= y < grid_rows - 1
    }
    return [(x, y, 1, 1) for x, y in sorted(pitfall_cells)]


STAGES: list[Stage] = [
    Stage(
        id="stage1",
        name_key="stages.stage1.name",
        description_key="stages.stage1.description",
        available=True,
        exterior_spawn_weight=0.97,
        interior_spawn_weight=0.03,
        zombie_normal_ratio=1.0,
    ),
    Stage(
        id="stage2",
        name_key="stages.stage2.name",
        description_key="stages.stage2.description",
        available=True,
        fuel_mode=FuelMode.FUEL_CAN,
        initial_interior_spawn_rate=0.007,
        exterior_spawn_weight=0.97,
        interior_spawn_weight=0.03,
        zombie_normal_ratio=1.0,
    ),
    Stage(
        id="stage3",
        name_key="stages.stage3.name",
        description_key="stages.stage3.description",
        available=True,
        fuel_mode=FuelMode.FUEL_CAN,
        buddy_required_count=1,
        initial_interior_spawn_rate=0.007,
        exterior_spawn_weight=0.97,
        interior_spawn_weight=0.03,
        zombie_normal_ratio=1.0,
    ),
    Stage(
        id="stage4",
        name_key="stages.stage4.name",
        description_key="stages.stage4.description",
        available=True,
        survivor_rescue_stage=True,
        waiting_car_target_count=2,
        initial_interior_spawn_rate=0.007,
        zombie_normal_ratio=1.0,
        survivor_spawn_rate=SURVIVOR_SPAWN_RATE,
    ),
    Stage(
        id="stage5",
        name_key="stages.stage5.name",
        description_key="stages.stage5.description",
        intro_key="stages.stage5.intro",
        available=True,
        wall_algorithm="default.120%",
        endurance_stage=True,
        endurance_goal_ms=1_200_000,
        fuel_spawn_count=0,
        initial_interior_spawn_rate=0.02,
        exterior_spawn_weight=0.15,
        interior_spawn_weight=0.85,
        zombie_normal_ratio=1.0,
        zombie_decay_duration_frames=int(ZOMBIE_DECAY_DURATION_FRAMES * 1.2),
    ),
    Stage(
        id="stage6",
        name_key="stages.stage6.name",
        description_key="stages.stage6.description",
        available=True,
        fuel_mode=FuelMode.FUEL_CAN,
        initial_interior_spawn_rate=0.01,
        exterior_spawn_weight=0.8,
        interior_spawn_weight=0.2,
        zombie_tracker_ratio=0.6,
        zombie_normal_ratio=0.4,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage7",
        name_key="stages.stage7.name",
        description_key="stages.stage7.description",
        available=True,
        wall_algorithm="grid_wire",
        fuel_mode=FuelMode.FUEL_CAN,
        buddy_required_count=1,
        initial_interior_spawn_rate=0.01,
        exterior_spawn_weight=0.7,
        interior_spawn_weight=0.3,
        zombie_tracker_ratio=0.3,
        zombie_wall_hugging_ratio=0.3,
        zombie_normal_ratio=0.4,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage8",
        name_key="stages.stage8.name",
        description_key="stages.stage8.description",
        available=True,
        cell_size=35,
        wall_algorithm="grid_wire",
        fuel_mode=FuelMode.FUEL_CAN,
        initial_interior_spawn_rate=0.01,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.6,
        zombie_tracker_ratio=0.3,
        zombie_wall_hugging_ratio=0.7,
        zombie_normal_ratio=0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage9",
        name_key="stages.stage9.name",
        description_key="stages.stage9.description",
        available=True,
        cell_size=35,
        fuel_mode=FuelMode.FUEL_CAN,
        survivor_rescue_stage=True,
        waiting_car_target_count=1,
        initial_interior_spawn_rate=0.01,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.6,
        zombie_tracker_ratio=0.3,
        zombie_wall_hugging_ratio=0.7,
        zombie_normal_ratio=0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
        survivor_spawn_rate=SURVIVOR_SPAWN_RATE,
    ),
    Stage(
        id="stage10",
        name_key="stages.stage10.name",
        description_key="stages.stage10.description",
        intro_key="stages.stage10.intro",
        available=True,
        cell_size=40,
        wall_algorithm="sparse_moore.10%",
        survivor_rescue_stage=True,
        waiting_car_target_count=1,
        initial_interior_spawn_rate=0.02,
        exterior_spawn_weight=0.7,
        interior_spawn_weight=0.3,
        zombie_tracker_ratio=0.4,
        zombie_wall_hugging_ratio=0.2,
        zombie_normal_ratio=0.4,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
        survivor_spawn_rate=0.35,
    ),
    Stage(
        id="stage11",
        name_key="stages.stage11.name",
        description_key="stages.stage11.description",
        available=True,
        grid_cols=120,
        grid_rows=7,
        wall_algorithm="sparse_moore.10%",
        initial_shoes_count=1,
        waiting_car_target_count=1,
        initial_interior_spawn_rate=0.1,
        exterior_spawn_weight=0.3,
        interior_spawn_weight=0.7,
        zombie_tracker_ratio=0.5,
        zombie_normal_ratio=0.5,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage12",
        name_key="stages.stage12.name",
        description_key="stages.stage12.description",
        available=True,
        grid_cols=32,
        grid_rows=32,
        fall_spawn_zones=[
            (4, 4, 10, 10),
            (4, 18, 10, 10),
            (18, 4, 10, 10),
            (18, 18, 10, 10),
        ],
        fuel_mode=FuelMode.FUEL_CAN,
        initial_flashlight_count=5,
        initial_shoes_count=1,
        exterior_spawn_weight=0.5,
        interior_spawn_weight=0.2,
        interior_fall_spawn_weight=0.3,
        zombie_normal_ratio=1.0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage13",
        name_key="stages.stage13.name",
        description_key="stages.stage13.description",
        available=True,
        grid_cols=46,
        grid_rows=30,
        wall_algorithm="grid_wire",
        fall_spawn_zones=[
            (x, y, 2, 2)
            for y in range(2, DEFAULT_GRID_ROWS - 2, 4)
            for x in range(2, DEFAULT_GRID_COLS - 2, 4)
        ],
        fuel_mode=FuelMode.FUEL_CAN,
        buddy_required_count=1,
        initial_flashlight_count=3,
        initial_shoes_count=1,
        exterior_spawn_weight=0.6,
        interior_spawn_weight=0.1,
        interior_fall_spawn_weight=0.3,
        zombie_tracker_ratio=0.3,
        zombie_wall_hugging_ratio=0.3,
        zombie_normal_ratio=0.4,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage14",
        name_key="stages.stage14.name",
        description_key="stages.stage14.description",
        available=True,
        grid_cols=34,
        grid_rows=20,
        wall_rubble_ratio=0.35,
        fall_spawn_cell_ratio=0.05,
        fuel_mode=FuelMode.FUEL_CAN,
        initial_flashlight_count=3,
        initial_shoes_count=1,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.1,
        interior_fall_spawn_weight=0.7,
        zombie_normal_ratio=1.0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage15",
        name_key="stages.stage15.name",
        description_key="stages.stage15.description",
        intro_key="stages.stage15.intro",
        available=True,
        cell_size=35,
        grid_cols=64,
        grid_rows=24,
        wall_algorithm="grid_wire",
        fall_spawn_zones=[
            (33, 2, 4, 18),
        ],
        fuel_mode=FuelMode.FUEL_CAN,
        buddy_required_count=1,
        initial_flashlight_count=3,
        initial_shoes_count=1,
        initial_interior_spawn_rate=0.02,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.1,
        interior_fall_spawn_weight=0.7,
        zombie_wall_hugging_ratio=0.5,
        zombie_normal_ratio=0.5,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage16",
        name_key="stages.stage16.name",
        description_key="stages.stage16.description",
        available=True,
        cell_size=60,
        grid_cols=40,
        grid_rows=25,
        wall_algorithm="sparse_moore.25%",
        pitfall_density=0.04,
        fuel_mode=FuelMode.FUEL_CAN,
        initial_flashlight_count=1,
        initial_shoes_count=1,
        initial_interior_spawn_rate=0.05,
        exterior_spawn_weight=0.7,
        interior_spawn_weight=0.3,
        zombie_normal_ratio=1.0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage17",
        name_key="stages.stage17.name",
        description_key="stages.stage17.description",
        available=True,
        grid_cols=40,
        grid_rows=26,
        wall_algorithm="sparse_moore.25%",
        wall_rubble_ratio=0.25,
        pitfall_density=0.08,
        fuel_mode=FuelMode.FUEL_CAN,
        initial_flashlight_count=1,
        initial_shoes_count=1,
        initial_interior_spawn_rate=0.1,
        exterior_spawn_weight=0.5,
        interior_spawn_weight=0.5,
        zombie_tracker_ratio=1.0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage18",
        name_key="stages.stage18.name",
        description_key="stages.stage18.description",
        available=True,
        grid_cols=36,
        grid_rows=36,
        wall_algorithm="sparse_ortho.30%",
        wall_rubble_ratio=0.15,
        fall_spawn_cell_ratio=0.03,
        reinforced_wall_zones=_build_stage18_reinforced_wall_zones(
            grid_cols=36,
            grid_rows=36,
            rooms_per_side=3,
            room_size=10,
            gap_width=1,
        ),
        pitfall_zones=_build_stage18_pitfall_zones(
            grid_cols=36,
            grid_rows=36,
            rooms_per_side=3,
            room_size=10,
            gap_width=1,
        ),
        fuel_mode=FuelMode.FUEL_CAN,
        initial_interior_spawn_rate=0.08,
        exterior_spawn_weight=0.6,
        interior_spawn_weight=0.4,
        zombie_tracker_ratio=0.5,
        zombie_normal_ratio=0.5,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage19",
        name_key="stages.stage19.name",
        description_key="stages.stage19.description",
        available=True,
        grid_cols=35,
        grid_rows=35,
        cell_size=35,
        wall_algorithm="grid_wire.170%",
        fall_spawn_cell_ratio=0.02,
        pitfall_density=0.008,
        fuel_mode=FuelMode.FUEL_CAN,
        buddy_required_count=1,
        initial_interior_spawn_rate=0.08,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.0,
        interior_fall_spawn_weight=0.6,
        zombie_tracker_ratio=0.5,
        zombie_wall_hugging_ratio=0.5,
        zombie_normal_ratio=0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage20",
        name_key="stages.stage20.name",
        description_key="stages.stage20.description",
        intro_key="stages.stage20.intro",
        available=True,
        grid_cols=40,
        grid_rows=25,
        cell_size=60,
        wall_algorithm="default.80%",
        wall_rubble_ratio=0.2,
        fall_spawn_cell_ratio=0.008,
        fall_spawn_zones=[
            (19, 10, 10, 10),
        ],
        pitfall_density=0.01,
        fuel_mode=FuelMode.FUEL_CAN,
        buddy_required_count=3,
        initial_interior_spawn_rate=0.08,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.2,
        interior_fall_spawn_weight=0.4,
        zombie_tracker_ratio=0.4,
        zombie_wall_hugging_ratio=0.4,
        zombie_normal_ratio=0.2,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage21",
        name_key="stages.stage21.name",
        description_key="stages.stage21.description",
        available=True,
        cell_size=60,
        grid_cols=25,
        grid_rows=25,
        wall_algorithm="sparse_ortho.10%",
        pitfall_density=0.01,
        fuel_mode=FuelMode.FUEL_CAN,
        initial_interior_spawn_rate=0.05,
        exterior_spawn_weight=0.7,
        interior_spawn_weight=0.3,
        zombie_dog_ratio=0.5,
        zombie_normal_ratio=0.5,
        zombie_tracker_ratio=0.0,
        zombie_wall_hugging_ratio=0.0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage22",
        name_key="stages.stage22.name",
        description_key="stages.stage22.description",
        available=True,
        cell_size=50,
        grid_cols=25,
        grid_rows=25,
        wall_algorithm="grid_wire.120%",
        fuel_mode=FuelMode.FUEL_CAN,
        buddy_required_count=1,
        initial_interior_spawn_rate=0.1,
        patrol_bot_spawn_rate=0.05,
        zombie_normal_ratio=1.0,
        zombie_tracker_ratio=0.0,
        zombie_wall_hugging_ratio=0.0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage23",
        name_key="stages.stage23.name",
        description_key="stages.stage23.description",
        available=True,
        wall_algorithm="grid_wire.25%",
        pitfall_density=0.01,
        fuel_mode=FuelMode.FUEL_CAN,
        initial_interior_spawn_rate=0.06,
        patrol_bot_spawn_rate=0.04,
        exterior_spawn_weight=0.7,
        interior_spawn_weight=0.3,
        zombie_dog_ratio=1.0,
        zombie_normal_ratio=0.0,
        zombie_tracker_ratio=0.0,
        zombie_wall_hugging_ratio=0.0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
    ),
    Stage(
        id="stage24",
        name_key="stages.stage24.name",
        description_key="stages.stage24.description",
        available=True,
        cell_size=50,
        grid_cols=35,
        grid_rows=23,
        wall_algorithm="sparse_ortho.50%",
        fuel_mode=FuelMode.FUEL_CAN,
        initial_flashlight_count=3,
        initial_interior_spawn_rate=0.06,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.8,
        zombie_normal_ratio=1.0,
        zombie_tracker_ratio=0.0,
        zombie_wall_hugging_ratio=0.0,
        zombie_dog_ratio=0.0,
        pitfall_zones=[(11, 9, 14, 5)],
        moving_floor_zones={
            "right": [(6, 5, 23, 1)],
            "down": [(29, 5, 1, 12)],
            "left": [(7, 17, 23, 1)],
            "up": [(6, 6, 1, 12)],
        },
        zombie_decay_duration_frames=int(ZOMBIE_DECAY_DURATION_FRAMES * 1.5),
    ),
    Stage(
        id="stage25",
        name_key="stages.stage25.name",
        description_key="stages.stage25.description",
        intro_key="stages.stage25.intro",
        available=True,
        cell_size=60,
        grid_cols=57,
        grid_rows=38,
        wall_rubble_ratio=0.5,
        wall_algorithm="normal.80%",
        fuel_mode=FuelMode.FUEL_CAN,
        initial_flashlight_count=10,
        fuel_spawn_count=1,
        patrol_bot_spawn_rate=0.01,
        initial_interior_spawn_rate=0.05,
        exterior_spawn_weight=0.05,
        interior_spawn_weight=0.95,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
        zombie_normal_ratio=0.4,
        zombie_tracker_ratio=0.2,
        zombie_wall_hugging_ratio=0,
        zombie_dog_ratio=0.4,
        moving_floor_zones={
            "up": [
                (8, 3, 1, 14),
                (21, 3, 1, 14),
                (34, 3, 1, 14),
                (47, 3, 1, 14),
                (8, 21, 1, 14),
                (21, 21, 1, 14),
                (34, 21, 1, 14),
                (47, 21, 1, 14),
            ],
            "down": [
                (9, 3, 1, 14),
                (22, 3, 1, 14),
                (35, 3, 1, 14),
                (48, 3, 1, 14),
                (9, 21, 1, 14),
                (22, 21, 1, 14),
                (35, 21, 1, 14),
                (48, 21, 1, 14),
            ],
            "left": [
                (3, 19, 5, 1),
                (10, 19, 5, 1),
                (16, 19, 5, 1),
                (23, 19, 5, 1),
                (29, 19, 5, 1),
                (36, 19, 5, 1),
                (42, 19, 5, 1),
                (49, 19, 5, 1),
            ],
            "right": [
                (3, 18, 5, 1),
                (10, 18, 5, 1),
                (16, 18, 5, 1),
                (23, 18, 5, 1),
                (29, 18, 5, 1),
                (36, 18, 5, 1),
                (42, 18, 5, 1),
                (49, 18, 5, 1),
            ],
        },
        fall_spawn_zones=[
            (2, 2, 53, 1),
            (2, 3, 1, 33),
            (15, 3, 1, 33),
            (28, 3, 1, 33),
            (41, 3, 1, 33),
            (54, 3, 1, 33),
            (3, 35, 12, 1),
            (16, 35, 12, 1),
            (29, 35, 12, 1),
            (42, 35, 12, 1),
        ],
        buddy_required_count=1,
        survivor_spawn_rate=0.07,
        exit_sides=["top", "bottom"],
    ),
    Stage(
        id="stage26",
        name_key="stages.stage26.name",
        description_key="stages.stage26.description",
        available=True,
        cell_size=50,
        grid_cols=30,
        grid_rows=25,
        wall_algorithm="sparse_ortho.10%",
        fuel_mode=FuelMode.REFUEL_CHAIN,
        buddy_required_count=1,
        initial_interior_spawn_rate=0.05,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.0,
        interior_fall_spawn_weight=0.8,
        zombie_normal_ratio=1.0,
        zombie_tracker_ratio=0.0,
        zombie_wall_hugging_ratio=0.0,
        zombie_dog_ratio=0.0,
        initial_flashlight_count=2,
        initial_shoes_count=2,
        waiting_car_target_count=1,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
        moving_floor_zones={
            "up": [],
            "down": [
                (5, 7, 5, 1),
                (11, 7, 5, 1),
                (17, 7, 5, 1),
                (23, 7, 5, 1),
                (5, 12, 5, 1),
                (11, 12, 5, 1),
                (17, 12, 5, 1),
                (23, 12, 5, 1),
                (5, 16, 2, 1),
                (8, 16, 2, 1),
                (11, 16, 2, 1),
                (14, 16, 2, 1),
                (17, 16, 2, 1),
                (20, 16, 2, 1),
                (23, 16, 2, 1),
                (26, 16, 2, 1),
                (5, 20, 2, 1),
                (8, 20, 2, 1),
                (11, 20, 2, 1),
                (14, 20, 2, 1),
                (17, 20, 2, 1),
                (20, 20, 2, 1),
                (23, 20, 2, 1),
                (26, 20, 2, 1),
            ],
            "left": [],
            "right": [],
        },
        pitfall_zones=[
            (28, 2, 1, 19),
            (4, 3, 1, 18),
            (10, 7, 1, 1),
            (16, 7, 1, 14),
            (22, 7, 1, 1),
            (10, 12, 1, 9),
            (22, 12, 1, 9),
            (7, 16, 1, 5),
            (13, 16, 1, 5),
            (19, 16, 1, 5),
            (25, 16, 1, 5),
        ],
        fall_spawn_zones=[
            (5, 4, 2, 2),
            (8, 4, 2, 2),
            (11, 4, 2, 2),
            (14, 4, 2, 2),
            (17, 4, 2, 2),
            (20, 4, 2, 2),
            (23, 4, 2, 2),
            (26, 4, 2, 2),
        ],
    ),
    Stage(
        id="stage27",
        name_key="stages.stage27.name",
        description_key="stages.stage27.description",
        available=True,
        cell_size=60,
        grid_cols=30,
        grid_rows=30,
        wall_algorithm="sparse_ortho.20%",
        fuel_mode=FuelMode.FUEL_CAN,
        initial_interior_spawn_rate=0.1,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.8,
        zombie_normal_ratio=0.125,
        zombie_lineformer_ratio=0.75,
        zombie_tracker_ratio=0.125,
        zombie_wall_hugging_ratio=0.0,
        zombie_dog_ratio=0.0,
        initial_flashlight_count=2,
        initial_shoes_count=0,
        waiting_car_target_count=1,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
        zombie_spawn_count_per_interval=4,
        survivor_spawn_rate=0.02,
    ),
    Stage(
        id="stage28",
        name_key="stages.stage28.name",
        description_key="stages.stage28.description",
        fuel_mode=FuelMode.REFUEL_CHAIN,
        available=True,
        cell_size=60,
        grid_cols=39,
        grid_rows=14,
        wall_algorithm="empty",
        initial_interior_spawn_rate=0.05,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.2,
        interior_fall_spawn_weight=0.6,
        zombie_normal_ratio=0.5,
        zombie_dog_ratio=0.5,
        initial_flashlight_count=0,
        initial_shoes_count=2,
        waiting_car_target_count=1,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
        moving_floor_zones={
            "up": [],
            "down": [],
            "left": [(3, 10, 33, 1)],
            "right": [(3, 3, 33, 1)],
        },
        fall_spawn_zones=[
            (3, 2, 3, 1),
            (8, 2, 3, 1),
            (13, 2, 3, 1),
            (18, 2, 3, 1),
            (23, 2, 3, 1),
            (28, 2, 3, 1),
            (33, 2, 3, 1),
            (3, 11, 3, 1),
            (8, 11, 3, 1),
            (13, 11, 3, 1),
            (18, 11, 3, 1),
            (23, 11, 3, 1),
            (28, 11, 3, 1),
            (33, 11, 3, 1),
        ],
        puddle_zones=[
            (2, 3, 1, 8),
            (36, 3, 1, 8),
            (6, 4, 2, 6),
            (11, 4, 2, 6),
            (16, 4, 2, 6),
            (21, 4, 2, 6),
            (26, 4, 2, 6),
            (31, 4, 2, 6),
        ],
        puddle_density=0.05,
        exit_sides=["top", "bottom"],
        spiky_plant_density=0.04,
    ),
    Stage(
        id="stage29",
        name_key="stages.stage29.name",
        description_key="stages.stage29.description",
        available=True,
        fuel_mode=FuelMode.FUEL_CAN,
        cell_size=40,
        grid_cols=44,
        grid_rows=44,
        wall_algorithm="empty",
        buddy_required_count=1,
        initial_interior_spawn_rate=0.1,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.8,
        zombie_normal_ratio=1.0,
        zombie_dog_ratio=0.0,
        zombie_lineformer_ratio=0.0,
        initial_flashlight_count=3,
        waiting_car_target_count=1,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
        spiky_plant_zones=[
            (3, 3, 38, 2),
            (3, 5, 2, 36),
            (7, 5, 2, 36),
            (11, 5, 2, 36),
            (15, 5, 2, 36),
            (19, 5, 2, 36),
            (23, 5, 2, 36),
            (27, 5, 2, 36),
            (31, 5, 2, 36),
            (35, 5, 2, 36),
            (39, 5, 2, 36),
            (5, 7, 2, 2),
            (9, 7, 2, 2),
            (13, 7, 2, 2),
            (17, 7, 2, 2),
            (21, 7, 2, 2),
            (25, 7, 2, 2),
            (29, 7, 2, 2),
            (33, 7, 2, 2),
            (37, 7, 2, 2),
            (5, 11, 2, 2),
            (9, 11, 2, 2),
            (13, 11, 2, 2),
            (17, 11, 2, 2),
            (21, 11, 2, 2),
            (25, 11, 2, 2),
            (29, 11, 2, 2),
            (33, 11, 2, 2),
            (37, 11, 2, 2),
            (5, 15, 2, 2),
            (9, 15, 2, 2),
            (13, 15, 2, 2),
            (17, 15, 2, 2),
            (21, 15, 2, 2),
            (25, 15, 2, 2),
            (29, 15, 2, 2),
            (33, 15, 2, 2),
            (37, 15, 2, 2),
            (5, 19, 2, 2),
            (9, 19, 2, 2),
            (13, 19, 2, 2),
            (17, 19, 2, 2),
            (21, 19, 2, 2),
            (25, 19, 2, 2),
            (29, 19, 2, 2),
            (33, 19, 2, 2),
            (37, 19, 2, 2),
            (5, 23, 2, 2),
            (9, 23, 2, 2),
            (13, 23, 2, 2),
            (17, 23, 2, 2),
            (21, 23, 2, 2),
            (25, 23, 2, 2),
            (29, 23, 2, 2),
            (33, 23, 2, 2),
            (37, 23, 2, 2),
            (5, 27, 2, 2),
            (9, 27, 2, 2),
            (13, 27, 2, 2),
            (17, 27, 2, 2),
            (21, 27, 2, 2),
            (25, 27, 2, 2),
            (29, 27, 2, 2),
            (33, 27, 2, 2),
            (37, 27, 2, 2),
            (5, 31, 2, 2),
            (9, 31, 2, 2),
            (13, 31, 2, 2),
            (17, 31, 2, 2),
            (21, 31, 2, 2),
            (25, 31, 2, 2),
            (29, 31, 2, 2),
            (33, 31, 2, 2),
            (37, 31, 2, 2),
            (5, 35, 2, 2),
            (9, 35, 2, 2),
            (13, 35, 2, 2),
            (17, 35, 2, 2),
            (21, 35, 2, 2),
            (25, 35, 2, 2),
            (29, 35, 2, 2),
            (33, 35, 2, 2),
            (37, 35, 2, 2),
            (5, 39, 2, 2),
            (9, 39, 2, 2),
            (13, 39, 2, 2),
            (17, 39, 2, 2),
            (21, 39, 2, 2),
            (25, 39, 2, 2),
            (29, 39, 2, 2),
            (33, 39, 2, 2),
            (37, 39, 2, 2),
        ],
        puddle_density=0.05,
    ),
    Stage(
        id="stage30",
        name_key="stages.stage30.name",
        description_key="stages.stage30.description",
        intro_key="stages.stage30.intro",
        available=True,
        cell_size=40,
        grid_cols=40,
        grid_rows=25,
        wall_algorithm="corridor.15%",
        initial_interior_spawn_rate=0.08,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.6,
        zombie_normal_ratio=0.2,
        zombie_lineformer_ratio=0.4,
        zombie_tracker_ratio=0.2,
        zombie_wall_hugging_ratio=0.2,
        zombie_dog_ratio=0.0,
        initial_flashlight_count=3,
        initial_shoes_count=2,
        waiting_car_target_count=0,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
        endurance_stage=True,
        endurance_goal_ms=900_000,
        fuel_spawn_count=0,
        survivor_spawn_rate=0.05,
    ),
    Stage(
        id="stage31",
        name_key="stages.stage31.name",
        description_key="stages.stage31.description",
        fuel_mode=FuelMode.REFUEL_CHAIN,
        available=True,
        cell_size=50,
        grid_cols=35,
        grid_rows=35,
        wall_algorithm="empty",
        reinforced_wall_density=0.25,
        initial_interior_spawn_rate=0.02,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.6,
        zombie_normal_ratio=0.0,
        zombie_dog_ratio=0.3,
        zombie_tracker_ratio=0.0,
        zombie_wall_hugging_ratio=0.0,
        zombie_lineformer_ratio=0.0,
        zombie_nimble_dog_ratio=0.7,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
        patrol_bot_spawn_rate=0.02,
    ),
    Stage(
        id="stage32",
        name_key="stages.stage32.name",
        description_key="stages.stage32.description",
        fuel_mode=FuelMode.REFUEL_CHAIN,
        available=True,
        cell_size=50,
        grid_cols=20,
        grid_rows=53,
        wall_algorithm="empty",
        reinforced_wall_density=0.15,
        initial_interior_spawn_rate=0.03,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.6,
        zombie_normal_ratio=0.5,
        zombie_dog_ratio=0.0,
        zombie_tracker_ratio=0.4,
        zombie_wall_hugging_ratio=0.0,
        zombie_lineformer_ratio=0.0,
        zombie_nimble_dog_ratio=0.1,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 2,
        fire_floor_zones=[
            (3, 11, 14, 1),
            (3, 21, 14, 1),
            (3, 31, 14, 1),
            (3, 41, 14, 1),
        ],
        exit_sides=["top", "bottom"],
    ),
    Stage(
        id="stage33",
        name_key="stages.stage33.name",
        description_key="stages.stage33.description",
        fuel_mode=FuelMode.REFUEL_CHAIN,
        available=True,
        cell_size=50,
        grid_cols=30,
        grid_rows=24,
        wall_algorithm="empty",
        initial_interior_spawn_rate=0.08,
        exterior_spawn_weight=0.2,
        interior_spawn_weight=0.5,
        interior_fall_spawn_weight=0.3,
        fall_spawn_cell_ratio=0.08,
        zombie_normal_ratio=0.2,
        zombie_lineformer_ratio=0.0,
        zombie_tracker_ratio=0.0,
        zombie_wall_hugging_ratio=0.0,
        zombie_dog_ratio=0.0,
        zombie_nimble_dog_ratio=0.8,
        initial_flashlight_count=5,
        initial_shoes_count=2,
        moving_floor_zones={
            "down": [
                (3, 3, 4, 1),
                (8, 3, 4, 1),
                (13, 3, 4, 1),
                (18, 3, 4, 1),
                (23, 3, 4, 1),
                (3, 5, 4, 1),
                (8, 5, 4, 1),
                (13, 5, 4, 1),
                (18, 5, 4, 1),
                (23, 5, 4, 1),
                (3, 7, 4, 1),
                (8, 7, 4, 1),
                (13, 7, 4, 1),
                (18, 7, 4, 1),
                (23, 7, 4, 1),
                (3, 9, 4, 1),
                (8, 9, 4, 1),
                (13, 9, 4, 1),
                (18, 9, 4, 1),
                (23, 9, 4, 1),
                (3, 11, 4, 1),
                (8, 11, 4, 1),
                (13, 11, 4, 1),
                (18, 11, 4, 1),
                (23, 11, 4, 1),
                (3, 13, 4, 1),
                (8, 13, 4, 1),
                (13, 13, 4, 1),
                (18, 13, 4, 1),
                (23, 13, 4, 1),
                (3, 15, 4, 1),
                (8, 15, 4, 1),
                (13, 15, 4, 1),
                (18, 15, 4, 1),
                (23, 15, 4, 1),
                (3, 17, 4, 1),
                (8, 17, 4, 1),
                (13, 17, 4, 1),
                (18, 17, 4, 1),
                (23, 17, 4, 1),
                (3, 19, 4, 1),
                (8, 19, 4, 1),
                (13, 19, 4, 1),
                (18, 19, 4, 1),
                (23, 19, 4, 1),
            ],
        },
        reinforced_wall_zones=[
            (7, 3, 1, 1),
            (12, 3, 1, 1),
            (17, 3, 1, 1),
            (22, 3, 1, 1),
            (27, 3, 1, 1),
            (2, 5, 1, 1),
            (7, 5, 1, 1),
            (12, 5, 1, 1),
            (17, 5, 1, 1),
            (22, 5, 1, 1),
            (7, 7, 1, 1),
            (12, 7, 1, 1),
            (17, 7, 1, 1),
            (22, 7, 1, 1),
            (27, 7, 1, 1),
            (2, 9, 1, 1),
            (7, 9, 1, 1),
            (12, 9, 1, 1),
            (17, 9, 1, 1),
            (22, 9, 1, 1),
            (7, 11, 1, 1),
            (12, 11, 1, 1),
            (17, 11, 1, 1),
            (22, 11, 1, 1),
            (27, 11, 1, 1),
            (2, 13, 1, 1),
            (7, 13, 1, 1),
            (12, 13, 1, 1),
            (17, 13, 1, 1),
            (22, 13, 1, 1),
            (7, 15, 1, 1),
            (12, 15, 1, 1),
            (17, 15, 1, 1),
            (22, 15, 1, 1),
            (27, 15, 1, 1),
            (2, 17, 1, 1),
            (7, 17, 1, 1),
            (12, 17, 1, 1),
            (17, 17, 1, 1),
            (22, 17, 1, 1),
            (7, 19, 1, 1),
            (12, 19, 1, 1),
            (17, 19, 1, 1),
            (22, 19, 1, 1),
            (27, 19, 1, 1),
        ],
        pitfall_zones=[
            (2, 21, 26, 1),
        ],
        exit_sides=["top", "bottom"],
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
    ),
    Stage(
        id="stage34",
        name_key="stages.stage34.name",
        description_key="stages.stage34.description",
        available=True,
        cell_size=50,
        grid_cols=30,
        grid_rows=30,
        wall_algorithm="sparse_ortho.30%",
        fuel_mode=FuelMode.REFUEL_CHAIN,
        initial_interior_spawn_rate=0.2,
        exterior_spawn_weight=0.4,
        interior_spawn_weight=0.6,
        interior_fall_spawn_weight=0.0,
        zombie_normal_ratio=0.25,
        zombie_tracker_ratio=0.25,
        zombie_wall_hugging_ratio=0.25,
        zombie_lineformer_ratio=0.25,
        zombie_solitary_ratio=0.0,
        zombie_dog_ratio=0.0,
        zombie_nimble_dog_ratio=0.0,
        initial_flashlight_count=1,
        initial_shoes_count=1,
        reinforced_wall_density=0.18,
        fire_floor_density=0.18,
        patrol_bot_spawn_rate=0.02,
    ),
    # Stage(
    #     id="stage34",
    #     name_key="stages.stage34.name",
    #     description_key="stages.stage34.description",
    #     fuel_mode=FuelMode.REFUEL_CHAIN,
    #     available=False,
    #     cell_size=50,
    #     grid_cols=30,
    #     grid_rows=30,
    #     wall_algorithm="grid_wire.40%",
    #     fall_spawn_cell_ratio=0.04,
    #     reinforced_wall_density=0.12,
    #     initial_interior_spawn_rate=0.1,
    #     exterior_spawn_weight=0.1,
    #     interior_spawn_weight=0.6,
    #     interior_fall_spawn_weight=0.3,
    #     zombie_normal_ratio=0.6,
    #     zombie_tracker_ratio=0.0,
    #     zombie_wall_hugging_ratio=0.0,
    #     zombie_lineformer_ratio=0.0,
    #     zombie_solitary_ratio=0.4,
    #     zombie_dog_ratio=0.0,
    #     zombie_nimble_dog_ratio=0.0,
    #     zombie_spawn_count_per_interval=2,
    #     zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
    #     pitfall_density=0.01,
    # ),
    Stage(
        id="stage35",
        name_key="stages.stage35.name",
        description_key="stages.stage35.description",
        intro_key="stages.stage35.intro",
        available=True,
        cell_size=40,
        grid_cols=25,
        grid_rows=25,
        wall_algorithm="sparse_moore.20%",
        wall_rubble_ratio=0.5,
        reinforced_wall_density=0.05,
        initial_interior_spawn_rate=0.12,
        exterior_spawn_weight=0.7,
        interior_spawn_weight=0.27,
        interior_fall_spawn_weight=0.03,
        zombie_normal_ratio=0.6,
        zombie_lineformer_ratio=0.2,
        zombie_tracker_ratio=0.2,
        zombie_wall_hugging_ratio=0.0,
        zombie_dog_ratio=0.0,
        initial_flashlight_count=3,
        initial_shoes_count=2,
        waiting_car_target_count=1,
        zombie_decay_duration_frames=ZOMBIE_DECAY_DURATION_FRAMES * 3,
        spiky_plant_density=0.12,
        puddle_density=0.01,
        # pitfall_zones=[(12, 12, 1, 1)],
        spiky_plant_zones=[
            (12, 11, 1, 1),
            (11, 12, 1, 1),
            (13, 12, 1, 1),
            (12, 13, 1, 1),
        ],
        fall_spawn_zones=[
            (3, 3, 1, 1),
            (9, 3, 1, 1),
            (15, 3, 1, 1),
            (21, 3, 1, 1),
            (3, 21, 1, 1),
            (9, 21, 1, 1),
            (15, 21, 1, 1),
            (21, 21, 1, 1),
            (3, 3, 1, 1),
            (3, 9, 1, 1),
            (3, 15, 1, 1),
            (3, 21, 1, 1),
            (21, 3, 1, 1),
            (21, 9, 1, 1),
            (21, 15, 1, 1),
            (21, 21, 1, 1),
        ],
        zombie_spawn_count_per_interval=3,
        endurance_stage=True,
        endurance_goal_ms=600_000,
    ),
]
DEFAULT_STAGE_ID = "stage1"


__all__ = [
    "STAGES",
    "DEFAULT_STAGE_ID",
]
