Category Archives: Basternae and ModernMUD

Posts about the Basternae MUD and/or the ModernMUD codebase.

22 Hours Uptime

Mind you, only about 5 players have logged into the Magma 3.04 demo site, but it’s been up 22 hours so far.

I remember back when Magma was first being developed. An hour of uptime was considered a good thing.

Funny how things progress. I remember my first MUD in 1999, Illustrium Arcana, running on a Cyrix 6×86-PR200 on a 32MB machine co-located on a friend’s ISP (stax.net, apparently shut down around the end of 2006). Having T1 access was so amazing ten years ago. Now I’d be angry if my cable modem slowed down to 1.5 MBPS.

The original Cyrix machine ran at about 200 BogoMIPS, which was screaming fast. Right now I have what is effectively 1/10 of a Xeon 2.5 GHz processor. That gives me 500 BogoMIPS and 320 MB of RAM. That’s more than enough to run a MUD and a few websites.

Visual Studio Refactoring And Encapsulation

I love the refactoring support in MS Visual Studio.  It makes certain things like field encapsulation incredibly easy.

For instance, thanks to its origins in C, most of the Basternae 3 codebase doesn’t have encapsulation yet.  This means that there are tons of class member variables declared like this:

public string _keyword;

Setting the _keyword member variable to private and creating a property named Keyword with getters and setters that reference the _keyword variable would take about 30 seconds.

With Visual Studio it’s easier:  Just right-click on the variable and select “Encapsulate Field”.  It will come up with a reasonable property name and automatically generate the code and set the variable to private.

Pretty nice, but nothing to write home about.

But, here’s the magic:

All references to that variable in code are AUTOMATICALLY changed to refer to the property.  If that member variable was used in 50 different places, Visual Studio just saved you the trouble of making 50 different changes or doing a search-and-replace that may or may not get everything on the first try.

Of course, this doesn’t automatically update any XML files that have been saved using the old variable name.  To take care of that you can do one of two things.

