DGD FAQ

Greg Lewis

Erwin Harte


Table of Contents
Preface
What this document is
What this document isn't
1. Introduction to DGD
What is DGD?
What does DGD stand for?
What makes DGD different?
What can I do with DGD?
2. Getting and Compiling DGD
Where can I get DGD from?
Is DGD available on my platform/OS?
Compiling DGD
Driver/kfun packages for DGD
DGD's extension interface
3. What mudlibs are available for DGD?
4. Q and A.
What's a kernel function (kfun)?
What's the auto object?
Is it bad to have a large auto object?
What's the driver object?
What does atomic mean or do?
What are LWOs?
Why isn't my create() function called when I compile an object?
Are there any function pointer/lambda closure equivalents?
Can I compile my LPC to C
Multiple inheritance with DGD?
ANSI colours?
What is parse_string()?
What is an ASN?
Does DGD have encryption/decryption support?
5. Miscellaneous Topics
Can I use DGD commercially?
Getting help with DGD
A. Credits and Legal
Credits
Legal
B. Various Links
Glossary
List of Tables
2-1. Stable versus experimental
2-2. OS versions available
2-3. Packages for DGD (stable)
2-4. Packages for DGD (experimental)
List of Examples
4-1. An atomic function
4-2. Multiple inheritance with DGD

Preface

What this document is

This FAQ is an attempt to answer some of the more common questions concerning DGD. It was written in response to a perceived lack of general information about DGD.

The most recent version can always be found here.


What this document isn't

This document isn't an FAQ on LPMuds in general. An LPMud FAQ written by George Reese is available among the LPMud web pages at the Centre for Imaginary Environments (CIE).

Nor is it an FAQ about Muds in general. A four part general Mud FAQ is available. This was originally written by Jennifer Smith and is now maintained by Andrew Cowan at The Mud Connector.

If you are seeking information on Muds in general, or LPMuds in particular, I refer you to these documents.


Chapter 1. Introduction to DGD

What is DGD?

DGD is an LPC driver. In brief, this means that it provides facilities that allow people to execute LPC code, much in the same way that a Java virtual machine provides facilities for the execution of Java. DGD also provides people with the ability to connect to it, most often to some sort of virtual environment built with objects written in LPC.


What does DGD stand for?

DGD stands for Dworkin's Generic Driver, being named after its author and developer -- Dworkin (Felix Croes). This originally was Dworkin's Game Driver but was changed (at the suggestion of Robert Leslie, author of LPMOO).


What makes DGD different?

DGD differs firstly in that it wasn't derived from a version of Lars Pensjö's original LPC driver. It is a complete rewrite of the driver by Dworkin from the ground up. In this way it has managed to get rid of a lot of baggage and legacy code which other LPC drivers still possess to some degree.

Another important difference is that DGD's default set up is to be disk based rather than memory based, unlike other LPC drivers. This means you can load a huge number of LPC objects without DGD taking up a lot of memory.

DGD also possesses (at driver level) the ability to perform a state dump, that is, to dump the state of all loaded objects to a file and restart the driver with them exactly as they were (with the exception of active TCP connections being closed during this process).

Finally, DGD allows changes in object LPC code to be realised in already existing objects by recompiling in situ, rather than having to destruct, recompile and then recreate the object. In this functionality DGD moves away from traditional LPC driver practice towards persistent database backed drivers such as Cold and MOO.


What can I do with DGD?

Pretty much anything. The most common application for DGD is still running muds, but there is no reason why it couldn't be used (with appropriate LPC objects) as a httpd for example. DGD itself contains nothing specific to any application, only certain kernel functions (kfuns) which Dworkin felt necessary to LPC object coding, compiling and management, and multiple connections.

This minimalistic philosophy and lack of application specific code allow you to create any look and feel you choose through building around basics written into the auto and driver objects. A classic example of making DGD appear to be something other than an LPMud using this methodology is the LPMOO simulation by Robert Leslie.


Chapter 2. Getting and Compiling DGD

Where can I get DGD from?

Dworkin hosts the primary distribution site for DGD himself. Both the source code (with patches up to the current version of 1.2p2) and binary releases (for selected architectures) of the stable development branch of DGD can be found at the site.

