Commit graph

67 commits

Author SHA1 Message Date
d8cd880b61
Add sleep command for deep rest recovery 2026-02-14 01:00:37 -05:00
36fcbecc12
Block quit command during combat 2026-02-14 01:00:37 -05:00
292557e5fd
Add power up/down commands
Implements power level management system with tick-based power-up loop.
Players can raise PL toward max_pl (costs stamina per tick), lower PL
instantly, set exact PL targets, and cancel ongoing power-ups.
2026-02-13 23:01:33 -05:00
593bfd3028
Add prompt command for customization 2026-02-13 22:48:59 -05:00
780501ceed
Add render_prompt with modal templates 2026-02-13 22:48:59 -05:00
525b2fd812
Refactor look command to use structured room display
- 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
2026-02-13 22:20:48 -05:00
b63b054997
Show entities at player position beneath the map
Adds a "Here: goblin, Ally" line after the map grid listing mobs and
other players sharing the tile. Dead mobs are excluded.
2026-02-12 17:00:19 -05:00
4cff1475c3
Remove player from zone contents on disconnect
Player objects were removed from the players dict on quit/disconnect
but never removed from zone._contents, leaving ghost * markers on
other players' maps.
2026-02-12 16:41:04 -05:00
aeb3d31702
Add client command to show protocol and terminal info 2026-02-12 15:58:54 -05:00
e247d70612
Send Char.Status on combat end and rest state changes 2026-02-11 23:13:14 -05:00
e9f70ebd2f
Send Char.Vitals on combat resolution and rest completion 2026-02-11 23:13:14 -05:00
889a0d7bcf
Add paint mode for terrain editing 2026-02-11 22:38:14 -05:00
d6920834c8
Add auto-trigger portal on movement 2026-02-11 22:38:14 -05:00
d2de6bdc16
Add use command for verb-based interaction
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.
2026-02-11 21:47:33 -05:00
9534df8f9c
Add examine command for object inspection
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.
2026-02-11 21:47:33 -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
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
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
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
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
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
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
602da45ac2
Fix IF bugs: case-insensitive story lookup, double prompt, phantom restore command
- _find_story() now compares path.stem.lower() so "lostpig" matches "LostPig.z8"
- Server no longer writes its own prompt in IF mode (game handles prompting)
- Suppress phantom game output on restore (saved PC past sread causes garbage)
- Route .z5/.z8 files to EmbeddedIFSession now that V5+ is supported
2026-02-10 14:16:19 -05:00
15e1d807aa
Move z-machine restore before interpreter thread start
Replaces the async _do_restore() (called after thread launch) with a
synchronous _try_restore() called before the thread starts. This
eliminates the race condition where restore mutates z-machine state
while the interpreter thread is running.

The restore prefix message is now part of start()'s return value
instead of being sent separately in play.py.
2026-02-10 11:51:45 -05:00
7c1d1efcdb
Wire embedded z-machine interpreter into MUD mode stack
EmbeddedIFSession runs the hybrid interpreter in a daemon thread,
bridged to the async MUD loop via threading.Event synchronization.
.z3 files use the embedded path; other formats fall back to dfrotz.

- MUD ZUI components: MudScreen (buffered output), MudInputStream
  (thread-safe input), MudFilesystem (quetzal saves), NullAudio
- save/restore via QuetzalWriter/QuetzalParser and :: escape commands
- state inspection: get_location_name(), get_room_objects()
- error reporting for interpreter crashes
- fix quetzal parser bit slice bug: _parse_stks used [0:3] (3 bits,
  max 7 locals) instead of [0:4] (4 bits, max 15) — Zork uses 15
2026-02-10 11:18:16 -05:00
57afe9a3ce
Wire restore into play command
When starting an IF game, check for existing save file and restore
if present. Shows 'restoring saved game...' message and broadcasts
restored game state to spectators.

Also cleaned up redundant tests that didn't properly mock the
auto-save functionality now present in ::quit and stop().
2026-02-09 16:39:15 -05:00
057a746687
Wire up spectator broadcasting in server and play command
- server.py: broadcast IF output to spectators after each input (skip :: escape commands)
- server.py: broadcast leave message when player exits IF mode
- play.py: broadcast game intro text when player starts a game

Spectators at the same x,y coordinates now see formatted output with
[PlayerName's terminal] header and game text.
2026-02-09 16:25:39 -05:00
3dd095b9ea
Add broadcast_to_spectators helper
Helper function sends messages to all players at the same x,y coordinates
as the source player, skipping the source player themselves. Used for IF
spectator broadcasting.
2026-02-09 16:24:48 -05:00
c246732b86
Add mention of ::help 2026-02-09 16:14:34 -05:00
bc69f46d1a
List stories when cannot find 2026-02-09 16:14:21 -05:00
6308248d14
Fix IF session cleanup on failure and player disconnect 2026-02-09 16:11:28 -05:00
b133f2febe
Add play command for starting interactive fiction games 2026-02-09 16:10:29 -05:00
af941b329b
Add spawn command and wire mobs into server
Phase 6: spawn command creates mobs at player position from loaded
templates. Server loads mob templates from content/mobs/ at startup,
injects world into combat/commands module, and runs process_mobs()
each game loop tick after process_combat().
2026-02-09 11:54:29 -05:00
ca53357730
Render mobs as * in viewport
Phase 3: look command now collects alive mob positions using the same
wrapping-aware relative position calc as players, and renders them as *
with the same priority as other players (after @ but before effects).
2026-02-09 11:54:29 -05:00
f36085c921
Add rest command for stamina recovery 2026-02-08 22:16:47 -05:00
9c1c6a9e22
Add description field to CombatMove dataclass 2026-02-08 14:32:51 -05:00
77c2e40e0e
Add reload command for hot-reloading TOML content 2026-02-08 14:32:51 -05:00
37766ad69f
Fix typecheck errors in prefix disambiguation 2026-02-08 13:50:26 -05:00
68fa08d776
Extract shared prefix matching helper 2026-02-08 13:48:00 -05:00
7c21310dcd
Remove alias display from command and skill listings 2026-02-08 13:42:00 -05:00
7ae56106d6
Update tests for alias removal 2026-02-08 13:39:58 -05:00
20f33f45e1
Implement standalone help command 2026-02-08 13:33:46 -05:00
7d3b02f6ff
Implement collision detection in register 2026-02-08 13:33:19 -05:00
529320acb5
Split commands and skills into separate listings 2026-02-08 13:15:04 -05:00
9e5003e52c
Hide variant aliases from commands listing 2026-02-08 13:04:54 -05:00