101 lines
3.0 KiB
Python
101 lines
3.0 KiB
Python
"""Tests for the room graph + ASCII map renderer."""
|
|
from __future__ import annotations
|
|
|
|
from progetto2.mapper import Mapper
|
|
|
|
|
|
def test_visit_returns_stable_id() -> None:
|
|
m = Mapper()
|
|
a = m.visit("Cave Entrance", "", ["n", "s"])
|
|
b = m.visit("Cave Entrance", "", ["n", "s"])
|
|
assert a == b
|
|
|
|
|
|
def test_dynamic_description_does_not_break_id() -> None:
|
|
m = Mapper()
|
|
a = m.visit("Cave Entrance", "Dry and dusty.", ["n"])
|
|
b = m.visit("Cave Entrance", "Now dripping with water.", ["n"])
|
|
assert a == b
|
|
assert len(m.rooms) == 1
|
|
|
|
|
|
def test_render_empty() -> None:
|
|
assert Mapper().render() == "[mappa vuota]"
|
|
|
|
|
|
def test_render_single_room() -> None:
|
|
m = Mapper()
|
|
m.visit("Lobby", "Wide open space.", [])
|
|
out = m.render()
|
|
assert "Lobby" in out
|
|
assert "»" in out # current marker
|
|
assert "·" not in out # no neighbours
|
|
|
|
|
|
def test_render_grid_with_connectors() -> None:
|
|
m = Mapper()
|
|
a = m.visit("Hub", "central.", ["n", "e", "s", "w"])
|
|
b = m.visit("NorthRoom", "cold.", ["s"])
|
|
m.link_rooms(a, "n", b)
|
|
m.link_rooms(b, "s", a)
|
|
c = m.visit("EastRoom", "drafty.", ["w"])
|
|
m.link_rooms(a, "e", c)
|
|
m.link_rooms(c, "w", a)
|
|
out = m.render()
|
|
assert "Hub" in out
|
|
assert "NorthRoom" in out
|
|
assert "EastRoom" in out
|
|
assert "│" in out or "───" in out
|
|
|
|
|
|
# ----- multi-source BFS / orphan placement -------------------------------
|
|
|
|
def test_backtracking_visits_are_connected() -> None:
|
|
"""Walking A → B and never back should NOT leave B as orphan, because
|
|
B's exits include the back-edge to A.
|
|
"""
|
|
m = Mapper()
|
|
a = m.visit("A", "", ["n"])
|
|
b = m.visit("B", "", ["s"])
|
|
# No link_rooms() — but B has 's' which would point to A.
|
|
out = m.render(max_cols=20, max_rows=20)
|
|
assert "A" in out
|
|
assert "B" in out
|
|
# Both rooms must be visible in the rendered map.
|
|
rows = [r for r in out.splitlines() if r.strip()]
|
|
# Find the row containing B
|
|
assert any("B" in r for r in rows)
|
|
assert any("A" in r for r in rows)
|
|
|
|
|
|
def test_isolated_room_lands_somewhere_visible() -> None:
|
|
"""A room that has no edges at all should still end up in the rendered
|
|
map (stacked in the isolated-corner fallback).
|
|
"""
|
|
m = Mapper()
|
|
m.visit("Lobby", "", [])
|
|
m.visit("Void", "", []) # no edges to anyone
|
|
out = m.render(max_cols=20, max_rows=20)
|
|
assert "Lobby" in out
|
|
assert "Void" in out
|
|
|
|
|
|
def test_id_override_used_for_visit() -> None:
|
|
"""When GMCP supplies a vnum, ``id_override`` is used instead of name-hash."""
|
|
m = Mapper()
|
|
a = m.visit("Outer Courtyard", "", ["n"], id_override="vnum42")
|
|
b = m.visit("Outer Courtyard", "", ["n", "e"], id_override="vnum42")
|
|
assert a == b == "vnum42"
|
|
|
|
|
|
def test_multi_source_render_does_not_split_obviously_connected_rooms() -> None:
|
|
m = Mapper()
|
|
a = m.visit("A", "", ["n", "s"])
|
|
b = m.visit("B", "", ["s"])
|
|
m.link_rooms(a, "n", b)
|
|
c = m.visit("C", "", [])
|
|
out = m.render(max_cols=10, max_rows=10)
|
|
assert "A" in out
|
|
assert "B" in out
|
|
assert "C" in out
|