Commit graph

361 commits

Author SHA1 Message Date
4ec09cffda
Improve doc discovery 2026-02-11 21:47:05 -05:00
7d4a75f973
Show portals in look output
Look command now displays portals separately from ground items.
Portals at the player's position are shown after ground items with
the format "Portals: name1, name2". This separates portals from
regular items since they serve a different purpose in gameplay.
2026-02-11 20:58:55 -05:00
aa720edae5
Add enter command for portal zone transitions
Implements portal-based zone transitions with the enter command.
Players can enter portals at their position to move to target zones
with specified coordinates. Includes departure/arrival messaging to
nearby players and automatic look output in the destination zone.
Portals are matched by partial name or exact alias match.
2026-02-11 20:58:55 -05:00
557fffe5fa
Add put and take-from commands for containers 2026-02-11 20:58:55 -05:00
68161fd025
Add container support to thing template loader
Extended ThingTemplate with optional container fields (capacity, closed, locked).
When a template includes capacity, spawn_thing now creates a Container instead
of a regular Thing.

Added two example container templates:
- chest.toml: non-portable, capacity 5, starts closed
- sack.toml: portable, capacity 3, starts open
2026-02-11 20:58:55 -05:00
3be4370b2f
Show container state in look and inventory display
Containers now display their state when viewed:
- Closed containers show "(closed)"
- Open empty containers show "(open, empty)"
- Open containers with items show "(open, containing: item1, item2)"

This applies to both ground items in the look command and inventory items.
Added _format_thing_name helper to both look.py and things.py to handle
the display formatting consistently.
2026-02-11 20:58:55 -05:00
d18f21a031
Add zone TOML loader and tavern interior zone
Implements load_zone() and load_zones() functions to parse zone
definitions from TOML files. Wires zone loading into server startup
to register all zones from content/zones/ directory. Updates player
zone lookup to use the registry instead of hardcoded overworld check.

Includes tavern.toml as first hand-built interior zone (8x6 bounded).
2026-02-11 20:58:55 -05:00
5b9a43617f
Add open and close commands for containers 2026-02-11 20:58:55 -05:00
b3471a8b94
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.
2026-02-11 20:40:31 -05:00
303ce2c89e
Add Portal class with target zone and coordinates
Portals are non-portable Things that exist in zones and define
transitions to other zones via target coordinates.
2026-02-11 20:38:47 -05:00
621c42b833
Add Container class with capacity and open/closed state 2026-02-11 20:38:40 -05:00
05a739da74
Add test for duplicate item persistence 2026-02-11 20:29:59 -05:00
8acfa5ea22
Wire thing templates and inventory into server startup
Loads thing templates from content/things/ at startup. Registers
get/drop/inventory commands via things module import. Reconstructs
player inventory from saved template names on login, with graceful
fallback for unknown templates.
2026-02-11 20:29:59 -05:00
6081c90ad1
Add inventory persistence to player saves
Inventory saved as JSON list of thing template names in an inventory
column. Migration adds column to existing databases. load_player_data
returns inventory list, save_player serializes Thing names from contents.
2026-02-11 20:29:58 -05:00
c43b3346ae
Add Thing templates, TOML loading, and spawning
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.
2026-02-11 20:01:15 -05:00
2e79255aec
Show ground items in look command
After the viewport, look lists Things at the player's position
in a "On the ground: item1, item2" line. No output when empty.
2026-02-11 20:01:10 -05:00
e96fd50de5
Add inventory command with alias "i"
Lists Thing objects in player.contents with 2-space indented format.
Shows "You aren't carrying anything." when inventory is empty.
2026-02-11 20:01:05 -05:00
7c12bf3318
Add Object.move_to(), get and drop commands
Object.move_to() handles containment transfer: removes from old location's
contents, updates location pointer and coordinates, adds to new location.
get/drop commands use move_to to transfer Things between zone and inventory.
Supports name and alias matching for item lookup.
2026-02-11 19:57:38 -05:00
9437728435
Add Thing class and Entity.can_accept() for inventory
Thing is an Object subclass with description, portable flag, and aliases.
Entity.can_accept() returns True for portable Things, enabling the
containment model where entities carry items in their contents.
2026-02-11 19:55:58 -05:00
957a411601
Clean up global state, migrate broadcast_to_spectators to Zone
Removes dependency on global players dict for spatial queries by using
Zone.contents_at() for spectator lookup. Makes _world local to run_server()
since it's only used during initialization to create the overworld Zone.
Updates test fixtures to provide zones for spatial query tests.
2026-02-11 19:42:12 -05:00
f5646589b5
Migrate look to use player.location (Zone)
- Removed world module-level variable from look.py
- look.cmd_look() now uses player.location.get_viewport() instead of world.get_viewport()
- look.cmd_look() uses zone.contents_near() to find nearby entities instead of iterating global players/mobs lists
- Wrapping calculations use zone.width/height/toroidal instead of world properties
- Added type check for player.location being a Zone instance
- Removed look.world injection from server.py
- Updated all tests to remove look.world injection
- spawn_mob() and combat commands also migrated to use Zone (player.location)
- Removed orphaned code from test_mob_ai.py and test_variant_prefix.py
2026-02-11 19:36:46 -05:00
1349c2f860
Add zone_name to persistence schema
Adds zone_name field to PlayerData and accounts table to track which
zone a player is in. Defaults to 'overworld'. Includes migration logic
to handle existing databases without the column. Server now resolves
zone from zone_name when loading player data.
2026-02-11 19:33:23 -05:00
875ded5762
Migrate fly to use player.location (Zone)
Removed module-level world variable and replaced all world.wrap() calls
with player.location.wrap(). Added Zone assertion for type safety,
matching the pattern in movement.py. Updated tests to remove fly.world
injection since it's no longer needed.
2026-02-11 19:33:15 -05:00
404a1cdf0c
Migrate movement to use player.location (Zone)
Movement commands now access the zone through player.location instead of
a module-level world variable. send_nearby_message uses
zone.contents_near() to find nearby entities, eliminating the need for
the global players dict and manual distance calculations.