This site also provides patches for the experimental releases. These experimental releases are (by definition) not guaranteed to be stable but contain developmental code which will eventually become the next stable release (likely DGD 1.3).

In terms of bug fixes the following table indicates the correspondence between the experimental and stable branches.

Table 2-1. Stable versus experimental

DGD seriesCorresponding versions
1.21.2p11.2p2
1.2.281.2.50

There is also an earlier DGD distribution site (which only contains patches up to 1.1p5). In addition to what one can find at the main site there are some LPC packages for DGD.

Note that the contents of the README file on lysator are outdated, the main site is now ftp.dworkin.nl, not ftp.imaginary.com.


Is DGD available on my platform/OS?

DGD is available as both source code and precompiled binary distributions. The source code is primarily provided for Unix-like operating systems and will compile on just about all such systems and platforms. Binary distributions are provided for a variety of operating systems where this the traditional method of distributing applications. Specifically, binaries for Windows 9x/NT are available in zip format, for MacOS as a binhex'ed stuffit archive, for BeOS in zip format, for the Amiga as an lha archive, and for the Atari as a zoo archive.

A list of the current versions available for each OS is:

Table 2-2. OS versions available

Platform:UnixWindows 9x/NT/2000/ME/XPMacOSBeOSAmigaAtari
Version:1.2 (source code)1.2p21.2p21.2p1 (for the ppc architecture) 1_1p61.0a71 (very out of date and no current support)
patches p1 and p2 1.2p2 (for the i386 architecture)

Compiling DGD

For this task you will need a C compiler, the gunzip/gzip program, the tar program, the make program and the patch program (should you wish to install the patches -- and you really do). These are standard on most Unix-like systems. You will also need to select the appropriate HOST Makefile -- see doc/Platforms for more information on selecting the appropriate HOST setting for your machine. If you do not have one or more of these tools, the excellent GNU versions are available for almost any flavour of Unix (plus a few other platforms) from the main GNU ftp site or any of its many mirror sites.

DGD is known to compile on Windows 95/NT using MSVC++ 4.x and better. It should be noted, however, that while this compilation works out of the box with MSVC++ 4.x, users of 5.x and later will need to turn off optimizations in the supplied project file. DGD source has also been compiled on Windows 95 with gcc from the Cygwin tools (beta 20.1 version) using a HOST configuration of LINUX and replacing src/host/lrand48.c with src/host/pc/local.c. One suspects it would also compile with the Borland compiler as well, although there are no reports one way or the other on this.

If you are using OS X you can compile the unix source code if you have the Mac Dev Tools. One user points out that you may run into trouble with the ones prior to 10.2 (Jaguar) due to missing support for random().


Driver/kfun packages for DGD

As has been mentioned before DGD is built with a minimalistic philosophy. This has resulted in a number of people issuing "packages" for DGD. The general idea behind most of these is to extend the functionality of DGD in some way that is of use to the author (and hopefully others) but that isn't essential. Currently the following packages are available (in the pkg directory unless otherwise specified) for the stable branch of DGD development. These packages must all be installed prior to compilation. Those listed in the following table were all written for DGD 1.1 or DGD 1.2.

Table 2-3. Packages for DGD (stable)

AuthorPackageDGDDescription
Th. Lockert of SigmaSoftalarms1.1Replaces the call_out related kfuns with kfuns that provide fraction (1/10th) of a second alarms and which are repeatable.
comment1.1Allows LPC coders to use C++ style // comments.
ctors1.1Provides LPC objects with constructors/destructors.
str2val1.1Converts any variable to and from the string format used in save files produced by save_object.
strftime1.1Ability to format dates and times as per the C strftime function is provided by this package.
wildmat1.1A subset of regexp string pattern matching functionality is provided by this package.
Richard Braakmannet-101.1The network package extends the IP networking features, allowing you to open/close TCP ports, start outgoing TCP connections and receive and send UDP packets.
precomp-31.1This package makes it easier to compile your LPC objects into C by keeping track of inherited programs for objects you wish to compile this way. It is only available for Unix-like operating systems.
Wim van der Vegt95-api1.1Adds 4 kfuns to dgd which make use of the win32 API and thus are specifically for Windows 95/NT.
NT-api1.1Adds an extra 2 kfuns on top of the 95-api package which makes specific use of the NT API. This package is specifically for Windows NT.
ansi1.1By default DGD filters out the escape code of the so-called ANSI colour codes and the VT100 terminal codes. This package provides a patch which allows these codes to be input and output successfully.
Robert Lesliergx1.1Full regular expression string pattern matching facilities are provided by this package. It was written for DGD 1.0.9 and uses the GNU regex library.
Greg Lewismdbm1.1This package provides a kfun interface for manipulation of ndbm/gdbm databases.
regex1.1Full regular expression string pattern matching facilities are provided by this package in a somewhat different fashion than that used by the rgx package (no external libraries are involved).
object_info1.1Provides kfuns which give you information about inherited programs, functions and global variables in an LPC object.
Unknownrusage1.1Borrows the rusage efun code from the 3.2 LPC (Amylaar) driver and adds it as a kfun. It uses the getrusage(2) system call.

