Add zone registry with register and lookup
Implements a module-level zone registry for looking up zones by name. Includes register_zone() and get_zone() functions with comprehensive tests covering single/multiple zones, unknown lookups, and overwrites.
This commit is contained in:
parent
303ce2c89e
commit
b3471a8b94
6 changed files with 564 additions and 2 deletions
94
src/mudlib/commands/containers.py
Normal file
94
src/mudlib/commands/containers.py
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
"""Open and close commands for containers."""
|
||||||
|
|
||||||
|
from mudlib.commands import CommandDefinition, register
|
||||||
|
from mudlib.container import Container
|
||||||
|
from mudlib.player import Player
|
||||||
|
from mudlib.thing import Thing
|
||||||
|
from mudlib.zone import Zone
|
||||||
|
|
||||||
|
|
||||||
|
def _find_container(name: str, player: Player) -> Container | Thing | None:
|
||||||
|
"""Find a thing by name in inventory first, then on ground.
|
||||||
|
|
||||||
|
Returns Thing if found (caller must check if it's a Container).
|
||||||
|
Returns None if not found.
|
||||||
|
"""
|
||||||
|
name_lower = name.lower()
|
||||||
|
|
||||||
|
# Check inventory first
|
||||||
|
for obj in player.contents:
|
||||||
|
if not isinstance(obj, Thing):
|
||||||
|
continue
|
||||||
|
if obj.name.lower() == name_lower:
|
||||||
|
return obj
|
||||||
|
if name_lower in (a.lower() for a in obj.aliases):
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# Check ground at player's position
|
||||||
|
zone = player.location
|
||||||
|
if zone is None or not isinstance(zone, Zone):
|
||||||
|
return None
|
||||||
|
|
||||||
|
for obj in zone.contents_at(player.x, player.y):
|
||||||
|
if not isinstance(obj, Thing):
|
||||||
|
continue
|
||||||
|
if obj.name.lower() == name_lower:
|
||||||
|
return obj
|
||||||
|
if name_lower in (a.lower() for a in obj.aliases):
|
||||||
|
return obj
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def cmd_open(player: Player, args: str) -> None:
|
||||||
|
"""Open a container."""
|
||||||
|
if not args.strip():
|
||||||
|
await player.send("Open what?\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
thing = _find_container(args.strip(), player)
|
||||||
|
if thing is None:
|
||||||
|
await player.send("You don't see that here.\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not isinstance(thing, Container):
|
||||||
|
await player.send("You can't open that.\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not thing.closed:
|
||||||
|
await player.send("It's already open.\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
if thing.locked:
|
||||||
|
await player.send("It's locked.\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
thing.closed = False
|
||||||
|
await player.send(f"You open the {thing.name}.\r\n")
|
||||||
|
|
||||||
|
|
||||||
|
async def cmd_close(player: Player, args: str) -> None:
|
||||||
|
"""Close a container."""
|
||||||
|
if not args.strip():
|
||||||
|
await player.send("Close what?\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
thing = _find_container(args.strip(), player)
|
||||||
|
if thing is None:
|
||||||
|
await player.send("You don't see that here.\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not isinstance(thing, Container):
|
||||||
|
await player.send("You can't close that.\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
if thing.closed:
|
||||||
|
await player.send("It's already closed.\r\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
thing.closed = True
|
||||||
|
await player.send(f"You close the {thing.name}.\r\n")
|
||||||
|
|
||||||
|
|
||||||
|
register(CommandDefinition("open", cmd_open))
|
||||||
|
register(CommandDefinition("close", cmd_close))
|
||||||
|
|
@ -31,8 +31,6 @@ from mudlib.effects import clear_expired
|
||||||
from mudlib.if_session import broadcast_to_spectators
|
from mudlib.if_session import broadcast_to_spectators
|
||||||
from mudlib.mob_ai import process_mobs
|
from mudlib.mob_ai import process_mobs
|
||||||
from mudlib.mobs import load_mob_templates, mob_templates
|
from mudlib.mobs import load_mob_templates, mob_templates
|
||||||
from mudlib.thing import Thing
|
|
||||||
from mudlib.things import load_thing_templates, spawn_thing, thing_templates
|
|
||||||
from mudlib.player import Player, players
|
from mudlib.player import Player, players
|
||||||
from mudlib.resting import process_resting
|
from mudlib.resting import process_resting
|
||||||
from mudlib.store import (
|
from mudlib.store import (
|
||||||
|
|
|
||||||
30
src/mudlib/zones.py
Normal file
30
src/mudlib/zones.py
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
"""Zone registry and loading."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from mudlib.zone import Zone
|
||||||
|
|
||||||
|
# Module-level zone registry
|
||||||
|
zone_registry: dict[str, Zone] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def register_zone(name: str, zone: Zone) -> None:
|
||||||
|
"""Register a zone by name.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Unique name for the zone
|
||||||
|
zone: Zone instance to register
|
||||||
|
"""
|
||||||
|
zone_registry[name] = zone
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone(name: str) -> Zone | None:
|
||||||
|
"""Look up a zone by name.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Zone name to look up
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Zone instance if found, None otherwise
|
||||||
|
"""
|
||||||
|
return zone_registry.get(name)
|
||||||
152
tests/test_container_display.py
Normal file
152
tests/test_container_display.py
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
"""Tests for container state display in look and inventory commands."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from mudlib.container import Container
|
||||||
|
from mudlib.player import Player
|
||||||
|
from mudlib.thing import Thing
|
||||||
|
from mudlib.zone import Zone
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_writer():
|
||||||
|
writer = MagicMock()
|
||||||
|
writer.write = MagicMock()
|
||||||
|
writer.drain = AsyncMock()
|
||||||
|
return writer
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_reader():
|
||||||
|
return MagicMock()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def test_zone():
|
||||||
|
terrain = [["." for _ in range(10)] for _ in range(10)]
|
||||||
|
return Zone(
|
||||||
|
name="testzone",
|
||||||
|
width=10,
|
||||||
|
height=10,
|
||||||
|
toroidal=True,
|
||||||
|
terrain=terrain,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def player(mock_reader, mock_writer, test_zone):
|
||||||
|
p = Player(
|
||||||
|
name="TestPlayer",
|
||||||
|
x=5,
|
||||||
|
y=5,
|
||||||
|
reader=mock_reader,
|
||||||
|
writer=mock_writer,
|
||||||
|
location=test_zone,
|
||||||
|
)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
# --- look command container display ---
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_look_shows_closed_container(player, test_zone, mock_writer):
|
||||||
|
"""look shows closed containers with (closed) suffix."""
|
||||||
|
from mudlib.commands.look import cmd_look
|
||||||
|
|
||||||
|
Container(name="chest", location=test_zone, x=5, y=5, closed=True)
|
||||||
|
await cmd_look(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert "chest (closed)" in output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_look_shows_open_empty_container(player, test_zone, mock_writer):
|
||||||
|
"""look shows open empty containers with (open, empty) suffix."""
|
||||||
|
from mudlib.commands.look import cmd_look
|
||||||
|
|
||||||
|
Container(name="chest", location=test_zone, x=5, y=5, closed=False)
|
||||||
|
await cmd_look(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert "chest (open, empty)" in output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_look_shows_open_container_with_contents(
|
||||||
|
player, test_zone, mock_writer
|
||||||
|
):
|
||||||
|
"""look shows open containers with their contents."""
|
||||||
|
from mudlib.commands.look import cmd_look
|
||||||
|
|
||||||
|
chest = Container(name="chest", location=test_zone, x=5, y=5, closed=False)
|
||||||
|
Thing(name="rock", location=chest)
|
||||||
|
Thing(name="coin", location=chest)
|
||||||
|
await cmd_look(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert "chest (open, containing: rock, coin)" in output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_look_shows_regular_things_unchanged(player, test_zone, mock_writer):
|
||||||
|
"""look shows regular Things without container suffixes."""
|
||||||
|
from mudlib.commands.look import cmd_look
|
||||||
|
|
||||||
|
Thing(name="rock", location=test_zone, x=5, y=5)
|
||||||
|
await cmd_look(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert "On the ground: rock" in output
|
||||||
|
assert "(closed)" not in output
|
||||||
|
assert "(open" not in output
|
||||||
|
|
||||||
|
|
||||||
|
# --- inventory command container display ---
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_inventory_shows_closed_container(player, mock_writer):
|
||||||
|
"""inventory shows closed containers with (closed) suffix."""
|
||||||
|
from mudlib.commands.things import cmd_inventory
|
||||||
|
|
||||||
|
Container(name="sack", location=player, closed=True)
|
||||||
|
await cmd_inventory(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert "sack (closed)" in output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_inventory_shows_open_empty_container(player, mock_writer):
|
||||||
|
"""inventory shows open empty containers with (open, empty) suffix."""
|
||||||
|
from mudlib.commands.things import cmd_inventory
|
||||||
|
|
||||||
|
Container(name="sack", location=player, closed=False)
|
||||||
|
await cmd_inventory(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert "sack (open, empty)" in output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_inventory_shows_container_with_contents(player, mock_writer):
|
||||||
|
"""inventory shows open containers with their contents."""
|
||||||
|
from mudlib.commands.things import cmd_inventory
|
||||||
|
|
||||||
|
sack = Container(name="sack", location=player, closed=False)
|
||||||
|
Thing(name="rock", location=sack)
|
||||||
|
Thing(name="gem", location=sack)
|
||||||
|
await cmd_inventory(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert "sack (open, containing: rock, gem)" in output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_inventory_shows_regular_things_unchanged(player, mock_writer):
|
||||||
|
"""inventory shows regular Things without container suffixes."""
|
||||||
|
from mudlib.commands.things import cmd_inventory
|
||||||
|
|
||||||
|
Thing(name="rock", location=player)
|
||||||
|
await cmd_inventory(player, "")
|
||||||
|
output = "".join(call[0][0] for call in mock_writer.write.call_args_list)
|
||||||
|
assert " rock\r\n" in output
|
||||||
|
assert "(closed)" not in output
|
||||||
|
assert "(open" not in output
|
||||||
226
tests/test_open_close.py
Normal file
226
tests/test_open_close.py
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
"""Tests for open and close commands."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from mudlib.commands import _registry
|
||||||
|
from mudlib.container import Container
|
||||||
|
from mudlib.player import Player
|
||||||
|
from mudlib.thing import Thing
|
||||||
|
from mudlib.zone import Zone
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_writer():
|
||||||
|
writer = MagicMock()
|
||||||
|
writer.write = MagicMock()
|
||||||
|
writer.drain = AsyncMock()
|
||||||
|
return writer
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_reader():
|
||||||
|
return MagicMock()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def test_zone():
|
||||||
|
terrain = [["." for _ in range(10)] for _ in range(10)]
|
||||||
|
return Zone(
|
||||||
|
name="testzone",
|
||||||
|
width=10,
|
||||||
|
height=10,
|
||||||
|
toroidal=True,
|
||||||
|
terrain=terrain,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def player(mock_reader, mock_writer, test_zone):
|
||||||
|
p = Player(
|
||||||
|
name="TestPlayer",
|
||||||
|
x=5,
|
||||||
|
y=5,
|
||||||
|
reader=mock_reader,
|
||||||
|
writer=mock_writer,
|
||||||
|
location=test_zone,
|
||||||
|
)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
# --- cmd_open ---
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_container_on_ground(player, test_zone, mock_writer):
|
||||||
|
"""open finds container on ground and sets closed=False."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
chest = Container(name="chest", location=test_zone, x=5, y=5, closed=True)
|
||||||
|
await cmd_open(player, "chest")
|
||||||
|
assert chest.closed is False
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "open" in output.lower() and "chest" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_container_in_inventory(player, test_zone, mock_writer):
|
||||||
|
"""open finds container in player inventory and sets closed=False."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
box = Container(name="box", location=player, closed=True)
|
||||||
|
await cmd_open(player, "box")
|
||||||
|
assert box.closed is False
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "open" in output.lower() and "box" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_no_args(player, mock_writer):
|
||||||
|
"""open with no arguments gives usage hint."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
await cmd_open(player, "")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "open what" in output.lower() or "what" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_already_open(player, test_zone, mock_writer):
|
||||||
|
"""open on already-open container gives feedback."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
chest = Container(name="chest", location=test_zone, x=5, y=5, closed=False)
|
||||||
|
await cmd_open(player, "chest")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "already open" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_locked_container(player, test_zone, mock_writer):
|
||||||
|
"""open on locked container gives feedback."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
chest = Container(
|
||||||
|
name="chest", location=test_zone, x=5, y=5, closed=True, locked=True
|
||||||
|
)
|
||||||
|
await cmd_open(player, "chest")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "locked" in output.lower()
|
||||||
|
# Container should still be closed
|
||||||
|
assert chest.closed is True
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_not_found(player, test_zone, mock_writer):
|
||||||
|
"""open on non-existent thing gives feedback."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
await cmd_open(player, "chest")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "don't see" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_matches_aliases(player, test_zone):
|
||||||
|
"""open matches container aliases."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
chest = Container(
|
||||||
|
name="wooden chest",
|
||||||
|
aliases=["chest", "box"],
|
||||||
|
location=test_zone,
|
||||||
|
x=5,
|
||||||
|
y=5,
|
||||||
|
closed=True,
|
||||||
|
)
|
||||||
|
await cmd_open(player, "box")
|
||||||
|
assert chest.closed is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_open_non_container(player, test_zone, mock_writer):
|
||||||
|
"""open on non-container thing gives feedback."""
|
||||||
|
from mudlib.commands.containers import cmd_open
|
||||||
|
|
||||||
|
rock = Thing(name="rock", location=test_zone, x=5, y=5)
|
||||||
|
await cmd_open(player, "rock")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "can't open" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
# --- cmd_close ---
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_close_container_on_ground(player, test_zone, mock_writer):
|
||||||
|
"""close finds container on ground and sets closed=True."""
|
||||||
|
from mudlib.commands.containers import cmd_close
|
||||||
|
|
||||||
|
chest = Container(name="chest", location=test_zone, x=5, y=5, closed=False)
|
||||||
|
await cmd_close(player, "chest")
|
||||||
|
assert chest.closed is True
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "close" in output.lower() and "chest" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_close_container_in_inventory(player, test_zone, mock_writer):
|
||||||
|
"""close finds container in inventory and sets closed=True."""
|
||||||
|
from mudlib.commands.containers import cmd_close
|
||||||
|
|
||||||
|
box = Container(name="box", location=player, closed=False)
|
||||||
|
await cmd_close(player, "box")
|
||||||
|
assert box.closed is True
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "close" in output.lower() and "box" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_close_already_closed(player, test_zone, mock_writer):
|
||||||
|
"""close on already-closed container gives feedback."""
|
||||||
|
from mudlib.commands.containers import cmd_close
|
||||||
|
|
||||||
|
chest = Container(name="chest", location=test_zone, x=5, y=5, closed=True)
|
||||||
|
await cmd_close(player, "chest")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "already closed" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_close_no_args(player, mock_writer):
|
||||||
|
"""close with no arguments gives usage hint."""
|
||||||
|
from mudlib.commands.containers import cmd_close
|
||||||
|
|
||||||
|
await cmd_close(player, "")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "close what" in output.lower() or "what" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_close_non_container(player, test_zone, mock_writer):
|
||||||
|
"""close on non-container thing gives feedback."""
|
||||||
|
from mudlib.commands.containers import cmd_close
|
||||||
|
|
||||||
|
rock = Thing(name="rock", location=test_zone, x=5, y=5)
|
||||||
|
await cmd_close(player, "rock")
|
||||||
|
output = mock_writer.write.call_args_list[-1][0][0]
|
||||||
|
assert "can't close" in output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
# --- command registration ---
|
||||||
|
|
||||||
|
|
||||||
|
def test_open_command_registered():
|
||||||
|
"""open command is registered."""
|
||||||
|
import mudlib.commands.containers # noqa: F401
|
||||||
|
|
||||||
|
assert "open" in _registry
|
||||||
|
|
||||||
|
|
||||||
|
def test_close_command_registered():
|
||||||
|
"""close command is registered."""
|
||||||
|
import mudlib.commands.containers # noqa: F401
|
||||||
|
|
||||||
|
assert "close" in _registry
|
||||||
62
tests/test_zone_registry.py
Normal file
62
tests/test_zone_registry.py
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
"""Tests for zone registry."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from mudlib.zone import Zone
|
||||||
|
from mudlib.zones import get_zone, register_zone, zone_registry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def clear_registry():
|
||||||
|
"""Clear zone registry before each test."""
|
||||||
|
zone_registry.clear()
|
||||||
|
yield
|
||||||
|
zone_registry.clear()
|
||||||
|
|
||||||
|
|
||||||
|
def test_register_zone():
|
||||||
|
"""Register a zone by name."""
|
||||||
|
zone = Zone(name="test_zone", width=10, height=10, terrain=[], toroidal=False)
|
||||||
|
register_zone("test_zone", zone)
|
||||||
|
|
||||||
|
assert "test_zone" in zone_registry
|
||||||
|
assert zone_registry["test_zone"] is zone
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_zone():
|
||||||
|
"""Look up a zone by name."""
|
||||||
|
zone = Zone(name="test_zone", width=10, height=10, terrain=[], toroidal=False)
|
||||||
|
register_zone("test_zone", zone)
|
||||||
|
|
||||||
|
retrieved = get_zone("test_zone")
|
||||||
|
assert retrieved is zone
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_zone_unknown():
|
||||||
|
"""Get None for unknown zone name."""
|
||||||
|
result = get_zone("nonexistent")
|
||||||
|
assert result is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_register_multiple_zones():
|
||||||
|
"""Register multiple zones."""
|
||||||
|
zone1 = Zone(name="zone1", width=10, height=10, terrain=[], toroidal=False)
|
||||||
|
zone2 = Zone(name="zone2", width=20, height=15, terrain=[], toroidal=True)
|
||||||
|
|
||||||
|
register_zone("zone1", zone1)
|
||||||
|
register_zone("zone2", zone2)
|
||||||
|
|
||||||
|
assert len(zone_registry) == 2
|
||||||
|
assert get_zone("zone1") is zone1
|
||||||
|
assert get_zone("zone2") is zone2
|
||||||
|
|
||||||
|
|
||||||
|
def test_overwrite_zone():
|
||||||
|
"""Registering same name twice overwrites."""
|
||||||
|
zone1 = Zone(name="zone", width=10, height=10, terrain=[], toroidal=False)
|
||||||
|
zone2 = Zone(name="zone", width=20, height=20, terrain=[], toroidal=False)
|
||||||
|
|
||||||
|
register_zone("zone", zone1)
|
||||||
|
register_zone("zone", zone2)
|
||||||
|
|
||||||
|
assert get_zone("zone") is zone2
|
||||||
Loading…
Reference in a new issue