1. Do a search and replace in every XML file that your class would have been serialized to and hope you didn’t miss one.
2. Use the XmlElementAttribute on your property to map the saved attributes to your new type:
[XmlElement(“_keyword”)]
public string Keyword
{

#2 is obviously safer and easier, especially since it doesn’t require changes to existing data.  Of course, your data files might be clearer to read if they used the exact property names, but do you want to go through the trouble?  Likely not.

The New Client In Action

In working on the new WPF-based client, I’ve redone the way I handle ANSI character code processing. Instead of a horrible multi-hundred-line nested if-statement-monster, I’ve created something based on regular expressions that is about 25 lines or so of code. It’s not absolutely perfect, but it’s already better than what we had with the wxWidgets + SDL client (what I call “Client #2”). (FYI: Client #1 was an SDL-only client that used a ridiculously huge amount of CPU and was unworkable in resolutions above 640×480).

Screenshot:

There’s still plenty more work to do on the client.

No Null Checks

After running the automated tests generated by Pex, it’s amazing how many functions in the old codebase received various class or structure arguments and immediately started working with the data in them without ever checking for null. It was a paradigm followed by the old public code release of Diku, Envy, Merc, etc. and was unthinkingly carried on by the Basternae 2 programmers, myself included. This lack of data validation is being corrected.

It’s no surprise that the old codebase crashed a lot. After seeing the extent of the damage, I feel like I need to go back and revisit the Magma codebase and add a lot of stabilization.

In fact, one of the main things with Basternae 3 that will help stability is the fact that all player-entered commands are executed within a try-catch block. This means that typing in a broken or unsupported command should never crash the MUD, which was a huge problem in the “bad old days”. Instead it will log an error and appear to do absolutely nothing from the player’s viewpoint.

The New Client So Far

It’s just screenshots of windows without anything in them — no fancy colors, images, or any bells and whistles yet.  This is just to show that it really exists:

.NET Basternae Client First Screenshot

C++ Is a Pain in the Arse (New Client)

Yesterday I opened up the source code for the Basternae Client in order to make a few changes, fixes, and updates.  What I had forgotten in the two years since I had been programming C++ actively is what a pain in the behind it is to get anything done in C++.

Sure, you can do anything with it, but there’s so much tedium and overhead involved that it takes forever to get anything done.  Sure, it’s great for low-level code where you’re tossing bits and bytes around, but for user interface development it’s just too unwieldy.

Out of frustration, I sat down and rewrote most of the client in C# in a few hours.  Mind you, it’s not fully implemented, but it’s usable as a telnet client.  I’d say about 8-10 more hours of development time and it’ll be ahead of where the other client was.

That makes this the third version of the client.  The first version was pure SDL with C++.  The second version was SDL combined with wxWidgets.  The third version is C#.NET and WPF.

Another benefit of switching to WPF is that the CPU utilization of the client has gone down tremendously, mainly because we’re using only one interface drawing library now.

FindMUD Becoming Somewhat Popular

I just checked Alexa stats for FindMUD.com.  Although Alexa isn’t exactly the full measure of the web since only a small percentage of people have the plugin installed, here are the MUD sites that FindMUD outranks:

mudmagic.com
mudbytes.net
mudlists.com
mudmaker.com
ftpgame.org
dikumud.com
mudlist.betterbox.net
dune.net
envy.com
silverden.com

It’s a respectable list, but we are far from surpassing the 800-pound-gorilla of MUD sites, the MUD Connector.  I don’t expect that to happen, but I do hope to get into the top three at some point (the other two being topmudsites.com and mud.de.)

Of course, FindMUD needs a lot more work that won’t happen in a single day, but I am gradually improving the site.  Just today we posted our own version of the MUD timeline.

Continuing Spell Migration

When we last saw our hero, he was working on migrating spells from being hard-coded in 15 different places to being individual XML data files that are loaded at boot time.

While this makes it easy to modify, enable, disable, rename, or adjust spells without a recompile, the main reason I’m doing so is because there’s just so dang much clutter in the codebase with spell info strewn about everywhere.  It’s like a pack of wizards exploded in there, I swear.

This will also make it far easier to make minor adjustments for balance.  Instead of having to track down a developer to go through many slow tweak-recompile-reboot cycles just to adjust spell damage, the “balance engineer” will be able to work independently.  In the future it may be possible to perform online editing of spell attributes without a reload.  This is obviously not something that everyone should be allowed to do.

Part of the migration will be to move most of the actual function code into the spell files.  Most spells are pretty generic in nature — add an affect (flight, strength, poison) or affect hitpoints in some way (fireball, heal).  Even so, the same ~10 lines of code are duplicated for pretty much every spell with only the name changed.

Making the spells somewhat independent of the game engine also makes the engine less “tied” to Basternae.  At some point I’d like to create a space-based MUD using the same code, and the spells would obviously be dead weight.

Magma MUD 3.04 Released!

I’ve made a minor update to the Magma codebase.  Here’s what’s changed:

1. Added support for loading 4 of the 5 remaining Envy 2.2 zones that wouldn’t load.
2. Bundled the MakeZonesFast32 and DikuEdit 3.10 zone editors in the MUD package.
3. Added DOS conversion utilities for assembling DikuEdit zones (makezone.bat).

MagmaMUD 3.04 is available for download at FindMUD.

First Zone Editor Preview Version

Here’s the first view of the Basternae Zone Editor available for download:

BasternaeEditorPreview1.zip (download removed, see the post about preview version 2)

Some warnings:

1. This is a pre-release version and it’s entirely likely that it will be unstable and lacking in features.
2. It has no help files.
3. It has no icons for the edit window buttons — just colors.  You have to guess what they do.
4. The map edit and walkthrough edit modes are not done yet (and haven’t been started yet either).
5. Save your work often and keep backup copies.

This is just to download, play around with a bit, and get a feel for.  I don’t expect that the area file format will change in a way that will break zones created with this editor, so you can actually start trying to use it to build something.

Check it out, see if it’s usable, and feel free to make requests, bug reports, or just say what would make you more likely to want to use the tool to create a zone for the new Basternae.

Rewiring The Core

In the process or getting an alpha version of the editor ready I’ve found that I had to separate the game code, a.k.a. “business logic” from the data, a.k.a. “object model”.  Otherwise I’d have to include the entire MUD engine in the editor download.  Since that’s not something I want to do I’ve had to pull them apart.  It’s a lot like pulling apart a cold grilled cheese sandwich, and as expected, the bread did tear a little.

The “core rewire” still needs some work, but I should have an “alpha”, a.k.a. “try it and see how broken it is or isn’t” version of the zone editor out sometime this month.

A Review of Duris

The MUD Connector has an interesting review of Duris posted:

http://www.mudconnect.com/mud-bin/new_prev/review.cgi?rid=25705

I’ve always enjoyed Duris and still play it off and on (maybe half a dozen weeks a year), but it has always had so many flaws that I end up getting fed up and walking away after a while. Part of it is administrative, sure, but a lot of the problems are core game design — at the core it’s an excellent MUD, but so much of it is an unnecessarily frustrating mess that it doesn’t really have much longevity for me. I think it comes from the original philosophy of the design — the creators really didn’t differentiate between “difficult” and “irritating”.

For example (and I’m mainly referring to Duris from a few years ago because that’s what I know best):

Randomly killed by random-spawn unpredictable scan-track mobs in the underdark for no logical reason, or = annoying.

Instantly killed because you were attacked by a drunk orc when you try to leave the inn in your hometown and since you’re level 1, assisting guards one-shot you (and your class doesn’t have sneak) = annoying.

Getting killed in artifact-wielding players in low-level zones and having your corpse looted of spellbooks/totems that you are too poor to replace because you’rer a newbie = annoying.

Player-wiping because you want to refresh the player base, purge an overabundance of equipment, or replace the world maps, or cover up the fact that the game mechanics still need some work = annoying.

Needing to use your head to come up with a strategy to defeat mobs, complete a zone, or accomplish a task = difficult.

Being forced to rely on your wits and diligently reading room descriptions to solve quests or puzzles = difficult.

Optimizing your equipment and stat bonuses based on how you want to perform in combat and doing so by real combat experience rather than reading the source code = difficult.

Somehow they seem to think that and difficult are both beneficial. Difficult makes players keep playing because things aren’t too easy. Annoying makes them log in to WoW.

I still find it incredibly amusing that I was more-or-less programming for Duris during the 2000-2001 “arms race” with Basternae 2 — every time I added a feature or convenience command that was neat but didn’t affect game balance it would show up on Duris a week later.

Even so, I can’t really say I have anything against any of the admins of Duris. After all, I’ve never even met any of them (except Xyzom from old Duris, who I actually lived with for a while and worked on Illustrium Arcana with — nice enough fella but we haven’t kept in touch). All I can do is judge by their product, Duris: Land of Bloodlust, which needs some work.

Unit Testing With MbUnit

In general either code works or it doesn’t and it’s easy to tell whether it does or doesn’t work. At least until you reach a certain level of complexity. At some point a project gets large enough that you can’t tell which project/dll your error is coming from, let alone which of the 100K or even 50M lines of code is doing naughty things.

Today I had a problem that was easier to solve by creating unit tests to point out where the flaw was. The tool uset? MbUnit.

Here’s an example of an MbUnit test I wrote in order to find a string processing bug:


using System;
using System.Collections.Generic;
using System.Text;
using MbUnit.Framework;
namespace UnitTests
{
[TestFixture]
public class MUDStringTests
{
[RowTest]
[Row(12, "12.box", "box")]
[Row(1, "cheese", "cheese")]
[Row(1, "1.pie", "pie")]
[Row(1, ".chicken", "chicken")]
public void NumberArgument(int expectedValue, string inputString, string expectedOutput)
{
string str = String.Empty;
Assert.AreEqual(expectedValue, BasternaeMud.MUDString.NumberArgument(inputString, ref str));
Assert.AreEqual(expectedOutput, str);
}
}
}

What this does is check whether we’re getting the expected output when we give a certain piece of input. It’s handy for detecting anomalies without having to boot up the server and/or mess with production code. Mind you, there’s no such thing as ‘production code’ since we don’t have a server up yet, but this sort of thing is likely to be handy in the future.

I’m not the type that has any chance of turning into a ‘write the unit tests first’ and ‘unit tests are more important than code’ evangelistic freak, but in most cases it is far easier than using trial-and-error to track down a bug.

I still hate the way WordPress formats my code.

Miscellaneous Fixes

I made a few changes to character creation today.  There were a few places where it was case-sensitive — you could create a “Troll” but not a “troll” and there were a few weird state changes.  For instance, when creating a character you would see the menu twice the first time it was displayed.

I also fixed a few immortal commands that will make it easier to create immortals and set command permissions for their abilities.

The say, emote, whisper, yell, shout, ask, and immtalk commands were broken (all messages came across blank), and are now fixed.

Issue Code Is Working

I finished testing the issue code today.  We now have a functional ‘help desk database’ for the MUD.  It’s primitive, but it should do the trick and can be expanded/changed as necessary.  At least we’ve eliminated the bug, idea, typo, and ‘helps needed’ files that admins would rarely, if ever, look at.  Here’s an example of usage:

< > issue update 2 This is a test issue.
Issue 2 updated with text This is a test issue.

< > issue close 2 Testing the issue entry system.
Issue 2 closed with resolution Testing the issue entry system.

< > issue show 2
Issue Number: 2   Priority: high   Type: helpentryrequest
Is Closed: True   Opened by Imm: True   In Room: 0
Created by: Xangis   Time: 7/6/2008 11:14 AM   Text:
disarm
Entered by: Xangis   Time: 7/6/2008 11:32 AM   Text:
this
Entered by: Xangis   Time: 7/6/2008 11:36 AM   Text:
This is a test issue.
Closed by: Xangis   Time: 7/6/2008 11:37 AM   Text:
Testing the issue entry system.

< > requesthelp disarm
Help entry request recorded.  Thank you.

< > issue list
Issues:
[3] (lowest) Help Request: disarm
[4] (lowest) Help Request: issue
[5] (lowest) Help Request: ignore

< > Issue Number: 3   Priority: lowest   Type: helpentryrequest
Is Closed: False   Opened by Imm: True   In Room: 0
Created by: Xangis   Time: 7/6/2008 11:25 AM   Text:
Help Request: disarm

< > issue priority 3 lowest
Issue 3 priority set to lowest.