In addition to those available for the stable branch of DGD, the following table lists packages (by name and DGD version) which have tracked at least partially into the experimental development line(s):

Table 2-4. Packages for DGD (experimental)

AuthorPackageDGDDescription
Richard Braakmannet-111.1.64The network package extends the IP networking features, allowing you to open/close TCP ports, start outgoing TCP connections and receive and send UDP packets. (Last maintained by Erwin Harte.)
precomp-31.1.44This package makes it easier to compile your LPC objects into C by keeping track of inherited programs for objects you wish to compile this way. It is only available for Unix-like operating systems at the moment.
Erwin Harteepp-2.31.2.48EPP is for "Easy Precompilation Package". Similar in purpose to the precomp-3 package, it is a package to allow LPC objects to be easily precompiled into the DGD driver. While we have noted, for consistency, the driver version this package was produced for it should work with any later version of DGD too, as it doesn't actually require any DGD source code alterations.

If you wish to use a Unix-only package on a Windows 95/NT box I suggest looking over the Cygwin package. Alternatively, if you wish to use a win32-only package on a (PC-based) Unix box then look at Wine (specifically, details on winelib, not the wine program itself).


DGD's extension interface

DGD has a documented extension interface to make it easier for others to add kfuns or add special object types. See the dgd/doc/Extensions interface for details and a worked out example.


Chapter 3. What mudlibs are available for DGD?

There are currently 6 publicly available (mud)libs for DGD:

  1. The kernel lib is the minimal lib written by Dworkin himself that is included with DGD. It provides a foundation which gives developers a working environment around which a fully featured mudlib can be developed.

  2. Noah Gibbs' Phantasmal mudlib

  3. GurbaLib, written by Erlend Simonsen:

    I want people to use it for whatever suits them best. I made it mostly as a learning experience, as I was fascinated by how LPC muds work. If it can help anyone get started coding, set up a test mud, or start fiddling around, I'm happy. All I ask, is that if anyone finds bugs, they report them to me, or even better send me fixes.

  4. The current release of Melville is 0.9.1 which was written for DGD 1.2. 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 Stephen Schmidt (a.k.a Mobydick).

  5. 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.

  6. 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 appears to be the only choice available, however, for people who wish to open a playable mud straight away.

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.


Chapter 4. Q and A.

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 <every> 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.

It is not unreasonable to assume 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.


What does atomic mean or do?

A function can be declared to be atomic:

Example 4-1. An atomic function

atomic void foo()
{
    ...
}

Atomic functions treat errors in a special way. If an error occurs, every change made by this function is undone, including changes made in functions called by this function.

It is illegal to use file or directory changing kfuns from atomically executed code:

  • write_file()

  • remove_file()

  • make_directory()

  • remove_directory()

  • save_object()

  • editor()

Atomically executed code uses twice as many ticks as normal code.

An example given by Dworkin on the mailing-list:

The 2.4.5 mudlib for DGD contains the following code in /dgd/lib/inventory.c:

private void move(object obj, object from, object dest)
{
    int light;

    light = query_light(obj);
    if (from != 0) {
        from->_F_rm_inv(obj, light);
    }
    obj->_F_move(dest);
    dest->_F_add_inv(obj, light);
}

