MUD on Urbit

Urbit MUD Considerations

research Doc 06

Why Urbit for a MUD?

Natural Advantages

  1. Decentralized by default: No single server to maintain, pay for, or become a single point of failure. Each player’s ship IS their game client and can host game state.

  2. Built-in identity: @p addresses provide unique, persistent, unforgeable player identities. No account system needed — your Urbit IS your account. Identity is tied to reputation and social graph.

  3. Persistent state without external DB: Urbit’s noun-based state model persists automatically. A Gall agent’s state survives restarts natively. No need for MySQL, PostgreSQL, or flat file serialization.

  4. Networking is native: Ames provides encrypted, authenticated peer-to-peer communication. No need to manage TCP connections, TLS certificates, or authentication tokens.

  5. Composability: A MUD agent can interact with %groups for chat, %furum for forums/lore, or custom agents for external integrations. The MUD becomes part of the Urbit ecosystem, not an isolated silo.

  6. Self-hosting philosophy: Aligns perfectly with MUD culture — players own their data, their identity, and their experience.

Philosophical Alignment

MUDs and Urbit share DNA:

  • Both are text-first, command-driven interfaces
  • Both value ownership and persistence
  • Both attract communities that prefer depth over polish
  • Both are fundamentally about building digital spaces for human connection

Architecture Mapping

MUD Concept → Urbit Primitive

MUD ConceptUrbit EquivalentNotes
Player identity@p (ship address)Unique, persistent, cryptographic
Player connectionAmes subscriptionEncrypted P2P
Game serverGall agent on host shipOr distributed across ships
Game stateAgent state (noun)Persisted automatically
Command inputPoke (from client)JSON or custom mark
Game outputSubscription updates (facts)Pushed to subscribed clients
Game tick/timerBehn timerKernel-level timer service
Read-only queriesScryFast, no side effects
Chat/channels%channels or customReuse existing infra
World dataPart of agent state or separate agentDepends on scale

Gall Agent Structure for a MUD

A Gall agent has exactly ten arms:

|_  =bowl:gall
++  on-init       :: startup initialization
++  on-save       :: serialize state for upgrade
++  on-load       :: deserialize state after upgrade
++  on-poke       :: handle incoming commands (player actions!)
++  on-watch      :: handle subscription requests (player connects!)
++  on-leave      :: handle unsubscription (player disconnects!)
++  on-peek       :: handle scry requests (read game state!)
++  on-agent      :: handle responses from other agents
++  on-arvo       :: handle kernel responses (timers!)
++  on-fail       :: handle crash notifications
--

Game loop mapping:

  • on-poke: Player commands (move north, attack goblin, get sword)
  • on-watch: Player joins game / subscribes to room updates
  • on-leave: Player leaves game
  • on-peek: Client queries game state (room contents, inventory, stats)
  • on-arvo: Game tick timer fires → process combat rounds, regen, mob AI, resets

Potential Architectures

Option A: Centralized Host Ship

Host Ship (~your-ship)
├── %mud-engine (Gall agent)
│   ├── World state (rooms, mobs, items)
│   ├── Player state (stats, inventory, position)
│   └── Game logic (combat, quests, progression)
└── Players connect via Ames subscriptions
    ├── ~player-one subscribes to room updates
    ├── ~player-two subscribes to room updates
    └── Commands sent as pokes to host

Pros: Simple, consistent state, traditional MUD model Cons: Single point of failure, scaling limits, host bears all compute

Option B: Distributed World

Ship A hosts Continent 1 (areas 1-100)
Ship B hosts Continent 2 (areas 101-200)
Ship C hosts Continent 3 (areas 201-300)

Players:
├── Connect to the ship hosting their current area
├── "Zone transfer" = resubscribe when moving between continents
└── Character state lives on player's own ship

Pros: Scales horizontally, load distribution, area hosts can be different builders Cons: Complex state synchronization, cross-zone interactions (combat, chat), consistency challenges

Option C: Player-Hosted Characters

Each player's ship:
├── %mud-character (local agent)
│   ├── Character stats, inventory, progression
│   └── Local game client / UI
World host ship(s):
├── %mud-world (shared agent)
│   ├── Room state, mob state, item spawns
│   └── Validates player actions, resolves combat
│   └── Sends room updates to subscribed players

Pros: Players own their character data, distributes storage, natural backup Cons: Trust issues (how to prevent character stat cheating?), state sync complexity

Start with Option A (centralized host). It maps most directly to traditional MUD architecture and avoids distributed systems complexity while you’re building core gameplay.

Add distribution later — Urbit’s networking makes it relatively straightforward to split the world across ships once the core engine works.

Hoon/Nock Considerations

Data Structures for MUD Concepts

:: Room definition
+$  room
  $:  id=@ud
      name=@t
      description=@t
      sector=?(%city %forest %mountain %water %underground %indoor)
      exits=(map direction @ud)  :: direction → room-id
      contents=(set item-id)
      mobs=(set mob-id)
      players=(set @p)
      flags=(set room-flag)
  ==

:: Direction type
+$  direction  ?(%north %south %east %west %up %down)

