Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/doc/KURS/COMMENTS b/doc/KURS/COMMENTS
new file mode 100644
index 0000000..4ef9ca9
--- /dev/null
+++ b/doc/KURS/COMMENTS
@@ -0,0 +1,75 @@
+	BEMERKUNGEN ZUM THEMA SPIELVERDERBER
+	------------------------------------
+
+	Eine konsequente Verwendung der Worte Moerder, Verbrecher,
+	o.ae. verkennt den wahren Charakter:
+	Es sind einfach nur Spielverderber, und sollten auch 
+	dementsprechend behandelt werden.
+
+	Im Moment wird noch nicht gespielt.
+	Ergo gibt es noch keine Spielverderber.
+
+	Wenn es denn welche gibt, wie geht man mit ihnen um ?
+	-	Man spielt nicht mehr mit Ihnen.
+	-	Man nimmt ihnen den Spass, sodass sie von selber
+		aufhoeren mitzuspielen, bzw. anderen das Spiel
+		zu verderben.
+
+	Vorschlaege(!) fuer Massnahmen:
+	
+	-	Belegen mit Fluechen.
+
+	(zB Erkaeltungen, oder zeitweiliger Verlust der Faehigkeit,
+	Waffen zu tragen, Schlechtes Gewissen, dass man immer wieder
+	daran erinnert wird, was man boeses getan hat. etc.)
+	Wer hat weitere Ideen ??
+
+	Vorteile:
+
+		+	Die Bestrafung erfolgt innerhalb des Spieles.
+		+	Durch die Dauer kann die Strafe fein dosiert
+			werden.
+
+	Nachteil: 
+
+		+	Magier sind auf diese Weise schwer zu
+			bestrafen.
+
+
+	-	Geld oder XP wegnehmen.
+
+	-	Herabstufung. Nur im NOTFALL
+
+	-	Aussschluss vom Spiel. Nur im AEUSSERSTEN NOTFALL
+
+
+	Wer ein Spielverderber ist, entscheidet im allgemeinen
+	die Gemeinschaft der Spielenden. Deshalb darf es keine
+	fatalen Eingriffe in das Spiel durch die Entscheidung 
+	einzelner Spieler geben!
+
+	BEMERKUNGEN ZUM THEMA FLEISS VON MAGIERN
+	----------------------------------------
+
+	Wenn ein Magier selten im Spiel ist, heisst das nicht,
+	dass er sich, wenn er einmal da ist, um so staerker
+	bemerkbar machen muss.
+
+
+	BEMERKUNGEN ZU GENAUEREN REGELN
+	-------------------------------
+
+	Man sollte sich nicht an irgendwelchen Zahlen (wiz_levels),
+	Verordnungen, Geschaeftsordnugnen etc. festhalten, sondern sich
+	immer vor Augen halten, dass es sich im ein Spiel handelt.
+	Es haben sich Leute zusammengefunden, um miteinander Spass zu
+	haben. Dieses Spiel ist keine so komplexe Gesellschaft wie die
+	reale; deshalb sollte es auch keiner so komplexen Regeln
+	beduerfen.
+
+	Olpp, Sheriff des MorgenGrauens
+	Rumata, MudAdm des MorgenGrauens
+
+	P.S.:
+		Kommentare und weitere Vorschlaege sind herzlich
+		willkommen.
diff --git a/doc/KURS/LPC-KURS/Contents b/doc/KURS/LPC-KURS/Contents
new file mode 100644
index 0000000..0dd4efb
--- /dev/null
+++ b/doc/KURS/LPC-KURS/Contents
@@ -0,0 +1,13 @@
+                             LPC Basics
+                      Written by Descartes of Borg
+                            23 april 1993
+
+Introduction
+Chapter 1: Introduction to the Coding Environment
+Chapter 2: The LPC Program
+Chapter 3: LPC Data Types
+Chapter 4: Functions
+Chapter 5: The Basics of Inheritance
+Chapter 6: Variable Handling
+Chapter 7: Flow Control
+Chapter 8: The Data Type Object
diff --git a/doc/KURS/LPC-KURS/Introduction b/doc/KURS/LPC-KURS/Introduction
new file mode 100644
index 0000000..2e3c7ff
--- /dev/null
+++ b/doc/KURS/LPC-KURS/Introduction
@@ -0,0 +1,106 @@
+                             LPC Basics
+                     Written by Descartes of Borg
+                            23 april 1993
+ 
+ 
+                            INTRODUCTION
+               This manual, how to use it, and its terms
+ 
+I have seen a lot of requests lately on USENET for LPC manuals.  In addition,
+the immortals on my mud have been telling how good the building documentation
+of Nightmare is, but that there was just no adequate explanation of the
+LPC programming language.  So I decided to try my hand at writing a manual.
+Some things you should keep in mind.
+LPC is a very easy programming language to learn, and it has real
+value in that place most of us know as the real world.  I began playing
+muds in 1991, and in the space of a month created an unimpressive area
+and musician's guild on the original Bates College MUD called Orlith.
+After that, I moved to Los Angeles for a year and had no contact with
+mudding or computers.  In June of 1992, I was back on the internet and
+a wizard of Igor.  In September of 1992 I began coding the Nightmare
+mudlib for our use, and then later decided to distribute it due to there
+not being any mudlibs for MudOS at the time that a person could just throw
+up a running mud with (now, that of course is not the case :)).
+So, I have been doing serious coding for less than a year.  As a
+Philosophy major in a world of Computer Science majors, I just want to
+make clear that it is not at all required that you have ever done anything
+with your computer than log into a mud in order for you to really come
+to understand LPC coding.  This manual makes the following assumptions:
+Someone has taught you basic UNIX commands like ls, cd, mkdir, mv, rm, etc.
+You know how to enter your mud's editor and write a file.  No other
+assumptions are made.  If you know C, you are handicapped in that LPC
+looks a lot like C, but it is not C.  Your preconceptions about
+modular programming development will be a hinderence you will have to
+overcome.  If you have never heard of the C programming language (like
+me in May of 1991), then you are only missing an understanding of the
+simple constructs of C like the flow of program execution and logical
+operators and such.  So a C guru has no real advantage over you, since
+what they know from C which is applicable to LPC is easy to pick up.
+The stuff they know about C which makes them a guru is irrelevant to
+LPC.
+ 
+The chapters of this manual are meant to be read in order.  Starting with
+the introduction, going sequentially through the chapter numbers as
+ordered in the contents file.  Each chapter begins with a paragraph or
+two explaining what you should have come to understand by that point
+in your studies.  After those introductory paragraphs, the chapter then
+begins to discuss its subject matter in nauseating detail.  At the end
+of the chapter is a briefly worded summary of what you should understand
+from that chapter if I have been successful.  Following that may or may
+not be some sidenotes relevant to the subject at hand, but not necessary
+to its understanding.
+ 
+If at any time you get to a chapter intro, and you have read the preceeding
+chapters thoroughly and you do not understand what it says you should
+understand by that point, please mail me!  Clearly, I have failed at that
+point and I need to know where it is I have gone wrong so I can revise
+it properly.  Similarly, if you do not understand what the chapter summary
+says you should, please mail me.  If your mumud is on the MudOS intermud
+system, mail descartes@nightmare.  Otherwise mail borg@hebron.connected.com.
+ 
+Some basic terms this manual uses:
+driver-
+This is the C program which is the game.  It accepts incoming sockets
+(links to other computers), interprets LPC code defined by the mudlib,
+keeps mud objects in memory, makes periodic attempts to clean unused
+mud objects from memory, makes periodic calls to objects, and so on.
+ 
+mudlib-
+LPC code which defines the world in which you are in.  The driver of itself
+is not a game.  It is just a program which allows the creation of a
+multi-user environment.  In some sense, the driver is like an LPC
+compiler, and the mudlib is like a compiler's library (a very loose
+analogy).  The mudlib defines basic objects which will likely be used
+over and over again by people creating in the mud world.  Examples of
+such objects are /std/room (or /room/room), /std/user.c (or /obj/player.c),
+and so on.
+ 
+area or castle:
+Specific creator coded objects which often use a feature of LPC called
+inheritance to make use of the properties of basic mudlib objects and
+turn them into specific objects to be used by players in the game
+ 
+object:
+a room, a weapon, a monster, a player, a bag, etc.  More importantly,
+every individual file with a .c extension is an object.  Objects are
+used in different ways.  Objects like /std/living.c are inherited by
+objects like monster.c and user.c.  Others are cloned, which means a
+duplicate of that code is loaded into memory.  And still others are
+simply loaded into memory to be referenced by other objects.
+ 
+native and compat:
+these two terms refer to two popular flavours of drivers.  Native mode
+mudlibs make use of on the design of LPMud driver 3.0 and later.  You may
+have a 3.0 driver however, but have a 2.4.5 style mudlib.  This is what
+is meant by compat mode.  Mudlibs which are native mode are any for
+MudOS, CD, and LPMud mudlibs that
+are listed as native.  Compat mudlibs are any LPMud mudlib before 3.0 and
+those which are 3.* compat mudlibs.  I believe Amylaar's is compat.
+[ Not true, Amylaar supports native and compat mudlibs, MorgenGrauen
+  is native - Boing ]
+
+Good Luck!
+George Reese
+(Descartes of Borg)
+12 july 1993
+borg@hebron.connected.com
diff --git a/doc/KURS/LPC-KURS/chapter1 b/doc/KURS/LPC-KURS/chapter1
new file mode 100644
index 0000000..6f233d0
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter1
@@ -0,0 +1,90 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: 25 may 1993
+
+CHAPTER 1: Introduction to the Coding Environment
+
+1.1 UNIX file structure
+LPMuds use basic UNIX commands and its file structure.  If you know
+UNIX commands already, then note (with a few exceptions) options are
+not available to the commands.  Like DOS, UNIX is heirarchical.  The
+root directory of which all directories are sub-directories is called
+root(/).  And from those sub-directories you may have further
+sub-directories.  A directory may be referred to in two different ways:
+1) by its full name, or absolute name, or 2) by its relative name.
+Absolute name refers to the directory's full path starting from / winding
+down the directory tree until you name the directory in question.  For
+example:
+
+    /players/descartes/obj/monster
+
+refers to the directory monster which is a sub-directory of obj which
+is a sub-directory of descartes which is a sub-directory of players
+which is a sudirectory of /.
+
+The relative name refers to the name relative to another directory.
+The above example is called monster relative to /players/descartes/obj,
+but it is also called obj/monster relative to /players/descartes,
+descartes/obj/monster relative to /players, and finally
+players/descartes/obj/monster relative to /.  You can tell the
+difference between absolute names and relative names because absolute
+names always start with /.  In order to know exactly which directory
+is being named by a relative name, you naturally must know what
+directory it is relative to.
+
+A directory contains sub-directories and files.  LPMuds only use text files
+inside the mudlib.  Like directories, files have both absolute and
+relative names.  The most basic relative name is often referred to as the file
+name, with the rest of the absolute name being referred to as the path.  So,
+for the file: /players/descartes/castle.c, castle.c is the file name, and
+/players/descartes is the path.
+
+On some muds, a file with a file name beginning with a . (like .plan) is
+not visible when you list files with the regular file listing command.
+
+1.2 UNIX Commands
+Along with the UNIX file structure, LPMuds use many UNIX commands.  Typical
+UNIX commands on most muds are:
+pwd, cd, ls, rm, mv, cp, mkdir, rmdir, more, head, cat, ed
+If you have never before seen UNIX commands, you probably are thinking this
+is all nonsense.  Well, it is, but you got to use them.  Before getting
+into what they mean though, first a discussion of current directory.
+If you know DOS, then you know what a current working directory is.
+At any given point, you are considered to be "in" some directory.  This
+means that any relative file or directory names you give in UNIX commands
+are relative to that directory.  For example, if my current directory is
+/players/descartes and I type "ed castle.c" (ed is the command to edit),
+then it assumes I mean the file /players/descartes/castle.c
+
+pwd: shows you your current working directory
+cd: changes your current working directory.  You may give either relative
+    or absolute path names.  With no arguments, it changes to your home
+    directory.
+ls: lists all files in the directory named.  If no directory is named,
+    it lists the files of the current working directory
+rm: deletes the file named
+mv: renames the file named
+cp: copies the file named
+mkdir: makes a new directory
+rmdir: deletes a directory.  All files must have been first removed.
+more: pages the file named so that the file appears on your screen one
+    page at a time.
+cat: shows the whole file to you at once
+head: shows you the first several lines of a file
+tail: shows you the last several lines of a file
+ed: allows you to edit a file using the mud editor
+
+1.3 Chapter Summary
+UNIX uses a heirarchical file structure with the root of the tree being
+named /.  Other directories branch off from that root directory and
+in turn have their own sub-directories.  All directories may contain
+directories and files.  Directories and files are referred to either
+by their absolute name, which always begins with /, or by their relative
+name which gives the file's name relative to a particular directory.
+In order to get around in the UNIX files structure, you have the
+typical UNIX commands for listing files, your current directory, etc.
+On your mud, all of the above commands should have detailed help commands
+to help you explore exactly what they do.  In addition, there should
+be a very detailed file on your mud's editor.  If you are unfamiliar
+with ed, you should go over this convoluted file.
diff --git a/doc/KURS/LPC-KURS/chapter2 b/doc/KURS/LPC-KURS/chapter2
new file mode 100644
index 0000000..f9ad566
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter2
@@ -0,0 +1,195 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: 16 june 1993
+
+CHAPTER 2: The LPC Program
+
+2.1 About programs
+The title of this chapter of the textbook is actually poorly named, since
+one does not write programs in LPC.  An LPC coder instead writes *objects*.
+What is the difference?  Well, for our purposes now, the difference is
+in the way the file is executed.  When you "run" a program, execution
+begins at a definite place in the program.  In other words, there
+is a place in all programs that is noted as the beginning where program
+execution starts.  In addition, programs have definite end points,
+so that when execution reaches that point, the execution of the program
+terminates.  So, in short, execution of a program runs from a definite
+beginning point through to a definite end point.  This is not so with
+LPC objects.
+
+With muds, LPC objects are simply distinct parts of the C program which
+is running the game (the driver).  In other words, execution of the mud
+program begins and ends in the driver.  But the driver in fact does
+very little in the way of creating the world you know when you play
+a mud.  Instead, the driver relies heavily on the code created in LPC,
+executing lines of the objects in the mud as needed.  LPC objects thus
+have no place that is necessarily the beginning point, nor do they
+have a definite ending point.
+
+Like other programming languages, an LPC "program" may be made up of
+one or more files.  For an LPC object to get executed, it simple
+needs to be loaded into the driver's memory.  The driver will call lines
+from the object as it needs according to a structure which will be
+defined throughout this textbook.  The important thing you need to
+understand at this point is that there is no "beginning" to an LPC
+object in terms of execution, and there is no "end".
+
+2.2 Driver-mudlib interaction
+As I have mentioned earlier, the driver is the C program that runs on
+the host machine.  It connects you into the game and processes LPC code.
+Note that this is one theory of mud programming, and not necessarily
+better than others.  It could be that the entire game is written in C.
+Such a game would be much faster, but it would be less flexible in
+that wizards could not add things to the game while it was running. This
+is the theory behind DikuMUDs.  Instead, LPMUDs run on the theory that
+the driver should in no define the nature of the game, that the nature
+of the game is to be decided by the individuals involved, and that
+you should be able to add to the game *as it is being played*.  This
+is why LPMUDs make use of the LPC programming language.  It allows
+you to define the nature of the game in LPC for the driver to read and
+execute as needed.  It is also a much simpler language to understand
+than C, thus making the process of world creation open to a greater
+number of people.
+
+Once you have written a file in LPC (assuming it is corrent LPC ), it justs
+sits there on the host machine's hard drive until something in the game
+makes reference to it.  When something in the game finally does make
+reference to the object, a copy of the file is loaded into memory and
+a special *function* of that object is called in order to initialize
+the values of the variables in the object.  Now, do not be concerned
+if that last sentence went right over your head, since someone brand
+new to programming would not know what the hell a function or a variable
+is.  The important thing to understand right now is that a copy of the
+object file is taken by the driver from the machine's hard drive and
+stored into memory (since it is a copy, multiple versions of that
+object may exist).  You will later understand what a function is, what
+a variable is, and exactly how it is something in the game made reference
+to your object.
+
+2.3 Loading an object into memory
+Although there is no particular place in an object code that must exist
+in order for the driver to begin executing it, there is a place for which
+the driver will search in order to initialize the object.  On compat 
+drivers, it is the function called reset().  On native muds it is the
+function called create(). [ MorgenGrauen is native - Boing ]
+
+LPC objects are made up of variables (values which can change) and
+functions which are used to manipulate those variables.  Functions
+manipulate variables through the use of LPC grammatical structures,
+which include calling other functions, using externally defined
+functions (efuns), and basic LPC expressions and flow control 
+mechanisms.
+
+Does that sound convoluted?  First lets start with a variable.  A
+variable might be something like: level.  It can "vary" from sitation
+to situation in value, and different things use the value of the player's
+level to make different things happen.  For instance, if you are a
+level 19 player, the value of the variable level will be 19.  Now
+if your mud is on the old LPMud 2.4.5 system where levels 1-19 are
+players and 20+ are wizards, things can ask for your level value to
+see if you can perform wizard type actions.  Basically, each object
+in LPC is a pile of variables with values which change over time.
+Things happen to these objects based on what values its variables
+hold.  Often, then things that happen cause the variables to change.
+
+So, whenever an object in LPC is referenced by another object currently
+in memory, the driver searches to see what places for values the
+object has (but they have no values yet).  Once that is done, the driver
+calls a function in the object called reset() or create() (depending
+on your driver) which will set up the starting values for the object's
+variables.  It is thus through *calls* to *functions* that variable
+values get manipulated.
+
+But create() or reset() is NOT the starting place of LPC code, although
+it is where most LPC code execution does begin.  The fact is, those
+functions need not exist.  If your object does just fine with its
+starting values all being NULL pointers (meaning, for our purposes
+here, 0), then you do not need a create() or reset() function.  Thus
+the first bit of execution of the object's code may begin somewhere
+completely different.
+
+Now we get to what this chapter is all about.  The question: What
+consists a complete LPC object?  Well, an LPC object is simply
+one or more functions grouped together manipulating 0 or more
+variables.  The order in which functions are placed in an object
+relative to one another is irrelevant.  In other words:
+
+-----
+void init() { add_action("smile", "smile"); }
+
+void create() { return; }
+
+int smile(string str) { return 0; }
+-----
+
+is exactly the same as:
+
+-----
+void create() { return; }
+
+int smile(string str) { return 0; }
+
+void init() { add_action("smile", "smile"); }
+_____
+
+Also important to note, the object containing only:
+
+-----
+void nonsense() {}
+-----
+
+is a valid, but trivial object, although it probably would not interact
+properly with other objects on your mud since such an object has no
+weight, is invisible, etc..
+
+2.4 Chapter summary
+LPC code has no beginning point or ending point, since LPC code is used
+to create objects to be used by the driver program rather than create
+individual programs.  LPC objects consist of one or more functions whose
+order in the code is irrelevant, as well as of zero or more variables whose
+values are manipulated inside those functions.  LPC objects simply sit
+on the host machine's hard driver until referenced by another object in
+the game (in other words, they do not really exist).  Once the object
+is referenced, it is loaded into the machine's memory with empty
+values for the variables.  The function reset() in compat muds or
+create() in native muds is called in that object if it exists to allow
+the variables to take on initial values.  Other functions in the object
+are used by the driver and other objects in the game to allow interaction
+among objects and the manipulation of the LPC variables.
+
+A note on reset() and create():
+create() is only used by muds in native mode (see the textbook Introduction
+for more information on native mode vs. compat mode).  It is only used
+to initialize newly referenced objects.
+
+reset() is used by both muds in compat mode and native mode.  In compat
+mode, reset() performs two functions.  First, it is used to initialize
+newly referenced objects.  In addition, however, compat mode muds use
+reset() to "reset" the object.  In other words, return it to its initial
+state of affairs.  This allows monsters to regenerate in a room and doors
+to start back in the shut position, etc..  Native mode muds use reset()
+to perform the second function (as its name implies).
+
+So there are two important things which happen in LP style muds which
+cause the driver to make calls to functions in objects.  The first is
+the creation of the object.  At this time, the driver calls a function
+to initalize the values in the object.  For compat mode muds, this
+is performed by the function named reset() (with an argument of 0,
+more on this later though).  For muds running in native mode, this is
+performed by the function create().
+
+The second is the returning of the room to some base state of affairs.
+This base set of affairs may or may not be different from the initial
+state of affairs, and certainly you would not want to take up time
+doing redundant things (like resetting variables that never change).
+Compat mode muds nevertheless use the same function that was used to
+create the object to reset it, that being reset().  Native mode muds,
+who use create() to create the room, instead use reset() to reset it.
+All is not lost in compat mode though, as there is a way to tell the
+difference between creation and resetting.  For reset purposes, the
+driver passes either 1 or the reset number as an argument to reset()
+in compat mode.  Now this is meaningless to you now, but just keep in
+mind that you can in fact tell the difference in compat mode.  Also
+keep in mind that the argment in the creation use of reset is 0 and
+the argument in the reset use is a nonzero number.
diff --git a/doc/KURS/LPC-KURS/chapter3 b/doc/KURS/LPC-KURS/chapter3
new file mode 100644
index 0000000..f7e89a4
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter3
@@ -0,0 +1,185 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: 17 june 1993
+
+CHAPTER 3: LPC Data Types
+
+3.1 What you should know by now
+LPC object are made up of zero or more variables manipulated by one or
+more functions.  The order in which these functions appear in code is
+irrelevant.  The driver uses the LPC code you write by loading copies of
+it into memory whenever it is first referenced and additional copies
+through cloning.  When each object is loaded into memory, all the variables
+initially point to no value.  The reset() function in compat muds, and
+create() in native muds are used to give initial values to variables in
+objects.  The function for creation is called immediately after the object
+is loaded into memory.  However, if you are reading this textbook with no
+prior programming experience, you may not know what a function is or how
+it gets called.  And even if you have programming experience, you may
+be wondering how the process of functions calling each other gets started
+in newly created objects.  Before any of these questions get answered,
+however, you need to know more about what it is the functions are
+manipulating.  You therefore should thouroughly come to know the concept
+behind LPC data types.  Certainly the most boring subject in this manual,
+yet it is the most crucial, as 90% of all errors (excepting misplaced
+{} and ()) involve the improper usage of LPC data types.  So bear through
+this important chapter, because it is my feeling that understanding this
+chapter alone can help you find coding much, much easier.
+
+3.2 Communicating with the computer
+You possibly already know that computers cannot understand the letters
+and numbers used by humans.  Instead, the "language" spoken by computers
+consists of an "alphabet" of 0's and 1's.  Certainly you know computers
+do not understand natural human languages.  But in fact, they do not
+understand the computer languages we write for them either.  Computer
+languages like BASIC, C, C++, Pascal, etc. are all intermediate
+languages.  They allow you to structure your thoughts more coherently
+for translation into the 0's and 1's of the computer's languages.
+
+There are two methods in which translation is done: compilation and
+interpretation.  These simply are differences betweem when the 
+programming language is translated into computer language.  With
+compiled languages, the programmer writes the code then uses a program
+called a compiler to translate the program into the computer's
+language.  This translation occurs before the program is run.  With
+interpreted languages however, the process of translation occurs as
+the program is being run.  Since the translation of the program is
+occurring during the time of the program's running in interpreted
+languages, interpreted languages make much slower programs than
+compiled languages.
+
+The bottom line is, no matter what language you are writing in, at
+some point this has to be changed into 0's and 1's which can be
+understood by the computer.  But the variables which you store in
+memory are not simply 0's and 1's.  So you have to have a way in
+your programming languages of telling the computer whether or not
+the 0's and 1's should be treated as decimal numbers or characters or
+strings or anything else.  You do this through the use of data types.
+
+For example, say you have a variable which you call 'x' and you give
+it the decimal whole number value 65.  In LPC you would do this through
+the statement:
+
+-----
+x = 65;
+-----
+
+You can later do things like:
+
+_____
+write(x+"\n");        /* \n is symbolically represents a carriage return */
+y = x + 5;
+-----
+
+The first line allows you to send 65 and a carriage return to someone's screen.
+The second line lets you set the value of y to 70.
+The problem for the computer is that it does not know what '65' means when
+you tell it x = 65;.  What you think of 65, it might think of as:
+00000000000000000000000001000001
+But, also, to the computer, the letter 'A' is represented as:
+00000000000000000000000001000001
+So, whenever you instruct the computer write(x+"\n");, it must have some
+way of knowing that you want to see '65' and not 'A'.
+
+The computer can tell the difference between '65' and 'A' through the use
+of data types.  A data types simply says what type of data is being stored
+by the memory location pointed to by a given variable.  Thus, each LPC
+variable has a variable type which guides conversions.  In the example
+given above, you would have had the following line somewhere in the
+code *before* the lines shown above:
+
+-----
+int x;
+-----
+
+This one line tells the driver that whatever value x points to, it will
+be used as the data type "int", which is short for integer, or whole
+number.  So you have a basic introduction into the reason why data types
+exist.  They exist so the driver can make sense of the 0's and 1's that
+the computer is storing in memory.
+
+3.3 The data types of LPC
+All LPMud drivers have the following data types:
+
+void, status, int, string, object, int *, string *, object *, mixed *
+
+Many drivers, but not all have the following important data types which
+are important to discuss:
+
+float, mapping, float *, mapping *
+
+And there are a few drivers with the following rarely used data types
+which are not important to discuss:
+
+function, enum, struct, char
+
+3.4 Simple data types
+This introductory textbook will deal with the data types void, status,
+int, float, string, object, mand mixed.  You can find out about the
+more complex data types like mappings and arrays in the intermediate
+textbook.  This chapter deals with the two simplest data types (from the
+point of view of the LPC coder), int and string.
+
+An int is any whole number.  Thus 1, 42, -17, 0, -10000023 are all type int.
+A string is one or more alphanumeric characters.  Thus "a", "we are borg",
+"42", "This is a string" are all strings.  Note that strings are always
+enclosed in "" to allow the driver to distinguish between the int 42 and
+the string "42" as well as to distinguish between variable names (like x)
+and strings by the same names (like "x").
+
+When you use a variable in code, you must first let the driver know
+what type of data to which that variable points.  This process is
+called *declaration*.  You do this at the beginning of the function
+or at the beginning of the object code (outside of functions before all
+functions which use it).  This is done by placing the name of the data type
+before the name of the variable like in the following example:
+
+-----
+void add_two_and_two() {
+    int x;
+    int y;
+
+    x = 2;
+    y = x + x;
+}
+-----
+
+Now, this is a complete function.  The name of the function is 
+add_two_and_two().  The function begins with the declaration of an
+int variable named x followed by the declaration of an in variable
+named y.  So now, at this point, the driver now has two variables which
+point to NULL values, and it expects what ever values end up there to be
+of type int.
+
+A note about the data types void and status:
+Void is a trivial data type which points to nothing.  It is not used
+with respect to variables, but instead with respect to functions.  You
+will come to understand this better later.  For now, you need only
+understand that it points to no value.  
+
+The data type status is a boolean data type.  That is, it can only have
+1 or 0 as a value.  This is often referred to as being true or false.
+
+3.5 Chapter summary
+For variables, the driver needs to know how the 0's and 1's the computer
+stores in memory get converted into the forms in which you intend them
+to be used.  The simplest LPC data types are void, status, int, and string.
+You do not user variables of type void, but the data type does come
+into play with respect to functions.  In addition to being used for
+translation from one form to the next, data types are used in determining
+what rules the driver uses for such operations as +, -, etc.  For example,
+in the expression 5+5, the driver knows to add the values of 5 and 5
+together to make 10.  With strings however, the rules for int addition
+make no sense.  So instead, with "a"+"b", it appends "b" to the string "a"
+so that the final string is "ab".  Errors can thus result if you mistakenly
+try to add "5"+5.  Since int addition makes no sense with strings, the
+driver will convert the second 5 to "5" and use string addition.  The final
+result would be "55".  If you were looking for 10, you would therefore
+have ended up with erroneous code.  Keep in mind, however, that in most
+instances, the driver will not do something so useful as coming up with
+"55".  It comes up with "55" cause it has a rule for adding a string
+to an int, namely to treat the int as a string.  In most cases, if you
+use a data type for which an operation or function is not defined
+(like if you tried to divide "this is" by "nonsense", "this is"/"nonsense"),
+the driver will barf and report an error to you.
diff --git a/doc/KURS/LPC-KURS/chapter4 b/doc/KURS/LPC-KURS/chapter4
new file mode 100644
index 0000000..4f44cdc
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter4
@@ -0,0 +1,225 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: 22 june 1993
+
+CHAPTER 4: Functions
+
+4.1 Review
+By this point, you should be aware that LPC objects consist of functions
+which manipulate variables.  The functions manipulate variables when they
+are executed, and they get executed through *calls* to those functions.
+The order in which the functions are placed in a file does not matter.
+Inside a function, the variables get manipulated.  They are stored in
+computer memory and used by the computer as 0's and 1's which
+get translated to and from useable output and input through a device
+called data typing.  String data types tell the driver that the
+data should appear to you and come from you in the form of alphanumeric
+characters.  Variables of type int are represented to you as whole
+number values.  Type status is represented to you as either 1 or 0.
+And finally type void has no value to you or the machine, and is not
+really used with variable data types.
+
+4.2 What is a function?
+Like math functions, LPC functions take input and return output.
+Languages like Pascal distinguish between the concept of proceedure abd
+the concept of function.  LPC does not, however, it is useful to
+understand this distinction.  What Pascal calls a proceedure, LPC
+calls a function of type void.  In other words, a proceedure, or function
+of type void returns no output.  What Pascal calls a function differs
+in that it does return output.  In LPC, the most trivial, correct
+function is:
+
+-----
+void do_nothing() { }
+-----
+
+This function accepts no input, performs no instructions, and returns no
+value.
+
+There are three parts to every properly written LPC function:
+1) The declaration
+2) The definition
+3) The call
+
+Like with variables, functions must be declared.  This will allow the
+driver to know 1) what type of data the function is returning as output,
+and 2) how many input(s) and of what type those input(s) are.  The
+more common word for input is parameters.
+A function declaration therefore consists of:
+type name(parameter1, parameter2, ..., parameterN);
+The declaration of a function called drink_water() which accepts a string as
+input and an int as output would thus look like this:
+
+-----
+int drink_water(string str);
+-----
+
+where str is the name of the input as it will be used inside the function.
+
+The function definition is the code which describes what the function actually
+does with the input sent to it.  
+The call is any place in other functions which invokes the execution of the
+function in question.  For two functions write_vals() and add(), you thus
+might have the following bit of code:
+
+-----
+/* First, function declarations.  They usually appear at the beginning
+   of object code. 
+*/
+void write_vals();
+int add(int x, int y);
+
+/* Next, the definition of the function write_vals().  We assume that
+   this function is going to be called from outside the object
+*/
+void write_vals() {
+    int x;
+
+    /*N Now we assign x the value of the output of add() through a call */
+    x = add(2, 2);
+    write(x+"\n");
+}
+
+/* Finally, the definition of add() */
+int add(int x, int y) {
+    return (x + y);
+}
+-----
+
+Remember, it does not matter which function definition appears first in the
+code.  This is because functions are not executed consecutively.  Instead,
+functions are executed as called.  The only requirement is that the
+declaration of a function appear before its definition and before the
+definition of any function which makes a call to it.
+
+4.3 Efuns
+Perhaps you have heard people refer to efuns.  They are externally defined
+functions.  Namely, they are defined by the mud driver.  If you have
+played around at all with coding in LPC, you have probably found some
+expressions you were told to use like this_player(), write(), say(),
+this_object(), etc. look a lot like functions.  That is because they are
+efuns.  The value of efuns is that they are much faster than LPC functions,
+since they already exist in the binary form the computer understands.
+
+In the function write_vals() above, two functions calls were made.  The first was to
+the functions add(), which you declared and defined.  The second call, however,
+was to a function called write(), and efun.  The driver has already declared
+and defined this function for you.  You needs only to make calls to it.
+
+Efuns are created to hanldle common, every day function calls, to handle
+input/output to the internet sockets, and other matters difficult to be
+dealt with in LPC.  They are written in C in the game driver and compiled
+along with the driver before the mud comes up, making them much faster
+in execution.  But for your purposes, efun calls are just like calls
+made to your functions.  Still, it is important to know two things of any
+efun: 1) what return type does it have, and 2) what parameters of what
+types does it take.
+
+Information on efuns such as input parameters and return types is often
+found in a directory called /doc/efun on your mud.  I cannot
+detail efuns here, because efuns vary from driver to driver.  However,
+you can often access this information using the commands "man" or "help"
+depending on your mudlib.  For instance, the command "man write" would
+give you information on the write efun.  But if all else fails,
+"more /doc/efun/write" should work.
+
+By looking it up, you will find write is declared as follows:
+
+-----
+void write(string);
+-----
+
+This tells you an appropriate call to write expects no return value and
+passes a single parameter of type string.
+
+4.4 Defining your own functions
+Although ordering your functions within the file does not matter, ordering
+the code which defines a function is most important.  Once a function
+has been called, function code is executed in the order it appears
+in the function definition.  In write_vals() above, the instruction:
+    
+-----
+x = add(2, 2);
+-----
+
+Must come before the write() efun call if you want to see the appropriate
+value of x used in write().  
+
+With respect to values returned by function, this is done through the "return"
+instruction followed by a value of the same data type as the function.  In
+add() above, the instruction is "return (x+y);", where the value of (x+y)
+is the value returned to write_vals() and assigned to x.  On a more
+general level, "return" halts the execution of a function and returns
+code execution to the function which called that function.  In addition,
+it returns to the calling function the value of any expression that follows.
+To stop the execution of a function of type void out of order, use
+"return"; without any value following.  Once again, remember, the data
+type of the value of any expression returned using "return" MUST be the
+same as the data type of the function itself.
+
+4.5 Chapter Summary
+The files which define LPC objects are made of of functions.  Functions, in
+turn, are made up of three parts:
+    1) The declaration
+    2) The definition
+    3) The call
+Function declarations generally appear at the top of the file before any
+defintions, although the requirement is that the declaration must appear
+before the function definition and before the definition of any function
+which calls it.
+Function definitions may appear in the file in any order so long as they
+come after their declaration.  In addition, you may not define one function
+inside another function.
+Function calls appear inside the definition of other functions where you
+want the code to begin execution of your function.  They may also appear
+within the definition of the function itself, but this is not recommended
+for new coders, as it can easily lead to infinite loops.
+
+The function definition consists of the following in this order:
+    1) function return type
+    2) function name
+    3) opening ( followed by a parameter list and a closing )
+    4) an opening { instructing the driver that execution begins here
+    5) declarations of any variables to be used only in that function
+    6) instructions, expressions, and calls to other functions as needed
+    7) a closing } stating that the function code ends here and, if no
+       "return" instruction has been given at this point (type void functions
+       only), execution returns to the calling function as if a r"return"
+       instruction was given
+
+The trivial function would thus be:
+
+-----
+void do_nothing() {}
+-----
+
+since this function does not accept any input, perform any instructions, or
+return any output.
+
+Any function which is not of type void MUST return a value of a data type
+matching the function's data type.
+
+Each driver has a set of functions already defined for you called efuns
+These you need neither need to declare nor define since it has already
+been done for you.  Furthermore, execution of these functions is faster
+than the execution of your functions since efuns are in the driver.
+In addition, each mudlib has special functions like efuns in that they
+are already defined and declared for you, but different in that they
+are defined in the mudlib and in LPC.  They are called simul_efuns, or
+simulated efuns.  You can find out all about each of these as they are
+listed in the /doc/efun directory on most muds.  In addition many
+muds have a command called "man" or a "help" command which allows you
+simply to call up the info files on them.
+
+Note on style:
+Some drivers may not require you to declare your functions, and some
+may not require you to specify the return type of the function in its
+definition.  Regardless of this fact, you should never omit this information
+for the following reasons:
+    1) It is easier for other people (and you at later dates) to read your
+       code and understand what is meant.  This is particularly useful
+       for debugging, where a large portion of errors (outside of misplaced
+       parentheses and brackets) involve problems with data types (Ever
+       gotten "Bad arg 1 to foo() line 32"?).
+    2) It is simply considered good coding form.
diff --git a/doc/KURS/LPC-KURS/chapter5 b/doc/KURS/LPC-KURS/chapter5
new file mode 100644
index 0000000..29d2a0c
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter5
@@ -0,0 +1,161 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: 01 july 1993
+
+CHAPTER 5: The Basics of Inheritance
+
+5.1 Review
+You should now understand the basic workings of functions.  You should be
+able to declare and call one.  In addition, you should be able to recognize
+function definitions, although, if this is your first experience with LPC,
+it is unlikely that you will as yet be able to define your own functions.
+There functions form the basic building blocks of LPC objects.  Code
+in them is executed when another function makes a call to them.  In making
+a call, input is passed from the calling function into the execution of
+the called one.  The called function then executes and returns a value
+of a certain data type to the calling function.  Functions which return
+no value are of type void.
+
+After examining your workroom code, it might look something like this
+(depending on the mudlib):
+
+-----
+inherit "/std/room";
+
+void create() {
+    ::create();
+    set_property("light", 2);
+    set_property("indoors", 1);
+    set("short", "Descartes' Workroom");
+    set("long", "This is where Descartes works.\nIt is a cube.\n");
+    set_exits( ({ "/d/standard/square" }), ({ "square" }) );
+}
+-----
+
+If you understand the entire textbook to this point, you should recognize
+of the code the following:
+    1) create() is the definition of a function (hey! he did not declare it)
+    2) It makes calls to set_property(), set(), and set_exits(), none
+       of which are declared or defined in the code.
+    3) There is a line at the top that is no variable or function declaration
+       nor is it a function definition!
+
+This chapter will seek to answer the questions that should be in your head
+at this point:
+    1) Why is there no declaration of create()?
+    2) Where are the functions set_property(), set(), and set_exits() declared
+       and defined?
+    3) What the hell is that line at the top of the file?
+
+5.2 Object oriented programming
+Inheritance is one of the properties which define true object oriented
+programming (OOP).  It allows you to create generic code which can be used
+in many different ways by many different programs.  What a mudlib does is
+create these generalized files (objects) which you use to make very specific
+objects.
+
+If you had to write the code necessary for you to define the workroom above,
+you would have to write about 1000 lines of code to get all the functionality
+of the room above.  Clearly that is a waste of disk space.  In addition,
+such code does not interact well with players and other rooms since every
+creator is making up his or her own functions to perform the functionality
+of a room.  Thus, what you might use to write out the room's long description,
+query_long(), another wizard might be calling long().  This is the primary
+reason mudlibs are not compatible, since they use different protocols for
+object interaction.
+
+OOP overcomes these problems.  In the above workroom, you inherit the
+functions already defined in a file called "/std/room.c".  It has all
+the functions which are commonly needed by all rooms defined in it.  When
+you get to make a specific room, you are taking the general functionality
+of that room file and making a unique room by adding your own function,
+create().
+
+5.3 How inheritance works
+As you might have guessed by now, the line:
+
+-----
+inherit "/std/room";
+-----
+
+has you inherit the functionality of the room "/std/room.c".  By inheriting
+the functionality, it means that you can use the functions which have
+been declared and defined in the file "/std/room.c"  In the Nightmare Mudlib,
+"/std/room.c" has, among other functions, set_property(), set(), and
+set_exits() declared and defined.  In your function create(), you are
+making calls to those functions in order to set values you want your
+room to start with.  These values make your room different from others, yet
+able to interact well with other objects in memory.
+
+In actual practice, each mudlib is different, and thus requires you to use
+a different set of standard functions, often to do the same thing.  It is
+therefore beyond the scope of this textbook even to describe what
+functions exist and what they do.  If your mudlib is well documented,
+however, then (probably in /doc/build) you will have tutorials on how
+to use the inheritable files to create such objects.  These tutorials
+should tell you what functions exist, what input they take, the data
+type of their output, and what they do.
+
+5.4 Chapter summary
+This is far from a complete explanation of the complex subject of inheritance.
+The idea here is for you to be able to understand how to use inheritance in
+creating your objects.  A full discussion will follow in a later textbook.
+Right now you should know the following:
+    1) Each mudlib has a library of generic objects with their own general
+       functions used by creators through inheritance to make coding objects
+       easier and to make interaction between objects smoother.
+    2) The functions in the inheritable files of a mudlib vary from mudlib
+       to mudlib.  There should exist documentation on your mud on how to
+       use each inheritable file.  If you are unaware what functions are
+       available, then there is simply no way for you to use them.  Always
+       pay special attention to the data types of the input and the data
+       types of ay output.
+    3) You inherit the functionality of another object through the line:
+
+-----
+inherit "filename";
+-----
+       
+       where filename is the name of the file of the object to be inherited.
+       This line goes at the beginning of your code.
+
+Note:
+You may see the syntax ::create() or ::init() or ::reset() in places.
+You do not need fully to understand at this point the full nuances of this,
+but you should have a clue as to what it is. The "::" operator is a way
+to call a function specifically in an inherited object (called the scope
+resolution operator).  For instance, most muds' room.c has a function
+called create().  When you inherit room.c and configure it, you are doing
+what is called overriding the create() function in room.c.  This means
+that whenever ANYTHING calls create(), it will call *your* version and not
+the one in room.c.  However, there may be important stuff in the room.c
+version of create().  The :: operator allows you to call the create() in
+room.c instead of your create().
+An example:
+
+-----
+#1
+
+inherit "/std/room";
+
+void create() { create(); }
+-----
+
+-----
+#2
+
+inherit "/std/room";
+
+void create() { ::create(); }
+-----
+
+Example 1 is a horror.  When loaded, the driver calls create(), and then
+create() calls create(), which calls create(), which calls create()...
+In other words, all create() does is keep calling itself until the driver
+detects a too deep recursion and exits.
+
+Example 2 is basically just a waste of RAM, as it is no different from room.c
+functionally.  With it, the driver calls its create(), which in turn calls
+::create(), the create() in room.c.  Otherwise it is functionally
+exactly the same as room.c.
diff --git a/doc/KURS/LPC-KURS/chapter6 b/doc/KURS/LPC-KURS/chapter6
new file mode 100644
index 0000000..6a64215
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter6
@@ -0,0 +1,333 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: july 5 1993
+
+CHAPTER 6: Variable Handling
+
+6.1 Review
+By now you should be able to code some simple objects using your muds standard
+object library.  Inheritance allows you to use functions defined in those
+objects without having to go and define yourself.  In addition,
+you should know how to declare your own functions.  This
+chapter will teach you about the basic elements of LPC which will allow you to
+define your own functions using the manipulation of variables.
+
+6.2 Values and objects
+Basically, what makes objects on the mud different are two things:
+1) Some have different functions
+2) All have different values
+
+Now, all player objects have the same functions.  They are therefore
+differentiated by the values they hold.  For instance, the player
+named "Forlock" is different from "Descartes" *at least* in that they
+have different values for the variable true_name, those being
+"descartes" and "forlock".
+
+Therefore, changes in the game involve changes in the values of the objects
+in the game.  Functions are used to name specific process for manipulating
+values.  For instance, the create() function is the function whose
+process is specifically to initialize the values of an object.
+Within a function, it is specifically things called instructions which are
+responsible for the direct manipulation of variables.
+
+6.3 Local and global variables
+Like variables in most programming language, LPC variables may be declared
+as variables "local" to a specific function, or "globally" available
+to all functions.  Local variables are declared inside the function which
+will use them.  No other function knows about their existence, since
+the values are only stored in memory while that function is being executed.
+A global variable is available to any function which comes after its
+declaration in the object code.  Since global variables take up RAM for
+the entire existence of the object, you should use them only when
+you need a value stored for the entire existence of the object.
+Have a look at the following 2 bits of code:
+
+-----
+int x;
+
+int query_x() { return x; }
+
+void set_x(int y) { x = y; }
+-----
+
+-----
+void set_x(int y) {
+    int x;
+
+    x = y;
+    write("x is set to x"+x+" and will now be forgotten.\n");
+}
+-----
+
+In the first example, x is declared outside of any functions, and therefore
+will be available to any function declared after it.  In that example,
+x is a global variable.
+In the second example, x is declared inside the function set_x().  It
+only exists while the function set_x() is being executed.  Afterwards,
+it ceases to exist.  In that example, x is a local variable.
+
+6.4 Manipulating the values of variables
+Instructions to the driver are used to manipulate the values of variables.
+An example of an instruction would be:
+
+-----
+x = 5;
+-----
+
+The above instruction is self-explanatory.  It assigns to the variable
+x the value 5.  However, there are some important concepts in involved
+in that instruction which are involved in instructions in general.
+The first involves the concept of an expression.  An expression is
+any series of symbols which have a value.  In the above instruction,
+the variable x is assigned the value of the expression 5.  Constant
+values are the simplest forms in which expressions can be put.  A constant
+is a value that never changes like the int 5 or the string "hello".
+The last concept is the concept of an operator.  In the above example,
+the assignment operator = is used.
+
+There are however many more operators in LPC, and expressions can get
+quite complex.  If we go up one level of complexity, we get:
+
+-----
+y = 5;
+x = y +2;
+-----
+
+The first instruction uses the assignment operator to assign the value
+of the constant expression 5 to the variable y.  The second one
+uses the assignment operator to assign to x the value of the expression
+(y+2) which uses the addition operator to come up with a value which
+is the sum of the value of y and the value of the constant expression 2.
+Sound like a lot of hot air?
+
+In another manner of speaking, operators can be used to form complex
+expressions.  In the above example, there are two expressions in the
+one instruction x = y + 2;:
+    1) the expression y+2
+    2) the expression x = y + 2
+As stated before, all expressions have a value.  The expression
+y+2 has the value of the sum of y and 2 (here, 7);
+The expression x = y + 2 *also* has the value of 7.
+So operators have to important tasks:
+    1) They *may* act upon input like a function
+    2) They evaluate as having a value themselves.
+Now, not all operators do what 1 does.  The = operators does act upon
+the value of 7 on its right by assigning that value to x.  The operator
++ however does nothing.  They both, however, have their own values.
+
+6.5 Complex expressions
+As you may have noticed above, the expression x = 5 *itself* has a value
+of 5.  In fact, since LPC operators themselves have value as expressions,
+they cal allow you to write some really convoluted looking nonsense like:
+    i = ( (x=sizeof(tmp=users())) ? --x : sizeof(tmp=children("/std/monster"))-1)
+which says basically:
+    assing to tmp the array returned by the efun users(), then assign to x
+    the value equal to the number of elements to that array.  If the value
+    of the expression assigning the value to x is true (not 0), then assign
+    x by 1 and assign the value of x-1 to i.  If x is false though,
+    then set tmp to the array returned by the efun children(), and then
+    assign to i the value of the number of members in the array tmp -1.
+Would you ever use the above statement? I doubt it.  However you might
+see or use expressions similar to it, since the ability to consolidate
+so much information into one single line helps to speed up the execution of
+your code.  A more often used version of this property of LPC operators
+would be something like:
+    x = sizeof(tmp = users());
+    while(i--) write((string)tmp[i]->query_name()+"\n");
+instead of writing something like:
+    tmp = users();
+    x = sizeof(tmp);
+    for(i=0; i<x; i++) write((string)tmp[i]->query_name()+"\n");
+Things like for(), while(), arrays and such will be explained later.
+But the first bit of code is more concise and it executed faster.
+
+NOTE: A detailed description of all basic LPC operators follows the chapter
+summary.
+
+
+6.6 Chapter Summary
+You now know how to declare variables and understand the difference between
+declaring and using them globally or locally.  Once you become familiar
+with your driver's efuns, you can display those values in many different
+ways.  In addition, through the LPC operators, you know how to change
+and evaluate the values contained in variables.  This is useful of course
+in that it allows you to do something like count how many apples have
+been picked from a tree, so that once all apples have been picked, no
+players can pick more.  Unfortunately, you do not know how to have
+code executed in anything other than a linera fashion.  In other words,
+hold off on that apple until the next chapter, cause you do not know
+how to check if the apples picked is equal to the number of apples in the
+tree.  You also do not know about the special function init() where you
+give new commands to players.  But you are almost ready to code a nice,
+fairly complex area.
+
+6.7 LPC operators
+This section contains a detailed listing of the simpler LPC operators,
+including what they do to the values they use (if anything) and the value
+that they have.
+
+The operators described here are:
+=    +    -    *    /    %    +=    -=    *=    /=    %=
+--    ++    ==    !=    >    <    >=    <=    !    &&    ||
+->    ? :
+
+Those operators are all described in a rather dry manner below, but it is best
+to at least look at each one, since some may not behave *exactly* as
+you think.  But it should make a rather good reference guide.
+
+= assignment operator:
+    example: x = 5;
+    value: the value of the variable on the *left* after its function is done
+    explanation: It takes the value of any expression on the *right* and
+      assigns it to the variable on the *left*.  Note that you must use
+      a single variable on the left, as you cannot assign values to 
+      constants or complex expressions.
+
++ addition operator:
+    example: x + 7
+    value: The sum of the value on the left and the value on the right
+    exaplanation: It takes the value of the expression on the right and
+      adds it to the value of the expression on the left. For values
+      of type int, this means the numerical sum.  For strings,
+      it means that the value on the right is stuck onto the value on
+      the left ("ab" is the value of "a"+"b").  This operator does not
+      modify any of the original values (i.e. the variable x from
+      above retains its old value).
+
+- subtraction operator:
+    example: x - 7
+    value: the value of the expression on the left reduced by the right
+    explanation:  Same characteristics as addition, except it subtracts.
+      With strings: "a" is the value of "ab" - "b"
+
+* multiplication operator:
+    example: x*7
+    value and explanation: same as with adding and subtracting except
+      this one performs the math of multiplication
+
+/ division operator:
+    example: x/7
+    value and explanation: see above
+
++= additive assignment operator:
+    example: x += 5
+    value: the same as x + 5
+    exaplanation: It takes the value of the variable on the left
+      and the value of the expression on the right, adds them together
+      and assigns the sum to the variable on the left.
+      example: if x = 2... x += 5 assigns the value
+        7 to the variable x.  The whole expression
+        has the value of 7.
+
+-= subtraction assignment operator
+    example: x-=7
+    value: the value of the left value reduced by the right value
+    examplanation: The same as += except for subtraction.
+
+*= multiplicative assignment operator
+    example: x *= 7
+    value: the value of the left value multiplied by the right
+    explanation: Similar to -= and += except for addition.
+
+/= division assignment operator
+    example: x /= 7
+    value: the value of the variable on the left divided by the right value
+    explanation: similar to above, except with division
+
+++ post/pre-increment operators
+    examples: i++ or ++i
+    values: 
+      i++ has the value of i
+      ++i has the value of i+1
+    explanation: ++ changes the value of i by increasing it by 1.
+      However, the value of the expression depends on where you
+      place the ++.  ++i is the pre-increment operator.  This means
+      that it performs the increment *before* giving a value.
+      i++ is the post-ncrement operator.  It evalutes before incrementing
+      i.  What is the point?  Well, it does not much matter to you at
+      this point, but you should recognize what it means.
+
+-- post/pre-decrement operators
+    examples: i-- or --i
+    values:
+      i-- the value of i
+      --i the value of i reduced by 1
+    explanation: like ++ except for subtraction
+
+== equality operator
+    example: x == 5
+    value: true or false (not 0 or 0)
+    explanation: it does nothing to either value, but
+      it returns true if the 2 values are the same.
+      It returns false if they are not equal.
+
+!= inequality operator
+    example: x != 5
+    value: true or false
+    explanation returns true if the left expression is not equal to the right
+      expression.  It returns fals if they are equal
+
+> greater than operator
+    example: x > 5
+    value: true or false
+    explanation: true only if x has a value greater than 5
+      false if the value is equal or less
+
+< less than operator
+>= greater than or equal to operator
+<= less than or equal to operator
+    examples: x < y    x >= y    x <= y
+    values: true or false
+    explanation: similar as to > except
+      < true if left is less than right
+      >= true if left is greater than *or equal to* right
+      <= true if the left is less than *or equal to* the right
+
+&& logical and operator
+|| logical or operator
+    examples: x && y      x || y
+    values: true or false
+    explanation: If the right value and left value are non-zero, && is true.
+      If either are false, then && is false.
+      For ||, only one of the values must be true for it to evaluate
+      as true.  It is only false if both values indeed
+      are false
+
+! negation operator
+    example: !x
+    value: true or false
+    explanation: If x is true, then !x is false
+      If x is false, !x is true.
+
+A pair of more complicated ones that are here just for the sake of being
+here.  Do not worry if they utterly confuse you.
+
+-> the call other operator
+    example: this_player()->query_name()
+    value: The value returned by the function being called
+    explanation:  It calls the function which is on the right in the object
+      on the left side of the operator.  The left expression *must* be
+      an object, and the right expression *must* be the name of a function.
+      If not such function exists in the object, it will return 0 (or
+      more correctly, undefined).
+
+? : conditional operator
+    example: x ? y : z
+    values: in the above example, if x is try, the value is y
+      if x is false, the value of the expression is z
+    explanation: If the leftmost value is true, it will give the expression as
+      a whole the value of the middle expression.  Else, it will give the
+      expression as a whole the value of the rightmost expression.
+
+A note on equality:  A very nasty error people make that is VERY difficult
+to debug is the error of placing = where you mean ==.  Since
+operators return values, they both make sense when being evaluated.
+In other words, no error occurs.  But they have very different values.  For example:
+  if(x == 5)    if(x = 5)
+The value of x == 5 is true if the value of x is 5, false othewise.
+The value of x = 5 is 5 (and therefore always true).
+The if statement is looking for the expression in () to be either true or false,
+so if you had = and meant ==, you would end up with an expression that is
+always true.  And you would pull your hair out trying to figure out
+why things were not happening like they should :)
diff --git a/doc/KURS/LPC-KURS/chapter7 b/doc/KURS/LPC-KURS/chapter7
new file mode 100644
index 0000000..39f311b
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter7
@@ -0,0 +1,432 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: 10 july 1993
+
+CHAPTER 7: Flow Control
+
+7.1 Review of variables
+Variables may be manipulated by assigning or changing values with the
+expressions =, +=, -=, ++, --.  Those expressions may be combined with
+the expressions -, +, *, /, %.  However, so far, you have only been
+shown how to use a function to do these in a linear way.  For example:
+ 
+int hello(int x) {
+    x--;
+    write("Hello, x is "+x+".\n");
+    return x;
+}
+ 
+is a function you should know how to write and understand.  But what
+if you wanted to write the value of x only if x = 1?  Or what if
+you wanted it to keep writing x over and over until x = 1 before
+returning?  LPC uses flow control in exactly the same way as C and C++.
+
+7.2 The LPC flow control statements
+LPC uses the following expressions:
+ 
+if(expression) instruction;
+ 
+if(expression) instruction;
+else instruction;
+ 
+if(expression) instruction;
+else if(expression) instruction;
+else instruction;
+ 
+while(expression) instruction;
+ 
+do { instruction; } while(expression);
+ 
+switch(expression) {
+    case (expression): instruction; break;
+    default: instruction;
+}
+ 
+Before we discuss these, first something on what is meant by expression and
+instruction.  An expression is anything with a value like a variable,
+a comparison (like x>5, where if x is 6 or more, the value is 1, else the
+value is 0), or an assignment(like x += 2).  An instruction can be any
+single line of lpc code like a function call, a value assignment or
+modification, etc.
+ 
+You should know also the operators &&, ||, ==, !=, and !.  These are the
+logical operators.  They return a nonzero value when true, and 0 when false.
+Make note of the values of the following expressions:
+ 
+(1 && 1) value: 1   (1 and 1)
+(1 && 0) value: 0   (1 and 0)
+(1 || 0) value: 1   (1 or 0)
+(1 == 1) value: 1   (1 is equal to 1)
+(1 != 1) value: 0   (1 is not equal to 1)
+(!1) value: 0       (not 1)
+(!0) value: 1       (not 0)
+ 
+In expressions using &&, if the value of the first item being compared
+is 0, the second is never tested even.  When using ||, if the first is
+true (1), then the second is not tested.
+ 
+7.3 if()
+The first expression to look at that alters flow control is if().  Take
+a look at the following example:
+ 
+1 void reset() {
+2     int x;
+3
+4     ::reset();
+5     x = random(10);
+6     if(x > 50) set_search_func("floorboards", "search_floor");
+7 }
+ 
+The line numbers are for reference only.
+In line 2, of course we declare a variable of type int called x.  Line 3
+is aethetic whitespace to clearly show where the declarations end and the
+function code begins.  The variable x is only available to the function
+reset().
+Line 4 makes a call to the room.c version of reset().
+Line 5 uses the driver efun random() to return a random number between
+0 and the parameter minus 1.  So here we are looking for a number between
+0 and 99.
+In line 6, we test the value of the expression (x>50) to see if it is true
+or false.  If it is true, then it makes a call to the room.c function
+set_search_func().  If it is false, the call to set_search_func() is never
+executed.
+In line 7, the function returns driver control to the calling function
+(the driver itself in this case) without returning any value.
+ 
+If you had wanted to execute multiple instructions instead of just the one,
+you would have done it in the following manner:
+ 
+if(x>50) {
+    set_search_func("floorboards", "search_floor");
+    if(!present("beggar", this_object())) make_beggar();
+}
+ 
+Notice the {} encapsulate the instructions to be executed if the test
+expression is true.  In the example, again we call the room.c function
+which sets a function (search_floor()) that you will later define yourself
+to be called when the player types "search floorboards" (NOTE: This is
+highly mudlib dependent.  Nightmare mudlibs have this function call.
+Others may have something similar, while others may not have this feature
+under any name).  Next, there is another if() expression that tests the
+truth of the expression (!present("beggar",this_object())).  The ! in the
+test expression changes the truth of the expression which follows it.  In
+this case, it changes the truth of the efun present(), which will return
+the object that is a beggar if it is in the room (this_object()), or it
+will return 0 if there is no beggar in the room.  So if there is a beggar
+still living in the room, (present("beggar", this_object())) will have
+a value equal to the beggar object (data type object), otherwise it will
+be 0.  The ! will change a 0 to a 1, or any nonzero value (like the
+beggar object) to a 0.  Therefore, the expression
+(!present("beggar", this_object())) is true if there is no beggar in the
+room, and false if there is.  So, if there is no beggar in the room,
+then it calls the function you define in your room code that makes a
+new beggar and puts it in the room. (If there is a beggar in the room,
+we do not want to add yet another one :))
+ 
+Of course, if()'s often comes with ands or buts :).  In LPC, the formal
+reading of the if() statement is:
+ 
+if(expression) { set of intructions }
+else if(expression) { set of instructions }
+else { set of instructions }
+ 
+This means:
+ 
+If expression is true, then do these instructions.
+Otherise, if this second expression is true, do this second set.
+And if none of those were true, then do this last set.
+ 
+You can have if() alone:
+ 
+if(x>5) write("Foo,\n");
+ 
+with an else if():
+ 
+if(x > 5) write("X is greater than 5.\n");
+else if(x >2) write("X is less than 6, but greater than 2.\n");
+ 
+with an else:
+ 
+if(x>5) write("X is greater than 5.\n");
+else write("X is less than 6.\n");
+ 
+or the whole lot of them as listed above.  You can have any number of
+else if()'s in the expression, but you must have one and only one
+if() and at most one else.  Of course, as with the beggar example,
+you may nest if() statements inside if() instructions. (For example,
+    if(x>5) {
+        if(x==7) write("Lucky number!\n");
+        else write("Roll again.\n");
+    }
+    else write("You lose.\n");
+ 
+7.4 The statements: while() and do {} while()
+Prototype:
+while(expression) { set of instructions }
+do { set of instructions } while(expression);
+ 
+These allow you to create a set of instructions which continue to
+execute so long as some expression is true.  Suppose you wanted to
+set a variable equal to a player's level and keep subtracting random
+amounts of either money or hp from a player until that variable equals
+0 (so that player's of higher levels would lose more).  You might do it
+this way:
+ 
+1    int x;
+2
+3    x = (int)this_player()->query_level();  /* this has yet to be explained */
+4    while(x > 0) {
+5        if(random(2)) this_player()->add_money("silver", -random(50));
+6        else this_player()->add_hp(-(random(10));
+7        x--;
+8    }
+ 
+The expression this_player()->query_level() calIn line 4, we start a loop that executes so long as x is greater than 0.
+    Another way we could have done this line would be:
+        while(x) {
+    The problem with that would be if we later made a change to the funtion
+y anywhere between 0 and 49 coins.
+In line 6, if instead it returns 0, we call the add_hp() function in the
+    player which reduces the player's hit points anywhere between 0 and 9 hp.
+In line 7, we reduce x by 1.
+At line 8, the execution comes to the end of the while() instructions and
+    goes back up to line 4 to see if x is still greater than 0.  This
+    loop will keep executing until x is finally less than 1.
+ 
+You might, however, want to test an expression *after* you execute some
+instructions.  For instance, in the above, if you wanted to execute
+the instructions at least once for everyone, even if their level is
+below the test level:
+ 
+    int x;
+ 
+    x = (int)this_player()->query_level();
+    do {
+        if(random(2)) this_player()->add_money("silver", -random(50));
+        else this_player()->add_hp(-random(10));
+        x--;
+    } while(x > 0);
+ 
+This is a rather bizarre example, being as few muds have level 0 players.
+And even still, you could have done it using the original loop with
+a different test.  Nevertheless, it is intended to show how a do{} while()
+works.  As you see, instead of initiating the test at the beginning of the
+loop (which would immediately exclude some values of x), it tests after
+the loop has been executed.  This assures that the instructions of the loop
+get executed at least one time, no matter what x is.
+ 
+7.5 for() loops
+Prototype:
+for(initialize values ; test expression ; instruction) { instructions }
+ 
+initialize values:
+This allows you to set starting values of variables which will be used
+in the loop.  This part is optional.
+ 
+test expression:
+Same as the expression in if() and while().  The loop is executed
+as long as this expression (or expressions) is true. You must have a
+test expression.
+ 
+instruction:
+An expression (or expressions) which is to be executed at the end of each
+loop.  This is optional.
+ 
+Note:
+for(;expression;) {}
+IS EXACTLY THE SAME AS
+while(expression) {}
+ 
+Example:
+ 
+1    int x;
+2
+3    for(x= (int)this_player()->query_level(); x>0; x--) {
+4        if(random(2)) this_player()->add_money("silver", -random(50));
+5        else this_player()->add_hp(-random(10));
+6    }
+ 
+This for() loop behaves EXACTLY like the while() example.
+Additionally, if you wanted to initialize 2 variables:
+ 
+for(x=0, y=random(20); x<y; x++) { write(x+"\n"); }
+ 
+Here, we initialize 2 variables, x and y, and we separate them by a
+comma.  You can do the same with any of the 3 parts of the for()
+expression.
+ 
+7.6 The statement: switch()
+Prototype:
+switch(expression) {
+    case constant: instructions
+    case constant: instructions
+    ...
+    case constant: instructions
+    default: instructions
+}
+ 
+This is functionally much like if() expressions, and much nicer to the
+CPU, however most rarely used because it looks so damn complicated.
+But it is not.
+ 
+First off, the expression is not a test.  The cases are tests.  A English
+sounding way to read:
+ 
+1    int x;
+2
+3    x = random(5);
+4    switch(x) {
+5        case 1: write("X is 1.\n");
+6        case 2: x++;
+7        default: x--;
+8    }
+9    write(x+"\n");
+ 
+is:
+ 
+set variable x to a random number between 0 and 4.
+In case 1 of variable x write its value add 1 to it and subtract 1.
+In case 2 of variable x, add 1 to its value and then subtract 1.
+In other cases subtract 1.
+Write the value of x.
+ 
+switch(x) basically tells the driver that the variable x is the value
+we are trying to match to a case.
+Once the driver finds a case which matches, that case *and all following
+cases* will be acted upon.  You may break out of the switch statement
+as well as any other flow control statement with a break instruction in
+order only to execute a single case.  But that will be explained later.
+The default statement is one that will be executed for any value of
+x so long as the switch() flow has not been broken.  You may use any
+data type in a switch statement:
+ 
+string name;
+ 
+name = (string)this_player()->query_name();
+switch(name) {
+    case "descartes": write("You borg.\n");
+    case "flamme":
+    case "forlock":
+    case "shadowwolf": write("You are a Nightmare head arch.\n");
+    default: write("You exist.\n");
+}
+ 
+For me, I would see:
+You borg.
+You are a Nightmare head arch.
+You exist.
+ 
+Flamme, Forlock, or Shadowwolf would see:
+You are a Nightmare head arch.
+You exist.
+ 
+Everyone else would see:
+You exist.
+ 
+7.7 Altering the flow of functions and flow control statements
+The following instructions:
+return    continue    break
+ 
+alter the natural flow of things as described above.
+First of all,
+return
+no matter where it occurs in a function, will cease the execution of that
+function and return control to the function which called the one the
+return statement is in.  If the function is NOT of type void, then a
+value must follow the return statement, and that value must be of a
+type matching the function.  An absolute value function would look
+like this:
+ 
+int absolute_value(int x) {
+    if(x>-1) return x;
+    else return -x;
+}
+ 
+In the second line, the function ceases execution and returns to the calling
+function because the desired value has been found if x is a positive
+number.
+ 
+continue is most often used in for() and while statements.  It serves
+to stop the execution of the current loop and send the execution back
+to the beginning of the loop.  For instance, say you wanted to avoid
+division by 0:
+ 
+x= 4;
+while( x > -5) {
+    x--
+    if(!x) continue;
+    write((100/x)+"\n");
+}
+write("Done.\n")
+ 
+You would see the following output:
+33
+50
+100
+-100
+-50
+-33
+-25
+Done.
+To avoid an error, it checks in each loop to make sure x is not 0.
+If x is zero, then it starts back with the test expression without
+finishing its current loop.
+ 
+In a for() expression
+ for(x=3; x>-5; x--) {
+    if(!x) continue;
+    write((100/x)+"\n");
+ }
+ write("Done.\n");
+It works much the same way.  Note this gives exactly the same output
+as before. At x=1, it tests to see if x is zero, it is not, so it
+writes 100/x, then goes back to the top, subtracts one from x, checks to
+see if it is zero again, and it is zero, so it goes back to the top
+and subtracts 1 again.
+ 
+break
+This one ceases the function of a flow control statement.  No matter
+where you are in the statement, the control of the program will go
+to the end of the loop.  So, if in the above examples, we had
+used break instead of continue, the output would have looked like this:
+ 
+33
+50
+100
+Done.
+ 
+continue is most often used with the for() and while() statements.
+break however is mostly used with switch()
+ 
+switch(name) {
+    case "descartes": write("You are borg.\n"); break;
+    case "flamme": write("You are flamme.\n"); break;
+    case "forlock": write("You are forlock.\n"); break;
+    case "shadowwolf": write("You are shadowwolf.\n"); break;
+    default: write("You will be assimilated.\n");
+}
+ 
+This functions just like:
+ 
+if(name == "descartes") write("You are borg.\n");
+else if(name == "flamme") write("You are flamme.\n");
+else if(name == "forlock") write("You are forlock.\n");
+else if(name == "shadowwolf") write("You are shadowwolf.\n");
+else write("You will be assimilated.\n");
+ 
+except the switch statement is much better on the CPU.
+If any of these are placed in nested statements, then they alter the
+flow of the most immediate statement.
+ 
+7.8 Chapter summary
+This chapter covered one hell of a lot, but it was stuff that needed to
+be seen all at once.  You should now completely understand if() for()
+while() do{} while() and switch(), as well as how to alter their flow
+using return, continue, and break.  Effeciency says if it can be done in
+a natural way using switch() instead of a lot of if() else if()'s, then
+by all means do it.  You were also introduced to the idea of calling
+functions in other objects.  That however, is a topic to be detailed later.
+You now should be completely at ease writing simple rooms (if you have
+read your mudlib's room building document), simple monsters, and
+other sorts of simple objects.
diff --git a/doc/KURS/LPC-KURS/chapter8 b/doc/KURS/LPC-KURS/chapter8
new file mode 100644
index 0000000..a794713
--- /dev/null
+++ b/doc/KURS/LPC-KURS/chapter8
@@ -0,0 +1,195 @@
+                           LPC Basics
+                  Written by Descartes of Borg
+                  first edition: 23 april 1993
+                  second edition: 12 july 1993
+
+CHAPTER 8: The data type "object"
+
+8.1 Review
+You should now be able to do anything so long as you stick to calling
+functions within your own object.  You should also know, that at the
+bare minimum you can get the create() (or reset()) function in your object
+called to start just by loading it into memory, and that your reset()
+function will be called every now and then so that you may write the
+code necessary to refresh your room.  Note that neither of these
+functions MUST be in your object.  The driver checks to see if the
+function exists in your object first.  If it does not, then it does not
+bother.  You are also acquainted with the data types void, int, and string.
+ 
+7.2 Objects as data types
+In this chapter you will be acquainted with a more complex data type,
+object.  An object variable points to a real object loaded into the
+driver's memory.  You declare it in the same manner as other data types:
+    object ob;
+It differs in that you cannot use +, -, +=, -=, *, or / (what would it
+mean to divide a monster by another monster?).  And since efuns like
+say() and write() only want strings or ints, you cannot write() or
+say() them (again, what would it mean to say a monster?).
+But you can use them with some other of the most important efuns on any
+LPMud.
+ 
+8.3 The efun: this_object()
+This is an efun which returns an object in which the function being executed
+exists.  In other words, in a file, this_object() refers to the object your
+file is in whether the file gets cloned itself or inherted by another file.
+It is often useful when you are writing a file which is getting inherited
+by another file.  Say you are writing your own living.c which gets
+inherited by user.c and monster.c, but never used alone.  You want to log
+the function set_level() it is a player's level being set (but you do not
+care if it is a monster.
+You might do this:
+ 
+void set_level(int x) {
+    if(this_object()->is_player()) log_file("levels", "foo\n");
+    level = x;
+}
+ 
+Since is_player() is not defined in living.c or anything it inherits,
+just saying if(is_player()) will result in an error since the driver
+does not find that function in your file or anything it inherits.
+this_object() allows you to access functions which may or may not be
+present in any final products because your file is inherited by others
+without resulting in an error.
+ 
+8.4 Calling functions in other objects
+This of course introduces us to the most important characteristic of
+the object data type.  It allows us to access functions in other objects.
+In previous examples you have been able to find out about a player's level,
+reduce the money they have, and how much hp they have.
+Calls to functions in other objects may be done in two ways:
+ 
+object->function(parameters)
+call_other(object, "function", parameters);
+ 
+example:
+this_player()->add_money("silver", -5);
+call_other(this_player(), "add_money", "silver", -5);
+ 
+In some (very loose sense), the game is just a chain reaction of function
+calls initiated by player commands.  When a player initiates a chain of
+function calls, that player is the object which is returned by
+the efun this_player().  So, since this_player() can change depending
+on who initiated the sequence of events, you want to be very careful
+as to where you place calls to functions in this_player().  The most common
+place you do this is through the last important lfun (we have mentioned
+create() and reset()) init().
+ 
+8.5 The lfun: init()
+Any time a living thing encounters an object (enters a new room, or enters
+the same room as a certain other object), init() is called in all of
+the objects the living being newly encounters.  It is at this point
+that you can add commands the player can issue in order to act.
+Here is a sample init() function in a flower.
+ 
+void init() {
+    ::init();
+    add_action("smell_flower", "smell");
+}
+ 
+Ito smell_flower().  So you should have smell_flower() look like this:
+ 
+1 int smell_flower(string str);        /* action functions are type int */
+2
+3 int smell_flower(string str) {
+4    if(str != "flower") return 0;     /* it is not the flower being smelled */
+5    write("You sniff the flower.\n");
+6    say((string)this_player()->query_cap_name()+" smells the flower.\n");
+7    this_player()->add_hp(random(5));
+8    return 1;
+9 }
+ 
+In line 1, we have our function declared.
+In line 3, smell_flower() begins.  str becomes whatever comes after the
+    players command (not including the first white space).
+In line 4, it checks to see if the player had typed "smell flower".  If
+    the player had typed "smell cheese", then str would be "cheese".  If
+    it is not in fact "flower" which is being smelled, then 0 is returned,
+    letting the driver know that this was not the function which should
+    have been called.  If in fact the player had a piece of cheese as well
+    which had a smell command to it, the driver would then call the function
+    for smelling in that object.  The driver will keep calling all functions
+    tied to smell commands until one of them returns 1.  If they all return
+    0, then the player sees "What?"
+In line 5, the efun write() is called.  write() prints the string which
+    is passed to it to this_player().  So whoever typed the command here
+    sees "You sniff the flower."
+In line 6, the efun say() is called.  say() prints the string which is
+    doing the sniffing, we have to call the query_cap_name() function
+    in this_player().  That way if the player is invis, it will say
+    "Someone" (or something like that), and it will also be properly
+    capitalized.
+In line 7, we call the add_hp() function in the this_player() object,
+    since we want to do a little healing for the sniff (Note: do not
+    code this object on your mud, whoever balances your mud will shoot you).
+In line 8, we return control of the game to the driver, returning 1 to
+    let it know that this was in fact the right function to call.
+ 
+8.6 Adding objects to your rooms
+And now, using the data type object, you can add monsters to your rooms:
+ 
+void create() {
+    ::create();
+    set_property("light", 3);
+    set("short", "Krasna Square");
+    set("long", "Welcome to the Central Square of the town of Praxis.\n");
+    set_exits( ({ "d/standard/hall" }), ({ "east" }) );
+}
+ 
+void reset() {
+    object ob;
+ 
+    ::reset();
+    if(present("guard")) return;     /* Do not want to add a guard if */
+    ob = new("/std/monster");        /* one is already here           */
+    ob->set_name("guard");
+    ob->set("id", ({ "guard", "town guard" }) );
+    ob->set("short", "Town guard");
+    ob->set("long", "He guards Praxis from nothingness.\n");
+    ob->set_gender("male");
+    ob->set_race("human");
+    ob->set_level(10);
+    ob->set_alignment(200);
+    ob->set_humanoid();
+    ob->set_hp(150);
+    ob->set_wielding_limbs( ({ "right hand", "left hand" }) );
+    ob->move(this_object());
+}
+ 
+Now, this will be wildly different on most muds.  Some, as noted before,
+in that object so you have a uniquely configured monster object.  The
+last act in native muds is to call move() in the monster object to move
+it to this room (this_object()).  In compat muds, you call the efun
+move_object() which takes two parameters, the object to be moved, and the
+object into which it is being moved.
+ 
+8.7 Chapter summary
+At this point, you now have enough knowledge to code some really nice
+stuff.  Of course, as I have been stressing all along, you really need
+to read the documents on building for your mud, as they detail which
+functions exist in which types of objects for you to call.  No matter
+what your knowledge of the mudlib is, you have enough know-how to
+give a player extra things to do like sniffing flowers or glue or whatever.
+At this point you should get busy coding stuff.  But the moment things
+even look to become tedious, that means it is time for you to move to
+the next level and do more.  Right now code yourself a small area.
+Make extensive use of the special functions coded in your mud's
+room.c (search the docs for obscure ones no one else seems to use).
+Add lots o' neat actions.  Create weapons which have magic powers which
+gradually fade away.  All of this you should be able to do now.  Once
+this becomes routine for you, it will be time to move on to intermediate
+stuff.  Note that few people actually get to the intermediate stuff.
+If you have played at all, you notice there are few areas on the mud
+which do what I just told you you should be able to do.  It is not
+because it is hard, but because there is a lot of arrogance out there
+on the part of people who have gotten beyond this point, and very little
+communicating of that knowledge.  The trick is to push yourself and
+think of something you want to do that is impossible.  If you ask someone
+in the know how to do X, and they say that is impossible, find out
+youself how to code it by experimenting.
+
+George Reese
+Descartes of Borg
+12 july 1993
+borg@hebron.connected.com
+Descartes@Nightmare (intermud)
+Descartes@Igor (not intermud)
diff --git a/doc/KURS/LPC-KURS2/Contents b/doc/KURS/LPC-KURS2/Contents
new file mode 100644
index 0000000..ff58a8a
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/Contents
@@ -0,0 +1,15 @@
+Intermediate LPC
+Descartes of Borg 
+November 1993
+
+                                   Contents
+
+1: Introduction
+2: The LPMud Driver
+3: Complex Data Types
+4: The LPC Pre-Compiler
+5: Advanced String Handling
+6: Intermediate Inheritance
+7: Debugging
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/LPC-KURS2/Copyright b/doc/KURS/LPC-KURS2/Copyright
new file mode 100644
index 0000000..29a2620
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/Copyright
@@ -0,0 +1,62 @@
+                      Intermediate LPC first edition
+
+Copyright (c) 1993 George Reese
+All rights to this text are retained by the author.
+
+
+Permission is granted to distrubute and display the contents of this
+document in full so long as the following conditions are met:
+1) No payment may be received for the redistribution or display of this text,
+except to cover the costs for distribution media and and shipping and/or
+transmission charges.
+2) The textbook must be distributed or displayed in its entirety in its original
+form.  Changes may only be made to private, individual copies, except as
+outlined below.
+
+Acceptable changes are defined as the following:
+1) Format changes, such as changing from WordPerfect to Word 
+2) Medium changes, such as from electronic copy to paper
+3) Content changes are only acceptable under the following circumstances:
+	a) In electronic media: none of the original text may be ommitted. 
+        You may add comments
+	as you feel necessary, so long as comments are enclosed in <* *>
+        and are accompanied by
+	the game name or real name of the author of the comments
+	b) In hard copy: none of the original text may be omitted, but it may
+        be struck out so long
+	as the content of the original text is visible.  Comments may be made
+        in any form so long 
+	as they are made in handwriting and they are signed by the author. 
+        Comments which are typed or printed must be made in accordance with the
+        format for electronic media.
+
+Practically speaking, this is what I mean:
+First, I wrote this mostly for mud admins to put onto their muds for learning
+coders to read as they are learning to build realms.  I did not do this for
+someone else to make a buck.  So if you charge money for redistributing it
+or allowing someone else to see it, you are in violation of this copyright. 
+Unless you are simply charging for what it cost you to print up a copy or
+what the diskettes and postage cost to mail it.
+Second, I wrote this textbook, and I should receive credit/blame for what I
+say, and others should receive credit/blame for what they say.  For example,
+if I said something completely wrong, and you simply corrected it, I would
+be getting credit for something I did not do.  Yet, if you comment according
+to the outline above, you will be properly credited for your comments. 
+More important to me, however, is the practical effect of having hundreds of
+copies of this textbook everywhere.  If you change something I had right
+without noting it as a comment, I will be blamed for spreading
+misinformation.  This problem is only compunded if the text is redistributed. 
+So I prefer my words to remain my own.  But, when I make mistakes, or if
+something I say does not fit your driver/mudlib, please comment it so people
+will know.  In addition, having the comments side-by-side allows people to
+see other ideas, like how another driver might handle something.
+
+
+I want to please note again, you may display this on your mud (like in /doc). 
+You do not need to
+mail me for permission.  I would not mind email, since it is nice to know
+people are using it, but that is not required.  Also, if you really feel I have
+done such a wonderful job that you should pay money to use this, then give
+$5 to your local ASPCA (or international equivalent).
+
+See the file titled Contents for a full list of textbook chapters.
diff --git a/doc/KURS/LPC-KURS2/chapter1 b/doc/KURS/LPC-KURS2/chapter1
new file mode 100644
index 0000000..6c459cd
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/chapter1
@@ -0,0 +1,143 @@
+Intermediate LPC
+Descartes of Borg
+Novermber 1993
+
+                         Chapter 1: Introduction
+
+1.1 LPC Basics
+Anyone reading this textbook should either have read the textbook LPC
+Basics or be familiar enough with mud realm coding such that not only are
+they capable of building rooms and other such objects involved in area
+coding, but they also have a good idea of what is going on when the code
+they write is executing.  If you do not feel you are at this point, then go
+back and read LPC Basics before continuing.  If you do so, you will find
+that what you read here will be much more meaningful to you.
+
+1.2 Goals of This Textbook
+The introductory textbook was meant to take people new to LPC from
+knowing nothing to being able to code a nice realm on any LPMud.  There
+is naturally much more to LPC and to LPMud building, however, than
+building rooms, armours, monsters, and weapons.  As you get into more
+complicated concepts like guilds, or desire to do more involved things with
+your realm, you will find the concepts detailed in LPC Basics to be lacking
+in support for these projects.  Intermediate LPC is designed to take you
+beyond the simple realm building process into a full knowledge of LPC for
+functioning as a realm builder on an LPMud.  The task of mudlib building
+itself is left to a later text.  After reading this textbook and working through
+it by experimenting with actual code, the reader should be able to code game
+objects to fit any design or idea they have in mind, so long as I have been
+successful.
+
+1.3 An Overview
+What more is there?  Well many of you are quite aware that LPC supports
+mappings and arrays and have been asking me why those were not detailed
+in LPC Basics.  I felt that those concepts were beyond the scope of what I
+was trying to do with that textbook and were more fitting to this textbook. 
+But new tools are all fine and dandy, what matters, however, is what you
+can do with those tools.  The goal of LPC Basics was to get you to building
+quality LPMud realms.  Mappings and arrays are not necessary to do that. 
+The goal of this book is to allow you to code any idea you might want to
+code in your area.  That ability requires the knowledge of mappings and
+arrays.
+
+Any idea you want to code in an LPMud is possible.  LPC is a language
+which is amazingly well suited to this task.  All that prevents you from
+coding your ideas is your knowledge of LPC or an inadequate mudlib or
+your mudÕs theme or administrative policies.  This textbook cannot make
+the mudlib you are working with any better, and it cannot change the mud
+theme or the mudÕs administrative policies.  Never once think that LPC is
+incapable of doing what you want to do.  If your idea is prevented by
+administrative policies or themes, then it is simply not an idea for your
+current mud.  If the mudlib is inadequate, talk to the people in charge of
+your mudlib about what can be done at the mudlib level to facilitate it.  You
+would be surprised by what is actually in the mudlib you did not know
+about.  More important, after reading this textbook, you should be able to
+read all of the mudlib code in your mudÕs mudlib and understand what is
+going on at each line in the mudlib code.  You may not as yet be able to
+reproduce that code on your own, but at least you can understand what is
+going on at the mudlib level.
+
+This textbook starts out with a discussion about what the LPMud driver is
+doing.  One nice thing about this textbook, in general it is completely driver
+and mudlib independent (excepting for the Dworkin Game Driver).  The
+chapter on the game driver does not get into actual implementation, but
+instead deals with what all game drivers basically do in order to run the
+mud.
+
+Next I discuss those magic topics everyone wants to know more about,
+arrays and mappings.  Mappings may be simultaneously the easiest and
+most difficult data type to understand.  Since they are sort of complex arrays
+in a loose sense, you really need to understand arrays before discussing
+them.  All the same, once you understand them, they are much easier than
+arrays to use in real situations.  At any rate, spend most of your time
+working with that chapter, because it is probably the most difficult, yet most
+useful chapter in the book.
+
+After that follows a brief chapter on the LPC pre-compiler, a tool you can
+use for sorting out how your code will look before it gets sent to the
+compiler.  Despite my horrid intro to it here, this chapter is perhaps the
+easiest chapter in the textbook.  I put it after the mappings and arrays
+chapter for exactly that reason.
+
+Strings are re-introduced next, going into more detail with how you can do
+such things as advanced command handling by breaking up strings.  Once
+you understand arrays fairly well, this chapter should be really simple.
+
+The next chapter is the second most important in the book.  It may be the
+most important if you ever intend to go beyond the intermediate stage and
+dive into mudlib coding.  That chapter involves the complex ideas behind
+LPC inheritance.  Since the goal of this textbook is not to teach mudlib
+programming, the chapter is not a detailed discussion on object oriented
+programming.  Understanding this chapter, however, will give you some
+good insights into what is involved with object oriented programming, as
+well as allow you to build more complex objects by overriding functions
+and defining your own base classes.
+
+Finally, the textbook ends with a simple discussion of code debugging. 
+This is not an essential chapter, but instead it is meant as more of an
+auxiliary supplement to what the knowledge you have accumulated so far.
+
+1.4 Not Appearing in This Textbook
+Perhaps what might appear to some as the most glaring omission of this
+textbook is largely a political omission, shadows.  Never have I ever
+encountered an example of where a shadow was either the best or most
+effecient manner of doing anything.  It does not follow from that, however,
+that there are no uses for shadows.  My reasoning for omitting shadows
+from this textbook is that the learner is best served by learning the concepts
+in this textbook first and having spent time with them before dealing with
+the subject of shadows.  In that way, I feel the person learning LPC will be
+better capable of judging the merits of using a shadow down the road.  I
+will discuss shadows in a future textbook.
+
+If you are someone who uses shadows some or a lot, please do not take the
+above paragraph as a personal attack.  There may be some perfectly valid
+uses for shadows somewhere which I have yet to encounter.  Nevertheless,
+they are not the ideal way to accomplish any given task, and therefore they
+are not considered for the purposes of this textbook an intermediate coding
+tool.
+
+I have also omitted discussions of security and object oriented
+programming.  Both are quite obviously mudlib issues.  Many people,
+however, might take exception with my leaving out a discussion of object
+oriented programming.  I chose to leave that for a later text, since most area
+builders code for the creativity, not for the computer science theory.  In both
+the intermediate and beginner textbooks, I have chosen only to discuss
+theory where it is directly applicable to practical LPC programming.  For
+people who are starting out green in LPC and want to code the next great
+mudlib, perhaps theory would be more useful.  But for the purposes of this
+book, a discussion of object oriented programming is simply a snoozer.  I
+do plan to get heavy into theory with the next textbook.
+
+1.5 Summary
+LPC is not difficult to learn.  It is a language which, although pathetic
+compared to any other language for performing most computer language
+tasks, is incredibly powerful and unequalled for the tasks of building an
+area in MUD type games.  For the beginner, it allows you to easily jump in
+and code useful objects without even knowing what you are doing.  For the
+intermediate person, it allows you to turn any idea you have into textual
+virtual reality.  And for the advanced person, itÕs object oriented features
+can allow you to build one of the most popular games on the internet.  What
+you can do is simply limited by how much you know.  And learning more
+does not require a computer science degree.
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/LPC-KURS2/chapter2 b/doc/KURS/LPC-KURS2/chapter2
new file mode 100644
index 0000000..51a4c3c
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/chapter2
@@ -0,0 +1,223 @@
+Intermediate LPC
+Descartes of Borg
+Novermber 1993
+
+                         Chapter 2: The LPMud Driver
+
+2.1 Review of Basic Driver/Mudlib Interaction
+In the LPC Basics textbook, you learned a lot about the way the mudlib
+works, specifically in relation to objects you code in order to build your
+realm.  Not much was discussed about the interaction between the
+mudlib and the driver.  You should know, however, that the driver
+does the following:
+1) When an object is first loaded into memory, the driver will call
+create() in native muds and reset() in compat muds.  A creator
+uses create() or reset() to give initial values to the object.
+2) At an interval setup by the game administrator, the driver calls the
+function reset().  This allows the object to regenerate monsters and
+such.  Notice that in a compat mud, the same function is used to set up
+initial values as is used to reset the room.
+3) Any time a living object comes in contact with an object of any sort,
+the driver calls init() in the newly encountered object.  This allows
+newly encountered objects to give living objects commands to execute
+through the add_action() efun, as well as perform other actions which
+should happen whenever a living thing encounters a given object.
+4) The driver defines a set of functions known as efuns which are
+available to all objects in the game.  Examples of commonly used efuns
+are: this_player(), this_object(), write(), say(), etc.
+
+2.2 The Driver Cycle
+The driver is a C program which runs the game.  Its basic functions are
+to accept connections from the outside world so people can login,
+interpret the LPC code which defines LPC objects and how they
+function in the game, and accept user input and call the appropriate LPC
+functions which match the event.  In its most simplest essence, it is an
+unending loop.
+
+Once the game has booted up and is properly functioning (the boot up
+process will be discussed in a future, advanced LPC textbook), the
+driver enters a loop which does not terminate until the shutdown() efun
+is legally called or a bug causes the driver program to crash.  First off,
+the driver handles any new incoming connections and passes control of
+the connection to a login object.  After that, the driver puts together a
+table of commands which have been entered by users since the last cycle
+of the driver.  After the command table is assembled, all messages
+scheduled to be sent to the connection from the last driver cycle are sent
+out to the user.  At this point, the driver goes through the table of
+commands to be executed and executes each set of commands each
+object has stored there.  The driver ends its cycle by calling the function
+heart_beat() in every object with a heart_beat() set and finally
+performing all pending call outs.  This chapter will not deal with the
+handling of connections, but instead will focus on how the driver
+handles user commands and heartbeats and call outs.
+
+2.3 User Commands
+As noted in section 1.2, the driver stores a list of commands for each
+user to be executed each cycle.  The commands list has the name of the
+living object performing the command, the object which gave the living
+object that command, and the function which is to be executed in order
+to perform the command.  The driver refers to the object which typed in
+the command as the command giver.  It is the command giver which
+gets returned as this_player() in most cases.
+
+The driver starts at the top of the list of living objects with pending
+commands, and successively performs each command it typed by calling
+the function associated with the command and passing any arguments
+the command giver gave as arguments to the function.  As the driver
+starts with the commands issued by a new living object, the command
+giver variable is changed to be equal to the new living object, so that
+during the sequence of functions initiated by that command, the efun
+this_player() returns the object which issued the command.
+
+Let's look at the command buffer for an example player.  Since the
+execution of his last command, Bozo has typed "north" and "tell
+descartes when is the next reboot".  The command "north" is associated
+with the function "Do_Move()" in the room Bozo is in (the command
+"north" is automatically setup by the set_exits() efun in that room).  The
+command "tell" is not specifically listed as a command for the player,
+however, in the player object there is a function called "cmd_hook()"
+which is associated with the command "", which matches any possible
+user input.
+
+Once the driver gets down to Bozo, the command giver variable is set to
+the object which is Bozo.  Then, seeing Bozo typed "north" and the
+function "north" is associated with, the driver calls Bozo's_Room-
+>Do_Move(0).  An argument of 0 is passed to the function since Bozo
+only typed the command "north" with no arguments.  The room
+naturally calls some functions it needs, all the while such that the efun
+this_player() returns the object which is Bozo.  Eventually, the room
+object will call move_player() in Bozo, which in turn calls the
+move_object() efun.  This efun is responsible for changing an object's
+environment.
+
+When the environment of an object changes, the commands available to
+it from objects in its previous environment as well as from its previous
+environment are removed from the object.  Once that is done, the driver
+calls the efun init() in the new environment as well as in each object in
+the new environment.  During each of these calls to init(), the object
+Bozo is still the command giver.  Thus all add_action() efuns from this
+move will apply to Bozo.  Once all those calls are done, control passes
+back from the move_object() efun to the move_player() lfun in Bozo. 
+move_player() returns control back to Do_Move() in the old room,
+which returns 1 to signify to the driver that the command action was
+successful.  If the Do_Move() function had returned 0 for some reason,
+the driver would have written "What?" (or whatever your driver's
+default bad command message is) to Bozo.
+
+Once the first command returns 1, the driver proceeds on to Bozo's
+second command, following much the same structure.  Note that with
+"tell descartes when is the next reboot", the driver passes "descartes
+when is the next reboot" to the function associated with tell.  That
+function in turn has to decide what to do with that argument.  After that
+command returns either 1 or 0, the driver then proceeds on to the next
+living object with commands pending, and so on until all living objects
+with pending commands have had their commands performed.
+
+2.4 The Efuns set_heart_beat() and call_out()
+Once all commands are performed for objects with commands pending,
+the driver then proceeds to call the heart_beat() function in all objects
+listed with the driver as having heartbeats.  Whenever an object calls the
+efun set_heart_beat() with a non-zero argument (depending on your
+driver, what non-zero number may be important, but in most cases you
+call it with the int 1).  The efun set_heart_beat() adds the object which
+calls set_heart_beat() to the list of objects with heartbeats.  If you call it
+with an argument of 0, then it removes the object from the list of objects
+with heartbeats.
+
+The most common use for heartbeats in the mudlib is to heal players and
+monsters and perform combat.  Once the driver has finished dealing with
+the command list, it goes through the heartbeat list calling heart_beat() in
+each object in the list.  So for a player, for example, the driver will call
+heart_beat() in the player which will:
+1) age the player
+2) heal the player according to a heal rate
+3) check to see if there are any hunted, hunting, or attacking objects
+around
+4) perform an attack if step 3 returns true.
+5) any other things which need to happen automatically roughly every
+second
+
+Note that the more objects which have heartbeats, the more processing
+which has to happen every cycle the mud is up.  Objects with heartbeats
+are thus known as the major hog of CPU time on muds.  
+
+The call_out() efun is used to perform timed function calls which do not
+need to happen as often as heartbeats, or which just happen once.  Call
+outs let you specify the function in an object you want called.  The
+general formula for call outs is:
+call_out(func, time, args);
+The third argument specifying arguments is optional.  The first argument
+is a string representing the name of the function to be called.  The second
+argument is how many seconds should pass before the function gets
+called.
+
+Practically speaking, when an object calls call_out(), it is added to a list
+of objects with pending call outs with the amount of time of the call out
+and the name of the function to be called.  Each cycle of the driver, the
+time is counted down until it becomes time for the function to be called. 
+When the time comes, the driver removes the object from the list of
+objects with pending call outs and performs the call to the call out
+function, passing any special args originally specified by the call out
+function.
+
+If you want a to remove a pending call before it occurs, you need to use
+the remove_call_out() efun, passing the name of the function being
+called out.  The driver will remove the next pending call out to that
+function.  This means you may have some ambiguity if more than one
+call out is pending for the same function.
+
+In order to make a call out cyclical, you must reissue the call_out() efun
+in the function you called out, since the driver automatically removes the
+function from the call out table when a call out is performed.  Example:
+
+void foo() { call_out("hello", 10); }
+
+void hello() { call_out("hello", 10); }
+
+will set up hello() to be called every 10 seconds after foo() is first called. 
+There are several things to be careful about here.  First, you must watch
+to make sure you do not structure your call outs to be recursive in any
+unintended fashion.  Second, compare what a set_heart_beat() does
+when compared directly to what call_out() does.
+
+set_heart_beat():
+a) Adds this_object() to a table listing objects with heartbeats.
+b) The function heart_beat() in this_object() gets called every single
+driver cycle.
+
+call_out():
+a) Adds this_object(), the name of a function in this_object(), a time
+delay, and a set of arguments to a table listing functions with pending
+call outs.  
+b) The function named is called only once, and that call comes after the
+specified delay.
+
+As you can see, there is a much greater memory overhead associated
+with call outs for part (a), yet that there is a much greater CPU overhead
+associated with heartbeats as shown in part (b), assuming that the delay
+for the call out is greater than a single driver cycle. 
+
+Clearly, you do not want to be issuing 1 second call outs, for then you
+get the worst of both worlds.  Similarly, you do not want to be having
+heart beats in objects that can perform the same functions with call outs
+of a greater duration than 1 second.  I personally have heard much talk
+about at what point you should use a call out over a heartbeat.  What I
+have mostly heard is that for single calls or for cycles of a duration
+greater than 10 seconds, it is best to use a call out.  For repetitive calls of
+durations less than 10 seconds, you are better off using heartbeats.  I do
+not know if this is true, but I do not think following this can do any
+harm.
+
+2.5 Summary
+Basic to a more in depth understanding of LPC is and understanding of
+the way in which the driver interacts with the mudlib.  You should now
+understand the order in which the driver performs functions, as well as a
+more detailed knowledge of the efuns this_player(), add_action(), and
+move_object() and the lfun init().  In addition to this building upon
+knowledge you got from the LPC Basics textbook, this chapter has
+introduced call outs and heartbeats and the manner in which the driver
+handles them.  You should now have a basic understanding of call outs
+and heartbeats such that you can experiment with them in your realm
+code.
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/LPC-KURS2/chapter3 b/doc/KURS/LPC-KURS2/chapter3
new file mode 100644
index 0000000..f986737
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/chapter3
@@ -0,0 +1,481 @@
+Intermediate LPC
+Descartes of Borg
+November 1993
+
+                        Chapter 3: Complex Data Types
+
+3.1 Simple Data Types
+In the textbook LPC Basics, you learned about the common, basic LPC
+data types: int, string, object, void.  Most important you learned that
+many operations and functions behave differently based on the data type
+of the variables upon which they are operating.  Some operators and
+functions will even give errors if you use them with the wrong data
+types.  For example, "a"+"b" is handled much differently than 1+1. 
+When you ass "a"+"b", you are adding "b" onto the end of "a" to get
+"ab".  On the other hand, when you add 1+1, you do not get 11, you get
+2 as you would expect.
+
+I refer to these data types as simple data types, because they atomic in
+that they cannot be broken down into smaller component data types. 
+The object data type is a sort of exception, but you really cannot refer
+individually to the components which make it up, so I refer to it as a
+simple data type.
+
+This chapter introduces the concept of the complex data type, a data type
+which is made up of units of simple data types.  LPC has two common
+complex data types, both kinds of arrays.  First, there is the traditional
+array which stores values in consecutive elements accessed by a number
+representing which element they are stored in.  Second is an associative
+array called a mapping.  A mapping associates to values together to
+allow a more natural access to data.
+
+3.2 The Values NULL and 0
+Before getting fully into arrays, there first should be a full understanding
+of the concept of NULL versus the concept of 0.  In LPC, a null value is
+represented by the integer 0.  Although the integer 0 and NULL are often
+freely interchangeable, this interchangeability often leads to some great
+confusion when you get into the realm of complex data types.  You may
+have even encountered such confusion while using strings.
+
+0 represents a value which for integers means the value you add to
+another value yet still retain the value added.  This for any addition
+operation on any data type, the ZERO value for that data type is the value
+that you can add to any other value and get the original value.  Thus:   A
+plus ZERO equals A where A is some value of a given data type and
+ZERO is the ZERO value for that data type.  This is not any sort of
+official mathematical definition.  There exists one, but I am not a
+mathematician, so I have no idea what the term is.  Thus for integers, 0
+is the ZERO value since 1 + 0 equals 1.
+
+NULL, on the other hand, is the absence of any value or meaning.  The
+LPC driver will interpret NULL as an integer 0 if it can make sense of it
+in that context.  In any context besides integer addition, A plus NULL
+causes an error.  NULL causes an error because adding valueless fields
+in other data types to those data types makes no sense.
+
+Looking at this from another point of view, we can get the ZERO value
+for strings by knowing what added to "a" will give us "a" as a result. 
+The answer is not 0, but instead "".  With integers, interchanging NULL
+and 0 was acceptable since 0 represents no value with respect to the
+integer data type.  This interchangeability is not true for other data types,
+since their ZERO values do not represent no value.  Namely, ""
+represents a string of no length and is very different from 0.  
+
+When you first declare any variable of any type, it has no value.  Any
+data type except integers therefore must be initialized somehow before
+you perform any operation on it.  Generally, initialization is done in the
+create() function for global variables, or at the top of the local function
+for local variables by assigning them some value, often the ZERO value
+for that data type.  For example, in the following code I want to build a
+string with random words:
+
+string build_nonsense() {
+    string str;
+    int i;
+
+    str = ""; /* Here str is initialized to the string
+ZERO value */
+    for(i=0; i<6; i++) {
+        switch(random(3)+1) {
+            case 1: str += "bing"; break;
+            case 2: str += "borg"; break;
+            case 3: str += "foo"; break;
+        }
+        if(i==5) str += ".\n";
+        else str += " ";
+    }
+    return capitalize(str);
+}
+
+If we had not initialized the variable str, an error would have resulted
+from trying to add a string to a NULL value.  Instead, this code first
+initializes str to the ZERO value for strings, "".  After that, it enters a
+loop which makes 6 cycles, each time randomly adding one of three
+possible words to the string.  For all words except the last, an additional
+blank character is added.  For the last word, a period and a return
+character are added.  The function then exits the loop, capitalizes the
+nonsense string, then exits.
+
+3.3 Arrays in LPC
+An array is a powerful complex data type of LPC which allows you to
+access multiple values through a single variable.  For instance,
+Nightmare has an indefinite number of currencies in which players may
+do business.  Only five of those currencies, however, can be considered
+hard currencies.  A hard currency for the sake of this example is a
+currency which is readily exchangeable for any other hard currency,
+whereas a soft currency may only be bought, but not sold.  In the bank,
+there is a list of hard currencies to allow bank keepers to know which
+currencies are in fact hard currencies.  With simple data types, we would
+have to perform the following nasty operation for every exchange
+transaction:
+
+int exchange(string str) {
+    string from, to;
+    int amt;
+
+    if(!str) return 0;
+    if(sscanf(str, "%d %s for %s", amt, from, to) != 3)
+      return 0;
+    if(from != "platinum" && from != "gold" && from !=
+      "silver" &&
+      from != "electrum" && from != "copper") {
+        notify_fail("We do not buy soft currencies!\n");
+        return 0;
+    }
+    ...
+}
+
+With five hard currencies, we have a rather simple example.  After all it
+took only two lines of code to represent the if statement which filtered
+out bad currencies.  But what if you had to check against all the names
+which cannot be used to make characters in the game?  There might be
+100 of those; would you want to write a 100 part if statement?
+What if you wanted to add a currency to the list of hard currencies?  That
+means you would have to change every check in the game for hard
+currencies to add one more part to the if clauses.  Arrays allow you
+simple access to groups of related data so that you do not have to deal
+with each individual value every time you want to perform a group
+operation.
+
+As a constant, an array might look like this:
+    ({ "platinum", "gold", "silver", "electrum", "copper" })
+which is an array of type string.  Individual data values in arrays are
+called elements, or sometimes members.  In code, just as constant
+strings are represented by surrounding them with "", constant arrays are
+represented by being surrounded by ({ }), with individual elements of
+the array being separated by a ,.
+
+You may have arrays of any LPC data type, simple or complex.  Arrays
+made up of mixes of values are called arrays of mixed type.  In most
+LPC drivers, you declare an array using a throw-back to C language
+syntax for arrays.  This syntax is often confusing for LPC coders
+because the syntax has a meaning in C that simply does not translate into
+LPC.  Nevertheless, if we wanted an array of type string, we would
+declare it in the following manner:
+
+string *arr;
+
+In other words, the data type of the elements it will contain followed by
+a space and an asterisk.  Remember, however, that this newly declared
+string array has a NULL value in it at the time of declaration.
+
+3.4 Using Arrays
+You now should understand how to declare and recognize an array in
+code.  In order to understand how they work in code, let's review the
+bank code, this time using arrays:
+
+string *hard_currencies;
+
+int exchange(string str) {
+    string from, to;
+    int amt;
+
+    if(!str) return 0;
+    if(sscanf(str, "%d %s for %s", amt, from, to) != 3)
+return 0;
+    if(member_array(from, hard_currencies) == -1) {
+        notify_fail("We do not buy soft currencies!\n");
+        return 0;
+    }
+    ...
+}
+
+This code assumes hard_currencies is a global variable and is initialized
+in create() as:
+    hard_currencies = ({ "platinum", "gold", "electrum", "silver",
+   "copper" });
+Ideally, you would have hard currencies as a #define in a header file for
+all objects to use, but #define is a topic for a later chapter.
+
+Once you know what the member_array() efun does, this method
+certainly is much easier to read as well as is much more efficient and
+easier to code.  In fact, you can probably guess what the
+member_array() efun does:  It tells you if a given value is a member of
+the array in question.  Specifically here, we want to know if the currency
+the player is trying to sell is an element in the hard_curencies array. 
+What might be confusing to you is, not only does member_array() tell us
+if the value is an element in the array, but it in fact tells us which element
+of the array the value is.
+
+How does it tell you which element?  It is easier to understand arrays if
+you think of the array variable as holding a number.  In the value above,
+for the sake of argument, we will say that hard_currencies holds the
+value 179000.  This value tells the driver where to look for the array
+hard_currencies represents.  Thus, hard_currencies points to a place
+where the array values may be found.  When someone is talking about
+the first element of the array, they want the element located at 179000. 
+When the object needs the value of the second element of the array, it
+looks at 179000 + one value, then 179000 plus two values for the third,
+and so on.  We can therefore access individual elements of an array by
+their index, which is the number of values beyond the starting point of
+the array we need to look to find the value.  For the array
+hard_currencies array:
+"platinum" has an index of 0.
+"gold" has an index of 1.
+"electrum" has an index of 2.
+"silver" has an index of 3.
+"copper" has an index of 4.
+
+The efun member_array() thus returns the index of the element being
+tested if it is in the array, or -1 if it is not in the array.  In order to
+reference an individual element in an array, you use its index number in
+the following manner:
+array_name[index_no]
+Example:
+hard_currencies[3]
+where hard_currencies[3] would refer to "silver".
+
+So, you now should now several ways in which arrays appear either as
+a whole or as individual elements.  As a whole, you refer to an array
+variable by its name and an array constant by enclosing the array in ({ })
+and separating elements by ,.  Individually, you refer to array variables
+by the array name followed by the element's index number enclosed in
+[], and to array constants in the same way you would refer to simple data
+types of the same type as the constant.  Examples:
+
+Whole arrays:
+variable:  arr
+constant: ({ "platinum", "gold", "electrum", "silver", "copper" })
+
+Individual members of arrays:
+variable: arr[2]
+constant: "electrum"
+
+You can use these means of reference to do all the things you are used to
+doing with other data types.  You can assign values, use the values in
+operations, pass the values as parameters to functions, and use the
+values as return types.  It is important to remember that when you are
+treating an element alone as an individual, the individual element is not
+itself an array (unless you are dealing with an array of arrays).  In the
+example above, the individual elements are strings.  So that:
+    str = arr[3] + " and " + arr[1];
+will create str to equal "silver and gold".  Although this seems simple
+enough, many people new to arrays start to run into trouble when trying
+to add elements to an array.  When you are treating an array as a whole
+and you wish to add a new element to it, you must do it by adding
+another array.
+
+Note the following example:
+string str1, str2;
+string *arr;
+
+str1 = "hi";
+str2 = "bye";
+/* str1 + str2 equals "hibye" */
+arr = ({ str1 }) + ({ str2 });
+/* arr is equal to ({ str1, str2 }) */
+Before going any further, I have to note that this example gives an
+extremely horrible way of building an array.  You should set it: arr = ({
+str1, str2 }).  The point of the example, however, is that you must add
+like types together.  If you try adding an element to an array as the data
+type it is, you will get an error.  Instead you have to treat it as an array of
+a single element.
+
+3.5 Mappings
+One of the major advances made in LPMuds since they were created is
+the mapping data type.  People alternately refer to them as associative
+arrays.  Practically speaking, a mapping allows you freedom from the
+association of a numerical index to a value which arrays require. 
+Instead, mappings allow you to associate values with indices which
+actually have meaning to you, much like a relational database.
+
+In an array of 5 elements, you access those values solely by their integer
+indices which cover the range 0 to 4.  Imagine going back to the example
+of money again.  Players have money of different amounts and different
+types.  In the player object, you need a way to store the types of money
+that exist as well as relate them to the amount of that currency type the
+player has.  The best way to do this with arrays would have been to
+store an array of strings representing money types and an array of
+integers representing values in the player object.  This would result in
+CPU-eating ugly code like this:
+
+int query_money(string type) {
+    int i;
+
+    i = member_array(type, currencies);
+    if(i>-1 && i < sizeof(amounts))  /* sizeof efun
+returns # of elements */
+        return amounts[i];
+    else return 0;
+}
+
+And that is a simple query function.  Look at an add function:
+
+void add_money(string type, int amt) {
+    string *tmp1;
+    int * tmp2;
+    int i, x, j, maxj;
+    
+    i = member_array(type, currencies);
+    if(i >= sizeof(amounts)) /*  corrupt data, we are in
+      a bad way */
+        return;
+    else if(i== -1) {
+        currencies += ({ type });
+        amounts += ({ amt });
+        return;
+    }
+    else {
+        amounts[i] += amt;
+        if(amounts[i] < 1) {
+            tmp1 = allocate(sizeof(currencies)-1);
+            tmp2 = allocate(sizeof(amounts)-1);
+            for(j=0, x =0, maxj=sizeof(tmp1); j < maxj;
+              j++) {
+                if(j==i) x = 1;
+                tmp1[j] = currencies[j+x];
+                tmp2[j] = amounts[j+x];
+            }
+            currencies = tmp1;
+            amounts = tmp2;
+        }
+    }
+}
+
+That is really some nasty code to perform the rather simple concept of
+adding some money.  First, we figure out if the player has any of that
+kind of money, and if so, which element of the currencies array it is. 
+After that, we have to check to see that the integrity of the currency data
+has been maintained.  If the index of the type in the currencies array is
+greater than the highest index of the amounts array, then we have a
+problem since the indices are our only way of relating the two arrays. 
+Once we know our data is in tact, if the currency type is not currently
+held by the player, we simply tack on the type as a new element to the
+currencies array and the amount as a new element to the amounts array. 
+Finally, if it is a currency the player currently has, we just add the
+amount to the corresponding index in the amounts array.  If the money
+gets below 1, meaning having no money of that type, we want to clear
+the currency out of memory.
+
+Subtracting an element from an array is no simple matter.  Take, for
+example, the result of the following:
+
+string *arr;
+
+arr = ({ "a", "b", "a" });
+arr -= ({ arr[2] });
+
+What do you think the final value of arr is? Well, it is:
+    ({ "b", "a" })
+Subtracting arr[2] from the original array does not remove the third
+element from the array.  Instead, it subtracts the value of the third
+element of the array from the array.  And array subtraction removes the
+first instance of the value from the array.  Since we do not want to be
+<* NOTE Highlander@MorgenGrauen 11.2.94:
+	WRONG in MorgenGrauen (at least). The result is actually ({ "b" }). Array
+	subtraction removes ALL instances of the subtracted value from the array.
+	This holds true for all Amylaar-driver LPMuds.
+*>
+forced on counting on the elements of the array as being unique, we are
+forced to go through some somersaults to remove the correct element
+from both arrays in order to maintain the correspondence of the indices
+in the two arrays.
+
+Mappings provide a better way.  They allow you to directly associate the
+money type with its value.  Some people think of mappings as arrays
+where you are not restricted to integers as indices.  Truth is, mappings
+are an entirely different concept in storing aggregate information.  Arrays
+force you to choose an index which is meaningful to the machine for
+locating the appropriate data.  The indices tell the machine how many
+elements beyond the first value the value you desire can be found.  With
+mappings, you choose indices which are meaningful to you without
+worrying about how that machine locates and stores it.
+
+You may recognize mappings in the following forms:
+
+constant values:
+whole: ([ index:value, index:value ]) Ex: ([ "gold":10, "silver":20 ])
+element:  10
+
+variable values:
+whole:    map   (where map is the name of a mapping variable)
+element: map["gold"]
+
+So now my monetary functions would look like:
+
+int query_money(string type) { return money[type]; }
+
+void add_money(string type, int amt) {
+    if(!money[type]) money[type] = amt;
+    else money[type] += amt;
+    if(money[type] < 1)
+      map_delete(money, type);          /* this is for
+          MudOS */
+            ...OR... 
+            money = m_delete(money, type)  /* for some
+          LPMud 3.* varieties */
+            ... OR... 
+         m_delete(money, type);    /* for other LPMud 3.*
+          varieties */
+}
+
+Please notice first that the efuns for clearing a mapping element from the
+mapping vary from driver to driver.  Check with your driver's
+documentation for the exact name an syntax of the relevant efun.
+
+As you can see immediately, you do not need to check the integrity of
+your data since the values which interest you are inextricably bound to
+one another in the mapping.  Secondly, getting rid of useless values is a
+simple efun call rather than a tricky, CPU-eating loop.  Finally, the
+query function is made up solely of a return instruction. 
+
+You must declare and initialize any mapping before using it. 
+Declarations look like:
+mapping map;
+Whereas common initializations look like:
+map = ([]);
+map = m_allocate(10)   ...OR...   map = m_allocate(10);
+map = ([ "gold": 20, "silver": 15 ]);
+
+As with other data types, there are rules defining how they work in
+common operations like addition and subtraction:
+    ([ "gold":20, "silver":30 ]) + ([ "electrum":5 ]) 
+gives:
+    (["gold":20, "silver":30, "electrum":5])   
+Although my demonstration shows a continuity of order, there is in fact
+no guarantee of the order in which elements of mappings will stored. 
+Equivalence tests among mappings are therefore not a good thing.
+
+3.6 Summary
+Mappings and arrays can be built as complex as you need them to be. 
+You can have an array of mappings of arrays.  Such a thing would be
+declared like this:
+
+mapping *map_of_arrs;
+which might look like:
+({ ([ ind1: ({ valA1, valA2}), ind2: ({valB1, valB2}) ]), ([ indX:
+({valX1,valX2}) ]) })
+
+Mappings may use any data type as an index, including objects. 
+Mapping indices are often referred to as keys as well, a term from
+databases.  Always keep in mind that with any non-integer data type,
+you must first initialize a variable before making use of it in common
+operations such as addition and subtraction.  In spite of the ease and
+dynamics added to LPC coding by mappings and arrays, errors caused
+by failing to initialize their values can be the most maddening experience
+for people new to these data types.  I would venture that a very high
+percentage of all errors people experimenting with mappings and arrays
+for the first time encounter are one of three error messages:
+	Indexing on illegal type.
+	Illegal index.
+	Bad argument 1 to (+ += - -=) /* insert your favourite operator */
+Error messages 1 and 3 are darn near almost always caused by a failure
+to initialize the array or mapping in question.  Error message 2 is caused
+generally when you are trying to use an index in an initialized array
+which does not exist.  Also, for arrays, often people new to arrays will
+get error message 3 because they try to add a single element to an array
+by adding the initial array to the single element value instead of adding
+an array of the single element to the initial array.  Remember, add only
+arrays to arrays.
+
+At this point, you should feel comfortable enough with mappings and
+arrays to play with them.  Expect to encounter the above error messages
+a lot when first playing with these.  The key to success with mappings is
+in debugging all of these errors and seeing exactly what causes wholes
+in your programming which allow you to try to work with uninitialized
+mappings and arrays.  Finally, go back through the basic room code and
+look at things like the set_exits() (or the equivalent on your mudlib)
+function.  Chances are it makes use of mappings.  In some instances, it
+will use arrays as well for compatibility with mudlib.n.
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/LPC-KURS2/chapter4 b/doc/KURS/LPC-KURS2/chapter4
new file mode 100644
index 0000000..c3e9905
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/chapter4
@@ -0,0 +1,195 @@
+Intermediate LPC
+Descartes of Borg
+November 1993
+
+                       Chapter 4: The LPC Pre-Compiler
+
+4.1 Review
+The previous chapter was quite heavy, so now I will slow down a bit so
+you can digest and play with mappings and arrays by taking on the
+rather simple topic of the LPC pre-compiler.  By this point, however,
+you should well understand how the driver interacts with the mudlib and
+be able to code objects which use call outs and heart beats.  In addition,
+you should be coding simple objects which use mappings and arrays,
+noting how these data types perform in objects.  It is also a good idea to
+start looking in detail at the actual mudlib code that makes up your mud. 
+See if you understand everything which is going on in your mudlibs
+room and monster codes.  For things you do not understand, ask the
+people on your mud designated to answer creator coding questions.
+
+Pre-compiler is actually a bit of a misnomer since LPC code is never
+truly compiled.  Although this is changing with prototypes of newer
+LPC drivers, LPC drivers interpret the LPC code written by creators
+rather than compile it into binary format.  Nevertheless, the LPC pre-
+compiler functions still perform much like pre-compilers for compiled
+languages in that pre-compiler directives are interpreted before the driver
+even starts to look at object code. 
+
+4.2 Pre-compiler Directives
+If you do not know what a pre-compiler is, you really do not need to
+worry.  With respect to LPC, it is basically a process which happens
+before the driver begins to interpret LPC code which allows you to
+perform actions upon the entire code found in your file.  Since the code
+is not yet interpreted, the pre-compiler process is involved before the file
+exists as an object and before any LPC functions or instructions are ever
+examined.  The pre-compiler is thus working at the file level, meaning
+that it does not deal with any code in inherited files.
+
+The pre-compiler searches a file sent to it for pre-compiler directives. 
+These are little instructions in the file meant only for the pre-compiler
+and are not really part of the LPC language.  A pre-compiler directive is
+any line in a file beginning with a pound (#) sign.  Pre-compiler
+directives are generally used to construct what the final code of a file will
+look at.  The most common pre-compiler directives are:
+
+#define
+#undefine
+#include
+#ifdef
+#ifndef
+#if
+#elseif
+#else
+#endif
+#pragma
+
+Most realm coders on muds use exclusively the directives #define and
+#include.  The other directives you may see often and should understand
+what they mean even if you never use them.
+
+The first pair of directives are:
+#define
+#undefine
+
+The #define directive sets up a set of characters which will be replaced
+any where they exist in the code at precompiler time with their definition. 
+For example, take:
+
+#define OB_USER "/std/user"
+
+This directive has the pre-compiler search the entire file for instances of
+OB_USER.  Everywhere it sees OB_USER, it replaces with "/std/user". 
+<* NOTE Highlander@MorgenGrauen 11.2.94:
+	WRONG. OB_USER will _not_ be replaced if within "" in which case it is
+	treated as a normal string. So it is possible to write the text OB_USER.
+*>
+Note that it does not make OB_USER a variable in the code.  The LPC
+interpreter never sees the OB_USER label.  As stated above, the pre-
+compiler is a process which takes place before code interpretation.  So
+what you wrote as:
+
+#define OB_USER "/std/user"
+
+void create() {
+    if(!file_exists(OB_USER+".c")) write("Merde! No user file!");
+    else write("Good! User file still exists!");
+}
+
+would arrive at the LPC interpreter as:
+
+void create() {
+    if(!file_exists("/std/user"+".c")) write("Merde! No user file!");
+    else write("Good! User file still exists!");
+}
+
+<* NOTE Highlander@MorgenGrauen 11.2.94
+	But: write("Text is OB_USER foo bar\n");
+	simply writes "Text is OB_USER foo bar". Confer previous note.
+*>
+
+Simply put, #define just literally replaces the defined label with whatever
+follows it.  You may also use #define in a special instance where no
+value follows.  This is called a binary definition.  For example:
+
+#define __NIGHTMARE
+
+exists in the config file for the Nightmare Mudlib.  This allows for pre-
+compiler tests which will be described later in the chapter.
+
+The other pre-compiler directive you are likely to use often is #include. 
+As the name implies, #include includes the contents of another file right
+into the file being pre-compiled at the point in the file where the directive
+is placed.  Files made for inclusion into other files are often called header
+files.  They sometimes contain things like #define directives used by
+multiple files and function declarations for the file.  The traditional file
+extension to header files is .h.
+
+Include directives follow one of 2 syntax's:
+
+#include <filename>
+#include "filename"
+
+If you give the absolute name of the file, then which syntax you use is
+irrelevant.  How you enclose the file name determines how the pre-
+compiler searches for the header files.  The pre-compiler first searches in
+system include directories for files enclosed in <>.  For files enclosed in
+"", the pre-compiler begins its search in the same directory as the file
+going through the pre-compiler.  Either way, the pre-compiler will
+search the system include directories and the directory of the file for the
+header file before giving up.  The syntax simply determines the order.
+<* NOTE Highlander@MorgenGrauen 11.2.94
+	When using standard-headerfiles one should choose <>. "" is appropriate
+	when dealing with selfdefined headerfiles.
+*>
+
+The simplest pre-compiler directive is the #pragma directive.  It is
+doubtful you will ever use this one.  Basically, you follow the directive
+with some keyword which is meaningful to your driver.  The only
+keyword I have ever seen is strict_types, which simply lets the driver
+know you want this file interpreted with strict data typing.  I doubt you
+will ever need to use this, and you may never even see it.  I just included
+it in the list in the event you do see it so you do not think it is doing
+anything truly meaningful.
+
+The final group of pre-compiler directives are the conditional pre-
+compiler directives.  They allow you to pre-compile the file one way
+given the truth value of an expression, otherwise pre-compile the file
+another way.  This is mostly useful for making code portable among
+mudlibs, since putting the m_delete() efun in code on a MudOS mud
+would normally cause an error, for example.  So you might write the
+following:
+
+#ifdef  MUDOS
+    map_delete(map, key);
+#else
+    map = m_delete(map, key);
+#endif
+
+which after being passed through the pre-compiler will appear to the
+interpreter as:
+
+    map_delete(map, key);   
+
+on a MudOS mud, and:
+  
+    map = m_delete(map, key);
+
+on other muds.  The interpreter never sees the function call that would
+cause it to spam out in error. 
+
+Notice that my example made use of a binary definition as described
+above.  Binary definitions allow you to pass certain code to the
+interpreter based on what driver or mudlib you are using, among other
+conditions.
+
+4.3 Summary
+The pre-compiler is a useful LPC tool for maintaining modularity among
+your programs.  When you have values that might be subject to change,
+but are used widely throughout your files, you might stick all of those
+values in a header file as #define statements so that any need to make a
+future change will cause you to need to change just the #define directive. 
+A very good example of where this would be useful would be a header
+file called money.h  which includes the directive:
+#define HARD_CURRENCIES ({ "gold", "platinum", "silver",
+"electrum", "copper" })
+so that if ever you wanted to add a new hard currency, you only need
+change this directive in order to update all files needing to know what the
+hard currencies are.
+
+The LPC pre-compiler also allows you to write code which can be
+ported without change among different mudlibs and drivers.  Finally,
+you should be aware that the pre-compiler only accepts lines ending in
+carriage returns.  If you want a multiple line pre-compiler directive, you
+need to end each incomplete line with a backslash(\).
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/LPC-KURS2/chapter5 b/doc/KURS/LPC-KURS2/chapter5
new file mode 100644
index 0000000..f45b6fa
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/chapter5
@@ -0,0 +1,186 @@
+Intermediate LPC
+Descartes of Borg
+November 1993
+
+                     Chapter 5: Advanced String Handling
+
+5.1 What a String Is
+The LPC Basics textbook taught strings as simple data types.  LPC
+generally deals with strings in such a matter.  The underlying driver
+program, however, is written in C, which has no string data type.  The
+driver in fact sees strings as a complex data type made up of an array of
+characters, a simple C data type.  LPC, on the other hand does not
+recognize a character data type (there may actually be a driver or two out
+there which do recognize the character as a data type, but in general not). 
+The net effect is that there are some array-like things you can do with
+strings that you cannot do with other LPC data types.
+
+The first efun regarding strings you should learn is the strlen() efun. 
+This efun returns the length in characters of an LPC string, and is thus
+the string equivalent to sizeof() for arrays.  Just from the behaviour of
+this efun, you can see that the driver treats a string as if it were made up
+of smaller elements.  In this chapter, you will learn how to deal with
+strings on a more basic level, as characters and sub strings.
+
+5.2 Strings as Character Arrays
+You can do nearly anything with strings that you can do with arrays,
+except assign values on a character basis.  At the most basic, you can
+actually refer to character constants by enclosing them in '' (single
+quotes).  'a' and "a" are therefore very different things in LPC.  'a'
+represents a character which cannot be used in assignment statements or
+any other operations except comparison evaluations.  "a" on the other
+hand is a string made up of a single character.  You can add and subtract
+other strings to it and assign it as a value to a variable.
+
+With string variables, you can access the individual characters to run
+comparisons against character constants using exactly the same syntax
+that is used with arrays.  In other words, the statement:
+    if(str[2] == 'a')
+is a valid LPC statement comparing the second character in the str string
+to the character 'a'.  You have to be very careful that you are not
+comparing elements of arrays to characters, nor are you comparing
+characters of strings to strings.
+
+LPC also allows you to access several characters together using LPC's
+range operator ..:
+    if(str[0..1] == "ab")
+In other words, you can look for the string which is formed by the
+characters 0 through 1 in the string str.  As with arrays, you must be
+careful when using indexing or range operators so that you do not try to
+reference an index number larger than the last index.  Doing so will
+result in an error.
+
+Now you can see a couple of similarities between strings and arrays:
+1) You may index on both to access the values of individual elements.
+	a) The individual elements of strings are characters
+	b) The individual elements of arrays match the data type of the
+array.
+2) You may operate on a range of values
+	a) Ex: "abcdef"[1..3] is the string "bcd"
+	b) Ex: ({ 1, 2, 3, 4, 5 })[1..3] is the int array ({ 2, 3, 4 })
+<* NOTE Highlander@MorgenGrauen
+	Also possible in MorgenGrauen (in common: Amylaar-driver LPMuds):
+	"abcdef"[2..]    -> "cdef" and
+	"abcdef"[1..<2]  -> "bcde"  (< means start counting from the end and with 1)
+*>
+
+And of course, you should always keep in mind the fundamental
+difference: a string is not made up of a more fundamental LPC data type. 
+In other words, you may not act on the individual characters by
+assigning them values.
+
+5.3 The Efun sscanf()
+You cannot do any decent string handling in LPC without using
+sscanf().  Without it, you are left trying to play with the full strings
+passed by command statements to the command functions.  In other
+words, you could not handle a command like: "give sword to leo", since
+you would have no way of separating "sword to leo" into its constituent
+parts.  Commands such as these therefore use this efun in order to use
+commands with multiple arguments or to make commands more
+"English-like".
+
+Most people find the manual entries for sscanf() to be rather difficult
+reading.  The function does not lend itself well to the format used by
+manual entries.  As I said above, the function is used to take a string and
+break it into usable parts.  Technically it is supposed to take a string and
+scan it into one or more variables of varying types.  Take the example
+above:
+
+int give(string str) {
+    string what, whom;
+
+    if(!str) return notify_fail("Give what to whom?\n");
+    if(sscanf(str, "%s to %s", what, whom) != 2) 
+      return notify_fail("Give what to whom?\n");
+    ... rest of give code ...
+}
+
+The efun sscanf() takes three or more arguments.  The first argument is
+the string you want scanned.  The second argument is called a control
+string.  The control string is a model which demonstrates in what form
+the original string is written, and how it should be divided up.  The rest
+of the arguments are variables to which you will assign values based
+upon the control string.
+
+The control string is made up of three different types of elements: 1)
+constants, 2) variable arguments to be scanned, and 3) variable
+arguments to be discarded.  You must have as many of the variable
+arguments in sscanf() as you have elements of type 2 in your control
+string.  In the above example, the control string was "%s to %s", which
+is a three element control string made up of one constant part (" to "),
+and two variable arguments to be scanned ("%s").  There were no
+variables to be discarded.
+
+The control string basically indicates that the function should find the
+string " to " in the string str.  Whatever comes before that constant will
+be placed into the first variable argument as a string.  The same thing
+will happen to whatever comes after the constant.
+
+Variable elements are noted by a "%" sign followed by a code for
+decoding them.  If the variable element is to be discarded, the "%" sign
+is followed by the "*" as well as the code for decoding the variable. 
+Common codes for variable element decoding are "s" for strings and "d"
+for integers.  In addition, your mudlib may support other conversion
+codes, such as "f" for float.  So in the two examples above, the "%s" in
+the control string indicates that whatever lies in the original string in the
+corresponding place will be scanned into a new variable as a string.
+
+A simple exercise.  How would you turn the string "145" into an
+integer?
+
+Answer:
+int x;
+sscanf("145", "%d", x);
+
+After the sscanf() function, x will equal the integer 145.
+
+Whenever you scan a string against a control string, the function
+searches the original string for the first instance of the first constant in
+the original string.  For example, if your string is "magic attack 100" and
+you have the following:
+int improve(string str) {
+    string skill;
+    int x;
+
+    if(sscanf(str, "%s %d", skill, x) != 2) return 0;
+    ...
+}
+you would find that you have come up with the wrong return value for
+sscanf() (more on the return values later).  The control string, "%s %d",
+is made up of to variables to be scanned and one constant.  The constant
+is " ".  So the function searches the original string for the first instance
+of " ", placing whatever comes before the " " into skill, and trying to
+place whatever comes after the " " into x.  This separates "magic attack
+100" into the components "magic" and "attack 100".  The function,
+however, cannot make heads or tales of "attack 100" as an integer, so it
+returns 1, meaning that 1 variable value was successfully scanned
+("magic" into skill).
+
+Perhaps you guessed from the above examples, but the efun sscanf()
+returns an int, which is the number of variables into which values from
+the original string were successfully scanned.  Some examples with
+return values for you to examine:
+
+sscanf("swo  rd descartes", "%s to %s", str1, str2)           return: 0
+sscanf("swo  rd descartes", "%s %s", str1, str2)              return: 2
+sscanf("200 gold to descartes", "%d %s to %s", x, str1, str2) return: 3
+sscanf("200 gold to descartes", "%d %*s to %s", x, str1)      return: 2
+where x is an int and str1 and str2 are string
+
+5.4 Summary
+LPC strings can be thought of as arrays of characters, yet always
+keeping in mind that LPC does not have the character data type (with
+most, but not all drivers).  Since the character is not a true LPC data
+type, you cannot act upon individual characters in an LPC string in the
+same manner you would act upon different data types.  Noticing the
+intimate relationship between strings and arrays nevertheless makes it
+easier to understand such concepts as the range operator and indexing on
+strings.
+
+There are efuns other than sscanf() which involve advanced string
+handling, however, they are not needed nearly as often.  You should
+check on your mud for man or help files on the efuns: explode(),
+implode(), replace_string(), sprintf().  All of these are very valuable
+tools, especially if you intend to do coding at the mudlib level.
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/LPC-KURS2/chapter6 b/doc/KURS/LPC-KURS2/chapter6
new file mode 100644
index 0000000..98b3552
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/chapter6
@@ -0,0 +1,276 @@
+Intermediate LPC
+Descartes of Borg
+November 1993
+
+                       Chapter 6: Intermediate Inheritance
+
+6.1 Basics of Inheritance
+In the textbook LPC Basics, you learned how it is the mudlib maintains
+consistency amoung mud objects through inheritance.  Inheritance
+allows the mud administrators to code the basic functions and such that
+all mudlib objects, or all mudlib objects of a certain type must have so
+that you can concentrate on creating the functions which make these
+objects different.  When you build a room, or a weapon, or a monster,
+you are taking a set of functions already written for you and inheriting
+them into your object.  In this way, all objects on the mud can count on
+other objects to behave in a certain manner.  For instance, player objects
+can rely on the fact that all room objects will have a function in them
+called query_long() which describes the room.  Inheritance thus keeps
+you from having to worry about what the function query_long() should
+look like.
+
+Naturally, this textbook tries to go beyond this fundamental knowledge
+of inheritance to give the coder a better undertstanding of how
+inheritance works in LPC programming.  Without getting into detail that
+the advanced domain coder/beginner mudlib coder simply does not yet
+need, this chapter will try to explain exactly what happens when you
+inherit an object.
+
+6.2 Cloning and Inheritance
+Whenever a file is referenced for the first time as an object (as opposed
+to reading the contents of the file), the game tries to load the file into
+memory and create an object.  If the object is successfully loaded into
+memory, it becomes as master copy.  Master copies of objects may be
+cloned but not used as actual game objects.  The master copy is used to
+support any clone objects in the game.
+
+The master copy is the source of one of the controversies of mud LPC
+coding, that is whether to clone or inherit.  With rooms, there is no
+question of what you wish to do, since there should only be one instance
+of each room object in the game.  So you generally use inheritance in
+creating rooms.  Many mud administrators, including myself, however
+encourage creators to clone the standard monster object and configure it
+from inside room objects instead of keeping monsters in separate files
+which inherit the standard monster object.
+
+As I stated above, each time a file is referenced to create an object, a
+master copy is loaded into memory.  When you do something like:
+void reset() {
+    object ob;
+    ob = new("/std/monster");
+      /* clone_object("/std/monster") some places */
+    ob->set_name("foo monster");
+    ...  rest of monster config code followed by moving
+it to the room ...
+}
+the driver searches to see if their is a master object called "/std/monster". 
+If not, it creates one.  If it does exist, or after it has been created, the
+driver then creates a clone object called "/std/monster#<number>".  If
+this is the first time "/std/monster" is being referenced, in effect, two
+objects are being created: the master object and the cloned instance.
+
+On the other hand, let's say you did all your configuring in the create()
+of a special monster file which inherits "/std/monster".  Instead of
+cloning the standard monster object from your room, you clone your
+monster file.  If the standard monster has not been loaded, it gets loaded
+since your monster inherits it.  In addition, a master copy of your file
+gets loaded into memory.  Finally, a clone of your monster is created
+and moved into the room, for a total of three objects added to the game. 
+Note that you cannot make use of the master copy easily to get around
+this.  If, for example, you were to do:
+    "/wizards/descartes/my_monster"->move(this_object());
+instead of
+    new("/wizards/descartes/my_monster")->move(this_object());
+you would not be able to modify the file "my_monster.c" and update it,
+since the update command destroys the current master version of an
+object.  On some mudlibs it also loads the new version into memory. 
+Imagine the look on a player's face when their monster disappears in
+mid-combat cause you updated the file!
+
+Cloning is therefore a useful too when you plan on doing just that-
+cloning.  If you are doing nothing special to a monster which cannot be
+done through a few call others, then you will save the mud from getting
+loaded with useless master copies.  Inheritance, however, is useful if
+you plan to add functionality to an object (write your own functions) or
+if you have a single configuration that gets used over and over again
+(you have an army of orc guards all the same, so you write a special orc
+file and clone it).
+
+6.3 Inside Inheritance
+When objects A and B inherit object C, all three objects have their own
+set of data sharing one set of function definitions from object C.  In
+addition, A and B will have separate functions definitions which were
+entered separately into their code.  For the sake of example throughout
+the rest of the chapter, we will use the following code.  Do not be
+disturbed if, at this point, some of the code makes no sense:
+
+OBJECT C
+private string name, cap_name, short, long;
+private int setup;
+
+void set_name(string str)
+nomask string query_name();
+private int query_setup();
+static void unsetup();
+void set_short(string str);
+string query_short();
+void set_long(string str);
+string query_long();
+
+
+void set_name(string str) { 
+    if(!query_setup()) {
+        name = str;
+    setup = 1;
+}
+
+nomask string query_name() { return name; }
+
+private query_setup() { return setup; }
+
+static void unsetup() { setup = 0; }
+
+string query_cap_name() {
+    return (name ? capitalize(name) : ""); }
+}
+
+void set_short(string str) { short = str; }
+
+string query_short() { return short; }
+
+void set_long(string str) { long = str; }
+
+string query_long() { return str; }
+
+void create() { seteuid(getuid()); }
+
+OBJECT B
+inherit "/std/objectc";
+
+private int wc;
+
+void set_wc(int wc);
+int query_wc();
+int wieldweapon(string str);
+
+void create() { ::create(); }
+
+void init() {
+    if(environment(this_object()) == this_player())
+      add_action("wieldweapon", "wield");
+}
+
+void set_wc(int x) { wc = x; }
+
+int query_wc() { return wc; }
+
+int wieldweapon(string str) {
+    ... code for wielding the weapon ...
+}
+
+OBJECT A
+inherit "/std/objectc";
+
+int ghost;
+
+void create() { ::create(); }
+
+void change_name(string str) {
+    if(!((int)this_object()->is_player())) unsetup();
+    set_name(str);
+}
+
+string query_cap_name() {
+    if(ghost) return "A ghost";
+    else return ::query_cap_name();
+}
+
+As you can see, object C is inherited both by object A and object B. 
+Object C is a representation of a much oversimplified base object, with B
+being an equally oversimplified weapon and A being an equally
+simplified living object.  Only one copy of each function is retained in
+memory, even though we have here three objects using the functions. 
+There are of course, three instances of the variables from Object C in
+memory, with one instance of the variables of Object A and Object B in
+memory.  Each object thus gets its own data.  
+
+6.4 Function and Variable Labels
+Notice that many of the functions above are proceeded with labels which
+have not yet appeared in either this text or the beginner text, the labels
+static, private, and nomask.  These labels define special priveledges
+which an object may have to its data and member functions.  Functions
+you have used up to this point have the default label public.  This is
+default to such a degree, some drivers do not support the labeling.
+
+A public variable is available to any object down the inheritance tree
+from the object in which the variable is declared.  Public variables in
+object C may be accessed by both objects A and B.  Similarly, public
+functions may be called by any object down the inheritance tree from the
+object in which they are declared. 
+
+The opposite of public is of course private.  A private variable or
+function may only be referenced from inside the object which declares it. 
+If object A or B tried to make any reference to any of the variables in
+object C, an error would result, since the variables are said to be out of
+scope, or not available to inheriting classes due to their private labels. 
+Functions, however, provide a unique challenge which variables do not. 
+External objects in LPC have the ability to call functions in other objects
+through call others.  The private label does not protect against call
+others.
+
+To protect against call others, functions use the label static.  A function
+which is static may only be called from inside the complete object or
+from the game driver.  By complete object, I mean object A can call
+static functions in the object C it inherits.  The static only protects against
+external call others.  In addition, this_object()->foo() is considered an
+internal call as far as the static label goes.
+
+Since variables cannot be referenced externally, there is no need for an
+equivalent label for them.  Somewhere along the line, someone decided
+to muddy up the waters and use the static label with variables to have a
+completely separate meaning.  What is even more maddening is that this
+label has nothing to do with what it means in the C programming
+language.  A static variable is simply a variable that does not get saved to
+file through the efun save_object() and does not get restored through
+restore_object().  Go figure.
+
+In general, it is good practice to have private variables with public
+functions, using query_*() functions to access the values of inherited
+variables, and set_*(), add_*(), and other such functions to change
+those values.  In realm coding this is not something one really has to
+worry a lot about.  As a matter of fact, in realm coding you do not have
+to know much of anything which is in this chapter.  To be come a really
+good realm coder, however, you have to be able to read the mudlib
+code.  And mudlib code is full of these labels.  So you should work
+around with these labels until you can read code and understand why it
+is written that way and what it means to objects which inherit the code.
+
+The final label is nomask, and it deals with a property of inheritance
+which allows you to rewrite functions which have already been defined. 
+For example, you can see above that object A rewrote the function
+query_cap_name().  A rewrite of  function is called overriding the
+function.  The most common override of a function would be in a case
+like this, where a condition peculiar to our object (object A) needs to
+happen on a call ot the function under certain circumstances.  Putting test
+code into object C just so object A can be a ghost is plain silly.  So
+instead, we override query_cap_name() in object A, testing to see if the
+object is a ghost.  If so, we change what happens when another object
+queries for the cap name.  If it is not a ghost, then we want the regular
+object behaviour to happen.  We therefore use the scope resolution
+operator (::) to call the inherited version of the query_cap_name()
+function and return its value.
+
+A nomask function is one which cannot be overridden either through
+inheritance or through shadowing.  Shadowing is a sort of backwards
+inheritance which will be detailed in the advanced LPC textbook.  In the
+example above, neither object A nor object B (nor any other object for
+that matter) can override query_name().  Since we want to use
+query_name() as a unique identifier of objects, we don't want people
+faking us through shadowing or inheritance.  The function therefore gets
+the nomask label.
+
+6.5 Summary
+Through inheritance, a coder may make user of functions defined in
+other objects in order to reduce the tedium of producing masses of
+similar objects and to increase the consistency of object behaviour across
+mudlib objects.  LPC inheritance allows objects maximum priveledges in
+defining how their data can be accessed by external objects as well as
+objects inheriting them.  This data security is maintained through the
+keywords, nomask, private, and static.
+
+In addition, a coder is able to change the functionality of non-protected
+functions by overriding them.  Even in the process of overriding a
+function, however, an object may access the original function through
+the scope resolution operator.
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/LPC-KURS2/chapter7 b/doc/KURS/LPC-KURS2/chapter7
new file mode 100644
index 0000000..aa8cc0e
--- /dev/null
+++ b/doc/KURS/LPC-KURS2/chapter7
@@ -0,0 +1,298 @@
+Intermediate LPC
+Descartes of Borg
+November 1993
+
+                            Chapter 7: Debugging
+
+7.1 Types of Errors
+By now, you have likely run into errors here, there, and everywhere.  In
+general, there are three sorts of errors you might see: compile time
+errors, run time errors, and malfunctioning code.  On most muds you
+will find a personal file where your compile time errors are logged.  For
+the most part, this file can be found either in your home directory as the
+file named "log" or ".log", or somewhere in the directory "/log" as a file
+with your name..  In addition, muds tend to keep a log of run time errors
+which occur while the mud is up.  Again, this is generally found in
+"/log".  On MudOS muds it is called "debug.log".  On other muds it may
+be called something different like "lpmud.log".  Ask your administrators
+where compile time and run time errors are each logged if you do not
+already know.
+
+Compile time errors are errors which occur when the driver tries to load
+an object into memory.  If, when the driver is trying to load an object
+into memory, it encounters things which it simply does not understand
+with respect to what you wrote, it will fail to load it into memory and log
+why it could not load the object into your personal error log.  The most
+common compile time errors are typos, missing or extra (), {}. [], or "",
+and failure to declare properly functions and variables used by the
+object.
+
+Run time errors occur when something wrong happens to an object in
+memory while it is executing a statement.  For example, the driver
+cannot tell whether the statement "x/y" will be valid in all circumstances. 
+In fact, it is a valid LPC expression.  Yet, if the value of y is 0, then a
+run time error will occur since you cannot divide by 0.  When the driver
+runs across an error during the execution of a function, it aborts
+execution of the function and logs an error to the game's run time error
+log.  It will also show the error to this_player(), if defined, if the player
+is a creator, or it will show "What?" to players.  Most common causes
+for run time errors are bad values and trying to perform operations with
+data types for which those operations are not defined.
+
+The most insideous type of error, however, is plain malfunctioning
+code.  These errors do not log, since the driver never really realizes that
+anything is wrong.  In short, this error happens when you think the code
+says one thing, but in fact it says another thing.  People too often
+encounter this bug and automatically insist that it must be a mudlib or
+driver bug.  Everyone makes all types of errors though, and more often
+than not when code is not functioning the way you should, it will be
+because you misread it.  
+
+7.2 Debugging Compile Time Errors
+Compile time errors are certainly the most common and simplest bugs to
+debug.  New coders often get frustrated by them due to the obscure
+nature of some error messages.  Nevertheless, once a person becomes
+used to the error messages generated by their driver, debugging compile
+time errors becomes utterly routine.
+
+In your error log, the driver will tell you the type of error and on which
+line it finally noticed there was an error.  Note that this is not on which
+line the actual error necessarily exists.  The most common compile time
+error, besides the typo, is the missing or superfluous parentheses,
+brackets, braces, or quotes.  Yet this error is the one that most baffles
+new coders, since the driver will not notice the missing or extra piece
+until well after the original.  Take for example the following code:
+
+1 int test(string str) {
+2    int x;
+3    for(x =0; x<10; x++)
+4        write(x+"\n");
+5    }
+6    write("Done.\n");
+7 }
+
+Depending on what you intended, the actual error here is either at line 3
+(meaning you are missing a {) or at line 5 (meaing you have an extra }). 
+Nevertheless, the driver will report that it found an error when it gets to
+line 6.  The actual driver message may vary from driver to driver, but no
+matter which driver, you will see an error on line 6, since the } in line 5
+is interpreted as ending the function test().  At line 6, the driver sees that
+you have a write() sitting outside any function definition, and thus
+reports an error.  Generally, the driver will also go on to report that it
+found an error at line 7 in the form of an extra }.
+
+The secret to debugging these is coding style.  Having closing } match
+up vertically with the clauses they close out helps you see where you are
+missing them when you are debugging code.  Similarly, when using
+multiple sets of parentheses, space out different groups like this:
+    if( (x=sizeof(who=users()) > ( (y+z)/(a-b) + (-(random(7))) ) ) 
+As you can see, the parentheses for the for() statement, are spaced out
+from the rest of the statement.  In addition, individual sub-groups are
+spaced so they can easily be sorted out in the event of an error.
+
+Once you have a coding style which aids in picking these out, you learn
+which error messages tend to indicate this sort of error.  When
+debugging this sort of error, you then view a section of code before and
+after the line in question.  In most all cases, you will catch the bug right
+off.
+
+Another common compile time error is where the driver reports an
+unknown identifier.  Generally, typos and failure to declare variables
+causes this sort of error.  Fortunately, the error log will almost always
+tell you exactly where the error is.  So when debugging it, enter the
+editor and find the line in question.  If the problem is with a variable and
+is not a typo, make sure you declared it properly.  On the other hand, if
+it is a typo, simply fix it!
+
+One thing to beware of, however, is that this error will sometimes be
+reported in conjunction with a missing parentheses, brackets, or braces
+type error.  In these situations, your problem with an unknown identifier
+is often bogus.  The driver misreads the way the {} or whatever are
+setup, and thus gets variable declarations confused.  Therefore make
+sure all other compile time errors are corrected before bothering with
+these types of errors.
+
+In the same class with the above error, is the general syntax error.  The
+driver generates this error when it simply fails to understand what you
+said.  Again, this is often caused by typos, but can also be caused by not
+properly understanding the syntax of a certain feature like writing a for()
+statement: for(x=0, x<10, x++).  If you get an error like this which is
+not a syntax error, try reviewing the syntax of the statement in which the
+error is occurring.
+
+7.3 Debugging Run Time Errors
+Run time errors are much more complex than their compile time
+counterparts.  Fortunately these errors do get logged, though many
+creators do not realise or they do not know where to look.  The error log
+for run time errors are also generally much more detailed than compile
+time errors, meaning that you can trace the history of the execution train
+from where it started to where it went wrong.  You therefore can setup
+debugging traps using precompiler statements much easier using these
+logs.  Run time errors, however, tend to result from using more
+complex codign techniques than beginners tend to use, which means you
+are left with errors which are generally more complicated than simple
+compile time errors.
+
+Run time errors almost always result from misusing LPC data types. 
+Most commonly, trying to do call others using object variables which are
+NULL, indexing on mapping, array, or string variables which are
+NULL, or passing bad arguments to functions.  We will look at a real
+run time error log from Nightmare:
+
+Bad argument 1 to explode()
+program: bin/system/_grep.c, object: bin/system/_grep
+line 32
+'       cmd_hook' in '        std/living.c' ('      
+std/user#4002')line 83
+'       cmd_grep' in '  bin/system/_grep.c' ('   
+bin/system/_grep')line 32     
+Bad argument 2 to message()
+program: adm/obj/simul_efun.c, object: adm/obj/simul_efun
+line 34
+'       cmd_hook' in '        std/living.c' ('      
+std/user#4957')line 83
+'       cmd_look' in '  bin/mortal/_look.c' ('   
+bin/mortal/_look')line 23
+' examine_object' in '  bin/mortal/_look.c' ('   
+bin/mortal/_look')line 78
+'          write' in 'adm/obj/simul_efun.c' (' 
+adm/obj/simul_efun')line 34
+Bad argument 1 to call_other()
+program: bin/system/_clone.c, object: bin/system/_clone
+line 25
+'       cmd_hook' in '        std/living.c' ('      
+std/user#3734')line 83
+'      cmd_clone' in ' bin/system/_clone.c' ('  
+bin/system/_clone')line 25
+Illegal index
+program: std/monster.c, object:
+wizards/zaknaifen/spy#7205 line 76
+'     heart_beat' in '       std/monster.c'
+('wizards/zaknaifen/spy#7205')line
+76                                                                                  
+
+All of the errors, except the last one, involve passing a bad argument to a
+function.  The first bug, involves passing a bad first arument to the efun
+explode().  This efun expects a string as its first argment.  In debugging
+these kinds of errors, we would therefore go to line 32 in
+/bin/system/_grep.c and check to see what the data type of the first
+argument being passed in fact is.  In this particular case, the value being
+passed should be a string.
+
+If for some reason I has actually passed something else, I would be done
+debugging at that point and fix it simply by making sure that I was
+passing a string.  This situation is more complex.  I now need to trace
+the actual values contained by the variable being passed to explode, so
+that I can see what it is the explode() efun sees that it is being passed.
+
+The line is question is this:
+ borg[files[i]] = regexp(explode(read_file(files[i]), "\n"), exp);
+where files is an array for strings, i is an integer, and borg is a mapping. 
+So clearly we need to find out what the value of read_file(files[i]) is. 
+Well, this efun returns a string unless the file in question does not exist,
+the object in question does not have read access to the file in question, or
+the file in question is an empty file, in which cases the function will
+return NULL.  Clearly, our problem is that one of these events must
+have happened.  In order to see which, we need to look at files[i].
+
+Examining the code, the files array gets its value through the get_dir()
+efun.  This returns all the files in a directory if the object has read access
+to the directory.  Therefore the problem is neither lack of access or non-
+existent files.  The file which caused this error then must have been an
+empty file.  And, in fact, that is exactly what caused this error.  To
+debug that, we would pass files through the filter() efun and make
+sure that only files with a file size greater than 0 were allowed into the
+array.
+
+The key to debugging a run time error is therefore knowing exactly what
+the values of all variables in question are at the exact moment where the
+bug created.  When reading your run time log, be careful to separate the
+object from the file in which the bug occurred.  For example, the
+indexing error above came about in the object /wizards/zaknaifen/spy,
+but the error occured while running a function in /std/monster.c, which
+the object inherited.
+
+7.4 Malfunctioning Code
+The nastiest problem to deal with is when your code does not behave the
+way you intended it to behave.  The object loads fine, and it produces no
+run time errors, but things simply do not happen the way they should. 
+Since the driver does not see a problem with this type of code, no logs
+are produced.  You therefore need to go through the code line by line
+and figure out what is happening.
+
+Step 1: Locate the last line of code you knew successfully executed
+Step 2: Locate the first line of code where you know things are going
+wrong
+Step 3: Examine the flow of the code from the known successful point to
+the first known unsuccessful point.
+
+More often than not, these problems occurr when you are using if()
+statements and not accounting for all possibilities.  For example:
+
+int cmd(string tmp) {
+    if(stringp(tmp)) return do_a()
+    else if(intp(tmp)) return do_b()
+    return 1;
+}
+
+In this code, we find that it compiles and runs fine.  Problem is nothing
+happens when it is executed.  We know for sure that the cmd() function
+is getting executed, so we can start there.  We also know that a value of
+1 is in fact being returned, since we do not see "What?" when we enter
+the command.  Immediately, we can see that for some reason the
+variable tmp has a value other than string or int.  As it turns out, we
+issued the command without parameters, so tmp was NULL and failed
+all tests.
+
+The above example is rather simplistic, bordering on silly. 
+Nevertheless, it gives you an idea of how to examine the flow of the
+code when debugging malfunctioning code.  Other tools are available as
+well to help in debugging code.  The most important tool is the use of
+the precompiler to debug code.  With the code above, we have a clause
+checking for integers being passed to cmd().  When we type "cmd 10",
+we are expecting do_b() to execute.  We need to see what the value of
+tmp is before we get into the loop:
+
+#define DEBUG
+int cmd(string tmp) {
+#ifdef DEBUG
+    write(tmp);
+#endif
+    if(stringp(tmp)) return do_a();
+    else if(intp(tmp)) return do_b();
+    else return 1;
+}
+
+We find out immediately upon issuing the command, that tmp has a
+value of "10".  Looking back at the code, we slap ourselves silly,
+forgetting that we have to change command arguments to integers using
+sscanf() before evaluating them as integers.
+
+7.5 Summary
+The key to debugging any LPC problem is always being aware of what
+the values of your variables are at any given step in your code.  LPC
+execution reduces on the simplest level to changes in variable values, so
+bad values are what causes bad things to happen once code has been
+loaded into memory.  If you get errors about bad arguments to
+functions, more likely than not you are passing a NULL value to a
+function for that argument.  This happens most often with objects, since
+people will do one of the following:
+    1) use a value that was set to an object that has since destructed
+    2) use the return value of this_player() when there is no this_player()
+    3) use the return value of this_object() just after this_object() was
+    destructed
+
+In addition, people will often run into errors involving illegal indexing or
+indexing on illegal types.  Most often, this is because the mapping or
+array in question was not initialized, and therefore cannot be indexed. 
+The key is to know exactly what the full value of the array or mapping
+should be at the point in question.  In addition, watch for using index
+numbers larger than the size of given arrays
+
+Finally, make use of the precompiler to temporarly throw out code, or
+introduce code which will show you the values of variables.  The
+precompiler makes it easy to get rid of debugging code quickly once you
+are done.  You can simply remove the DEBUG define when you are
+done.
+
+Copyright (c) George Reese 1993
diff --git a/doc/KURS/RULES b/doc/KURS/RULES
new file mode 100644
index 0000000..ac88cfc
--- /dev/null
+++ b/doc/KURS/RULES
@@ -0,0 +1,60 @@
+		DIE ZWEI GEBOTE IN MORGENGRAUEN
+		===============================
+
+	Was sollen Gebote?
+	------------------
+
+	Wie in jedem Spiel so haben sich auch in unserem MUD alle
+	Mitspieler (Magier eingeschlossen) an Spielregeln zu halten.
+	Allerdings machen die Spiele am meisten Spass, die die
+	wenigsten Regeln besitzen. 
+
+	Um zu verhindern, dass jetzt schon angefangen wird, dass
+	unser MUD in feste Regeln gedraengt wird, habe ich mich 
+	entschlossen, selber dem Spiel ein Regelwerk zu geben.
+	Aber ich werde dafuer sorgen, dass sie kurz bleiben.
+	
+	1.Gebot )	DU SOLLST NETT SEIN.
+
+	Das MUD ist ein Spiel; und Spiele machen nur dann Spass,
+	wenn man sich nicht gegenseitig versucht in die Pfanne zu
+	hauen; somit gilt diese Regel fuer Spieler wie fuer Magier.
+
+	2.Gebot )	DU SOLLST DIE MUDLIB EHREN UND VERMEHREN.
+
+	Das MUD steht und faellt mit der Guete seiner Mudlib; und da
+	unser Hauptziel ein schoenes MUD ist, ist es die vorrangige
+	Aufgabe aller Magier, fuer den Aufbau, die Wartung und die
+	Erhaltung der Mudlib zu sorgen.
+
+	Zum Thema Vermehrung:
+	---------------------
+
+	Es gibt in einem MUD natuerlich auch noch andere Aufgaben:
+	-	Regionskoordination
+		(Regionsmagier,Erzmagier des Verkehrs)
+	-	Wahrung des Gleichgewichtes der Kraefte
+		(Waffen,Ruestungen,Geld,XP,Monster,u.s.w.)
+	-	Schutz des MUDs vor Spielverderbern.
+		(Sheriff)
+
+	Diese Aufgaben sind aber keine Lebensaufgaben; sie sind
+	Aufgaben, die sich den Geboten unterzuordnen haben.
+	Insbesondere sollen Magier, die nichts zur Vermehrung der
+	Mudlib beitragen, nicht ueber andere urteilen.
+
+	Zum Thema Ehrung:
+	-----------------
+
+	Hiermit meine ich den Aufruf an die Magier, keine Objekte
+	zu schreiben, die das Gleichtgewicht der Kraefte verletzen.
+
+	Und ich meine den Aufruf an die Magier, dafuer zu sorgen,
+	dass es in diesem MUD Herausforderungen gibt, die (zumindest
+	teilweise) nicht umgangen werden koennen.
+	Natuerlich ist damit auch gemeint, dass Spielern nur in den
+	Faellen geholfen wird, wo Fehler oder Luecken in der Mudlib
+	auftauchen.
+
+	Olpp, Sheriff des MorgenGrauens
+	Rumata, MudAdm des MorgenGrauens
diff --git a/doc/KURS/RULES.WIZ b/doc/KURS/RULES.WIZ
new file mode 100644
index 0000000..349f0b6
--- /dev/null
+++ b/doc/KURS/RULES.WIZ
@@ -0,0 +1,46 @@
+These are the rules for a wizard.
+(Wird noch ueberarbeitet, am besten Olpp oder Rumata fragen, was
+wirklich Sache ist. Aber eine grobe Richtung weisen diese "alten"
+Regeln schon :-)
+
+1. You may not help other players, even if they lost points due to
+   lost connection. They have to go to the post office and ask Lars,
+   or use bug.
+
+2. Never attack a player or kill him. If a player behaves badly, file
+   the complaint to Lars.
+
+3. Do not make 'deadly' trapps. 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 beside the giant lair).
+
+4. Never initialize the destination of an object outside your castle. If you
+   make a monster that can walk out of the castle, be sure that it is a
+   very nice monster.
+
+5. Never generate messages that looks like something it isn't (good and precise
+   rule :-). That is, don't try to fool the player that someone says something
+   when it isn't true etc.
+
+6. If you have a "test" character, make sure is isn't seen in the top score
+   list. He must no be wizard either.
+
+7. Try to avoid making devices, situations which makes the players loose
+   experience if they are adventuring or examining objects. Players should be
+   rewarded for adventuring and discovering things. If they get killed...
+   Well, they will then loose some experience, but this is a special case!
+
+8. The game is supposed to be in the "long distant past", and thus no
+   modern things should exist. If you want some kind of airplane, use a
+   flying horse in stead etc.
+
+9. If you make available some kind of restaurant that sells food that
+   heals, then the healing must cost on average 4 gp/hp (or more). The amount
+   of healing must also be limited per reset. Generating healing items for
+   free is only allowed if they heal at most 20 points, and are destructed.
+   Not more than one such item may be generated per room and reset.
+
+10.Teleporting items should be VERY restricted, and very rare. They must
+   not allow teleportations to anywhere, but only to one or more predefined
+   room. Never to a specific player. It must cost at least 50 spell points
+   to use each time.
diff --git a/doc/KURS/einleitung b/doc/KURS/einleitung
new file mode 100644
index 0000000..1483155
--- /dev/null
+++ b/doc/KURS/einleitung
@@ -0,0 +1,45 @@
+	Einfuehrung in die Progrmmierung der Morgengrauen-Mudlib
+	von Don Rumata, MudAdm des MorgenGrauens
+	========================================================
+
+	EINLEITUNG:
+	-----------
+
+	Herzlich willkommen als Magier im MorgenGrauen. Du bist
+	gerade Magier geworden. Dieser Kurs soll Dir helfen,
+	in diesem MUD alles Moegliche zu programmieren. 
+
+
+	WICHTIGE INFORMATIONEN FUER DEN ANFANG:
+	---------------------------------------
+
+	Ein Magier hat sich gewissen Regeln zu unterwerfen, wie man
+	sich bein einem Spiel auch in die Spielregeln zu halten hat.
+	Diese Spielregeln stehen in RULES (das sind die wichtigen)
+	und in RULES.WIZ (das sind die technischen Hinweise).
+
+	Wenn Du Files editieren willst, gibt es mehrere Moeglich-
+	keiten:
+
+	1.) Mit dem Befehl "ed <filename>":
+	    Eine Einleitung fuer ed kannst Du in /doc/ed/* finden.
+
+	2.) Fileuebertragung per ftp
+	3.) Fileuebertragung per mtp
+	    frage am besten einen der erfahrenen Magier.
+
+
+	KURSUEBERBLICK:
+	---------------
+
+	I	Programmierung von Raeumen
+	     1.	Ein einfacher Raum
+	 
+	II	Programmierung von Objekten
+	
+	III	Programmierung von Monstern
+
+
+	Achja: Ich bitte flehentlich um Korrekturlesen und
+	Verbesserungs/Ergaenzungsvorschlaege. Und noch mehr
+	um Mitarbeit. (Ich hab schon jetzt wunde Finger :-)
diff --git a/doc/KURS/objekte b/doc/KURS/objekte
new file mode 100644
index 0000000..fbb11d3
--- /dev/null
+++ b/doc/KURS/objekte
@@ -0,0 +1,29 @@
+	OBJEKTE
+	
+	Als erstes musst Du wissen, dass jedes Objekt in diesem
+	Mud durch ein File repraesentiert wird. Dieses File
+	wird auch die "Blueprint" genannt. Du kannst neue Objekte
+	auf 2 Arten erschaffen.
+
+	1.) "clone"n von Blueprints. Das bedeutet, dass Du ein
+	    Objekt erschaffst, das die Eigenschaften hat, die in
+	    der Blueprint programmiert worden sind. Von einer
+	    Blueprint koennen mehrere "Clones" existieren.
+	    Typische Beispiele fuer "Clones" sind Waffen,
+	    Monster, Geld oder Spieler.
+
+	2.) "load"en von Blueprints. Das bedeutet, dass Du
+	    diese Blueprint zu Leben erweckst. In gewisser Weise
+	    benehmen sich diese Objekte genauso wie die "Clones",
+	    allerdings koennen von einmal geladenen Blueprints
+	    keine "Clones" mehr erschaffen werden.
+	    Typische geladene Objekte sind Raeme.
+
+	KNIGGE FUER MAGIER
+
+	Dadurch, dass Du beliebige Files laden oder clonen kannst,
+	bist Du in der Lage, jedem Spieler das gewuenschte Objekt
+	zu beschaffen. Aber das ist natuerlich nicht der Sinn der
+	Sache. Als Magier bist Du verpflichtet, den Spielern nur
+	noch dann zu helfen, wenn sie aufgrund von Programmier-
+	fehlern in Schwierigkeiten geraten.
diff --git a/doc/KURS/raum1 b/doc/KURS/raum1
new file mode 100644
index 0000000..b623c35
--- /dev/null
+++ b/doc/KURS/raum1
@@ -0,0 +1,137 @@
+
+	PROGRAMMIERUNG VON RAEUMEN - TEIL 1
+	von Don Rumata, MudAdm des MorgenGrauens
+	=============================================================
+
+	Ein Raum ist sehr einfach zu programmieren. Man fuellt
+	ihn mit den Informationen, die man in ihm haben will.
+
+	Am besten erklaert sich alles an einem Beispiel. Zu den
+	Funktionen sind in /doc/efuns und /doc/lfuns weitere
+	Informationen erhaeltlich.
+
+	Nachfolgend kannst Du einen (zugegebeneermassen ueber-
+	ausfuehrlich) dokumentierten Beispielraum finden.
+	In /doc/beispiele/raum1.c kannst Du den selben Raum
+	noch einmal (ohne Kommentare) finden. Den Raum
+	kannst Du uebrigens auch betreten.
+
+/* beispielraum.c von Rumata */
+
+inherit "std/room";
+	// Alle Raeume muessen diese Zeile enthalten, da in dem
+	// Standardraum wichtige Funktionen definiert werden, die
+	// innerhalb des Spieles benoetigt werden.
+
+#include <properties.h>
+	// In diesem File sind die Namen der Properties definiert.
+	// Fuer naehre Informationen kannst Du in
+	// /doc/concepts/properties und in /doc/properties.h
+	// nachschauen, da es sehr viele verschiedene Properties
+	// gibt.
+
+#include <language.h>
+	// Diese Module enthalten alle Definitionen im Zusammenhang
+	// mit Sprache. Siehe /doc/language.h
+
+create()
+// Diese Funktion wird automatisch aufgerufen, wenn der Raum geladen
+// wird. Das passiert beim Kommando "load /doc/beispiel/bspraum1" oder
+// wenn ein Spieler den Raum als erster betritt.
+{
+	::create();
+	// Diese Funktion darf NIEMALS fehlen! Sie sorgt dafuer, dass
+	// der Raum auch die allgemeine Initialisierung durchfuehrt,
+	// da diese hier die der "Mutter-Klasse" std/room ueberlaedt.
+
+	SetProp( P_INT_SHORT, "Ein kleines Schreibzimmer" );
+	SetProp( P_INT_LONG,
+		"Du stehst in einem kleinen Schreibzimmer.\n"
+	+	"Es gehoerte wohl irgendwann einmal einem Magier, aber nun\n"
+	+	"ist dieser Raum verwaist und rottet vor sich hin.\n"
+	+	"Ein grosser Schreibtisch in der Mitte des Raumes scheint\n"
+	+	"noch einigermassen gut erhalten zu sein. Durch die Tuer\n"
+	+	"im Norden faellt etwas Licht hinein.\n"
+	);
+	SetProp( P_LIGHT, 1 );
+	SetProp( P_INDOORS, 1 );
+	// Diese Properties MUESSEN in JEDEM Raum gesetzt werden.
+	// P_INT_SHORT	= Beschreibung fuer Spieler im "kurz"-Modus.
+	// P_INT_LONG	= Beschreibung fuer Spieler im "lang"-Modus.
+	// P_LIGHT	= 1 fuer Hell, 0 fuer Dunkel
+	// P_INDOORS	= 1, wenn man den Himmel nicht sehen kann.
+
+	AddDetail( ({ "schreibtisch", "tisch" }),
+		"Auf dem Tisch liegt eine dicke Staubschicht.\n"
+	+	"Eine Schublade findest Du ebenfalls.\n"
+	);
+	AddDetail( ({ "staub", "staubschicht", "schicht" }),
+		"Du malst gelangweilt einige Kreise in den Staub.\n"
+	);
+	AddDetail( "schublade",
+		"So sehr Du Dich anstrengst; Du kannst sie nicht bewegen.\n"
+	);
+	AddDetail( "tuer" ,
+		"Sie steht seit Jahren offen und ist in dieser Lage\n"
+	+	"hoffnungslos festgerostet.\n"
+	);
+	// Details sind Dinge, die man sich in einem Raum anschauen
+	// aber nicht nehmen kann. Je mehr Details ein Raum hat, destso
+	// schoener ist er. Schaut sich ein Spieler ein Detail an,
+	// so bekommt der die angegebene Beschreibung.
+
+	AddRoomCmd( ({ "schliesse", "oeffne", "bewege",
+		"schliess", "beweg" }), "beweg_etwas" );
+	// RoomCommands sind Befehle, die man in diesem ausfuehren kann.
+	// Es wird die angegebene Funktion ausgefuehrt.
+	// WICHTIG: Als Verben sollten immer die IMPERATIVE benutzt
+	//	werden! Also nicht "lese", sondern "lies".
+	
+	AddExit( "norden", "players/rumata/workroom" );
+	// Definition eines Ausgangs. Das zeite Argument bestimmt den
+	// Raum, den ein Spieler erreicht, wenn er in die angegebene
+	// Richtung geht.
+
+}
+
+beweg_etwas( str )
+// Wenn ein Spieler ein Kommando ausfuehrt, so wird alles, was hinter
+// dem Verb steht als String uebergeben, es landet also hier in "str".
+// WICHTIG: Wenn der Befehl abgearbeitet wird, MUSS er eine 1 zurueck-
+//          geben. Wenn der Befehl nichts Sinnvolles tuen konnte, eine 0.
+{
+	notify_fail( "Was willst Du denn bewegen ?" );
+	// Meldung, die der Spieler bekommt, wenn ausser dem Raum auch
+	// kein anderes Objekt den Befehl verarbeiten konnte.
+	if( str == "tuer" )
+	{
+		write( "Die Tuer ist hoffnungslos festgerostet.\n" );
+		// Write gibt eine Meldung an den Spieler (und nur an ihn)
+		// aus.
+		return 1;
+		// Das Kommando bewirkt zwar aus Sicht des Spielers
+		// nichts, aber es konnte abgearbeitet werden.
+		// Also gib eine 1 zurueck.
+	}
+	if ( str == "lade" || str == "schublade" )
+	{
+		write( "Die Schublade klemmt einfach nur.\n" );
+		return 1;
+	}
+	if ( query_verb() == "bewege" &&
+		( str == "tisch" || str == "schreibtisch" ) )
+	{
+		write(
+			"Der Tisch scheint am Boden festgeschraubt zu sein.\n"
+		);
+		say(
+			this_player()->name(WER,2)+" zerrt am Schreibtisch.\n"
+		);
+		// say gibt eine Meldung an alle Spieler im selben
+		// Raum wie der Spieler (aber nicht an ihn selbst) aus.
+		return 1;
+	}
+	return 0;
+	// Der Raum konnte nichts mit dem Kommando anfangen, also gib
+	// eine 0 zurueck.
+}