- Add Where: header with zone description
- Add Location: line with quadrant and coordinates
- Add Nearby: line showing entities in viewport (not on player's tile)
- Add Exits: line showing available cardinal directions
- Replace 'Here:' with individual entity lines showing posture
- Replace 'Portals:' with individual 'You see {name}.' lines
- Add look <thing> routing to examine command
- Add comprehensive tests for new structured output
- Update existing tests to match new output format
Player objects were removed from the players dict on quit/disconnect
but never removed from zone._contents, leaving ghost * markers on
other players' maps.
Player objects were removed from the players dict on quit/disconnect
but never removed from zone._contents, leaving ghost * markers on
other players' maps.
The server now skips spurious empty lines from client negotiation bytes
during the name prompt, only closing on actual connection loss. This
makes the login flow robust against clients that send IAC bytes with
trailing CRLF during negotiation.
Also fixed tintin++ CATCH handlers to use proper \} syntax matching the
documented examples.
The old begin_advanced_negotiation relied on a telnetlib3 hook that races with the negotiation timer — by the time it fires, the timer has already declared negotiation complete. Moving to begin_negotiation sends the offers alongside standard options (TTYPE, NAWS, ECHO) so clients see them immediately.
The server never proactively offered GMCP or MSDP to clients, so
telnetlib3 logged "cannot send MSDP without negotiation" every second.
Now the server sends WILL GMCP and WILL MSDP on connection, and
send_msdp_vitals checks negotiation state before attempting to send.
Implements Phase 7 foundation:
- gmcp.py module with package builders for Char.Vitals, Char.Status,
Room.Info, Room.Map, and MSDP vitals
- Player helper methods send_gmcp() and send_msdp() for convenience
- Full test coverage for all GMCP/MSDP functions and edge cases
Zones can now define spawn rules in TOML:
- [[spawns]] sections specify mob type, max count, and respawn timer
- SpawnRule dataclass stores configuration
- load_zone() parses spawn rules from TOML
- Added example spawn rules to treehouse zone (squirrel, crow)
This is configuration infrastructure only - actual spawning logic
will be handled by the game loop in a future phase.
Implements the new player funnel with two tutorial zones:
- Flower: 7x7 sealed zone with translucent petals, spawn at center
- Treehouse: 20x15 platform zone with rope ladder and branch exits
Both zones are bounded (non-toroidal) and include portals for progression.
Zone TOML files can now define portals using [[portals]] sections.
Each portal specifies coordinates (x, y), a target (zone_name:x,y),
and a label. Optional aliases are supported. Portals are
automatically created and placed in the zone when it loads.
Thing templates can now define verbs in TOML using [verbs] section with
module:function references. Verbs are resolved at spawn time and bound
to the spawned object instance using functools.partial. Works for both
Thing and Container instances.
Implements unlock_handler that checks for a key in player inventory
and unlocks containers. Tests cover error cases (non-container,
not locked, no key), success case, key aliasing, and state preservation.
Implements a TDD-built 'use' command that lets players invoke
object verbs with optional targets:
- use X - calls X's use verb
- use X on Y - calls X's use verb with Y as args
- Proper error messages for missing objects/verbs
- Tests cover all edge cases including inventory/ground search
Also fixes type checking issue in verb dispatch where get_verb
could return None.
Implements a global examine/ex command that shows detailed descriptions
of objects. Searches inventory first, then ground at player position.
Works with Things, Containers, and Mobs.