:: Player character
+$  character
  $:  owner=@p
      name=@t
      race=race-type
      class=class-type
      level=@ud
      stats=stat-block
      hp=@ud
      max-hp=@ud
      mana=@ud
      max-mana=@ud
      moves=@ud
      max-moves=@ud
      inventory=(list item-id)
      equipment=(map wear-slot item-id)
      position=room-id=@ud
      experience=@ud
      gold=@ud
  ==

:: Stat block
+$  stat-block
  $:  str=@ud  int=@ud  wis=@ud
      dex=@ud  con=@ud  luck=@ud
  ==

Performance Considerations

Potential issues:

  • Game tick frequency: Behn timers have kernel-level overhead. Sub-second ticks may stress Arvo. Target 1-4 second ticks (standard for MUDs).
  • State size: Large world state (300+ areas × rooms × mobs × items) as a single noun could be unwieldy. Consider lazy loading or area segmentation.
  • Combat resolution: Per-round calculations are lightweight individually but multiply with concurrent fights.
  • Parser overhead: Command parsing in Hoon is natural (pattern matching on text) but complex natural-language parsing could be expensive.

Mitigations:

  • Keep game ticks at 2-4 second intervals (totally fine for MUDs)
  • Segment world state by area for efficient updates
  • Use scry for read-only operations (no state mutation overhead)
  • Pre-compute combat tables rather than calculating per-hit
  • Use threads for expensive operations (pathfinding, area resets)

Hoon Strengths for MUDs

  1. Pattern matching: Excellent for command parsing
  2. Immutable state: No race conditions in game logic
  3. Type system: Catches bugs at compile time (invalid room references, etc.)
  4. Persistent state: Agent state survives restarts without explicit save/load
  5. Kelvin versioning: Core stability guarantees

Hoon Challenges for MUDs

  1. Learning curve: Hoon is… Hoon. Builders/scripters won’t learn it casually
  2. String handling: Text manipulation in Hoon is verbose compared to Python/Lua
  3. Performance ceiling: Nock is not fast for compute-heavy operations
  4. Debugging: Hoon stack traces are legendary for their opacity
  5. Hot reloading: Updating a running agent requires careful state migration

Frontend Approaches

React/Sail frontend served by the ship’s HTTP server:

  • Rich HTML/CSS interface: room display, sidebar stats, clickable commands
  • WebSocket connection via Eyre for real-time updates
  • Can embed mapping, inventory management, equipment panels
  • Mobile-friendly
  • Reference: %groups and %furum both use this pattern

Option 2: Terminal Client

A terminal-based interface that connects to the ship:

  • Traditional MUD feel
  • Could use %shoe library for terminal agent interaction
  • ANSI colors, text formatting
  • Familiar to MUD veterans
  • Lower barrier to entry for Urbit users already in the terminal

Option 3: Telnet Bridge

Bridge traditional MUD clients (Mudlet, TinTin++) to Urbit:

  • Separate process: TCP telnet server ↔ Urbit pokes/subscriptions
  • Could implement GMCP, ANSI, etc. for full client compatibility
  • Lets existing MUD players connect without Urbit knowledge
  • Most complex option but widest reach

Option 4: Hybrid

Web UI as primary + telnet bridge for traditional clients. This is the ideal end state but not where you should start.

Integration Opportunities

With Existing Urbit Apps

  • %groups/%channels: Use for OOC communication, clan chat, game announcements
  • %furum: Game forums, lore posting, area guides, player-generated content
  • %pals: Social graph for friend lists, group-finding
  • Custom agents: Weather systems, economy simulators, world events

With External Systems

  • poke-remote-agent MCP tool: You already built this! Could enable external services to interact with the MUD (posting achievements, triggering events)
  • RSS feeds: Game news, update logs
  • Discord/Telegram bridges: Cross-platform communication for the community

Challenges and Risks

Technical Risks

RiskSeverityMitigation
State size growthMediumArea segmentation, pruning old data
Tick performanceLow-Medium2-4 sec ticks are fine; profile early
Player capacityMediumStart small, architect for distribution
Latency (Ames)LowP2P latency is fine for turn-based MUD combat
Kelvin versioningLowMUD state is application-level, survives kernel updates
Builder toolingHighHoon is hard; may need simplified building interface
Hot updatesMediumState migration between agent versions needs care

Community Risks

  • Small initial player base (Urbit users who want to play a MUD)
  • Need content creators willing to write area descriptions
  • Ongoing maintenance/development commitment

Design Risks

  • Trying to build too much at once
  • Over-engineering distributed architecture before basic gameplay works
  • Underestimating content needs (a MUD needs LOTS of rooms and areas)

Phase 1: Core Engine

  • Single host ship
  • Room navigation (move between rooms, look, exits)
  • Basic combat (auto-attack + a few skills)
  • Character creation (race, class, stats)
  • Leveling (kill mobs → gain XP → level up)
  • Simple web UI (room description, compass, status bar)

Phase 2: Depth

  • Equipment system (wear, wield, inventory)
  • Multiple areas with level ranges
  • NPC shops
  • Basic quest system
  • Communication channels (say, tell, gossip)
  • ANSI color in descriptions

Phase 3: Social

  • Clan system
  • Player housing (manor)
  • Helper channel / new player experience
  • Player trading

Phase 4: Scale

  • Distribute world across multiple ships
  • Builder tools (in-game or web-based area editor)
  • Scripting system for dynamic mob behavior
  • GMCP protocol support for traditional client compatibility

Sources