House of Maldorne

We play, host, build, develop and recover old and new retro online games, from muds to roguelikes.

#

Added functionp support for when DGD is compiled with the -DCLOSURES flag. Closures in DGD allow passing functions as values, similar to lambdas in other languages. Our functionp tries to emulate the MudOS functionp efun behavior.

Small change, but just in case you want to experiment with it, you have it available now in the Hexagon repository.

Hexagon

From Rooms to Locations: An ECS Approach

One of the biggest architectural changes in our MUD engine Hexagon is replacing the traditional room system with a new location system built around an Entity Component System (ECS) pattern.

The Problem with Rooms

The classic MUD room is a monolithic object. A room that contains a shop has to inherit from a shop class. A room with a pub inherits from a pub class. If you want a room that is both a shop and a pub, you need multiple inheritance, which in LPC gets messy fast. And then you want to add a sign, or make it dark at night, or have an NPC attendant, and you end up with inheritance chains five levels deep where half the code is workarounds for the other half.

Components Instead of Inheritance

The ECS approach flips the model: a location is a container, and features are components you attach to it. A shop is a component. A pub is a component. Having climate effects is a component. You can mix and match them freely without worrying about class hierarchies, because you compose locations by mixing components, not by stacking class hierarchies.

In practice, this means a location file could look something like this:

// A tavern that also sells equipment
add_component("shop", ([
"items": (["sword": 100, "shield": 150]),
]));

add_component("pub", ([
"menu": (["ale": 5, "mead": 7]),
]));

// And this location is outside and has weather effects
add_component("outside");

Each component manages its own state and responds to player actions independently. When a player types look, the location queries all its components for their descriptions. When a player types buy sword, the location routes the action to the component that responds to buy actions, which checks if it has that item for sale.

What Changed

The conversion touched almost every part of the codebase that dealt with rooms:

  • Actions and targets: the action system now treats components as valid targets. If a location has a shop component, buy and sell work without the location needing to know anything about commerce.
  • Builder tools: call function() @component: now you can call functions directly on components from the command line, which makes testing and debugging much easier.
  • Darkness and weather: the dark/night/outside system was refactored to work as a location property rather than a room class feature.

The old room system still works. We did not break backwards compatibility. Rooms and locations coexist, and you can convert rooms to locations incrementally.

Ventures: Managing It All

Along with locations, we built a new ventures handler. A venture is any player-facing business in the game world: a shop, a pub, etc. The handler tracks all of them across all areas, and the ventures admin command lets you list, inspect, and manage every venture in the system from one place.

Also, every behaviour that a venture can have has been refactored so we can share the code between the location system and the old room system. So if you have a shop in a room, it uses the same underlying code as a shop component in a location.

Next Steps

The plan is to gradually convert existing rooms to locations in the different games in Hexagon. We will be also adding new components and features to the location system as we go, such as support for dynamic events, more complex NPC interactions, and better integration with the quest system. The goal is to have a flexible, modular system that can support a wide variety of locations and gameplay styles without needing to rewrite code every time we want to add a new feature or mix and match different types of locations. The old room code will stay around for a while, both for compatibility and because some simple rooms do not need components at all.

The source code is available in the Hexagon repository.

Hexagon

MUD Emotes Reworked: The Souls System

The soul system in Hexagon has been completely reworked. Souls (also called emotes or social commands in other MUD codebases) are what lets players express themselves beyond game mechanics: waving, laughing, hugging, sighing, facepalming. The stuff that turns a text game into a social space.

Why This Took So Long

Hexagon is bilingual. Every soul needs to produce correct output in both English and Spanish, accounting for verb conjugation, gender, target presence, and self-targeting. “You wave at John” becomes “Saludas a John” in Spanish, but “John waves at you” becomes “John te saluda”. Multiply that by about 80 different souls and every possible combination of arguments.

The original soul data was a tangled mix of code and translated strings. Pulling them apart into clean data files (soul-data.en.h and soul-data.es.h) meant going through every single soul and testing every variation.

How It Works

Each soul has up to four different message patterns depending on context:

  1. What you see when you do it (no target)
  2. What the target sees
  3. What others in the room see

And then, maybe some souls can’t have targets at all, some other maybe only have self-targeting messages, or cannot be self-targeted.

For a soul like bow:

  • You type bow and see “You bow gracefully.”
  • Others see “Neverbot bows gracefully.”
  • You type bow john and see “You bow before John.”
  • John sees “Neverbot bows before you.”

And then you can add adjectives to the soul, like bow deeply: with this particular example, you could bow solemnly, deeply, formally, hastily, slightly, respectfully, insolently, clumsily, gracefully, dexterously, wildly or colorfully. And all of these combinations need to exist in both languages.

