Compare commits

..

2 commits

4 changed files with 286 additions and 8 deletions

View file

@ -193,7 +193,9 @@ a definition came from.
the entity model
================
current: Player is a dataclass. no mobs, no items, no NPCs yet.
current: Entity base class with Player and Mob subclasses. see
object-model.rst for the concrete class hierarchy (Object → Zone, Entity,
Thing) and the location-based containment system.
the ecosystem shows two paths:
- deep inheritance (evennia: Object > Character > NPC, most traditional MUDs)
@ -375,3 +377,4 @@ this document docs/how/architecture-plan.txt
dreambook DREAMBOOK.md
ecosystem research docs/how/mud-ecosystem.txt
landscape research docs/how/mudlib-landscape.txt
object model docs/how/object-model.rst

250
docs/how/object-model.rst Normal file
View file

@ -0,0 +1,250 @@
object model — containment, verbs, and the location tree
========================================================
a design doc for the object hierarchy that powers containment, inventory,
zones, and verb-driven interaction. captures the core rule, the class
structure, and how everything connects.
see also: ``things-and-building.rst`` (@thing/@verb decorator system),
``zones-and-building.rst`` (zone data format), ``architecture-plan.txt``
(engine/content boundary), ``combat.rst`` (combat on Entity subgraph).
the core rule
-------------
every object has a ``location`` attribute that points to another object, or
None. that's the entire containment system.
where something is = what its location points to. None means it's a top-level
thing — a zone, a template that hasn't spawned yet, or something removed from
the world.
here's what the tree looks like::
overworld zone (location=None)
├── player "jared" (location=overworld, x=50, y=30)
│ ├── sword (location=jared) ← inventory
│ └── backpack (location=jared) ← inventory
│ ├── gem (location=backpack) ← nested
│ └── potion (location=backpack)
├── oak tree (location=overworld, x=50, y=31) ← fixture
└── portal (location=overworld, x=52, y=30) ← leads to tavern zone
tavern zone (location=None)
├── bartender mob (location=tavern, x=3, y=2)
├── chair (location=tavern, x=1, y=1) ← fixture
└── mug (location=tavern, x=3, y=3) ← item on the floor
``contents`` is the reverse query — "give me everything whose location is me."
spatial position (x, y) is optional. objects in zones have coordinates. items
in inventory don't. a sword in your backpack has location=backpack, x=None,
y=None.
the hierarchy
-------------
::
Object (name, location, x, y) ← @verb targets this
├── Zone (width, height, toroidal, terrain)
├── Entity (combat stats)
│ ├── Player (session stuff)
│ └── Mob (ai stuff)
├── Thing (description, portable)
│ ├── Container (capacity, closed, locked)
│ └── Portal (target_zone, target_x, target_y)
└── (Exit — maybe, if portals don't cover it)
**Object**
base class for everything in the world. has name, location (Object or
None), optional x/y for spatial position within location. the @verb
decorator targets this — anything can have verbs. defines ``can_accept(obj)``
method (default: False) for controlling what can be placed inside.
**Zone**
a spatial area with a grid. the overworld, a tavern interior, a pocket
dimension. location=None (top-level). has terrain, dimensions, toroidal
flag. ``can_accept`` returns True (zones accept everything). defines
``contents_at(x, y)`` for spatial queries.
**Entity**
something that fights. adds combat stats (PL, stamina, defense timing).
``can_accept`` allows portable Things (inventory).
**Player**
a connected human. adds writer, mode_stack, caps, editor, if_session.
subclass of Entity.
**Mob**
AI-controlled entity. adds moves list, behavior. subclass of Entity.
**Thing**
an interactive object. adds description, portable flag. the @thing
decorator targets this for spawnable templates.
**Container**
a Thing that explicitly accepts contents. adds capacity, closed, locked
state. game-facing behaviors (open/close, lock/unlock, put/get).
**Portal**
a Thing that connects zones. adds target_zone, target_x, target_y.
portable=False.
**Exit**
not needed yet. portals + zone grids might cover all transitions. parked
until we discover it's necessary.
note: Fixture was considered as a class but we just use
``Thing(portable=False)`` instead. no shared behavior that warrants a class.
containment mechanics
---------------------
the containment MECHANISM is on Object (any object can technically be a
location via the location pointer). but the GAME restricts it via
``can_accept()``:
- Zone: accepts everything
- Entity: accepts portable Things (inventory)
- Container: accepts items up to capacity, if not closed
- Thing: rejects by default (can't put a sword inside another sword)
- Object base: rejects by default
this means containment is a capability, not a class. follows the Evennia/LPC
pattern. the Container class just bundles the common container game behaviors
— it's not special from a tree perspective.
location=None
-------------
three things have location=None:
1. **zones** — they're top-level containers. the overworld, tavern zone, etc.
2. **templates/prototypes** — things that exist but aren't placed anywhere yet.
a mob template, an item blueprint. they're in code or data files but not
spawned into the world.
3. **despawned objects** — removed from the world but not deleted. a mob dies
and goes back to location=None until respawn.
this is first-class. a mob template at location=None is the prototype. spawn
it = clone with location=zone. dies = back to location=None until respawn.
no special flags needed, just the natural state.
verbs on everything
-------------------
@verb targets Object, not Thing. everything in the world can have verbs:
- "pet" a mob (verb on Entity)
- "open" a chest (verb on Container)
- "drink from" a fountain (verb on Thing with portable=False)
- "dig" in a zone (verb on Zone)
- "high-five" a player (verb on Entity)
the verb system doesn't care about the class hierarchy. if it's an Object and
has a verb registered, players can use it.
how existing code maps in
--------------------------
Entity(name, x, y) → Entity(name, location=zone, x=5, y=10)
entities gain a location field. x/y stay but become relative to location.
Player/Mob → same, just gains location field from Object parent
existing code largely unchanged. location replaces implicit zone references.
overworld terrain grid → becomes a Zone object
the procedural perlin overworld becomes a Zone instance. toroidal, with
generator=perlin.
planned zones (tavern, tutorial) → each a Zone object
hand-built zones like the treehouse. bounded or toroidal, tile data from
TOML files.
planned portals → Portal things inside zones
portals are objects with target_zone, target_x, target_y. live inside zones
like any other Thing.
@thing PepsiCan from things-and-building doc → Thing subclass
same as planned. @thing decorator creates Thing templates. spawn them into
zones or player inventory.
combat encounters → still between Entities, unchanged
combat operates on the Entity subgraph. location doesn't matter for combat
resolution, only proximity (same zone, nearby x/y).
IF sessions → still on Player, unchanged
if_session lives on Player. the IF subprocess doesn't care about location.
mode stack → still on Player, unchanged
mode_stack is a Player concern. doesn't interact with the object tree.
the migration is gentle. Entity gains a location field and x/y become
optional (None when inside a non-spatial container like a backpack).
what this enables
-----------------
- **inventory** — put sword in backpack, backpack in player. nested
containment via location pointers.
- **items on the ground** — sword at location=zone, x=5, y=10. visible to
anyone at those coordinates.
- **furniture and fixtures** — Thing with portable=False. a fountain, a tree,
a statue. stays put, but can have verbs.
- **containers** — chests, bags, locked doors. Container subclass handles
capacity, closed, locked state.
- **zone transitions** — portals as objects. step on portal tile, location
changes to target zone.
- **mob templates and spawning** — location=None is the template. spawn =
clone with location=zone. dies = back to None.
- **verb-driven interaction on anything** — pet the cat, read the sign, dig
the ground. @verb on Object means no restrictions.
- **the "phone switch" navigation zone** — a zone full of portals. walk to
a portal, step through, appear in that world. the hub.
open questions (parked)
-----------------------
- **equipment slots** (wield, wear) — additive later when combat needs it. do
we track worn/wielded separately from inventory, or is it just metadata on
the Thing? defer until combat design demands it.
- **Exit class** — may not be needed. portals might cover it. if we discover
a need for one-way passages with different behavior than portals, revisit.
- **persistence** — which objects persist to SQLite, which are runtime-only?
player inventory persists. zone state (tile changes from paint mode)
persists to TOML. mob instances probably don't persist (respawn from
templates). decide per-class as we implement.
- **object registry implementation** — global dict? spatial index? contents
cache? probably: zones maintain contents_at(x, y) lookups, global registry
maps object IDs to instances for verb resolution.
related docs
------------
- ``things-and-building.rst`` — @thing/@verb decorator system, content layer
on top of this model
- ``zones-and-building.rst`` — zone data format, building tools, paint mode
- ``architecture-plan.txt`` — overall engine/content boundary
- ``combat.rst`` — combat system (operates on Entity subgraph)

View file

@ -7,7 +7,7 @@ WHAT'S PERSISTED
Player accounts:
- Username (case-insensitive)
- Password (hashed with PBKDF2-HMAC-SHA256 and random salt)
- Position (x, y coordinates)
- Position (zone, x, y — see object-model.rst for location system)
- Combat stats (pl, stamina, max_stamina)
- Flying status
- Created timestamp
@ -53,6 +53,21 @@ WHEN SAVES HAPPEN
The periodic auto-save runs in the game loop alongside combat and effects
processing. It only triggers if at least one player is connected.
WHAT'S NOT YET PERSISTED
The object model (object-model.rst) introduces containment, inventory, and
zones. Persistence for these is an open question:
- Player inventory (Things with location=player)
- Item instances on the ground (Things with location=zone)
- Container state (open/closed/locked, contents)
- Zone edits from paint mode (tile changes)
- Mob respawn state
These will be addressed as each system gets implemented. Player inventory
will likely go in SQLite alongside account data. Zone edits will persist to
TOML files. Mob instances probably don't persist (respawn from templates).
IMPLEMENTATION NOTES
Password hashing:

View file

@ -1,7 +1,9 @@
project documentation
=====================
all project docs, grouped by topic.
reading guide: start with DREAMBOOK.md for vision, then architecture-plan.txt
for the big picture, then object-model.rst for the core data model. everything
else builds on those three.
vision
------
@ -13,12 +15,17 @@ vision
engine
------
- ``docs/how/architecture-plan.txt`` — engine/content boundary, mode stack, entity model, game loop
read architecture-plan first (big picture), then object-model (core hierarchy).
zones/things build on object-model. commands/terrain/persistence/prompt are
mostly standalone subsystems.
- ``docs/how/architecture-plan.txt`` — engine/content boundary, mode stack, entity model, game loop (start here)
- ``docs/how/object-model.rst`` — object hierarchy, containment, verbs, location system (core data model)
- ``docs/how/zones-and-building.rst`` — zones as spatial unit, procedural overworld, player homes (builds on object-model)
- ``docs/how/things-and-building.rst`` — interactive objects, python class decorators (builds on object-model)
- ``docs/how/commands.txt`` — command registration, async handlers, aliases, mode filtering
- ``docs/how/persistence.txt`` — SQLite storage, what's persisted vs runtime
- ``docs/how/terrain-generation.txt`` — perlin noise, elevation thresholds, river tracing
- ``docs/how/things-and-building.rst`` — interactive objects, python class decorators
- ``docs/how/zones-and-building.rst`` — zones as spatial unit, procedural overworld, player homes
- ``docs/how/persistence.txt`` — SQLite storage, what's persisted vs runtime
- ``docs/how/prompt-system.txt`` — modal prompts, color markup, per-player customization
combat
@ -29,7 +36,10 @@ combat
interactive fiction
-------------------
- ``docs/how/if-journey.rst`` — master IF doc: five integration levels, audit findings, milestones
if-journey.rst is the master doc. everything else is supporting material
(audits, implementation details, performance work, design plans).
- ``docs/how/if-journey.rst`` — master IF doc: five integration levels, audit findings, milestones (start here)
- ``docs/how/if-terminal.txt`` — level 1: dfrotz subprocess, spectator broadcasting
- ``docs/how/if-integration.txt`` — original IF research (predates audits)
- ``docs/how/viola-embedding-audit.rst`` — viola interpreter audit