fix(examples): address PR review feedback (CodeQL + Copilot)

- CodeQL (implicit string concatenation in a list): collapse the wrapped
  bullets in cli._render_validate_coverage to single literals. The rendered
  output is byte-identical (the example's ruff ignores E501); clears all
  six alerts and reads cleaner.
- Copilot: packs/README no longer claims the directory ships "effectively
  empty" — it ships the bundled Cinder Wastes alternate world.
- Copilot: the Cinder Wastes' ash_flats and caldera_deep zones overlapped
  on column x=60 (inclusive bounds + first-match zone_for silently shadowed
  the tier-3..5 band onto a 1x5 deep-edge strip). Move caldera_deep to
  x0=61 — no overlap, no dead tiles, deep zone still covers the dungeon.
  And harden the loader: overlapping zone rectangles are now a
  WorldLoadError, so no authored pack can ship that bug unseen (the
  cold-author dogfood loop — a generated pack exposed a validator gap).

Tests 419 -> 420 (zone-overlap rejection). Both worlds validate sound and
remain winnable by the sim bot.
This commit is contained in:
Patrick Buckley
2026-06-13 00:30:18 -07:00
parent 30c09aaf51
commit a0a097dfa8
5 changed files with 49 additions and 26 deletions
@@ -828,3 +828,24 @@ def test_single_boss_accepted() -> None:
bosses = [m for m in world.monsters if m.boss]
assert len(bosses) == 1
assert bosses[0].name == "the Wyrm Below"
def test_overlapping_zones_rejected(tmp_path: Path) -> None:
"""Overlapping zone rectangles are a load error.
``zone_for`` returns the FIRST matching zone, so two zones sharing any cell
would silently shadow one tier band there — exactly the bug a cold-authored
pack shipped (a 1-column caldera-edge strip dropped to the low band). Pull
the deep zone west so its rect overlaps the near zone and confirm the loader
refuses it rather than loading the ambiguity.
"""
pack = _clone_pack(tmp_path)
def mutate(data: dict[str, Any]) -> None:
for zone in data["zones"]:
if zone["key"] == "dungeon_deep":
zone["rect"][0] = 50 # now overlaps forest_near's x30..60 strip
_rewrite(pack / "world.json", mutate)
with pytest.raises(WorldLoadError, match="overlap"):
load_world(pack)
+8 -22
View File
@@ -385,29 +385,15 @@ def _render_validate_coverage() -> str:
settings_count = len(loader.SETTINGS_BANDS)
reserved = ", ".join(f"`{g}`" for g in _reserved_glyph_list())
bullets = [
f"* **Economy and progression bands** — every one of the {settings_count} "
"`settings` fields must sit in its allowed range (the table above), and "
"`growth` must be present and non-negative.",
"* **Glyph safety** — every terrain, location, and legend glyph must render "
f"exactly one column and must not be a reserved marker ({reserved}).",
"* **Map integrity** — `width`/`height` in band, every `terrain_rows` row "
"exactly `width` long with `height` rows, and every row character in the "
"`legend`.",
"* **Walkability** — `spawn` and every placed location must sit on walkable "
"terrain (and no two locations share a cell).",
f"* **Display-name length** — every monster, item, and location name within "
f"`{loader.MAX_NAME_LEN}` printable characters; content lists within their caps.",
"* **The fight row** — `events.json` must hold at least one `fight` entry, "
"with weights `> 0`, `min <= max`, and amounts in their per-kind band.",
"* **Cross-references** — `legend` → terrain key, location placements → "
"`locations.json` keys, `starting_weapon`/`starting_armor` → item ids, "
'`boss_monster` → a monster flagged `"boss": true`, '
"`rare_drop_item` → a consumable item id, and `forge_ore_item` → a "
"`material` item id.",
f"* **Economy and progression bands** — every one of the {settings_count} `settings` fields must sit in its allowed range (the table above), and `growth` must be present and non-negative.",
f"* **Glyph safety** — every terrain, location, and legend glyph must render exactly one column and must not be a reserved marker ({reserved}).",
"* **Map integrity** — `width`/`height` in band, every `terrain_rows` row exactly `width` long with `height` rows, and every row character in the `legend`.",
"* **Walkability** — `spawn` and every placed location must sit on walkable terrain (and no two locations share a cell).",
f"* **Display-name length** — every monster, item, and location name within `{loader.MAX_NAME_LEN}` printable characters; content lists within their caps.",
"* **The fight row** — `events.json` must hold at least one `fight` entry, with weights `> 0`, `min <= max`, and amounts in their per-kind band.",
'* **Cross-references** — `legend` → terrain key, location placements → `locations.json` keys, `starting_weapon`/`starting_armor` → item ids, `boss_monster` → a monster flagged `"boss": true`, `rare_drop_item` → a consumable item id, and `forge_ore_item` → a `material` item id.',
"* **Zone tiers** — every zone's tier band must overlap at least one monster tier.",
"* **Dungeon ladder** — every `dungeon_tiers` tier must have a non-boss "
"monster, and that tier's FIRST monster (its fixed rung guardian) must "
"not be `rare`.",
"* **Dungeon ladder** — every `dungeon_tiers` tier must have a non-boss monster, and that tier's FIRST monster (its fixed rung guardian) must not be `rare`.",
'* **Exactly one boss** — at most one monster may carry `"boss": true`.',
]
return "\n".join(bullets)
@@ -579,6 +579,22 @@ def _decode_zones(
tier_hi=hi,
)
)
# Zones must not overlap: zone_for returns the FIRST match, so an overlap
# would silently shadow one zone's tier band on the shared cells. Reject it
# at load so an authored pack can't ship that bug unseen.
for i, first in enumerate(out):
for second in out[i + 1 :]:
if (
first.x0 <= second.x1
and second.x0 <= first.x1
and first.y0 <= second.y1
and second.y0 <= first.y1
):
raise WorldLoadError(
f"world.json zones {first.key!r} and {second.key!r} overlap; "
"give each zone a distinct rectangle (zone_for takes the first "
"match, so an overlap would silently shadow one tier band)"
)
return out
@@ -9,9 +9,9 @@ of the pack's JSON files). The slug is the subdirectory name. `understone
worlds` discovers the Vale plus every pack here that carries a `world.json`,
loads each one, and reports whether it is sound.
The directory ships effectively empty (this README is the placeholder that keeps
it under version control); alternate worlds are added here as they are authored.
To serve one, point the server at it:
This directory ships with one bundled alternate world — **The Cinder Wastes**
(`cinder-wastes/`), an ashen volcanic underworld authored against `AUTHORING.md`.
More are added here as they are written. To serve one, point the server at it:
```bash
UNDERSTONE_WORLD=understone/world/packs/<slug> understone
@@ -92,7 +92,7 @@
},
{
"key": "caldera_deep",
"rect": [60, 8, 82, 22],
"rect": [61, 8, 82, 22],
"tier_lo": 3,
"tier_hi": 5
}