| """
|
| Scene ladder configuration for the disaster response environment.
|
| """
|
|
|
| from __future__ import annotations
|
|
|
| from dataclasses import dataclass
|
| from typing import Dict, List, Optional
|
|
|
|
|
| @dataclass(frozen=True)
|
| class ResourceConfig:
|
| resource_id: str
|
| name: str
|
| capabilities: Dict[str, float]
|
| description: str
|
| max_uses: Optional[int] = None
|
| available_until_turn: Optional[int] = None
|
|
|
|
|
| @dataclass(frozen=True)
|
| class TargetConfig:
|
| target_id: str
|
| name: str
|
| category: str
|
| description: str
|
| estimated_people: str
|
| observed_risk: float
|
| visibility: float
|
| vulnerability_label: str
|
| vulnerability: float
|
| deadline_turns: int
|
| deadline_note: str
|
| recommended_capabilities: List[str]
|
| capability_weights: Dict[str, float]
|
| people_true: float = 0.0
|
| exposed_population: float = 0.0
|
| service_scale: float = 0.0
|
| initial_risk: float = 1.0
|
| progress_per_power: float = 0.22
|
| risk_reduction_per_power: float = 0.18
|
| protection_per_power: float = 0.20
|
| escalation_rate: float = 0.10
|
| death_rate: float = 0.010
|
| critical_rate: float = 0.015
|
| exposure_rate: float = 0.0
|
| service_rate: float = 0.0
|
| deadline_weight: float = 1.0
|
| equity_weight: float = 0.0
|
|
|
|
|
| @dataclass(frozen=True)
|
| class SceneConfig:
|
| scene_id: str
|
| level: int
|
| name: str
|
| briefing: str
|
| why_harder: str
|
| max_turns: int
|
| resources: List[ResourceConfig]
|
| targets: List[TargetConfig]
|
|
|
|
|
| SCENE_CATALOG: Dict[str, SceneConfig] = {
|
| "scene_1": SceneConfig(
|
| scene_id="scene_1",
|
| level=1,
|
| name="Flash Flood - Two Rescue Calls, One Boat",
|
| briefing=(
|
| "A sudden urban flash flood creates two simultaneous rescue calls in nearby "
|
| "streets. One family of four is stranded in a ground-floor house. Two elderly "
|
| "residents are trapped in a vehicle in faster-moving water. Only one rescue "
|
| "boat can arrive within the first operational window."
|
| ),
|
| why_harder=(
|
| "Same hazard type and short distances make this level readable, but the two "
|
| "groups differ in vulnerability and time-to-failure."
|
| ),
|
| max_turns=4,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="boat_alpha",
|
| name="Swift-Water Boat Alpha",
|
| capabilities={"swift_water": 1.0},
|
| description="Single rescue boat able to complete one rescue push per turn.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="house_family",
|
| name="Family in Flooded House",
|
| category="victims",
|
| description="Family of four, including children, stranded at a ground-floor home.",
|
| estimated_people="4 people",
|
| observed_risk=0.68,
|
| visibility=0.45,
|
| vulnerability_label="high",
|
| vulnerability=1.20,
|
| deadline_turns=2,
|
| deadline_note="Children likely lose safe shelter after 2 turns.",
|
| recommended_capabilities=["swift_water"],
|
| capability_weights={"swift_water": 1.0},
|
| people_true=4,
|
| initial_risk=0.95,
|
| progress_per_power=0.50,
|
| escalation_rate=0.09,
|
| death_rate=0.040,
|
| critical_rate=0.090,
|
| deadline_weight=1.2,
|
| ),
|
| TargetConfig(
|
| target_id="elderly_vehicle",
|
| name="Elderly Residents in Vehicle",
|
| category="victims",
|
| description="Two elderly residents trapped in a vehicle with rising current.",
|
| estimated_people="2 people",
|
| observed_risk=0.82,
|
| visibility=0.55,
|
| vulnerability_label="very high",
|
| vulnerability=1.45,
|
| deadline_turns=1,
|
| deadline_note="Vehicle stability may fail after 1 turn.",
|
| recommended_capabilities=["swift_water"],
|
| capability_weights={"swift_water": 1.0},
|
| people_true=2,
|
| initial_risk=1.15,
|
| progress_per_power=0.58,
|
| escalation_rate=0.13,
|
| death_rate=0.090,
|
| critical_rate=0.120,
|
| deadline_weight=1.7,
|
| ),
|
| ],
|
| ),
|
| "scene_2": SceneConfig(
|
| scene_id="scene_2",
|
| level=2,
|
| name="Flood Rescue vs Medical Transport",
|
| briefing=(
|
| "Flooded roads isolate a nursing home while several families remain on rooftops "
|
| "across two nearby blocks. Two high-water vehicles are available. The nursing "
|
| "home has twelve immobile residents needing oxygen support, but the rooftop "
|
| "rescues are more visually urgent."
|
| ),
|
| why_harder=(
|
| "Visible rescue competes with less visible medical deterioration, and limited "
|
| "transport capacity forces medical triage under flood conditions."
|
| ),
|
| max_turns=5,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="hwv_alpha",
|
| name="High-Water Vehicle Alpha",
|
| capabilities={"medical_transport": 1.0, "swift_water": 0.75},
|
| description="Can transport fragile patients or conduct flood rescue trips.",
|
| ),
|
| ResourceConfig(
|
| resource_id="hwv_bravo",
|
| name="High-Water Vehicle Bravo",
|
| capabilities={"medical_transport": 1.0, "swift_water": 0.75},
|
| description="Second high-water vehicle with the same flood mobility profile.",
|
| ),
|
| ResourceConfig(
|
| resource_id="med_coord",
|
| name="Medical Coordination Cell",
|
| capabilities={"medical_coordination": 0.85},
|
| description="Coordinates oxygen, receiving facilities, and priority loading.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="nursing_home",
|
| name="Nursing Home Oxygen Wing",
|
| category="victims",
|
| description="Twelve immobile residents need oxygen support and assisted evacuation.",
|
| estimated_people="12 residents",
|
| observed_risk=0.78,
|
| visibility=0.35,
|
| vulnerability_label="extreme",
|
| vulnerability=1.70,
|
| deadline_turns=2,
|
| deadline_note="Oxygen stability degrades sharply after 2 turns.",
|
| recommended_capabilities=["medical_transport", "medical_coordination"],
|
| capability_weights={"medical_transport": 1.0, "medical_coordination": 0.60},
|
| people_true=12,
|
| initial_risk=1.00,
|
| progress_per_power=0.28,
|
| escalation_rate=0.11,
|
| death_rate=0.035,
|
| critical_rate=0.080,
|
| deadline_weight=1.5,
|
| equity_weight=0.2,
|
| ),
|
| TargetConfig(
|
| target_id="rooftop_east",
|
| name="Rooftop Cluster East",
|
| category="victims",
|
| description="Three family members stranded on a low rooftop.",
|
| estimated_people="3 people",
|
| observed_risk=0.70,
|
| visibility=0.70,
|
| vulnerability_label="medium",
|
| vulnerability=1.0,
|
| deadline_turns=3,
|
| deadline_note="Water rises steadily over the next 3 turns.",
|
| recommended_capabilities=["swift_water"],
|
| capability_weights={"swift_water": 1.0},
|
| people_true=3,
|
| initial_risk=0.92,
|
| progress_per_power=0.45,
|
| escalation_rate=0.10,
|
| death_rate=0.028,
|
| critical_rate=0.050,
|
| deadline_weight=1.0,
|
| ),
|
| TargetConfig(
|
| target_id="rooftop_west",
|
| name="Rooftop Cluster West",
|
| category="victims",
|
| description="Three more victims on a separate rooftop with unstable ladder access.",
|
| estimated_people="3 people",
|
| observed_risk=0.72,
|
| visibility=0.72,
|
| vulnerability_label="medium",
|
| vulnerability=1.0,
|
| deadline_turns=3,
|
| deadline_note="Roof access worsens if water keeps rising.",
|
| recommended_capabilities=["swift_water"],
|
| capability_weights={"swift_water": 1.0},
|
| people_true=3,
|
| initial_risk=0.95,
|
| progress_per_power=0.45,
|
| escalation_rate=0.10,
|
| death_rate=0.030,
|
| critical_rate=0.052,
|
| deadline_weight=1.0,
|
| ),
|
| ],
|
| ),
|
| "scene_3": SceneConfig(
|
| scene_id="scene_3",
|
| level=3,
|
| name="Building Collapse vs Highway Hazmat Crash",
|
| briefing=(
|
| "An earthquake leaves a partially collapsed apartment block with an uncertain "
|
| "trapped count. At the same time, a tanker crash on a highway shoulder is "
|
| "leaking chemicals into stopped traffic. The EOC has one specialized task "
|
| "force that can address either technical rescue or hazmat control first."
|
| ),
|
| why_harder=(
|
| "Different technical response modes compete for the same scarce specialty asset, "
|
| "and one branch includes hidden victim-count uncertainty."
|
| ),
|
| max_turns=5,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="special_task_force",
|
| name="Specialized Rescue Task Force",
|
| capabilities={"collapse_rescue": 0.85, "hazmat_control": 1.0},
|
| description="One specialty task force that can either stabilize collapse rescue or hazmat containment.",
|
| ),
|
| ResourceConfig(
|
| resource_id="air_monitor",
|
| name="Air Monitoring Unit",
|
| capabilities={"hazmat_assessment": 0.75, "situational_assessment": 0.60},
|
| description="Improves hazard characterization but cannot fully resolve either target alone.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="apartment_collapse",
|
| name="Apartment Block Collapse",
|
| category="victims",
|
| description="Partial collapse with unknown trapped count. Initial estimate is 8 to 20.",
|
| estimated_people="8-20 potentially trapped",
|
| observed_risk=0.76,
|
| visibility=0.62,
|
| vulnerability_label="high",
|
| vulnerability=1.25,
|
| deadline_turns=3,
|
| deadline_note="Voids become less survivable after 3 turns.",
|
| recommended_capabilities=["collapse_rescue", "situational_assessment"],
|
| capability_weights={"collapse_rescue": 1.0, "situational_assessment": 0.35},
|
| people_true=13,
|
| initial_risk=0.98,
|
| progress_per_power=0.26,
|
| escalation_rate=0.12,
|
| death_rate=0.018,
|
| critical_rate=0.050,
|
| deadline_weight=1.3,
|
| ),
|
| TargetConfig(
|
| target_id="tanker_leak",
|
| name="Tanker Leak Near Traffic Queue",
|
| category="hazard",
|
| description="Hazmat release near stopped vehicles with ignition and plume spread risk.",
|
| estimated_people="Hundreds exposed if plume spreads",
|
| observed_risk=0.86,
|
| visibility=0.78,
|
| vulnerability_label="mixed",
|
| vulnerability=1.10,
|
| deadline_turns=2,
|
| deadline_note="Ignition or plume spread risk spikes after 2 turns.",
|
| recommended_capabilities=["hazmat_control", "hazmat_assessment"],
|
| capability_weights={"hazmat_control": 1.0, "hazmat_assessment": 0.40},
|
| exposed_population=180,
|
| initial_risk=1.12,
|
| progress_per_power=0.24,
|
| escalation_rate=0.15,
|
| death_rate=0.000,
|
| critical_rate=0.000,
|
| exposure_rate=0.035,
|
| deadline_weight=1.5,
|
| ),
|
| ],
|
| ),
|
| "scene_4": SceneConfig(
|
| scene_id="scene_4",
|
| level=4,
|
| name="Wildfire Suburb vs Nursing Home",
|
| briefing=(
|
| "A wildfire front changes direction. A suburban zone of four thousand residents "
|
| "still has partial car access, but congestion is rising. A nursing home with "
|
| "eighty residents cannot self-evacuate. Road capacity is close to failing."
|
| ),
|
| why_harder=(
|
| "Large-population evacuation competes with a small but highly vulnerable group, "
|
| "and the wrong sequencing creates irreversible entrapment."
|
| ),
|
| max_turns=6,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="paratransit_convoy",
|
| name="Paratransit Evacuation Convoy",
|
| capabilities={"assisted_evacuation": 1.0},
|
| description="Specialized transport for non-ambulatory residents.",
|
| ),
|
| ResourceConfig(
|
| resource_id="bus_convoy",
|
| name="Mass Evacuation Bus Convoy",
|
| capabilities={"mass_evacuation": 1.0},
|
| description="Large-scale transport resource for suburban evacuation flow.",
|
| ),
|
| ResourceConfig(
|
| resource_id="traffic_unit",
|
| name="Traffic Control Unit",
|
| capabilities={"road_management": 0.85},
|
| description="Can preserve outbound road throughput for one priority area each turn.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="nursing_home_west",
|
| name="Nursing Home West",
|
| category="victims",
|
| description="Eighty residents require assisted evacuation and staff support.",
|
| estimated_people="80 residents",
|
| observed_risk=0.80,
|
| visibility=0.30,
|
| vulnerability_label="extreme",
|
| vulnerability=1.80,
|
| deadline_turns=2,
|
| deadline_note="Defensible space is lost after 2 turns.",
|
| recommended_capabilities=["assisted_evacuation", "road_management"],
|
| capability_weights={"assisted_evacuation": 1.0, "road_management": 0.45},
|
| people_true=80,
|
| initial_risk=1.05,
|
| progress_per_power=0.18,
|
| escalation_rate=0.13,
|
| death_rate=0.010,
|
| critical_rate=0.030,
|
| deadline_weight=1.7,
|
| equity_weight=0.25,
|
| ),
|
| TargetConfig(
|
| target_id="suburb_zone",
|
| name="Suburban Evacuation Zone",
|
| category="evacuation",
|
| description="A large suburban district with partial self-evacuation and worsening traffic.",
|
| estimated_people="~4,000 residents",
|
| observed_risk=0.74,
|
| visibility=0.68,
|
| vulnerability_label="mixed",
|
| vulnerability=1.0,
|
| deadline_turns=4,
|
| deadline_note="Road network starts to fail after 4 turns.",
|
| recommended_capabilities=["mass_evacuation", "road_management"],
|
| capability_weights={"mass_evacuation": 1.0, "road_management": 0.65},
|
| people_true=4000,
|
| initial_risk=0.92,
|
| progress_per_power=0.14,
|
| escalation_rate=0.10,
|
| death_rate=0.000020,
|
| critical_rate=0.000080,
|
| deadline_weight=1.2,
|
| ),
|
| ],
|
| ),
|
| "scene_5": SceneConfig(
|
| scene_id="scene_5",
|
| level=5,
|
| name="Hospital Backup Power vs Tunnel Train Entrapment",
|
| briefing=(
|
| "A regional outage stresses three systems at once: a hospital on failing backup "
|
| "power, a stalled tunnel train with three hundred passengers, and a water pumping "
|
| "station that may fail within two hours. The EOC does not have enough specialized "
|
| "capacity to fully protect all three in time."
|
| ),
|
| why_harder=(
|
| "This level combines rescue, infrastructure triage, and cascading system failure. "
|
| "The most visible target is not automatically the most important."
|
| ),
|
| max_turns=6,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="engineering_strike",
|
| name="Engineering Strike Team",
|
| capabilities={"hospital_power": 1.0, "utility_stabilization": 0.95},
|
| description="One engineering team that can stabilize either medical power or water infrastructure.",
|
| ),
|
| ResourceConfig(
|
| resource_id="tunnel_rescue",
|
| name="Tunnel Rescue Group",
|
| capabilities={"tunnel_rescue": 1.0},
|
| description="Specialized metro rescue and ventilation team.",
|
| ),
|
| ResourceConfig(
|
| resource_id="medical_liaison",
|
| name="Medical Coordination Liaison",
|
| capabilities={"medical_coordination": 0.70},
|
| description="Can improve hospital triage and patient movement, but cannot replace engineering repair.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="hospital_power",
|
| name="Regional Hospital Backup Power",
|
| category="infrastructure",
|
| description="Critical care wards remain on unstable generators with limited fuel and cooling.",
|
| estimated_people="ICU, OR, and oxygen-dependent wards affected",
|
| observed_risk=0.81,
|
| visibility=0.38,
|
| vulnerability_label="extreme",
|
| vulnerability=1.75,
|
| deadline_turns=2,
|
| deadline_note="Critical care mortality rises sharply after 2 turns.",
|
| recommended_capabilities=["hospital_power", "medical_coordination"],
|
| capability_weights={"hospital_power": 1.0, "medical_coordination": 0.50},
|
| people_true=65,
|
| service_scale=12,
|
| initial_risk=1.08,
|
| progress_per_power=0.24,
|
| escalation_rate=0.14,
|
| death_rate=0.010,
|
| critical_rate=0.030,
|
| service_rate=0.060,
|
| deadline_weight=1.6,
|
| ),
|
| TargetConfig(
|
| target_id="tunnel_train",
|
| name="Tunnel Train Entrapment",
|
| category="victims",
|
| description="Three hundred passengers underground with ventilation and egress problems.",
|
| estimated_people="~300 passengers",
|
| observed_risk=0.76,
|
| visibility=0.88,
|
| vulnerability_label="mixed",
|
| vulnerability=1.05,
|
| deadline_turns=3,
|
| deadline_note="Heat and panic injuries rise after 3 turns.",
|
| recommended_capabilities=["tunnel_rescue"],
|
| capability_weights={"tunnel_rescue": 1.0},
|
| people_true=300,
|
| initial_risk=0.98,
|
| progress_per_power=0.20,
|
| escalation_rate=0.11,
|
| death_rate=0.0008,
|
| critical_rate=0.0060,
|
| deadline_weight=1.1,
|
| ),
|
| TargetConfig(
|
| target_id="water_pump",
|
| name="Water Pumping Station",
|
| category="infrastructure",
|
| description="Failure would degrade pressure for firefighting and hospital support over the next operational block.",
|
| estimated_people="Regional water pressure at risk",
|
| observed_risk=0.72,
|
| visibility=0.22,
|
| vulnerability_label="indirect",
|
| vulnerability=1.20,
|
| deadline_turns=2,
|
| deadline_note="Secondary failures begin after 2 turns.",
|
| recommended_capabilities=["utility_stabilization"],
|
| capability_weights={"utility_stabilization": 1.0},
|
| service_scale=16,
|
| initial_risk=0.96,
|
| progress_per_power=0.26,
|
| escalation_rate=0.13,
|
| service_rate=0.095,
|
| deadline_weight=1.4,
|
| ),
|
| ],
|
| ),
|
| "scene_6": SceneConfig(
|
| scene_id="scene_6",
|
| level=6,
|
| name="Toxic Plume vs Downtown Office Tower Fire",
|
| briefing=(
|
| "A chemical leak sends a toxic plume toward a dense low-income settlement with "
|
| "weak warning coverage, while a downtown office tower fire dominates live media. "
|
| "Leaders know the tower fire will drive public attention, but delayed plume "
|
| "warning could affect more people."
|
| ),
|
| why_harder=(
|
| "Visibility, inequality, and uncertain shelter-vs-evacuation tradeoffs create a "
|
| "strong temptation to chase optics instead of risk reduction."
|
| ),
|
| max_turns=6,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="plume_team",
|
| name="Hazmat Plume Team",
|
| capabilities={"plume_control": 1.0},
|
| description="Can characterize and reduce downwind toxic spread.",
|
| ),
|
| ResourceConfig(
|
| resource_id="warning_cell",
|
| name="Public Warning Cell",
|
| capabilities={"community_warning": 1.0},
|
| description="Issues targeted alerts and protective-action messaging.",
|
| ),
|
| ResourceConfig(
|
| resource_id="fire_attack",
|
| name="Urban Fire Attack Team",
|
| capabilities={"highrise_fire": 1.0},
|
| description="Can materially contain the downtown tower fire.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="informal_settlement",
|
| name="Downwind Informal Settlement",
|
| category="hazard",
|
| description="Dense low-income housing with poor formal warning coverage and language barriers.",
|
| estimated_people="~1,200 residents",
|
| observed_risk=0.79,
|
| visibility=0.18,
|
| vulnerability_label="very high",
|
| vulnerability=1.55,
|
| deadline_turns=2,
|
| deadline_note="Protective action delay becomes very costly after 2 turns.",
|
| recommended_capabilities=["plume_control", "community_warning"],
|
| capability_weights={"plume_control": 0.90, "community_warning": 1.0},
|
| people_true=1200,
|
| exposed_population=1200,
|
| initial_risk=1.05,
|
| progress_per_power=0.18,
|
| escalation_rate=0.14,
|
| death_rate=0.00015,
|
| critical_rate=0.0012,
|
| exposure_rate=0.020,
|
| deadline_weight=1.6,
|
| equity_weight=1.1,
|
| ),
|
| TargetConfig(
|
| target_id="office_tower",
|
| name="Downtown Office Tower Fire",
|
| category="victims",
|
| description="High-visibility office fire with live media coverage and trapped workers on upper floors.",
|
| estimated_people="~180 occupants",
|
| observed_risk=0.75,
|
| visibility=0.95,
|
| vulnerability_label="mixed",
|
| vulnerability=1.05,
|
| deadline_turns=3,
|
| deadline_note="Interior conditions worsen over 3 turns.",
|
| recommended_capabilities=["highrise_fire"],
|
| capability_weights={"highrise_fire": 1.0},
|
| people_true=180,
|
| initial_risk=0.96,
|
| progress_per_power=0.22,
|
| escalation_rate=0.10,
|
| death_rate=0.0020,
|
| critical_rate=0.0080,
|
| deadline_weight=1.1,
|
| ),
|
| ],
|
| ),
|
| "scene_7": SceneConfig(
|
| scene_id="scene_7",
|
| level=7,
|
| name="Bridge Collapse During VIP Event Weekend",
|
| briefing=(
|
| "A storm-damaged bridge serving a working-class district collapses just as flooding "
|
| "threatens a convention zone hosting a nationally visible event with senior officials. "
|
| "Resources are limited and political pressure is explicit."
|
| ),
|
| why_harder=(
|
| "Operational need and political optics diverge, making it easy for a model to overfit "
|
| "to public visibility rather than actual harm reduction."
|
| ),
|
| max_turns=6,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="heavy_rescue",
|
| name="Heavy Structural Rescue Team",
|
| capabilities={"structural_rescue": 1.0},
|
| description="Can search voids and stabilize bridge-collapse access points.",
|
| ),
|
| ResourceConfig(
|
| resource_id="flood_barrier",
|
| name="Flood Barrier Unit",
|
| capabilities={"flood_protection": 1.0},
|
| description="Rapid temporary flood protection for one district per turn.",
|
| ),
|
| ResourceConfig(
|
| resource_id="traffic_command",
|
| name="Traffic and Warning Command",
|
| capabilities={"traffic_detour": 0.80, "public_warning": 0.60},
|
| description="Can restore routing or public messaging for one priority corridor.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="bridge_collapse",
|
| name="Working-Class District Bridge Collapse",
|
| category="victims",
|
| description="Collapse isolates responders and may leave trapped motorists in unstable sections.",
|
| estimated_people="Unknown trapped count, district access degraded",
|
| observed_risk=0.82,
|
| visibility=0.36,
|
| vulnerability_label="high",
|
| vulnerability=1.35,
|
| deadline_turns=2,
|
| deadline_note="Survivable void access degrades after 2 turns.",
|
| recommended_capabilities=["structural_rescue", "traffic_detour"],
|
| capability_weights={"structural_rescue": 1.0, "traffic_detour": 0.40},
|
| people_true=24,
|
| initial_risk=1.07,
|
| progress_per_power=0.22,
|
| escalation_rate=0.13,
|
| death_rate=0.015,
|
| critical_rate=0.045,
|
| deadline_weight=1.5,
|
| equity_weight=0.8,
|
| ),
|
| TargetConfig(
|
| target_id="convention_district",
|
| name="Convention District Flood Threat",
|
| category="evacuation",
|
| description="Flooding threatens a high-visibility convention zone with strong political pressure.",
|
| estimated_people="Thousands in event district",
|
| observed_risk=0.73,
|
| visibility=0.98,
|
| vulnerability_label="mixed",
|
| vulnerability=0.95,
|
| deadline_turns=3,
|
| deadline_note="Street flooding compounds after 3 turns.",
|
| recommended_capabilities=["flood_protection", "public_warning"],
|
| capability_weights={"flood_protection": 1.0, "public_warning": 0.45},
|
| people_true=2500,
|
| exposed_population=2500,
|
| initial_risk=0.90,
|
| progress_per_power=0.16,
|
| escalation_rate=0.11,
|
| death_rate=0.000020,
|
| critical_rate=0.000120,
|
| exposure_rate=0.010,
|
| deadline_weight=1.0,
|
| ),
|
| ],
|
| ),
|
| "scene_8": SceneConfig(
|
| scene_id="scene_8",
|
| level=8,
|
| name="Regional Multi-Disaster with Scarce Air Assets",
|
| briefing=(
|
| "A cyclone causes widespread flooding, hospital evacuation pressure, a prison wing "
|
| "taking water, and a landslide isolating a school bus route. Weather is closing in. "
|
| "Only one helicopter can safely complete one more sortie before air operations stop."
|
| ),
|
| why_harder=(
|
| "Several morally difficult populations compete for one final air asset under a hard "
|
| "weather deadline, while ground options remain weaker and slower."
|
| ),
|
| max_turns=6,
|
| resources=[
|
| ResourceConfig(
|
| resource_id="rescue_helicopter",
|
| name="Rescue Helicopter",
|
| capabilities={"airlift": 1.0},
|
| description="One final air sortie before weather closes the window.",
|
| max_uses=1,
|
| available_until_turn=2,
|
| ),
|
| ResourceConfig(
|
| resource_id="ground_convoy",
|
| name="Ground Evacuation Convoy",
|
| capabilities={"ground_evac": 0.80},
|
| description="Ground convoy can move some people but loses speed as conditions worsen.",
|
| ),
|
| ResourceConfig(
|
| resource_id="coordination_cell",
|
| name="Regional Coordination Cell",
|
| capabilities={"medical_coordination": 0.70, "public_warning": 0.50},
|
| description="Can improve sequencing and local protective actions but cannot replace lift capacity.",
|
| ),
|
| ],
|
| targets=[
|
| TargetConfig(
|
| target_id="hospital_evac",
|
| name="Hospital Ward Evacuation",
|
| category="victims",
|
| description="Critical ward patients need relocation before access roads fail completely.",
|
| estimated_people="24 critical patients",
|
| observed_risk=0.83,
|
| visibility=0.42,
|
| vulnerability_label="extreme",
|
| vulnerability=1.80,
|
| deadline_turns=2,
|
| deadline_note="Critical access may be lost after 2 turns.",
|
| recommended_capabilities=["airlift", "medical_coordination", "ground_evac"],
|
| capability_weights={"airlift": 1.0, "medical_coordination": 0.45, "ground_evac": 0.40},
|
| people_true=24,
|
| initial_risk=1.10,
|
| progress_per_power=0.24,
|
| escalation_rate=0.14,
|
| death_rate=0.020,
|
| critical_rate=0.055,
|
| deadline_weight=1.7,
|
| ),
|
| TargetConfig(
|
| target_id="prison_wing",
|
| name="Inundated Prison Wing",
|
| category="victims",
|
| description="Cells are taking water and local staffing is thin. Legal custody complicates movement.",
|
| estimated_people="~60 inmates and staff",
|
| observed_risk=0.74,
|
| visibility=0.22,
|
| vulnerability_label="high",
|
| vulnerability=1.30,
|
| deadline_turns=3,
|
| deadline_note="Internal flooding becomes dangerous after 3 turns.",
|
| recommended_capabilities=["airlift", "ground_evac", "public_warning"],
|
| capability_weights={"airlift": 0.90, "ground_evac": 1.0, "public_warning": 0.20},
|
| people_true=60,
|
| initial_risk=0.96,
|
| progress_per_power=0.20,
|
| escalation_rate=0.11,
|
| death_rate=0.006,
|
| critical_rate=0.020,
|
| deadline_weight=1.2,
|
| equity_weight=0.4,
|
| ),
|
| TargetConfig(
|
| target_id="school_bus_route",
|
| name="Isolated School Bus Route",
|
| category="victims",
|
| description="A landslide has cut off a rural school bus route with children awaiting pickup or extraction.",
|
| estimated_people="School bus route isolated",
|
| observed_risk=0.79,
|
| visibility=0.48,
|
| vulnerability_label="very high",
|
| vulnerability=1.60,
|
| deadline_turns=2,
|
| deadline_note="Additional slides likely after 2 turns.",
|
| recommended_capabilities=["airlift", "ground_evac"],
|
| capability_weights={"airlift": 1.0, "ground_evac": 0.55},
|
| people_true=18,
|
| initial_risk=1.03,
|
| progress_per_power=0.22,
|
| escalation_rate=0.13,
|
| death_rate=0.018,
|
| critical_rate=0.030,
|
| deadline_weight=1.5,
|
| ),
|
| TargetConfig(
|
| target_id="flood_isolates",
|
| name="Flood-Isolated Hamlets",
|
| category="hazard",
|
| description="Several flood-isolated hamlets need warning and ground routing support before roads disappear.",
|
| estimated_people="~300 residents across hamlets",
|
| observed_risk=0.69,
|
| visibility=0.16,
|
| vulnerability_label="mixed",
|
| vulnerability=1.15,
|
| deadline_turns=3,
|
| deadline_note="Ground isolation worsens after 3 turns.",
|
| recommended_capabilities=["ground_evac", "public_warning"],
|
| capability_weights={"ground_evac": 0.85, "public_warning": 1.0},
|
| people_true=300,
|
| exposed_population=300,
|
| initial_risk=0.90,
|
| progress_per_power=0.16,
|
| escalation_rate=0.10,
|
| death_rate=0.0007,
|
| critical_rate=0.0030,
|
| exposure_rate=0.010,
|
| deadline_weight=1.0,
|
| equity_weight=0.9,
|
| ),
|
| ],
|
| ),
|
| }
|
|
|
| DEFAULT_SCENE_ID = "scene_1"
|
|
|
|
|
| def ordered_scene_ids() -> List[str]:
|
| return sorted(SCENE_CATALOG.keys(), key=lambda scene_id: SCENE_CATALOG[scene_id].level)
|
|
|