ThingTemplate dataclass mirrors MobTemplate pattern. load_thing_template and load_thing_templates parse TOML files from content/things/. spawn_thing creates Thing instances from templates. Includes rock and fountain examples.
152 lines
4 KiB
Python
152 lines
4 KiB
Python
"""Tests for thing template loading and spawning."""
|
|
|
|
import textwrap
|
|
|
|
import pytest
|
|
|
|
from mudlib.thing import Thing
|
|
from mudlib.things import (
|
|
ThingTemplate,
|
|
load_thing_template,
|
|
load_thing_templates,
|
|
spawn_thing,
|
|
)
|
|
from mudlib.zone import Zone
|
|
|
|
|
|
@pytest.fixture
|
|
def test_zone():
|
|
terrain = [["." for _ in range(10)] for _ in range(10)]
|
|
return Zone(
|
|
name="testzone",
|
|
width=10,
|
|
height=10,
|
|
terrain=terrain,
|
|
)
|
|
|
|
|
|
# --- ThingTemplate ---
|
|
|
|
|
|
def test_thing_template_creation():
|
|
"""ThingTemplate holds definition data."""
|
|
t = ThingTemplate(
|
|
name="rock",
|
|
description="a smooth grey rock",
|
|
portable=True,
|
|
aliases=["stone"],
|
|
)
|
|
assert t.name == "rock"
|
|
assert t.description == "a smooth grey rock"
|
|
assert t.portable is True
|
|
assert t.aliases == ["stone"]
|
|
|
|
|
|
def test_thing_template_defaults():
|
|
"""ThingTemplate has sensible defaults."""
|
|
t = ThingTemplate(name="rock", description="a rock")
|
|
assert t.portable is True
|
|
assert t.aliases == []
|
|
|
|
|
|
# --- load_thing_template ---
|
|
|
|
|
|
def test_load_thing_template(tmp_path):
|
|
"""Load a thing template from a TOML file."""
|
|
toml_content = textwrap.dedent("""\
|
|
name = "rusty sword"
|
|
description = "a sword covered in rust"
|
|
portable = true
|
|
aliases = ["sword", "rusty"]
|
|
""")
|
|
p = tmp_path / "sword.toml"
|
|
p.write_text(toml_content)
|
|
|
|
template = load_thing_template(p)
|
|
assert template.name == "rusty sword"
|
|
assert template.description == "a sword covered in rust"
|
|
assert template.portable is True
|
|
assert template.aliases == ["sword", "rusty"]
|
|
|
|
|
|
def test_load_thing_template_minimal(tmp_path):
|
|
"""Load thing template with only required fields."""
|
|
toml_content = textwrap.dedent("""\
|
|
name = "rock"
|
|
description = "a rock"
|
|
""")
|
|
p = tmp_path / "rock.toml"
|
|
p.write_text(toml_content)
|
|
|
|
template = load_thing_template(p)
|
|
assert template.name == "rock"
|
|
assert template.portable is True # default
|
|
assert template.aliases == [] # default
|
|
|
|
|
|
def test_load_thing_template_non_portable(tmp_path):
|
|
"""Load a non-portable thing template."""
|
|
toml_content = textwrap.dedent("""\
|
|
name = "fountain"
|
|
description = "a stone fountain"
|
|
portable = false
|
|
""")
|
|
p = tmp_path / "fountain.toml"
|
|
p.write_text(toml_content)
|
|
|
|
template = load_thing_template(p)
|
|
assert template.portable is False
|
|
|
|
|
|
# --- load_thing_templates ---
|
|
|
|
|
|
def test_load_thing_templates(tmp_path):
|
|
"""Load all thing templates from a directory."""
|
|
for name in ["rock", "sword"]:
|
|
p = tmp_path / f"{name}.toml"
|
|
p.write_text(f'name = "{name}"\ndescription = "a {name}"\n')
|
|
|
|
templates = load_thing_templates(tmp_path)
|
|
assert "rock" in templates
|
|
assert "sword" in templates
|
|
assert len(templates) == 2
|
|
|
|
|
|
def test_load_thing_templates_empty_dir(tmp_path):
|
|
"""Empty directory returns empty dict."""
|
|
templates = load_thing_templates(tmp_path)
|
|
assert templates == {}
|
|
|
|
|
|
# --- spawn_thing ---
|
|
|
|
|
|
def test_spawn_thing_in_zone(test_zone):
|
|
"""spawn_thing creates a Thing instance in a zone."""
|
|
template = ThingTemplate(
|
|
name="rock",
|
|
description="a smooth grey rock",
|
|
portable=True,
|
|
aliases=["stone"],
|
|
)
|
|
thing = spawn_thing(template, test_zone, x=3, y=7)
|
|
assert isinstance(thing, Thing)
|
|
assert thing.name == "rock"
|
|
assert thing.description == "a smooth grey rock"
|
|
assert thing.portable is True
|
|
assert thing.aliases == ["stone"]
|
|
assert thing.location is test_zone
|
|
assert thing.x == 3
|
|
assert thing.y == 7
|
|
assert thing in test_zone.contents
|
|
|
|
|
|
def test_spawn_thing_without_coordinates(test_zone):
|
|
"""spawn_thing can create a thing without position (template/inventory)."""
|
|
template = ThingTemplate(name="gem", description="a sparkling gem")
|
|
thing = spawn_thing(template, None)
|
|
assert thing.location is None
|
|
assert thing.x is None
|
|
assert thing.y is None
|