pipeworks_mud_mapper.models.zone

Zone model for game truth representation.

This module defines the Zone model - the “game truth” format that the MUD server consumes. Zone files contain everything the game engine needs to run: rooms, exits, items, and metadata. They explicitly exclude coordinates because the engine operates on topology (connections) not geometry (positions).

The Two-File Philosophy

As described in goblin_cartography.md Section 2.3, there’s a deliberate separation between:

  1. Zone files (game truth): What the server needs. Pure topology.

  2. Map files (authoring source): What humans need. Includes coordinates.

Zone files are “build artifacts” - they’re generated from map files by stripping coordinates. This separation ensures:

  • The server never sees or depends on visual layout

  • Authors can freely rearrange map layouts without affecting gameplay

  • Zone files remain clean and focused on game logic

Zone Structure

A zone is a self-contained region of the MUD world:

{
    "id": "crooked_pipe",
    "name": "Crooked Pipe District",
    "description": "A warren of goblin pubs...",
    "spawn_room": "spawn",
    "rooms": {
        "spawn": { ... },
        "front_parlour": { ... }
    },
    "items": {
        "ale_mug": { ... }
    }
}

Cross-Zone Exits

Exits can reference rooms in other zones using the format zone:room:

"exits": {
    "north": "front_parlour",          # Same zone
    "west": "cobbled_street:market"    # Cross-zone
}

The engine parses the : delimiter and loads the target zone if needed.

Examples

Creating a zone programmatically:

zone = Zone(
    id="tutorial",
    name="Tutorial Area",
    spawn_room="spawn",
    rooms={
        "spawn": Room(id="spawn", name="Arrival Chamber", exits={"north": "hall"}),
        "hall": Room(id="hall", name="Main Hall", exits={"south": "spawn"}),
    },
)

Serializing to JSON:

json_str = zone.model_dump_json(indent=2, exclude_none=True)

See also

MapFile

Authoring format that includes coordinates.

Room

Individual room within a zone.

Classes

Zone

A zone in game truth format (no coordinates).

Module Contents

class pipeworks_mud_mapper.models.zone.Zone(/, **data)[source]

Bases: pydantic.BaseModel

A zone in game truth format (no coordinates).

Zones are self-contained regions of the MUD world. Each zone has its own spawn point, rooms, and items. Zones connect to each other through cross-zone exits.

This model represents the format consumed by the MUD server. It excludes coordinates because the game engine operates on topology, not geometry.

id

Unique zone identifier. Used in cross-zone references and as filename. Should be lowercase with underscores (e.g., “crooked_pipe”).

Type:

str

name

Human-readable display name (e.g., “Crooked Pipe District”).

Type:

str

metadata

Versioning metadata that accompanies exported zone files.

Type:

ZoneMetadata

description

Optional zone description for authoring reference.

Type:

str

spawn_room

Room ID where players enter this zone. Must exist in rooms dict.

Type:

str

rooms

Mapping of room ID to Room objects.

Type:

dict[str, Room]

items

Mapping of item ID to item definitions. Item structure is flexible to support future item system expansion.

Type:

dict[str, dict]

Examples

>>> zone = Zone(
...     id="tutorial",
...     name="Tutorial Area",
...     spawn_room="spawn",
...     rooms={"spawn": Room(id="spawn", name="Start")},
... )

Validation ensures spawn_room exists:

>>> Zone(
...     id="bad",
...     name="Bad Zone",
...     spawn_room="nonexistent",
...     rooms={},
... )
Traceback (most recent call last):
...
pydantic_core._pydantic_core.ValidationError: ...

See also

MapFile

Authoring format with coordinates.

Room

Individual room model.

classmethod validate_id(v)[source]

Validate zone ID format.

Zone IDs must start with a letter and contain only lowercase letters, numbers, and underscores.

validate_spawn_room_exists()[source]

Ensure spawn_room references an existing room.

Returns:

The validated zone instance.

Return type:

Zone

Raises:

ValueError – If spawn_room is not in the rooms dictionary.

validate_room_ids_match_keys()[source]

Ensure room IDs match their dictionary keys.

Returns:

The validated zone instance.

Return type:

Zone

Raises:

ValueError – If any room’s ID doesn’t match its dictionary key.

get_room(room_id)[source]

Get a room by ID.

Parameters:

room_id (str) – The room ID to look up.

Returns:

The room if found, None otherwise.

Return type:

Room or None

Examples

>>> zone.get_room("spawn")
Room(id='spawn', ...)
>>> zone.get_room("nonexistent")
None
validate_exits()[source]

Validate all exit targets exist (within this zone).

Cross-zone exits (containing :) are skipped as they reference other zones that may not be loaded.

Returns:

List of warning messages for invalid exit targets.

Return type:

list[str]

Examples

>>> zone.validate_exits()
["Room 'spawn' has exit 'north' to nonexistent room 'bad_room'"]
find_unreachable_rooms()[source]

Find rooms that cannot be reached from the spawn room.

Uses breadth-first search from spawn_room to find all reachable rooms, then returns any rooms not in that set.

Returns:

List of room IDs that are unreachable from spawn.

Return type:

list[str]

Examples

>>> zone.find_unreachable_rooms()
['isolated_room', 'another_orphan']
find_dead_ends()[source]

Find rooms with no outgoing exits.

Note: Dead ends are not always errors - some rooms are intentionally terminal (treasure rooms, trap rooms, etc.).

Returns:

List of room IDs with no exits.

Return type:

list[str]

Examples

>>> zone.find_dead_ends()
['treasure_room', 'pit_of_doom']