"""Generate docs/scenarios.html — the human-readable scenario catalog. For every ACTIVE pack: title, capability, why-it-exists, the runnable configs (or 3 levels), and per cell the plain-language objective the model actually sees (objective_brief: description + WIN/LOSE + turn budget). Run: python scripts/gen_scenario_docs.py [--open] """ from __future__ import annotations import glob import html import os import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent PACKS = ROOT / "openra_bench" / "scenarios" / "packs" OUT = ROOT / "docs" / "scenarios.html" sys.path.insert(0, str(ROOT)) # runnable as a standalone script from openra_bench.game_knowledge import objective_brief # noqa: E402 from openra_bench.scenarios import load_pack # noqa: E402 _CAP_COLOR = { "perception": "#7497db", "reasoning": "#9b8cce", "action": "#5fae7a", "adversarial": "#d2683c", } def _esc(s) -> str: return html.escape(str(s)).replace("\n", "
") def _cells(pack): """[(label, CompiledLevel)] — configs if declared, else 3 levels.""" out = [] if pack.configs: for c in pack.configs: out.append((c.name, pack.compile_config(c.name))) else: for lv in ("easy", "medium", "hard"): out.append((lv, pack.compile(lv))) return out def build() -> str: packs = [] for f in sorted(glob.glob(str(PACKS / "*.yaml"))): b = os.path.basename(f) if b.startswith(("_", "TEMPLATE")): continue p = load_pack(f) if p.meta.status == "active": packs.append(p) by_cap: dict[str, list] = {} for p in packs: by_cap.setdefault(p.meta.capability, []).append(p) parts = [ "", "OpenRA-Bench — Scenario Catalog", """""", "

OpenRA-Bench — Scenario Catalog

", f"
{len(packs)} active scenarios · the title, why " "it exists, and the exact objective the model is given per " "runnable config.
", "
" + " ".join( f"{c} ({len(v)})" for c, v in sorted(by_cap.items()) ) + "
", ] for cap in sorted(by_cap): parts.append(f"

{cap}

") for p in sorted(by_cap[cap], key=lambda x: x.meta.id): col = _CAP_COLOR.get(cap, "#666") parts.append("
") parts.append( f"
{_esc(p.meta.title)}" f"{cap}" f"
{p.meta.id} · {p.base_map}
" ) parts.append( f"
Why: {_esc(p.meta.real_world_meaning)}" f"
Robotics analogue: " f"{_esc(p.meta.robotics_analogue)}
" ) try: cells = _cells(p) except Exception as e: # noqa: BLE001 parts.append(f"
(compile error: {_esc(e)})
") cells = [] for label, cl in cells: fog = getattr(cl, "fog_mode", "vision") ob = objective_brief( cl.scenario.description, cl.win_condition, cl.fail_condition, cl.max_turns, getattr(cl, "objective_coords", "exact"), ) parts.append( f"
{label} " f"(level {cl.level} · fog " f"{fog})
{_esc(ob)}
" ) parts.append("
") parts.append("
") return "".join(parts) def main(argv): OUT.parent.mkdir(parents=True, exist_ok=True) OUT.write_text(build(), encoding="utf-8") print(f"wrote {OUT}") if "--open" in argv: import subprocess subprocess.run(["open", str(OUT)], check=False) if __name__ == "__main__": main(sys.argv[1:])