This code is called from the move_object() efun to do the actual movement. If it were to fail halfway through, this would result in an inconsistency. For example, if the inventory array of `dest' already has the maximum size, adding the object `obj' to the inventory of `dest' will result in an error; this will leave the environment of `obj' set to `dest' while `obj' is not actually in the inventory of `dest'.

Furthermore, there are some errors that can happen in almost any code: running out of ticks, or out of stack space for nested function calls. (It so happens that this particular code snippet is safe from those errors.)

Now if the function were made atomic, it would either succeed normally, or fail without making any change at all. The object is either moved or not moved -- it cannot get stuck in an intermediate state where it is half moved.

Using atomic is not the only solution. It may be possible to check for all possible error conditions in advance, and only execute the code if it's safe. Alternatively, an error occurring halfway through could be caught, and the already-performed actions could be undone explicitly. However, using atomic is always the most simple solution, often the cheapest, and sometimes the only possible one.

There is a lot of code out there that doesn't check for errors at all, of course. The atomic function feature could be used to guard such code from inconsistencies with only minimal rewriting.


What are LWOs?

LWO is an abbreviation of light-weight object and it refers to a new feature introduced in the experimental branch of DGD 1.2 at version 1.2.18. Dworkin described them as follows:

Like clones, they are created from a master object, which is a normal, persistent object. Light-weight objects do have some restrictions:

  • they cannot be explicitly destruct

  • they cannot be used as an editor, user or parser object

  • they cannot have callouts

  • destruct a master object will also instantly destruct all light-weight objects made therefrom (!)

Furthermore, like arrays, they are local to the dataspace of some particular (persistent) object. This means that if a light-weight object is exported to some other object's dataspace, it will become a <copy> there at the end of the LPC thread, just as currently happens with arrays and mappings.


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 dgd/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.


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.

Example 4-2. Multiple inheritance with DGD

/* 
 * 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();
}
      

ANSI colours?

A good start would be to apply the ANSI patch that is listed in the list of packages for DGD. If it doesn't apply correctly you can quite likely figure out from the patch itself what the original intention was, since you only need to change one line in each file. The package also contains some documentation about vt100 escape sequences, which (as far as colours go) is probably what you want.


What is parse_string()?

If you're starting from scratch, I'd recommend checking this introduction that Steve Foley put together. It explains some of the basics.


What is an ASN?

ASN are a relatively recent addition to the experimental branch of DGD 1.2 (at 1.2.51), this is what Dworkin wrote at their introduction:

ASN stands for "arbitrary size number". In LPC, such numbers are represented by big-endian strings. If the highest bit of the first character of the string is set, the number is assumed to be negative, and in two's complement format. If you want to represent a positive number that starts with a byte that would make the string representation negative, simply precede it with a \0 character.

For example,

"\0\xff"

represents the positive number 0xff.

All of the ASN functions except for asn_mod() take 3 arguments, the third argument being the modulus, which must be a positive number greater than zero.

To compile DGD1.2.51 with MSVC, make sure to add the new source file, asn.c, to the project.

These kfuns were added to manipulate ASNs:

  • asn_add()

  • asn_and() (added in 1.2.55)

  • asn_cmp() (added in 1.2.52)

  • asn_div()

  • asn_lshift() (added in 1.2.55)

  • asn_mod()

  • asn_mult()

  • asn_or() (added in 1.2.55)

  • asn_pow() (added in 1.2.53)

  • asn_rshift() (added in 1.2.55)

  • asn_sub()

  • asn_xor() (added in 1.2.55)

It is recommended to upgrade at least to 1.2.55 to use this new feature.


Does DGD have encryption/decryption support?

Yes. From the very start there was the crypt() kfun which does the traditional DES encryption commonly used for passwords.

More recently Dworkin added the following kfuns for encryption and encryption related work:

  • hash_crc16() (added in 1.1.90)

  • hash_crc32() (added in 1.2.51)

  • hash_md5() (added in 1.1.90)

  • hash_sha1() (added in 1.2.51)

  • decrypt() (added in 1.2.55)

  • encrypt() (added in 1.2.55)

Dworkin wrote the following about this:

I'm going to start with providing basic DES encryption as a kfun. That should suffice to implement all the different DES modes (ECB, CBC, 3DES CBC, etc.) in LPC. I intend to wrap it in a general kfun, like this:

prepared_encrypt_key = encrypt("DES key", key);
encrypted = encrypt("DES", message, prepared_encrypt_key);

prepared_decrypt_key = decrypt("DES key", key);
message = decrypt("DES", encrypted, prepared_decrypt_key);
with
string encrypt(string cipher, string mesg_or_key, string keys...)
string decrypt(string cipher, string mesg_or_key, string keys...)
For unsupported ciphers, the kfuns would return nil. This way, it would be easy to make optional encryption packages that could be added or removed without breaking dumpfile compatibility. The kfuns could also be masked, for example in the implementation of 3DES CBC:
string encrypt(string cipher, string mesg, string keys...)
{
    switch (cipher) {
    case "3DES CBC key":
	return ::encrypt("DES key", mesg) +
	       ::decrypt("DES key", keys[0]) +
	       ::encrypt("DES key", keys[1]));

    case "3DES CBC":
	encrypted = "";
	keylen = strlen(keys[0]) / 3;
	while (strlen(mesg) >= 8) {
	    keys[1] = str = asn_xor(mesg[.. 7], keys[1]);
	    str = ::encrypt("DES", str, keys[0][.. keylen - 1]);
	    str = ::decrypt("DES", str, keys[0][keylen .. 2 * keylen - 1]);
	    str = ::encrypt("DES", str, keys[0][2 * keylen ..];
	    mesg = mesg[8 ..];
	    encrypted += str;
	}
	if (strlen(mesg) != 0) {
	    keys[1] = str = asn_xor(mesg, keys[1]);
	    str = ::encrypt("DES", str, keys[0][.. keylen - 1]);
	    str = ::decrypt("DES", str, keys[0][keylen .. 2 * keylen - 1]);
	    str = ::encrypt("DES", str, keys[0][2 * keylen ..];
	    keys[1] = str = asn_xor(str, keys[1]);
	    encrypted += str;
	}
	return encrypted;

    default:
	return ::encrypt(cipher, mesg, keys...);
    }
}


Chapter 5. Miscellaneous Topics

Can I use DGD commercially?

Yes you can. The email address to send enquiries to at BeeHive Internet can be found in the file dgd/doc/Commercial in the DGD distribution.

You may have heard of iChat Inc -- later renamed to Acuity Corporation and then turned into a subsidiary of Quintus Corporation -- in this respect, this would be because the commercial rights to DGD were licenced exclusively to that company from January 1996 until March 2001.

As an aside, the iChat.com domain is now owned by Apple and that company can now be found at globalchat.com. Such a confusing world we live in.

For more information see the dgd/Copyright and dgd/doc/Commercial files provided with DGD.


Getting help with DGD

There are a number of ports of call for help with DGD. A DGD mailing list is maintained by CIE and can be joined from the list's web page. For list-members there are also the list's archives, starting in July 2001, while for the period before that Dworkin has provided archives in mbox format.

The USENET newsgroup rec.games.mud.lp is also appropriate for postings about DGD. If you don't have access to a newsserver you can browse the archive at Google.


Appendix A. Credits and Legal

Credits

First and foremost thanks must go to Felix Croes (Dworkin) for creating DGD!

Several people (aside from Felix himself who has contributed to this FAQ in many ways) contributed to this FAQ, be it in terms of suggestions to the FAQ itself, by providing a webpage with helpful content, or some other way:

Erlend Simonsen, Frank Schmidt, Matt S., Mikael Lind, Noah Gibbs, Richard Braakman, Steve Foley, Wim van der Vegt.

And of course a big thank you to Greg Lewis for starting with this FAQ.


Legal

DGD itself is Copyright 1993 - 2002 BeeHive Internet Technologies, Inc. All Rights Reserved.

All trademarks mentioned in this FAQ are the property of their respective owners.

This FAQ was originally written by Greg Lewis but is currently maintained by Erwin Harte. You may redistribute it as you please in electronic or hard copy form as long as these credits and legal statements are left intact and any changes you make are marked as such.


Appendix B. Various Links

Glossary

This section was inspired by Noah Gibbs' page of DGD Terms and Concepts. I briefly considered merely linking to it (which is the WWW way, after all) but then decided to make it a section integrated with the rest of the FAQ instead.

atomic

Functions can be

DGD

Dworkin's Generic Driver

kfun

Kernel function. The functions built into the driver itself.

LWO

Light-weight object.

LPC

Lars Pensjö C, meaning the dialect of C that was interpreted by the gameengine (a.k.a. driver) he wrote.