This tutorial is intended for anyone with a basic knowledge of programming and a will to learn. You don't have to know C very well before you start, and I believe that even true programming beginners might be able to learn how to code. They will, of course, have far more to do. There is much more good material available on the topic of learning C than learning LPC, so it's recommended that novices attempt to learn at least the basics of C before attempting this book.
Experienced coders, including MUD coders, will need to read the tutorial since it explains concepts that are unique to DGD's LPC and to this book. They will be able to skim most of the book and then use it primarily as a reference. The selection of what is and what is not important is left to the reader.
The LPC language in actual application is closely wed to the driver and mudlib it uses. This edition of this textbook is meant for use with the DGD driver. Since the DGD driver includes a mudlib, the Kernel Library, in the standard distribution, and since the Kernel Library is public domain, we choose to include basic information on its use in this volume. The basic information all refers to plain, bare DGD, used with no other mudlib.
I'd like to start by thanking Thorsten Lockert and Christian Markus, perhaps better known as Plugh and Olorin, for their help in proofreading this text, suggesting improvements and in general being supportive and providing constructive feedback.
Without them this rather lengthy project would have taken even longer (mind-boggling, but true) to complete and ended up a lot worse.
I'd like to acknowledge Ronnie, of course, for writing the first, non-DGD edition of this text. I'd like to thank Felix Croes (Dworkin) for producing the excellent DGD driver that made all this possible. And I'd like to thank all the people out there writing MUDs and working on DGD. You've made the work that I do useful and in some cases, possible.
The manual is divided into three progressively more advanced sections. The first part explains the basics of coding and LPC without delving too deeply into specifics.
The second part is aimed at the intermediate audience, explaining many aspects of functions and operators more fully.
The third part handles applications and advanced topics that seemed inappropriate for the first two chapters. In addition to more advanced topics, this includes miscellaneous topics that the more casual programmer may not care about.
If you are a new MUD administrator you may be taken back at the thickness of this tutorial. Nonetheless, it's highly recommended that you read all of it eventually, and that you read at least an intermediate level of proficiency with all functions you commonly use. Bear in mind that in this era of internet security problems and rampant hacking, your MUD may be vulnerable as well. The better you understand your code, the harder it is for hackers and malevolent players or administrators to take advantage.
This manual is fairly extensive, but it's primarily aimed at builders and administrators rather than driver programmers or implementors who write mudlibs from scratch. It's important for those latter categories to know how their work is likely to be used, but the sort of very specific details that their work requires don't age well and require a massive amount of information that simply isn't useful to the more casual MUD administrator or builder. For such implementors working under DGD, I highly recommend the DGD mailing list. This list can be located from a web search engine. As of this writing, it is located at http://list.imaginary.com/mailman/listinfo/dgd. I recommend typing the words "DGD mailing list" into Google, just in case.
A note about gender: throughout the text I've used male pronouns. This is not meant as a statement on female coders, but simply a shorthand to avoid using the phrase "he or she" at every instance.
Chapters that describe functions and macros in detail have a subcaption with the names of the discussed items within brackets. This should make it easy to search for them, for later reference.
The distinction between driver (also called the "gamedriver") and mudlib is very simple in concept. The driver is the program that runs on the host computer. It is a language interpreter with an object management kernel, almost a small operating system in its own right. It defines the LPC language, interprets it and executes the instructions given to it through the LPC objects in the game.
Since the driver defines the LPC language, different LPC drivers define subtly different dialects of LPC. That's the reason for the specific DGD edition of this text. DGD's dialect includes some language features found in almost no other languages, and exports a very limited set of functions from the driver.
The mudlib is the collection of LPC objects that make up the basic game environment. It defines the "laws of physics" of the gameworld, or the program being used if it's not a game. For instance, DGD is used for Yahoo Chat. Therefore, there is somewhere a Yahoo Chat library for DGD. That's an example of a very unusual mudlib. More-standard mudlibs include GurbaLib, Phantasmal, Melville, and the LPMUD 2.4.5 library which has been adapted for use with DGD. Each of those mudlibs independently decides how its rooms, verbs, creatures and other defining characteristics work.
While the mudlib defines the standard objects and the commands a game uses, there is also code and data specific to an individual game. For instance, if you run an Old West game where the players can go into the Bar None Saloon, the code that makes the Saloon special is the domain code -- how the bartender acts, the mannerisms that the waitresses have, all of this is specific to an individual game, and usually kept separate from the mudlib code. This is called domain code and domain data.
The domain code and data is produced by administrators or builders of a game. A MUD also often calls these people wizards or immortals. Different games refer to them differently. This book will call all game staff "administrators". "Builder" denotes someone that produces domain code or domain data for the game.
Sub-areas of a MUD are also often called domains. The other common name for them is zones. This book will refer to them as zones to avoid confusion with the terms "domain code" and "domain data". Each zone will usually have a player in charge of it, one who regulates building within that area. Some zones will have only a single player in charge who will be the only builder of that zone.
While zones will be interconnected to some extent, usually they are kept as separate as the game allows. This prevents any conflict between the builders of the different areas over code or in-game objects.
If you're a new administrator or builder on an LPMUD, you'll want to find a zone to become part of, or start your own zone. Talk to the head administrator or builder of the MUD to find out how new builders are usually integrated into their MUD. Some MUDs like to start new builders on their own private area while others like to have them help out for awhile on existing areas.
Formatting code properly makes it easier to read, easier to use and generally more pleasant for all involved. This section describes some fairly standard code formatting conventions as well as why they may be worth the trouble.
Here are some good arguments for making the effort:
What follows here are some guidelines about how to format your code. Read it even though you might not fully understand what is being discussed, then go back and re-read it later after having learned the skills necessary. That way you won't pick up any bad habits and have to unlearn them.
Be aware also that the specifics of how a piece of code should be formatted is a very individual topic among programmers. Where and when whitespace should be added and the number of spaces in an indent are frequently disagreed on. If you're joining an existing MUD, find out if they have policies on code formatting. If you're starting your own, make sure to spell out your own policies on the topic.
if (this)
{
statement;
}
else if (that)
{
another_statement;
}
else
{
default_statement;
}
The important thing is to make sure to indent new blocks, and
to make sure you do it by the same amount everywhere you do it. If
you're modifying an existing piece of code, use the same number of
spaces that they do for indentation.
+ and -) have a space both before
and after the operator.
int a, b, c;
for (a = 0; a < 10; a++)
{
b = function_call(a, b * 2);
c = b * 3 / 4;
}
; on a separate line.
while (!(var = func(var)))
;
If you put it on the same line then it's very easy for
a reader to miss actual mistakes like this one:
for (i = 0 ; i < 100 ; i++);
{
<code that gets executed only once, but always>
}
#define and
#include statements should be placed at the top of
the file, or in a header file. The compiler allows you to spread
them through the file but that will often cause confusion.
/*
* <filename>
*
* <Short description of what the file does, no more than 5-7 lines.
* ...
* ... >
*
* Copyright (C): <your name and year>
*
*/
You should also include a brief note about the license on the
code you've written unless you have and retain all rights to all of
it. But if you're writing for a MUD, you need to grant them the
right to use the code. That's either done implicitly by the license
for the MUD or explicitly by getting you to sign over the rights
they need. Talk to your MUD administrators about this if you don't
understand. The MUD should have a license for any code and content
that you submit to them.
/*
* Author: <Your Name<
* Function name: <Function name>
* Description: <Short description of what the function does,
* usually no more than three lines.
* Arguments: <A list of all arguments, one per line
* arg1 - description no longer than the line.
* arg2 - next argument, etc. >
* Returns: <What the function returns>
*/
If the function doesn't take any arguments, or doesn't return
anything, simply remove those lines in the header.
#defines should be
written in capitals (e.g. #define AMOEBA "one celled
creature"). Doing this makes it easy to see what kind of
symbol is being handled at all times. Functions that use
#define are also called macros, or macro
functions.One of the easiest ways of getting a good editor is to use the emacs editor, set up to use a modified c++ mode. The c++ mode understands most LPC operators but needs a few hints on indentation. Some example lines of code for your .emacs file:
;; emacs lisp script start
(setq auto-mode-alist (append '(
("\\.l" . my-c++-mode)
("\\.y" . my-c++-mode)
("\\.c" . my-c++-mode)
("\\.h" . my-c++-mode))
auto-mode-alist))
(defun my-c++-mode () (interactive)
(c++-mode)
(setq c-indent-level 4)
(setq c-brace-offset 0)
(setq c-label-offset -4)
(setq c-continued-brace-offset -4)
(setq c-continued-statement-offset 4))
;; emacs end
An added advantage of using emacs is that you can correct another coder's indention by typing 'M-<', 'M->', 'M-x indent-region'.
If you have no clue what emacs is you can look it up on a web search engine or simply continue to use your favorite text editor. Some MUDs will require you to use a specific editor or submit code in specific ways, which may also affect your choice of editor.
This chapter will show you some more involved examples, and hit some of the more interesting features of LPC that set it apart from similar languages like C.
To present things on the screen for the player to read, the
message() function is called on that player's user
object. Different mudlibs supply the user object in different
ways.
There are two special characters that are often used to format
text, tab and newline. They are written as
\t and \n respectively within DGD
strings. The tab character inserts 8 space characters and
newline breaks the line.
void message(string text);
e.g.
user->message("Hello there!\n");
user->message("\tThis is an indented string.\n");
user->message("This is a string\non several lines\n\tpartly\nindented.\n");
/* The result is:
Hello there!
This is an indented string.
This is a string
on several lines
partly
indented.
*/