Lesson 1A (Introduction to LPC/Beginning Objects)

LPC is a small, object oriented type C language developed by Lars Pensj| for
LP-MUD, a Multi-User Dungeon environment under many UNIX systems.  Since the
premise of this language is based on C, it contains many of the syntactical
qualities of C, but also maintains a large set of functions capable of
performing many actions inside the game.  The objective is to begin to look at
LPC as a way of creating objects, rather than specific items, so that new
coders can begin to experience the way LPC actually works.  Rooms, weapons,
monsters, armor, and whatever creation you can think of, even yourself, are
objects.  LPC allows you to create, modify, delete, and reproduce these objects
in almost any manner you choose.  This tutorial will guide you through some of
the basic principles of LPC, and how to begin to design objects of your own
choosing.  All objects will be stored in .c files, using the 'ed' editor or
some uploading method of your choice.

Objects can be created easily, using some of the built-in functions that LPC
allows.  Here are a few of them; your local LPC site might have more available
for you.  From here on out, the functions listed below are RESERVED functions,
in that they serve a special purpose.  They should not be used in any manner
except for what their purpose entails.

NOTE: Always look in /doc/efun and /doc/lfun for a list of functions to use
      (These are the functions for 2.4.5...They may or may not be available
      for you to use.)

-------------------- LIST OF FUNCTIONS FOR YOUR MUD -----------------------
add_action      add_money      add_verb        add_weight       allocate
attacked_by     call_other     call_out        can_put_and_get  capitalize
cat             catch          catch_tell      clear_bit        clone_object
command         create_wizard  creator         crypt            ctime
destruct        drop           ed              enable_commands  environment
exit            explode        extra_look      extract          file_name
file_size       find_living    find_object     find_player      first_inventory
get             heal_self      heart_beat      hit_player       id
implode         init           input_to        intp             living
log_file        long           lower_case      ls               move_object
next_inventory  notify_fail    objectp         parse_command    people
pointerp        present        previous_object query_attack     query_auto_load
query_gender_string            query_idle      query_info       query_level
query_money     query_name     query_npc       query_value      query_verb
query_weight    random         remove_call_out reset            restore_object
save_object     say            set_bit         set_heart_beat   set_light
set_living_name short          shout           show_stats       sizeof
sscanf          stop_fight     stop_wielding   stringp          tell_object
tell_room       test_bit       this_object     this_player      time
transfer        users          write           write_file
---------------------------------------------------------------------------

Let's take an object of any kind, and build it from the ground up.  In order to
build something trivial, say, a small rose, we need to use certain functions
given to us by LPC.

To start, we will first need a description of the rose.  Two of the functions
from the list above that we will need are short() and long().  As a player of
LP-MUD, you may recognize these as the verbose and brief descriptions of an
object.  short() is the short description of an object, and returns the string
for that description, whereas the long() is a more verbose description of the
object, as is seen when someone examines it.  Remember that functions will for
the most part return a value to its caller.  In the case of short() and long(),
we are returning strings.  So, back to our rose example, we might have in our
rose.c file:

short()
{
    return "a small red rose";
}

long()
{
    write("This small red rose is very beautiful to look at.\n");
}

The two functions above are coded as follows.  Let's take short() for
starters.  short() is a way of defining a function in LPC, where 'short' is the
name of the function, and the information contained between the { and the } is
the action list for that function name.  The () is what is referred to as a
parameter list.  In this case, because there are no variables in between the
( and the ), there are no paramters.  short() is a RESERVED function, in that it
serves a special purpose.  short() returns to the user a string that will
contain a brief description of the item.  long(), on the other hand, uses
write() to tell users about the object.  We write out information to the person
holding the object, and tell them something about the rose.  In this case, we
write out that the rose is beautiful to look at.  By using write(), we can tell
users various things.  long() is another RESERVED function, and is called
whenever someone 'exa' or 'examine's the object.

So now we see how to make the objects with description.  But other questions
might pop up from this.  How do we get the object?  Can we set a price on the
object?  What about its weight?  And how to we assign a name to an object?

Let's finish off our object, and take a look at what it does, breaking down
each function as necessary.

/* Check for a name of the object */
id(str)
{
    return str == "rose";
}

/* The short description of the object */
short()
{
    return "a small red rose";
}

/* The long description of the object */
long()
{
    write("This small red rose is very beautiful to look at.\n");
}

/* Make sure that the object can be picked up */
get()
{
    return 1;
}

/* Set a weight of 1 on the object */
query_weight()
{
    return 1;
}

/* Set a value of 10 coins on the object */
query_value()
{
    return 10;
}

With all of the above code, you have just created a small rose!  To complete
our understanding of the code, we need to understand what get(), id(str),
query_value(), and query_weight() do.  get(), as you might guess, simply allows
the item to be picked up.  So, since get() is a RESERVED function, we can note
that by returning 1 to the caller, as we do above, we are saying that yes,
someone can pick up this object.  If we return 0, then we are saying that this
item cannot be picked up.  id(str) is another RESERVED function,
which serves to check if a string passed to id(str) is one of the names of
the function.  When we say (return str == "rose") what we are really doing
is saying that if the string passed to id(str) is "rose", then return 1,
or true; otherwise, return 0, or false.  It is simply checking to see that the
strings, when compared, are identical.  In LPC (as well as C), 0 is used to
represent a false condition, while 1 (or any other non-zero value) is used
to represent a true condition.  To add other strings to the comparison,
separate them with the 'or' sign (||).  For example, this is also a valid
setting for the id(str) function:

