A
/ \ _ Play Now Nemesis on
| | | | _______ _ _ _______ _______ _ _______
| |\ | | | ____| | \ / | | ____| / ____| | | / ____|
/-------/-------------------------------------------------------------------,
O= Home <=XX| About News Pics Adventurers Wizards Download Connect >
\-------\-------------------------------------------------------------------'
| | \ | | |____ | | | | | |____ ___ \ \ | | ___ \ \
| | \_| |_______| |_| |_| |_______| |_______/ |_| |_______/
\ /
V
Documentation Area
Document Path: /doc/misc/A_new_Wizard_is_born_part2
Being a wizard in an LPmud
--------------------------
Congratulations. The fact that you are reading this text probably means that
you have just become Wizard in Nemesis. As a wizard, you have an own workroom
and directory.
As a wizard you may extend the game by writing new rooms. But to prevent that
every wizard makes his own castle and doesn't care about the game as a whole,
there are domains in Nemesis. Domains are instutitions in Nemesis, where
several wizards work on the same project, led by a domain lord.
To be able to add new rooms to the game, you have to join one of the various
domains. You can inform yourself about domains in the two rooms reserved for
domains in the inner guild. If you know which domain to join you have to ask
the corresponding domain lord to join you into his domain.
Then you can start coding and if you think, your area is ready to open it for
players you have to ask your domain lord to approve it and he will put it into
the game then.
First of all, try to remember this at all times
-----------------------------------------------
As a wizard, you have immense powers. But, with those powers comes responsi-
bility - so always think before you do anything. For example, it is possible
to destroy other wizards' areas, to crash the game, and to kill all the
players. And it IS possible to do all these things accidentally, so PLEASE be
careful!
Remember that as far as the game is concerned you are NO LONGER a part of it.
Wizards do not play the game, they are above that and participate only by
adding new ideas, like quests and rooms.
If you don't know what you are doing, then you probably shouldn't do it. If
you know what you are doing, but not if you should do it, then you probably
shouldn't do that either.
You can view the rules for wizards any time, writing 'man RULES'. You should
have read them already if you are reading this text, though.
The file structure is a tree
----------------------------
LPmud mimics the file system hierarchy and file handling commands of UNIX. A
directory is a set of files, where those "files" can be both normal files and
other directories. Everything starts with the so-called root directory, the
name of which is "/" (at least from inside LPmud!).
As in UNIX, a file or a directory is referred to by its file name or its path
name, for example "workroom.c" and "/players/padrone/workroom.c". The rooms in
the "basic" LPmud world are in the directory "/room", the domains are in the
directory "/d" and the wizard home directories are in "/players", for example
"/players/padrone".
At the moment you can list only files belonging to you or to your domain.
How you can get access to more files is explained later.
Some commands for handling files:
ls - list the files in a directory
rm - remove a file
ed - edit a file using LPmud's built-in, line-oriented, editor
cat - print the contents of a file on the screen
more - print the contents of a file, approx. one screenful at a time
tail - print the last few lines of a file
cd - change the current directory
Where do I find the documentation?
----------------------------------
There is a directory called "/doc" (try the commands "ls" and "ls /doc"), that
contains documentation. For example the subdirectory "/doc/LPC" contains files
with information about the language LPC, and the subdirectory "/doc/build"
contains files about how to build.
You can easily find out documentation with the 'man' command, which searches
through all these directories for a specific file. If you want to code a
monster, you would write 'man monster', if you want to code a pub, you would
have to write 'man pub'.
It can happen that you won't find what you look for in the documentation. In
that case, either ask another wizard, read the code (which actually contains
some very useful comments), or find out by testing.
One of the first things you should do is to read the entire contents of /doc.
This is not as much work as it seems and it really pays off very soon, since
you later will remember where to look for explanations of commands and
routines.
Remember also that the Archwizards, i.e all wizards with level > 35, have as
part of their duties the obligation to help other wizards with their problems
in Nemesis.
The best way of reading the documentation is to do 'man' and then man the
sub-directories displayed, to see what you is there.
You can also use 'cd /doc' and 'ls' to find out, but man is normally more con-
venient. I especially want to point out that the information on the editor
"ed" can be found in "/doc/build/ed". Of course you can also read it with
'man ed'.
Object-oriented programming in LPmud
------------------------------------
When you play LPmud, everything you encounter (weapons, monsters, players,
rooms etc.) are OBJECTS. Each object is an INSTANCE of a CLASS of objects.
One class can INHERIT part of its design from another class.
In LPmud, an instance is either created by CLONING or LOADING the object
class, and each class is described in a file, written in a C-like language
called LPC.
These "class descriptions" are the programs in LPmud. All program code that
you write as a wizard, or that is part of the standard LPmud world, will be
part of a description of an object class, a class of objects that can be
loaded and cloned.
Loading, cloning and updating
-----------------------------
"Loading an object" means the process of taking a class description file, for
example "/obj/weapon.c", and reading it into the game. This is done as soon as
that object is used in any way.
For example if a function in the object is called from LPC, or if another
object tries to enter it (as when a player walks into a room) the object is
loaded. You can also force an object to load, using the 'load' command.
When the object is loaded, one instance of the object class is created. If
there should be only one instance, as for example for (most) rooms, this is
enough.
If you need to create several instances of a class of objects, you clone them.
Objects can be cloned using the command "clone", as in 'clone /obj/torch', and
with the LPC function clone_object, as in torch = clone_object("obj/torch");
Cloning an object will cause it to be loaded, if it wasn't already loaded.
When you have changed the description of an object by editing the file, and
want to load the new version of the object, you can use the wizard command
"update". Then load (or clone) the new version.
If the object in question is a room, a 'goto <roomname>' will load the room as
well. You can also update and reload on object in one go with the 'reload'
command.
LPC
---
LPC is a dialect of C and differs from C mainly in being simplified and in
that it allows for handling the objects. It has only four data types (plus
arrays of those data types), fewer operators and a simplified control
structure.
Note that before the contents of a file is read it is run through the standard
C pre-processor. This program can be used to insert other files into the file
being read, and to define constants and macros. Lines starting with '#', as
the lines (no blanks before the '#'!)
#include <room2.h>
#define INSURANCE_LIMIT 1000
#define CLONE(var, file) var = clone_object(file);
are all commands to the preprocessor.
Read more about LPC in the files in the directory /doc/LPC ! You can read more
about the C preprocessor in any book about C, but that is hardly neccesary for
the ordinary use of LPC.
Functions:
----------
There exists two types of functions in LPC, called LOCAL and EXTERNAL
functions. A local function is defined in LPC code in an LPC file, and is
contained in an object. A local function can be called from LPC code inside
the object or from LPC code in another object.
Objects communicate with each other by calling functions in each other.
A local function can be declared STATIC, meaning that it can only be called
from LPC code within the same object. External functions are "built in" in
LPC, so it has no definition in LPC code.
Examples of local functions are the functions set_value and query_value
in "/obj/treasure.c". Examples of external functions are write(), time()
and add_action().
Read more about functions in the file "/doc/LPC/function".
All external functions are documented in "/doc/efun/<function>", where
<function> is the name of the function. Local functions are documented in
other sub directories obj '/doc', depending on the object described.
For example local functions concerning monsters are listed in /doc/monster,
local functions concerning rooms are listed in /doc/room. Again, usr the
'man' command if you want to find out about certain manual files.
Error messages
--------------
If an error occurs when LPmud is trying to load one of your objects, an error
message will be printed on the file '/log/<name>' (where <name> is your name).
If you caused the error message, you will get it written on your screen as
well.
Those error messages, for all the wizards, and also some other error messages,
are also written on the file '/mud.log'. Sometimes you have to look at that
file too to find out what caused an error. That file will usually grow quickly,
and the command 'tail /mud.log' will prove useful.
The last error is stored for every wizard. It can be obtained simply by doing
'ed'. If there was an error, it will be displayed with the offending line
number, and the correct file will be edited.
Also, don't forget to check "/log/<name>.rep" often. When a player files a bug
report in one of your rooms, using "bug", "typo" or "idea", the message ends
up in that file!
Building
--------
Start by looking at the existing rooms. As a wizard, when you enter a room,
LPmud prints the path name of the object that is the room, for example
"/room/forest2". You can look at the definition of the room by using the
command "more /room/forest2.c" or "cat /room/forest2.c".
For most purposes it is sufficient to use the standard room routines that
you get by inherited by including <room2.h>. Read more about how to build in
the files in the directory "/doc/build".
Remember also that there exists a special directory called "/room/examples"
which contains lots of examples of how to write rooms and objects in LPC.
More about that later in this text.
An example of a room
--------------------
This is an example of how a file describing a room can look like. It is not
actually the code of your workroom, but it could be. To look at the actual
code of your workroom enter:
cd
more workroom.c
#include <room2.h>
reset(arg) {
if (arg) return;
set_short("wizard workroom");
set_long("This is your new workroom. Furnish it at your own will.\n");
set_exits( ({
"guild/adv/inner", "up",
"room/examples/room01", "out" }) );
set_items( ({
"workroom", "It is just your workroom" }) );
set_weather(LIGHT_ON);
}
When the first player enters the room after the game was started, the file is
run through the C preprocessor, yielding a much larger code which is then
interpreted by the gamedriver, the actual LPmud program.
The code produced is much larger and contains a lot of functions called lfuns
(local functions). Two of these local functions are of special interest, and
many objects will have them locally defined:
reset():This function is called automatically, with the argument 0, when the
object is created (that is, loaded or cloned), and after that every
2-3 hours or so, but then with the argument 1. It is used to init-
ialize things in an object, and to periodically reset it (like putting
new monsters in the different rooms, when they have been killed by all
those brutal players).
init(): When a living object (a player or a monster) sees this object (if he,
she or it enters the object, or arrives in the same room as the object,
or the object is moved into the player or monster, or the object is
moved into the same room as the player or object), the living object
calls the function init in this object, with the living object as
current player.
If you redefine functions that are automatically defined by the inherited
objects, you will sometimes want to call that function in the inherited code.
You do that with the operator "::". If you define the function "init()" in
your room but still would like to call the "init()" in "/room/room" you do
that with the command "::init();". Typically this IS something that you want
to do but remember to put the call to the inherited function first.
The example above was a special room called a "workroom". As a wizard you
have a command called "home" that will bring you to your workroom, which
you automatically receive when you receive your home directory.
As full wizard you enter the game there, not in the church. If there is an
error in your workroom, you will be teleported to the church. So always have a
look the code of your workroom to certify that it is without errors.
You can always enter "home" to go there. You can change this room later to fit
your own tastes.
Some more local functions that are defined in many objects
----------------------------------------------------------
heart_beat(): For objects that have a heart beat, the local function heart_beat
will be called (automatically) every two seconds. The heart beat is
started by calling the external function 'set_heart_beat()', with a
non-zero argument from the object. This can be used to simulate that
time is going between events in the room, but usually the external
function 'call_out()' is better to use for that purpose.
drop(): If an object has a local function called "drop", and it returns a
non-zero value, the object cannot be dropped. If such a non-droppable
object is held by a player that quits, it is destructed automatically.
get(): For a player or monster to be able to pick up an object, that object
must have a local function called "get", that returns a non-zero value.
query_value(), query_weight(), query_level(), query_npc(), etc:
Lots of different functions returning values of local variables in the
objects.
set_value(), set_weight(), set_level(), set_npc(), etc:
Lots of different functions for setting local variables in the objects.
Local functions that common to all objects in the game are documented in
'/doc/object'. Specific local functions are listed in other doc subdirectories,
like '/doc/monster' or '/doc/room'.
The documentation files say all about usable local functions in the standard
objects, but if you want to find out, what mechanism are used, you have to
look at the LPC files themselves. Here is a list of the most used and
inherited files:
/obj/player.c - For player functions.
/obj/monster.c - For monster functions.
/obj/living.c - For common monster and player functions.
/obj/item.c - For simple items
/obj/weapon.c - For weapon functions.
/obj/armour.c - For armour functions.
/obj/room/room.c - For standard room functions.
Player commands
---------------
A living object (a player or a monster) can perform commands. Every command
has to be defined in an object, although some commands are defined by the
player object itself, like "quit" and "look".
All other commands, like "south", "north" and "buy" (in the shop) has to be
defined in an object. If you look at the following piece of code (of a room)
you can see how the external function add_action is used to add one command.
This is usually done in the local function "init".
init() { ::init(); add_action("read", "read"); }
read(str) {
if (str=="sign") {
write("The sign reads: Don't enter the dungeon!\n");
return 1;
}
}
You could add this code to your workroom and add a sign to your description.
Then update and load the room and look at the result.
The "current player"
--------------------
The external function "this_player()" will return the current player. This is
the player OR monster that performed the command that LPmud is now executing
or caused the function "init()" in an object to be run.
The external function "write()" will send the text it is given as argument to
the current player. The function "say()" will send the text to all living
objects that are in the same room as the current player (or that are inside
the current player!), but NOT to the current player itself.
When changing your rooms etc
----------------------------
ALWAYS, ALWAYS, ALWAYS test all changes that you make to your code, at least
by doing update and clone or load on the object that you changed. Do this
even after a trivial change, like correcting the spelling of a word in a
message. It is very easy to put accidentaly a period or a semicolon somewhere
in your code, and even if the your code is correct there can be bugs in the
LPmud game itself that can cause it not to work.
Some non-technical hints on how to be a good and/or popular wizard
------------------------------------------------------------------
In this section I will relate parts of the /doc/build/RULES file. I believe
that some of the things discussed in the rules and guidelines can be of
general interest to how a wizard should behave and what things he (or she or
it) should build and not build. So here are some of the rules and guidelines:
Do not harm a player directly!
This means, among other things, that you must never attack or kill a
player. Also take care not to zap or teleport away (or heal) a monster
a player is currently fighting (stat the monster first). Never teleport a
player without a good reason.
Do not help a player directly!
This means, for example, that you must not help by killing or attacking
monsters, healing players or giving away items (an occasional beer might
be excused). Also take care not to leave valuable items lying around, eg.
don't zap a monster and leave its weapon-containing corpse to rot on the
street.
Remember that the business of players is their business only! A typical case
is when one player kills another and the killed one starts yelling for blood.
Let them sort it out on their own. You may NOT interfere and if you get really
mad about it, tell or mail an Archwizard or administrator.
Do not make deadly traps!
A player must never die because he didn't know what happens in the next
room. If some room is very dangerous, make some hint (like the giant
footprints outside the giant's lair). Deathtraps is about the only case
when Lars allowes a player to get back his previous level and equipment,
excluding bugs in the code. It also results in an angry letter from him or
an Archwizard, which you don't need or want!
Do not send killer-monsters out into the world!
This means that if you create a monster that can walk out of the castle,
make it a nice monster (ie. it should never attack players).
Don't make too good things!
For example, don't create weapons with weapon class > 20 if there is no
big drawback with them. Weapons with wc 20 should be at least as hard to
get as the swords of the three giants in the giant conference. Also, body
armour (type "armour") muas be max armour class 4, and additional armour,
like helmets, always class 1.
And don't make the monsters too easy to kill. A monster with much treasure
and/or many experience points should be big, dangerous and very hard to
kill.
Remember that the purpose of the game is for it to be fun and enjoyable
both for players and for wizards - not to have all players converge on
your castle just to get that wc 30 sword.
Don't make healing too easily available!
It's an important part of the game that players have to wait for their hit
points to regenerate. Also, the pub is one of the main sources of player
interaction and role playing. Remember that even if you only heal a few
points per player command (like "drink from fountain"), many players use
macros and abbreviations and can still heal almost instantly.
Make the players drunk, the healing very limited, the cost very high, or
the place very hard to get to! Portable healing in the way of potions and
food upsets the balance of the game. If you create such an object make
sure they are rare and very expensive.
Don't build lots and lots of extra pubs and shops!
The pub, as mentioned above, and also the shop, are natural meeting points
and important sources of player interaction. Therefore you should try not
to build your own pub or shop if you don't really need it (for example in
a quest or for a guild).
Don't make your own "perfect tool"!
It seems that every wizard wants to make a perfect tool that can do
anything. Use one of the common tools here and the quicktyper if are are
a lazy typist.
Prices of equipment.
Should be set with some sense. A player will NEVER be payed more than
1000 coins in a shop. The only reason to set a higher value is to prevent
another player from buying the same object back from the shop at a too low
price.
It is very easy to create powerful magic items in LPmud, but this is generally
NOT a good idea. The balance of the game must be kept and remember that
NOTHING in the world is given away for free. It's very hard to write rules
that define how magic may and may not be used, and becuace of that the
wizard's own judgement must be trusted in almost all cases. There are however
some things I'd like to warn about right now.
Teleporting players is a nuisance!
It wreaks havoc with quests and is generally disliked. Generally tele-
porting is only allowed within your own area (or the domain). Even then,
it must cost at least 50 spell points. In any case a special archwizard
approvement is required for teleports.
New magic spells for players.
Are very easy to write but it is very hard to judge what effect they will
have on the game in advance. A discussion about magic and how it should be
limited is currently on the way. Some very loose rules exist and the best
option is to ask an Archwizard FIRST and implement the spell AFTERWARDS,
if ever.
If you happily make something and put a lot of time into it only to be
told in no-negotiation-possible-terms to remove it, you will only get mad
and frustrated. Use your good judgement and in doubtful cases do something
else or ask the other wizards what they think first.
Examples of rooms, monsters, objects etc.
-----------------------------------------
Read the files in the directory /room/examples. They are all just documented
examples of standard problems in LPmud. Like creating new rooms, monsters
and equipment along with some general advice. The best thing might be to
"go" there by typing "goto /room/examples/room01" and walk around for a while,
before actually viewing the code. There should be also an exit called 'out'
in your workroom, which leads you to that example rooms.
File Transfer
-------------
There are 2 possibilies to transfer your files from and to Nemesis, if
you don't like to use ed, they are called Mtp and Ftp. Enter 'man mtp' or
'man ftp' to obtain further information about them.
Now read 'man RULES' if you haven't done.
This page was generated in LPC
Imprint / Impressum