Tests updated to create zones and add entities via location assignment.
2026-02-11 19:28:27 -05:00
66c6e1ebd4
Create overworld Zone at startup, set player.location 2026-02-11 19:19:15 -05:00
6f58ae0501
Add contents_near() spatial query to Zone 2026-02-11 19:17:17 -05:00
b4fca95830
Add Zone class with terrain, spatial queries, and viewport
Zone(Object) is a spatial area with a terrain grid. Supports
toroidal wrapping and bounded clamping, passability checks,
viewport extraction, and contents_at(x, y) spatial queries.
Zones are top-level containers (location=None) that accept
everything via can_accept().
2026-02-11 19:08:30 -05:00
51dc583818
Make Entity inherit from Object
Entity gains location from Object and narrows x/y back to int
(entities always have spatial coordinates). No behavioral change —
all existing tests pass unchanged.
2026-02-11 18:40:35 -05:00
d9e9d1b785
Add Object base class with containment primitives
Object provides name, location, x/y, contents reverse-lookup, and
can_accept() — the foundation for the containment tree that zones,
things, and inventory will build on.
2026-02-11 18:40:31 -05:00
9671f3c286
Add a roadmap outline 2026-02-11 18:21:43 -05:00
544b7dfee1
Add reading guide to index and refresh stale references 2026-02-11 16:19:34 -05:00
400ebe4275
Add object model design doc 2026-02-11 12:12:30 -05:00
94a01186c8
Add a doc index 2026-02-11 09:39:48 -05:00
da809bea31
Add zones and building doc 2026-02-10 22:48:44 -05:00
01d5848178
Add prompt system design doc 2026-02-10 19:07:32 -05:00
74538756d5
Handle object 0 (nothing) gracefully in object parser
Per the Z-machine spec, object 0 means "nothing" and operations on it
should be safe no-ops: get_child/get_sibling/get_parent return 0,
test_attr returns false, set/clear_attr are no-ops, etc. Previously
these threw ZObjectIllegalObjectNumber, crashing on games like Curses
that pass object 0 to get_child during room transitions.
2026-02-10 18:32:36 -05:00
5a98adb6ee
Add instruction tracing to step_fast and improve error messages
step_fast() never recorded trace entries, so crash dumps always showed
an empty trace. Now records PC + opcode info in the same deque as
step(). Also includes exception type in player-facing error messages
when the exception string is empty.
2026-02-10 18:29:27 -05:00
c8d9bdfae9
Map empty Enter to ZSCII 13 in read_char
MudInputStream.read_char() returned 0 for empty input, which no game
recognizes as a valid keypress. Now returns 13 (Enter/Return) so
"press any key" prompts like Curses' intro work from a MUD client.
2026-02-10 18:26:41 -05:00
fd977b91a2
Guard bare > stripping with has_prompt check 2026-02-10 17:53:11 -05:00
b81bc3edc8
Add consistent > prompt for IF mode in server loop 2026-02-10 17:50:35 -05:00
ac1d16095e
Strip trailing > prompt from embedded z-machine output 2026-02-10 17:50:06 -05:00
909ee0932b
Replace deprecated chunk module with inline IFF parser
The chunk module was deprecated in 3.11 and removed in 3.13.
Our usage was minimal (read name, size, data, skip padding),
so a small _read_iff_chunk() helper replaces it with no deps.
2026-02-10 17:20:01 -05:00
3140a4d617
Add return_addr to ZStackBottom for uniform frame access
ZStackBottom already had stack and local_vars for uniform treatment,
but was missing return_addr. Adding it removes 5 type: ignore
suppressions and fixes all ty possibly-missing-attribute warnings.
2026-02-10 17:16:25 -05:00
e72f13e78a
Add provenance documentation for test story files 2026-02-10 17:10:29 -05:00
6d7b404365
Add pytest regression harness for z-machine game compatibility
Implements Phase 4 of the z-machine compatibility plan.

Creates automated regression tests that smoke-test all supported games
(V3, V5, V8) by loading each story, executing basic commands, and verifying
the interpreter doesn't crash.

Key features:
- Parametrized test covering 7 games (zork1, curses, photopia, Tangle,
  shade, LostPig, anchor)
- QuietScreen class that disables [MORE] prompts for unattended testing
- AutoInputStream that auto-feeds commands then exits cleanly
- Tests verify: no crashes, unimplemented opcodes, and minimum instruction count
- All tests pass in ~2 seconds

Tests skip gracefully if story files aren't present, making this safe to
run in CI or on systems without all game files.
2026-02-10 17:10:29 -05:00
6d29ec00fb
Implement stub opcodes for game compatibility
set_colour, piracy, erase_line, get_cursor, not_v5, print_table
2026-02-10 17:10:29 -05:00
b08ce668a6
Add smoke test script for z-machine game compatibility 2026-02-10 17:10:04 -05:00
243a44e3fb
Add plan for zvm compatability 2026-02-10 16:50:23 -05:00
bc1a2e5489
Add undo command support 2026-02-10 16:49:46 -05:00
8288b2535a
Add multiplayer zmachine design notes 2026-02-10 16:09:33 -05:00