DGD Mudlibs

What mudlibs are available for DGD?

There are currently 6 mudlibs with publically available DGD versions.

Kernel mudlib This is the minimal kernel mudlib written by Dworkin that is released with DGD. It provides a foundation which gives developers a working environment around which a fully featured mudlib could be developed.
2.4.5 The venerable 2.4.5 mudlib was originally written for the 2.4.5 LPC driver. Unfortunately its LPC is quite dated both in design and implementation. It is the only choice available, however, for people who wish to open a playable mud straight away.
GurbaLib GurbaLib is a possible choice for people wanting to open a playable mud fairly quickly. Although there is currently no download site for it, a copy can be requested from the author, Erlend Simonsen.
LPMOO LPMOO is quite a different mudlib in that it completely masks LPC from users and developers and instead simulates the LambdaMOO driver complete with its MOO language. It was originally written for DGD 1.0.9 by Robert Leslie. A patch is available to update the lib for DGD 1.1.
Melville The current release of Melville is 0.9 which was written for DGD 1.1. The mudlib is designed to provide all the facilities necessary for a group of developers to connect to an environment in which communication and security features exist and begin designing and writing game specific features (which have been left out to allow for such customization). This mudlib was written by Steven Schmidt (Mobydick).
pblib This is an old release of the mudlib from Xyllomer. As such it is a possible choice for people wanting to open a playable mud quickly (areas are all that is required). Its important to note that this version of the mudlib was developed for DGD 1.0.9. There is, however, a patch which may allow the lib to load under DGD 1.1.

Another item that is of interest in this topic is the MudOS-alike package, written by Frank Schmidt. This package provides an auto object and associated support which is highly compatible with most of the efuns commonly compiled into the MudOS driver. This package can be used to aid in the porting of an existing MudOS mudlib or as a base for new mudlib development.

What's a kernel function (kfun)?

A kernel function is a function provided by DGD itself. Documentation for these functions can be found in the doc/kfun directory of the DGD distribution and online (unofficially). These functions are available to every object (unless redefined by an inherited object -- the auto object often does redefine them).

What's the auto object?

The auto object is one of two special objects in DGD. It is (automatically) inherited by every other object except the driver object. In this way, any function in the auto object that is declared static will act much the same as a kfun. Functions like this are alternatively called efuns (since they act as efuns do in other LPC drivers) or afuns.

It should be noted that even if a function that is static in the auto object isn't explicitly defined as nomask it will always act as if it is in the context of the auto object. That is, although it may be masked in an object, calls to it from within the auto object will always use the version in the auto object. This differs from the standard behaviour of functions which are static but not nomask in other objects, which will use the overriden version of the function. To quote Dworkin:

"To be yet more precise: any calls made to static functions in the auto object can never be redirected to a new function by masking the static function, no matter from where the calls are made. In C++ terminology, static functions in the auto object are not 'virtual'."

Is it bad to have a large auto object?

This question has been asked a number of times on the DGD mailing list, where large refers to a "lot" of functions. Dworkin has replied to this and stated that the function lookup time is constant and independent of the number of functions in the auto object. However, he has also said:

"There is an obscure cost associated with functions in the auto object that are neither static nor private: all such functions have a cost of two bytes a piece in inheriting object's program. This is also true for non-private functions in all other (i.e. non-auto) objects.

Normally, this is not much of a problem. However, if you were to have 200 such functions in the auto object, every other program in the game but that of the driver object would become 400 bytes larger."

My personal experience is that "functions in the auto object that are neither static nor private" are uncommon.

On the related question of using an inherited module rather than placing the code in the auto object Dworkin made the following statements:

"- A call to a function in the auto object uses the special CALL_AFUNC instruction, which is 3 bytes in size. Exactly the same functionality would be available with the CALL_DFUNC instruction, which takes 4 bytes. Thus, programs that call functions in the auto object will be slightly smaller. In the most extreme case, a function that consists of nothing but function calls will be almost 25% smaller if CALL_AFUNC can be used for every call. There will be a barely measurable performance difference.

Note that programs larger than 2K are compressed before being saved in the swap file, where the compression factor depends on the redundancy of the byte code, so the size advantage in the swap file would be much less than 25% if the function mentioned above is large enough.

- Inheriting a utility object, which itself does not inherit anything, increases the size of the inheriting program with about 16 bytes.

- Putting everything into the auto object increases the size of the working set. For a single object the difference won't amount to much, but a mudlib wholly designed with the idea of keeping the working set small will have a performance advantage."

With this in mind, it would seem that whether to have a large auto object or not is an issue which has pros and cons on both sides, that is, there is no canonical answer to this question.

What's the driver object?

The driver object is the interface between DGD and the mudlib. It is loaded before any other object and is the only object not to inherit the auto object. Various "applies" (see the LPMud FAQ -- these are functions called by DGD itself, not another LPC object) are called in the driver object by DGD in response to various events and are expected to perform various tasks such as dealing with compile or runtime errors, calling, compiling and inheriting objects, etc.

How do I do multiple inheritance with DGD?

Multiple inheritance in DGD is different from other LPC drivers. To inherit multiple files one must label the inherited files (other LPC drivers automatically label the inherited objects with the file name -- which is a problem if there are two files of the same name in different directories which you wish to inherit). The best way to illustrate the DGD method is via an example. In this example two objects A and B are inherited and given the labels foo and bar. These labels are used to call the inherited create functions.

/* 
 * Inherit program "A" and label it as foo.  
 * Inherit program "B" and label it as bar.
 */
inherit foo "A";
inherit bar "B";

void
create() {
   /*
    * Call the create functions in programs "A" and "B" via their inheritance
    * labels.
    */
   foo::create();
   bar::create();
}

Why isn't my create() function called when I compile an object?

This is mentioned in the DGD documentation. The create() function is only called just before the object is first accessed by a call_other. To change this behaviour one can simply mask compile_object in the auto object with a version which accesses the object straight after it is compiled and hence provokes the calling of the create() function by the driver.

Are there any function pointer/lambda closure equivalents?

No, but you can simulate this sort of functionality with LPC should you require it. Indeed, Dworkin at one point wrote a simulation for the lambda closures of the 3.2 LPC (Amylaar) driver.

Can I compile my LPC to C?

Yes, you can. This must be done at the time the driver is compiled though, one cannot (quite) do it on the fly. Look in the src/lpc directory for more information concerning this. The 2.4.5 mudlib simulation contains a good example of how to do this.

To perform this operation almost on the fly, compile the new version of the driver with the C version of the new LPC objects included then perform a state dump of the game before shutting down and restarting with the new driver.

Copyright © 1997-99 Greg Lewis