Commit graph

64 commits

Author SHA1 Message Date
05afff9538
Add is_admin column with first-account-is-admin migration 2026-02-14 19:21:37 -05:00
11636e073a
Add craft and recipes commands
Implements craft command to create items from recipes by consuming
ingredients from player inventory. Recipes command lists available
recipes or shows details for a specific recipe. Registers commands
and loads recipes at server startup.
2026-02-14 17:58:59 -05:00
7342a70ba2
Add furnish and unfurnish commands 2026-02-14 17:58:47 -05:00
5b6c808050
Add describe command for home zone descriptions
Allows players to set custom descriptions for their home zones.
Only works in the player's own home zone. Saves to TOML file.
2026-02-14 17:58:47 -05:00
acfff671fe
Wire character creation and housing into server login flow 2026-02-14 17:17:36 -05:00
32c570b777
Update roadmap to split furniture and crafting into phase 18 2026-02-14 17:17:36 -05:00
0f3ae87f33
Add description and home_zone fields to player and database 2026-02-14 17:17:36 -05:00
4d44c4aadd
Add librarian NPC with integration tests
Create librarian mob template as a non-combatant NPC with:
- dialogue tree linking (npc_name field)
- time-based schedule (working 7-21, idle otherwise)
- empty moves list (cannot fight)

Wire dialogue tree loading into server startup to load from content/dialogue/.

Add npc_name field to MobTemplate and spawn_mob to preserve dialogue tree links.

Integration tests verify:
- spawning from template preserves npc_name and schedule
- full conversation flow (start, advance, end)
- converse state blocks movement
- schedule transitions change behavior state
- working state blocks movement
- patrol behavior follows waypoints
2026-02-14 14:31:39 -05:00
52f49104eb
Add NPC schedule system with game time
Implements time-based behavior transitions for NPCs:
- GameTime converts real time to game time (1 real min = 1 game hour)
- ScheduleEntry defines hour/state/location/data transitions
- NpcSchedule manages multiple entries with midnight wrapping
- process_schedules() applies transitions when game hour changes
- TOML support for schedule data in mob templates
- Integrated into game loop with hourly checks

Tests cover schedule transitions, game time calculation, TOML loading, and preventing duplicate processing.
2026-02-14 14:31:39 -05:00
75da6871ba
Add mob pathfinding back to home region
Mobs with home regions now pathfind back when they've strayed. Each tick,
process_mob_movement() checks all mobs and moves them one tile toward their
home region center using Manhattan distance. Movement is throttled to 3
seconds, respects impassable terrain, skips mobs in combat, and broadcasts
to nearby players.
2026-02-14 12:39:48 -05:00
a398227814
Add player stats model and persistence
kills, deaths, mob_kills dict, play_time_seconds, unlocked_moves set
on Player. New player_stats SQLite table with save/load functions.
2026-02-14 11:40:45 -05:00
7ec5ccb87a
Set overworld zone description so "Where:" header displays correctly 2026-02-14 10:45:39 -05:00
56169a5ed6
Add corpse decomposition system with active_corpses registry
process_decomposing removes expired corpses and broadcasts messages
to entities at the same tile. Registered in game loop.
2026-02-14 10:02:33 -05:00
3f042de360
Add player alias system with persistence and dispatch
Implements a complete alias system allowing players to create command shortcuts.
Aliases are expanded during dispatch with a recursion guard (max 10 levels).

Changes:
- Add aliases field to Player dataclass (dict[str, str])
- Add player_aliases table to database schema
- Add save_aliases() and load_aliases() persistence functions
- Add alias/unalias commands with built-in command protection
- Integrate alias expansion into dispatch() before command resolution
- Add comprehensive test coverage for all features
2026-02-14 01:39:45 -05:00
b4dea1d349
Add unconscious state with automatic recovery
Players become unconscious when PL or stamina drops to 0. While unconscious, both stats slowly recover at 0.1 per tick (1.0 per second). When both reach above 0, player regains consciousness with a message. Recovery runs in the main game loop via process_unconscious.
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
72b877c5d1
Send GMCP Char.Vitals after each command 2026-02-13 22:48:59 -05:00
4930f1408b
Wire render_prompt into server shell loop 2026-02-13 22:48:59 -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
bd5f83e890
Skip empty lines during name prompt and fix tintin send syntax
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.
2026-02-12 16:24:37 -05:00
aafdcdca42
Move GMCP/MSDP offers to initial negotiation
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.
2026-02-12 16:24:37 -05:00
05b377f00a
Add debug logging for GMCP/MSDP negotiation offers 2026-02-12 16:24:37 -05:00
ee0dc839d8
Offer GMCP/MSDP during connection and guard tick sends
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.
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
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
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
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
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
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
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
b81bc3edc8
Add consistent > prompt for IF mode in server loop 2026-02-10 17:50:35 -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
108091bfae
Add blank line before IF mode prompt to match dfrotz 2026-02-09 17:55:14 -05:00
f8e9ae0acc
Add spacing between IF session exit messages 2026-02-09 17:55:14 -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
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
dc342224b1
Wire IF mode into server shell loop and player model 2026-02-09 15:57:24 -05:00
6fd19d769b
Add a docker container solution 2026-02-09 12:34:56 -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
f36085c921
Add rest command for stamina recovery 2026-02-08 22:16:47 -05:00
77c2e40e0e
Add reload command for hot-reloading TOML content 2026-02-08 14:32:51 -05:00
6fb48e9ae1
Add commands command to list available commands 2026-02-08 12:35:50 -05:00
9054962f5d
Add combat resolution messages with both-POV feedback
resolve() returns ResolveResult dataclass with attacker_msg, defender_msg,
damage, countered, and combat_ended fields. process_combat is now async
and sends messages to both participants on resolve. Counter, hit, and
slam messages give each player their own perspective on what happened.
2026-02-08 12:28:17 -05:00
a799b6716c
Add editor mode shell integration and edit command
Integrates the Editor class into the MUD server's shell loop, allowing
players to enter and use the text editor from the game.

Changes:
- Add editor field to Player dataclass
- Modify shell input loop to check player mode and route to editor
- Add edit command to enter editor mode from normal mode
- Use inp (not command.strip()) for editor to preserve indentation
- Show line-numbered prompt in editor mode
- Pop mode and clear editor when done=True
- Add comprehensive integration tests
- Fix test isolation issue in test_movement_updates_position
2026-02-07 22:59:37 -05:00