diff --git a/content/zones/flower.toml b/content/zones/flower.toml new file mode 100644 index 0000000..f0a1cad --- /dev/null +++ b/content/zones/flower.toml @@ -0,0 +1,27 @@ +name = "flower" +description = "you lie in the heart of a giant flower, warm light filtering through translucent petals" +width = 7 +height = 7 +toroidal = false +spawn_x = 3 +spawn_y = 3 + +[terrain] +rows = [ + "ooooooo", + "ooo.ooo", + "oo...oo", + "o.....o", + "oo...oo", + "ooo.ooo", + "ooo.ooo", +] + +[terrain.impassable] +tiles = ["o"] + +[[portals]] +x = 3 +y = 6 +target = "treehouse:10,7" +label = "an opening in the petals" diff --git a/content/zones/treehouse.toml b/content/zones/treehouse.toml new file mode 100644 index 0000000..0ac1cf2 --- /dev/null +++ b/content/zones/treehouse.toml @@ -0,0 +1,41 @@ +name = "treehouse" +description = "a sprawling treehouse platform high in an ancient oak, branches creaking in the wind" +width = 20 +height = 15 +toroidal = false +spawn_x = 10 +spawn_y = 7 + +[terrain] +rows = [ + "~TTTTTTTTTTTTTTTTTT~", + "~TToooooooooooooTTT~", + "~TToo..........ooTT~", + "~TTo............oT~~", + "~TTo............oT~~", + "~TTo............oT~~", + "~TTo............oT~~", + "...o............oT~~", + "~TTo............oT~~", + "~TTo............oT~~", + "~TTo............oT~~", + "~TTo............oT~~", + "~TToo..........ooT~~", + "~TTToooooooooooTTT~~", + "~TTT...oooo...TTTT~~", +] + +[terrain.impassable] +tiles = ["o", "~"] + +[[portals]] +x = 10 +y = 14 +target = "overworld:500,500" +label = "a rope ladder dangles into the mist below" + +[[portals]] +x = 0 +y = 7 +target = "hub:7,14" +label = "a narrow branch leads to a distant platform" diff --git a/tests/test_tutorial_zones.py b/tests/test_tutorial_zones.py new file mode 100644 index 0000000..e19bd31 --- /dev/null +++ b/tests/test_tutorial_zones.py @@ -0,0 +1,125 @@ +"""Tests for tutorial zones (flower and treehouse).""" + +import pathlib + +from mudlib.zones import load_zone + + +def test_load_flower_zone(): + """Load the flower zone and verify basic properties.""" + project_root = pathlib.Path(__file__).resolve().parents[1] + flower_path = project_root / "content" / "zones" / "flower.toml" + + zone = load_zone(flower_path) + + assert zone.name == "flower" + assert zone.width == 7 + assert zone.height == 7 + assert zone.toroidal is False + assert zone.spawn_x == 3 + assert zone.spawn_y == 3 + assert len(zone.terrain) == 7 + + +def test_flower_zone_mostly_sealed(): + """Verify flower zone has mostly sealed borders with impassable petals.""" + project_root = pathlib.Path(__file__).resolve().parents[1] + flower_path = project_root / "content" / "zones" / "flower.toml" + + zone = load_zone(flower_path) + + # Verify 'o' is impassable (petals) + assert "o" in zone.impassable + + # Count impassable border tiles + border_tiles = [] + # Top and bottom rows + for x in range(zone.width): + border_tiles.append((x, 0)) + border_tiles.append((x, zone.height - 1)) + # Left and right columns (excluding corners already counted) + for y in range(1, zone.height - 1): + border_tiles.append((0, y)) + border_tiles.append((zone.width - 1, y)) + + impassable_border_count = sum( + 1 for x, y in border_tiles if not zone.is_passable(x, y) + ) + + # Most of the border should be impassable (allow for 1-2 openings) + total_border = len(border_tiles) + assert impassable_border_count >= total_border - 2 + + +def test_flower_has_portal_to_treehouse(): + """Verify flower zone has a portal targeting treehouse.""" + project_root = pathlib.Path(__file__).resolve().parents[1] + flower_path = project_root / "content" / "zones" / "flower.toml" + + zone = load_zone(flower_path) + + # Find portals in zone contents + portals = [obj for obj in zone._contents if obj.__class__.__name__ == "Portal"] + assert len(portals) == 1 + + portal = portals[0] + assert portal.target_zone == "treehouse" + assert portal.target_x == 10 + assert portal.target_y == 7 + assert "petal" in portal.name.lower() or "opening" in portal.name.lower() + + +def test_load_treehouse_zone(): + """Load the treehouse zone and verify basic properties.""" + project_root = pathlib.Path(__file__).resolve().parents[1] + treehouse_path = project_root / "content" / "zones" / "treehouse.toml" + + zone = load_zone(treehouse_path) + + assert zone.name == "treehouse" + assert zone.width == 20 + assert zone.height == 15 + assert zone.toroidal is False + assert zone.spawn_x == 10 + assert zone.spawn_y == 7 + assert len(zone.terrain) == 15 + + +def test_treehouse_has_portal_to_overworld(): + """Verify treehouse has a portal to the overworld.""" + project_root = pathlib.Path(__file__).resolve().parents[1] + treehouse_path = project_root / "content" / "zones" / "treehouse.toml" + + zone = load_zone(treehouse_path) + + # Find portals + portals = [obj for obj in zone._contents if obj.__class__.__name__ == "Portal"] + + # Find the overworld portal + overworld_portals = [p for p in portals if p.target_zone == "overworld"] + assert len(overworld_portals) == 1 + + portal = overworld_portals[0] + assert portal.target_x == 500 + assert portal.target_y == 500 + assert "ladder" in portal.name.lower() or "mist" in portal.name.lower() + + +def test_treehouse_has_portal_to_hub(): + """Verify treehouse has a portal to the hub.""" + project_root = pathlib.Path(__file__).resolve().parents[1] + treehouse_path = project_root / "content" / "zones" / "treehouse.toml" + + zone = load_zone(treehouse_path) + + # Find portals + portals = [obj for obj in zone._contents if obj.__class__.__name__ == "Portal"] + + # Find the hub portal + hub_portals = [p for p in portals if p.target_zone == "hub"] + assert len(hub_portals) == 1 + + portal = hub_portals[0] + assert portal.target_x == 7 + assert portal.target_y == 14 + assert "branch" in portal.name.lower() or "platform" in portal.name.lower()