/* Add a name to the object */
id(str)
{
    return str == "rose" || str == "red rose";
}

If the caller of id(str) passes "rose" or "red rose", the function will return
1 back to the user, or 0 otherwise.  query_weight() and query_value() are two
functions which also return values to their caller, for weight and value
respectively.  We set a weight on the object so that someone carrying too much
can't pick up more than possible, and we set a value on the object so that they
can sell it for a certain amount of gold coins.  In the example above, we have
set the value of the object to 10 coins, and the weight on the object to 1.
Weights and values will vary according to both your personal tastes, and
specifications for your MUD.

Once this is saved in a file, we can then update the file, and clone it, and it
will appear in our inventory.  Assuming that we are in the proper directory,
and the code is in a file called 'rose.c', we can do the following:

> load rose
Ok.
> clone rose
Ok.
> i
a small red rose.
> exa rose
This small red rose is very beautiful to look at.
> sell rose
You get 10 gold coins.
>

At this point, it is best to explain what the differences between 'load',
'update', and 'clone' are.  You will be using these commands quite frequently,
especially as you make changes to your files.  'load' will load an object into
memory.  It will take the .c file your specify, and load an instance of it into
memory.  For example, if I type in 'load rose', it will load a copy of rose.c
into memory.  If a copy already exists, it does nothing.  When you 'update' a
file, you are removing the old instance of the file in memory.  That way, the
next time you decide to 'load' or 'clone' that object, it will put a new
version into memory.  Clone will create an instance of the object from memory.
If there isn't a copy in memory, it loads one up.  A scenario would be the
following:  First, you edit rose.c, then load it.  After that, you clone it.
You will find a copy of the rose in your inventory.  But say you made a new
version of rose.c.  If you don't 'update rose', then you will simply be getting
a copy of the old instance of rose.c, and not your newly edited one.  Once you
'update rose', you can 'load rose', then 'clone rose', or you can simply 'clone
rose' (Remember that 'clone' will also load the file into memory, if one
doesn't exist.)

Now let's get a bit more advanced with our object.

As you will notice, the ability to create objects has been made very easy by
the designers of LPC, and your usage of the RESERVED functions will enhance the
objects you create.  In order to spice up the rose we have created, we will
append these two functions onto the end of our rose.c file:

/* Set some initial actions for our object */
init()
{
    add_action("smell_rose", "smell");
}

/* smell_rose() -- smell the rose.  An assigned action from init() */
smell_rose(str)
{
    if ((!str) || !id(str))
    {
        return 0;
    }
    write("You smell the sweet fragrance of the rose.\n");
    return 1;
}

These lines will allow us the capability of actually 'smell'ing the object.  In
that sense, we are now assigning 'actions' to the object.  This is an important
point, in that everything in LPC revolves around an action of some sort.  A
person cannot move, walk, talk, breathe, or even exist if actions were not
allowed.  In the example above, we have added a function called init().
init(), as you will find out in future lessons, is one of the key functions in
LPC.  It will allow us to define actions and functions associated to those
actions.  In the previous example, we have set up add_action("smell_rose",
"smell").  "smell_rose" is the name of the function that will perform the write
to the user, and "smell" is the action.  So, when we type in "smell" in any
sense, the add_action() will catch that word, and try to perform some action in
the smell_rose() function.

Within the smell_rose() function, we need to check for a couple of things.
First, we need to make sure that the string that is being sent to the
smell_rose() function is actually "rose".  If it isn't, then we want to
return 0 back to the user, as this function is useless.

NOTE:  By setting up an add_action() function, we are saying that we catch
       the word "smell", but we do not pass it to the associated function.
       So, in other words, when we type in "smell rose", only "rose" goes to
       smell_rose().  And likewise, if we type in "smell     rose", then
       "    rose" goes to smell_rose().


> update rose
players/you/rose will be updated next reference.
> clone rose
Ok.
> smell rose
You smell the sweet fragrance of the rose.
> smell    rose
What ?
> smell
What ?
>

>From the example above, we notice that we must say "smell rose" properly
in order to get the function to work.  We will deal with how to handle improper
typing on the users side later, but for now, we will assume that the user
holding the object will not add extra spaces when typing in "smell rose".

There you have it!  One complete object.  Most objects from this point on in
the documentation will now become easier to develop, because we are no longer
think of specific objects, but rather an object in general.  This will become
very clear in the next lesson, when we begin to talk about inheritance, then
objects as rooms, and how they will take shape.

                  EXAMPLES TO USE AND STUDY FOR LESSON 1A
-------------------------------------------------------------------------------
Example #1 -- A small rose.
-------------------------------------------------------------------------------
/*
// Rose -- A small rose example
// By Matt D. Robinson
*/

/* Check for a name of the object */
id(str)
{
ret