← All Workshops

MudEngine Part 9: The Twin Guardians

Congratulations!

You just added a two-player cooperative quest to the MUD engine!

What we achieved:

  • Quest data in game.toml — a [quest] section defines the guardian pedestals and reward passage alongside rooms and items
  • Dynamic room exits — exits that appear and disappear based on game state, managed at runtime by the server
  • Real-time quest broadcastingQuestEvent messages announce quest activation and deactivation to all players
  • Atomic quest logicupdate_quest() runs inside the GAME_STATE lock, evaluating conditions and mutating state atomically on every player move and disconnect
  • Safe deactivation — when the quest deactivates, players inside the vault are teleported back to Town Square
  • Quest UI — a quest panel shows guardian status (✅ active / ⏳ waiting) and action buttons for descending/ascending
  • Return path — the vault gets a return exit ("up" back to Town Square) when the portal opens

Architecture recap

                    ┌─────────────────────────────┐
                    │     game.toml [quest]       │
                    │  guardians: sun, moon       │
                    │  reward: room 4 → room 9    │
                    └─────────────┬───────────────┘
                                  │ load at startup
                                  ▼
                    ┌─────────────────────────────┐
                    │     GameState.quest         │
                    │  config + previously_active │
                    └─────────────┬───────────────┘
                                  │
              ┌───────────────────┼───────────────────┐
              ▼                   ▼                   ▼
        Player moves          Player leaves      Player disconnects
              │                   │                   │
              └───────────────────┼───────────────────┘
                                  ▼
                        update_quest() runs
                         inside the Mutex lock
                                  │
                    ┌─────────────┴─────────────┐
                    ▼                           ▼
              Add/remove exit              Broadcast QuestEvent
              to/from room 4 & 9           to all connected clients

What's next?

  • Quest persistence — save completed flag to game.toml so quest progress survives restarts
  • Multiple quests — a quest registry supporting many independent quests with different phases
  • Full NPC dialog trees — NPCs with multiple dialog lines, branching conversations, and quest giver logic
  • Timed quests — quests that must be completed within a time limit, with countdown UI
  • Quest items — items that only appear while a quest is active (spawned by quest events)
  • Boss encounters — a room with a monster that spawns when the quest activates
📚 What we learned
ConceptHow we used it
Quest config in TOML[quest] section with guardian rooms and reward definition, parsed into TomlQuest
Dynamic exitsRoom exits added/removed at runtime based on quest state; existing can_move picks them up automatically
Server-side quest evaluationupdate_quest() checks if all guardian rooms are occupied, transitions state atomically
Quest event broadcastingServerMessage::QuestEvent { active, message } announced to all clients on state change
Quest completion detectioncheck_quest_completion() fires when retrieval_item enters completion_room — checks both floor and inventory
Three-phase quest flowPhase 1: guardians open gate → Phase 2: hero retrieves item → Phase 3: item reaches King, quest won
NPC dialogKing Aldric's speech changes based on quest state — portal active, fragment in hand, or quest complete
Safe deactivationPlayers in the vault are teleported back to source room when guardians part
Client quest UIQuestDisplay signal driven by server state; shows guardian status, phase hints, and completion banner
Return pathVault gets a return exit ("up") when the portal opens, ensuring players can always leave
Two-player minimum for gatestate.players.len() >= 2 prevents a single player from activating both pedestals
Completed quest lockOnce completed = true, update_quest short-circuits — guardians can leave without penalty