The Drunk Factor

On top of the souls rework, the intoxication system (drunk.c) was translated and connected to the soul output. A drunk character does not just type garbled text. Their emotes change too. Being drunk affects how souls display, adding slurring and stumbling to the output. And some chances of burping, puking, or some other fun drunk behaviour. This is the kind of detail, together with shops and pubs working as location components, that makes a MUD feel alive. Nobody needs it, but once it is there, players notice.

What’s Next

The soul system is working in both languages. The data files are clean and adding new souls is straightforward: define the four message patterns in each language file and the system picks them up.

The source code is available in the Hexagon repository.

Paper of the Week: Players Who Suit MUDs

The academic paper “Hearts, Clubs, Diamonds, Spades: Players Who Suit MUDs” was written by Richard Bartle. Published in 1996, it is a seminal work in the field of game studies and player psychology. In this paper, Bartle categorizes players of Multi-User Dungeons (MUDs) into four distinct types based on their preferred activities and motivations within the game.

Bartle's Taxonomy of Player Types
Recreation of the classic Bartle’s player types diagram from the original 1996 paper.

The Four Player Types

  1. Achievers: Players who focus on attaining in-game goals, collecting points, levels, equipment, and other measurable achievements. They want to win, or at least demonstrate mastery.
  2. Explorers: Players who enjoy discovering new areas, learning about the game mechanics, and finding out the secrets within the game world. The joy is in the discovery itself, not in what they find.
  3. Socialisers: Players who are primarily interested in interacting with other players, forming relationships, and engaging in conversations. The game is a backdrop for social interaction.
  4. Killers: Players who thrive on competition with other players, seeking to assert their dominance and affect other players’ gameplay. They need other players to exist, but not necessarily to cooperate.

The Player Dynamics

What makes Bartle’s taxonomy genuinely interesting is not just the classification itself, but the dynamics between player types. Bartle observed that increasing certain player types in a MUD directly affects the population of others. For instance, too many Killers will drive away Socialisers, which in turn reduces the supply of victims and eventually drives away the Killers themselves. A healthy MUD needs a balance of all four types.

This insight remains relevant for any online multiplayer game, even those far removed from text-based MUDs. Anyone who has seen a game community collapse under the weight of toxic PvP or watched an MMO server die after the social players left has witnessed Bartle’s dynamics in action.

Why It Matters for MUD Development

At Maldorne, we have been building multiplayer games with the Hexagon mudlib for years. Whether we are designing combat systems, crafting economies, or planning social spaces, Bartle’s framework helps us ask the right questions: which player types does this feature serve? Are we accidentally pushing a type away?

For example, the weather and climate systems in our games affect exploration and survival, giving Explorers and Achievers something to engage with. The towns, guilds, and public spaces are designed with Socialisers in mind. And combat provides the competitive edge that Killers seek.

Understanding these dynamics is also crucial when playtesting — observing which player type your testers gravitate towards tells you a lot about what your game is actually offering versus what you intended.

If you are interested in more MUD-related resources, we maintain a curated list in our awesome-muds repository.

Read the Original

Read it online, it is really worth it. At roughly 20 pages, it is an accessible and well-written read even if you have never played a MUD. The concepts apply to any multiplayer game.

Awesome-Muds

For some time now, we have been maintaining the GitHub repository awesome-muds, which contains a large list of resources, articles, technologies, etc., related to the world of MUDs. It includes some history, links to available clients for different operating systems… a little bit of everything.

Take a look, and if you think there is something that could or should be changed, improved, or added, feel free to open an issue to discuss it.

Link to the repository.

awesome-mud

New packages included with Hexagon

The Hexagon mudlib/framework has been updated with new packages, which include the following:

  • crypt: code and command to encrypt and decrypt files, based on Dave Ljung’s (Jubal) code, ported to be used with DGD and Hexagon.
  • json: code to encode and decode LPC values as json strings. Modified from an LPC snippet created for MudOS, changed to be executed with DGD.
  • uuid: easy way to create uuid strings (RFC4122), also addapted from an LPC snippet.

Take a look inside the /mudlib/packages directory in the repository to see the code, documentation and license for each package.

#

The Hexagon mudlib has reached at last its version 2.0, codenamed Castle Black. It’s a major release that includes a lot of changes and improvements, and it’s the first one that we can say is a beta version, after a lot of years in alpha. It’s a renaming of the v1.24.04 version. The next planned version will be v2.1 Daggerfall.

Release link.

#

For developers: The Docker container images we are using for the MUDs we host are not anymore in Docker Hub, now they are in the Github Container Registry, just in case anybody want to tests things in their own computers.

DGD image, MudOS Images. You can always find them in their respective repositories, in the right column, under the packages section.