diff --git a/src/mudlib/commands/look.py b/src/mudlib/commands/look.py index fe1556d..76b0592 100644 --- a/src/mudlib/commands/look.py +++ b/src/mudlib/commands/look.py @@ -201,16 +201,24 @@ async def cmd_look(player: Player, args: str) -> None: player.writer.write(entity_lines.replace("\n", "\r\n") + "\r\n") # Show items on the ground at player's position + from mudlib.corpse import Corpse from mudlib.portal import Portal contents_here = zone.contents_at(player.x, player.y) + corpses = [obj for obj in contents_here if isinstance(obj, Corpse)] ground_items = [ obj for obj in contents_here - if isinstance(obj, Thing) and not isinstance(obj, Portal) + if isinstance(obj, Thing) + and not isinstance(obj, Portal) + and not isinstance(obj, Corpse) ] portals = [obj for obj in contents_here if isinstance(obj, Portal)] + if corpses: + for corpse in corpses: + player.writer.write(f"{corpse.name} is here.\r\n") + if ground_items: names = ", ".join(_format_thing_name(item) for item in ground_items) player.writer.write(f"On the ground: {names}\r\n") diff --git a/tests/test_corpse.py b/tests/test_corpse.py index 0cc1554..a7c1696 100644 --- a/tests/test_corpse.py +++ b/tests/test_corpse.py @@ -406,3 +406,116 @@ class TestCombatDeathCorpse: # Verify it's the goblin's corpse corpse = next(obj for obj in contents if isinstance(obj, Corpse)) assert corpse.name == "goblin's corpse" + + +class TestCorpseDisplay: + """Tests for corpse display in look command.""" + + @pytest.fixture + def player(self, test_zone): + """Create a test player.""" + from unittest.mock import AsyncMock, MagicMock + + from mudlib.player import Player, players + + writer = MagicMock() + writer.write = MagicMock() + writer.drain = AsyncMock() + reader = MagicMock() + p = Player( + name="TestPlayer", + x=5, + y=10, + reader=reader, + writer=writer, + ) + p.location = test_zone + test_zone._contents.append(p) + players[p.name] = p + yield p + players.clear() + + @pytest.mark.asyncio + async def test_corpse_shown_in_look(self, player, test_zone): + """Corpse appears as 'X is here.' in look output.""" + from mudlib.commands.look import cmd_look + + # Create a corpse on player's tile + Corpse( + name="goblin's corpse", + location=test_zone, + x=5, + y=10, + decompose_at=time.monotonic() + 300, + ) + + await cmd_look(player, "") + + # Check output for corpse line + output = "".join( + call.args[0] for call in player.writer.write.call_args_list if call.args + ) + assert "goblin's corpse is here." in output + + @pytest.mark.asyncio + async def test_corpse_not_in_ground_items(self, player, test_zone): + """Corpse is NOT in 'On the ground:' list, but regular items are.""" + from mudlib.commands.look import cmd_look + + # Create a corpse and a regular item on player's tile + Corpse( + name="goblin's corpse", + location=test_zone, + x=5, + y=10, + decompose_at=time.monotonic() + 300, + ) + Thing(name="sword", location=test_zone, x=5, y=10) + + await cmd_look(player, "") + + output = "".join( + call.args[0] for call in player.writer.write.call_args_list if call.args + ) + + # Corpse should be shown as "is here", not in ground items + assert "goblin's corpse is here." in output + # Sword should be in ground items + assert "On the ground:" in output + assert "sword" in output + # Corpse name should NOT appear in the ground items line + lines = output.split("\r\n") + ground_line = next((line for line in lines if "On the ground:" in line), None) + assert ground_line is not None + assert "goblin's corpse" not in ground_line + + @pytest.mark.asyncio + async def test_multiple_corpses(self, player, test_zone): + """Multiple corpses each show as separate 'X is here.' lines.""" + from mudlib.commands.look import cmd_look + + # Create two corpses on player's tile + Corpse( + name="goblin's corpse", + location=test_zone, + x=5, + y=10, + decompose_at=time.monotonic() + 300, + ) + Corpse( + name="orc's corpse", + location=test_zone, + x=5, + y=10, + decompose_at=time.monotonic() + 300, + ) + + await cmd_look(player, "") + + output = "".join( + call.args[0] for call in player.writer.write.call_args_list if call.args + ) + + # Both corpses should appear + assert "goblin's corpse is here." in output + assert "orc's corpse is here." in output