"""Tests for room rendering functions.""" from mudlib.entity import Mob from mudlib.render.room import ( render_entity_lines, render_exits, render_location, render_nearby, render_where, ) from mudlib.zone import Zone def test_render_where(): """render_where returns 'Where: {zone description}'.""" zone = Zone(name="overworld", description="The Overworld") assert render_where(zone.description) == "Where: The Overworld" zone2 = Zone(name="cave", description="Dark Cave") assert render_where(zone2.description) == "Where: Dark Cave" def test_render_location_center(): """render_location shows 'center' for positions near zone center.""" zone = Zone(name="test", width=50, height=50, terrain=[]) # Center should be around 25, 25 (middle third of both axes) assert render_location(zone, 25, 25) == "Location: center 25, 25" assert render_location(zone, 20, 20) == "Location: center 20, 20" assert render_location(zone, 30, 30) == "Location: center 30, 30" def test_render_location_quadrants(): """render_location shows correct quadrants based on position.""" zone = Zone(name="test", width=60, height=60, terrain=[]) # Thirds: 0-19 west/north, 20-39 center, 40-59 east/south # Northwest assert render_location(zone, 5, 5) == "Location: northwest 5, 5" assert render_location(zone, 10, 10) == "Location: northwest 10, 10" # North (center horizontally, north vertically) assert render_location(zone, 30, 5) == "Location: north 30, 5" # Northeast assert render_location(zone, 50, 5) == "Location: northeast 50, 5" # West (west horizontally, center vertically) assert render_location(zone, 5, 30) == "Location: west 5, 30" # East assert render_location(zone, 50, 30) == "Location: east 50, 30" # Southwest assert render_location(zone, 5, 50) == "Location: southwest 5, 50" # South assert render_location(zone, 30, 50) == "Location: south 30, 50" # Southeast assert render_location(zone, 50, 50) == "Location: southeast 50, 50" def test_render_nearby_empty(): """render_nearby returns empty string when no nearby entities.""" assert render_nearby([], None) == "" def test_render_nearby_single(): """render_nearby shows count and single entity name.""" mob = Mob(name="saibaman", x=10, y=10) result = render_nearby([mob], None) assert result == "Nearby: (1) saibaman" def test_render_nearby_multiple(): """render_nearby shows count and names separated by '/'.""" mobs = [ Mob(name="saibaman", x=10, y=10), Mob(name="Master Roshi", x=11, y=10), Mob(name="Goku", x=10, y=11), ] result = render_nearby(mobs, None) assert result == "Nearby: (3) saibaman / Master Roshi / Goku" def test_render_exits_all_directions(): """render_exits shows all passable cardinal directions.""" # Create zone with all passable terrain (grass) terrain = [["." for _ in range(10)] for _ in range(10)] zone = Zone( name="test", width=10, height=10, terrain=terrain, impassable={"^", "~"} ) result = render_exits(zone, 5, 5) assert result == "Exits: north south east west" def test_render_exits_blocked_directions(): """render_exits only shows passable directions.""" # Create zone with mountains (^) blocking some directions terrain = [ [".", ".", ".", ".", "."], [".", ".", "^", ".", "."], # mountain north [".", "^", ".", "^", "."], # mountains west and east [".", ".", "^", ".", "."], # mountain south [".", ".", ".", ".", "."], ] zone = Zone(name="test", width=5, height=5, terrain=terrain, impassable={"^", "~"}) # Position at center (2, 2) — surrounded by mountains result = render_exits(zone, 2, 2) assert result == "Exits:" # no passable exits def test_render_exits_partial(): """render_exits shows only available exits.""" terrain = [ [".", ".", "."], ["^", ".", "."], # mountain to west [".", "^", "."], # mountain to south ] zone = Zone(name="test", width=3, height=3, terrain=terrain, impassable={"^"}) # Position at (1, 1) — north and east are passable result = render_exits(zone, 1, 1) assert result == "Exits: north east" def test_render_entity_lines_empty(): """render_entity_lines returns empty string when no entities.""" assert render_entity_lines([], None) == "" def test_render_entity_lines_single(): """render_entity_lines shows single entity with posture.""" mob = Mob(name="saibaman", x=10, y=10) # Default posture is "standing" (fallback) result = render_entity_lines([mob], None) assert result == "saibaman is standing here." def test_render_entity_lines_multiple(): """render_entity_lines shows multiple entities, each on own line.""" # Create entities with different states that affect posture mob1 = Mob(name="saibaman", x=10, y=10) # standing by default mob2 = Mob(name="Master Roshi", x=10, y=10, resting=True) # resting result = render_entity_lines([mob1, mob2], None) lines = result.split("\n") assert len(lines) == 2 assert lines[0] == "saibaman is standing here." assert lines[1] == "Master Roshi is resting here." def test_render_entity_lines_postures(): """render_entity_lines handles different posture types based on entity state.""" # Standing (default state) mob = Mob(name="Goku", x=10, y=10) assert render_entity_lines([mob], None) == "Goku is standing here." # Resting (resting=True) mob_resting = Mob(name="Goku", x=10, y=10, resting=True) assert render_entity_lines([mob_resting], None) == "Goku is resting here." # Unconscious (pl <= 0) mob_unconscious = Mob(name="Goku", x=10, y=10, pl=0) assert render_entity_lines([mob_unconscious], None) == "Goku is unconscious." # Unconscious (stamina <= 0) mob_exhausted = Mob(name="Goku", x=10, y=10, stamina=0) assert render_entity_lines([mob_exhausted], None) == "Goku is unconscious."