From the NannyMUD documentation

LAST CHANGE

2000-12-27

TOPIC

NAME

        basics - 

DESCRIPTION

                            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 can 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:
     assign 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; iquery_name()+"\n");
 Things like for(), while(), arrays and such will be explained later.
 But the first bit of code is more concise and is 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 no 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 :)