MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | LPC Basics |
| 2 | Written by Descartes of Borg |
| 3 | first edition: 23 april 1993 |
| 4 | second edition: july 5 1993 |
| 5 | |
| 6 | CHAPTER 6: Variable Handling |
| 7 | |
| 8 | 6.1 Review |
| 9 | By now you should be able to code some simple objects using your muds standard |
| 10 | object library. Inheritance allows you to use functions defined in those |
| 11 | objects without having to go and define yourself. In addition, |
| 12 | you should know how to declare your own functions. This |
| 13 | chapter will teach you about the basic elements of LPC which will allow you to |
| 14 | define your own functions using the manipulation of variables. |
| 15 | |
| 16 | 6.2 Values and objects |
| 17 | Basically, what makes objects on the mud different are two things: |
| 18 | 1) Some have different functions |
| 19 | 2) All have different values |
| 20 | |
| 21 | Now, all player objects have the same functions. They are therefore |
| 22 | differentiated by the values they hold. For instance, the player |
| 23 | named "Forlock" is different from "Descartes" *at least* in that they |
| 24 | have different values for the variable true_name, those being |
| 25 | "descartes" and "forlock". |
| 26 | |
| 27 | Therefore, changes in the game involve changes in the values of the objects |
| 28 | in the game. Functions are used to name specific process for manipulating |
| 29 | values. For instance, the create() function is the function whose |
| 30 | process is specifically to initialize the values of an object. |
| 31 | Within a function, it is specifically things called instructions which are |
| 32 | responsible for the direct manipulation of variables. |
| 33 | |
| 34 | 6.3 Local and global variables |
| 35 | Like variables in most programming language, LPC variables may be declared |
| 36 | as variables "local" to a specific function, or "globally" available |
| 37 | to all functions. Local variables are declared inside the function which |
| 38 | will use them. No other function knows about their existence, since |
| 39 | the values are only stored in memory while that function is being executed. |
| 40 | A global variable is available to any function which comes after its |
| 41 | declaration in the object code. Since global variables take up RAM for |
| 42 | the entire existence of the object, you should use them only when |
| 43 | you need a value stored for the entire existence of the object. |
| 44 | Have a look at the following 2 bits of code: |
| 45 | |
| 46 | ----- |
| 47 | int x; |
| 48 | |
| 49 | int query_x() { return x; } |
| 50 | |
| 51 | void set_x(int y) { x = y; } |
| 52 | ----- |
| 53 | |
| 54 | ----- |
| 55 | void set_x(int y) { |
| 56 | int x; |
| 57 | |
| 58 | x = y; |
| 59 | write("x is set to x"+x+" and will now be forgotten.\n"); |
| 60 | } |
| 61 | ----- |
| 62 | |
| 63 | In the first example, x is declared outside of any functions, and therefore |
| 64 | will be available to any function declared after it. In that example, |
| 65 | x is a global variable. |
| 66 | In the second example, x is declared inside the function set_x(). It |
| 67 | only exists while the function set_x() is being executed. Afterwards, |
| 68 | it ceases to exist. In that example, x is a local variable. |
| 69 | |
| 70 | 6.4 Manipulating the values of variables |
| 71 | Instructions to the driver are used to manipulate the values of variables. |
| 72 | An example of an instruction would be: |
| 73 | |
| 74 | ----- |
| 75 | x = 5; |
| 76 | ----- |
| 77 | |
| 78 | The above instruction is self-explanatory. It assigns to the variable |
| 79 | x the value 5. However, there are some important concepts in involved |
| 80 | in that instruction which are involved in instructions in general. |
| 81 | The first involves the concept of an expression. An expression is |
| 82 | any series of symbols which have a value. In the above instruction, |
| 83 | the variable x is assigned the value of the expression 5. Constant |
| 84 | values are the simplest forms in which expressions can be put. A constant |
| 85 | is a value that never changes like the int 5 or the string "hello". |
| 86 | The last concept is the concept of an operator. In the above example, |
| 87 | the assignment operator = is used. |
| 88 | |
| 89 | There are however many more operators in LPC, and expressions can get |
| 90 | quite complex. If we go up one level of complexity, we get: |
| 91 | |
| 92 | ----- |
| 93 | y = 5; |
| 94 | x = y +2; |
| 95 | ----- |
| 96 | |
| 97 | The first instruction uses the assignment operator to assign the value |
| 98 | of the constant expression 5 to the variable y. The second one |
| 99 | uses the assignment operator to assign to x the value of the expression |
| 100 | (y+2) which uses the addition operator to come up with a value which |
| 101 | is the sum of the value of y and the value of the constant expression 2. |
| 102 | Sound like a lot of hot air? |
| 103 | |
| 104 | In another manner of speaking, operators can be used to form complex |
| 105 | expressions. In the above example, there are two expressions in the |
| 106 | one instruction x = y + 2;: |
| 107 | 1) the expression y+2 |
| 108 | 2) the expression x = y + 2 |
| 109 | As stated before, all expressions have a value. The expression |
| 110 | y+2 has the value of the sum of y and 2 (here, 7); |
| 111 | The expression x = y + 2 *also* has the value of 7. |
| 112 | So operators have to important tasks: |
| 113 | 1) They *may* act upon input like a function |
| 114 | 2) They evaluate as having a value themselves. |
| 115 | Now, not all operators do what 1 does. The = operators does act upon |
| 116 | the value of 7 on its right by assigning that value to x. The operator |
| 117 | + however does nothing. They both, however, have their own values. |
| 118 | |
| 119 | 6.5 Complex expressions |
| 120 | As you may have noticed above, the expression x = 5 *itself* has a value |
| 121 | of 5. In fact, since LPC operators themselves have value as expressions, |
| 122 | they cal allow you to write some really convoluted looking nonsense like: |
| 123 | i = ( (x=sizeof(tmp=users())) ? --x : sizeof(tmp=children("/std/monster"))-1) |
| 124 | which says basically: |
| 125 | assing to tmp the array returned by the efun users(), then assign to x |
| 126 | the value equal to the number of elements to that array. If the value |
| 127 | of the expression assigning the value to x is true (not 0), then assign |
| 128 | x by 1 and assign the value of x-1 to i. If x is false though, |
| 129 | then set tmp to the array returned by the efun children(), and then |
| 130 | assign to i the value of the number of members in the array tmp -1. |
| 131 | Would you ever use the above statement? I doubt it. However you might |
| 132 | see or use expressions similar to it, since the ability to consolidate |
| 133 | so much information into one single line helps to speed up the execution of |
| 134 | your code. A more often used version of this property of LPC operators |
| 135 | would be something like: |
| 136 | x = sizeof(tmp = users()); |
| 137 | while(i--) write((string)tmp[i]->query_name()+"\n"); |
| 138 | instead of writing something like: |
| 139 | tmp = users(); |
| 140 | x = sizeof(tmp); |
| 141 | for(i=0; i<x; i++) write((string)tmp[i]->query_name()+"\n"); |
| 142 | Things like for(), while(), arrays and such will be explained later. |
| 143 | But the first bit of code is more concise and it executed faster. |
| 144 | |
| 145 | NOTE: A detailed description of all basic LPC operators follows the chapter |
| 146 | summary. |
| 147 | |
| 148 | |
| 149 | 6.6 Chapter Summary |
| 150 | You now know how to declare variables and understand the difference between |
| 151 | declaring and using them globally or locally. Once you become familiar |
| 152 | with your driver's efuns, you can display those values in many different |
| 153 | ways. In addition, through the LPC operators, you know how to change |
| 154 | and evaluate the values contained in variables. This is useful of course |
| 155 | in that it allows you to do something like count how many apples have |
| 156 | been picked from a tree, so that once all apples have been picked, no |
| 157 | players can pick more. Unfortunately, you do not know how to have |
| 158 | code executed in anything other than a linera fashion. In other words, |
| 159 | hold off on that apple until the next chapter, cause you do not know |
| 160 | how to check if the apples picked is equal to the number of apples in the |
| 161 | tree. You also do not know about the special function init() where you |
| 162 | give new commands to players. But you are almost ready to code a nice, |
| 163 | fairly complex area. |
| 164 | |
| 165 | 6.7 LPC operators |
| 166 | This section contains a detailed listing of the simpler LPC operators, |
| 167 | including what they do to the values they use (if anything) and the value |
| 168 | that they have. |
| 169 | |
| 170 | The operators described here are: |
| 171 | = + - * / % += -= *= /= %= |
| 172 | -- ++ == != > < >= <= ! && || |
| 173 | -> ? : |
| 174 | |
| 175 | Those operators are all described in a rather dry manner below, but it is best |
| 176 | to at least look at each one, since some may not behave *exactly* as |
| 177 | you think. But it should make a rather good reference guide. |
| 178 | |
| 179 | = assignment operator: |
| 180 | example: x = 5; |
| 181 | value: the value of the variable on the *left* after its function is done |
| 182 | explanation: It takes the value of any expression on the *right* and |
| 183 | assigns it to the variable on the *left*. Note that you must use |
| 184 | a single variable on the left, as you cannot assign values to |
| 185 | constants or complex expressions. |
| 186 | |
| 187 | + addition operator: |
| 188 | example: x + 7 |
| 189 | value: The sum of the value on the left and the value on the right |
| 190 | exaplanation: It takes the value of the expression on the right and |
| 191 | adds it to the value of the expression on the left. For values |
| 192 | of type int, this means the numerical sum. For strings, |
| 193 | it means that the value on the right is stuck onto the value on |
| 194 | the left ("ab" is the value of "a"+"b"). This operator does not |
| 195 | modify any of the original values (i.e. the variable x from |
| 196 | above retains its old value). |
| 197 | |
| 198 | - subtraction operator: |
| 199 | example: x - 7 |
| 200 | value: the value of the expression on the left reduced by the right |
| 201 | explanation: Same characteristics as addition, except it subtracts. |
| 202 | With strings: "a" is the value of "ab" - "b" |
| 203 | |
| 204 | * multiplication operator: |
| 205 | example: x*7 |
| 206 | value and explanation: same as with adding and subtracting except |
| 207 | this one performs the math of multiplication |
| 208 | |
| 209 | / division operator: |
| 210 | example: x/7 |
| 211 | value and explanation: see above |
| 212 | |
| 213 | += additive assignment operator: |
| 214 | example: x += 5 |
| 215 | value: the same as x + 5 |
| 216 | exaplanation: It takes the value of the variable on the left |
| 217 | and the value of the expression on the right, adds them together |
| 218 | and assigns the sum to the variable on the left. |
| 219 | example: if x = 2... x += 5 assigns the value |
| 220 | 7 to the variable x. The whole expression |
| 221 | has the value of 7. |
| 222 | |
| 223 | -= subtraction assignment operator |
| 224 | example: x-=7 |
| 225 | value: the value of the left value reduced by the right value |
| 226 | examplanation: The same as += except for subtraction. |
| 227 | |
| 228 | *= multiplicative assignment operator |
| 229 | example: x *= 7 |
| 230 | value: the value of the left value multiplied by the right |
| 231 | explanation: Similar to -= and += except for addition. |
| 232 | |
| 233 | /= division assignment operator |
| 234 | example: x /= 7 |
| 235 | value: the value of the variable on the left divided by the right value |
| 236 | explanation: similar to above, except with division |
| 237 | |
| 238 | ++ post/pre-increment operators |
| 239 | examples: i++ or ++i |
| 240 | values: |
| 241 | i++ has the value of i |
| 242 | ++i has the value of i+1 |
| 243 | explanation: ++ changes the value of i by increasing it by 1. |
| 244 | However, the value of the expression depends on where you |
| 245 | place the ++. ++i is the pre-increment operator. This means |
| 246 | that it performs the increment *before* giving a value. |
| 247 | i++ is the post-ncrement operator. It evalutes before incrementing |
| 248 | i. What is the point? Well, it does not much matter to you at |
| 249 | this point, but you should recognize what it means. |
| 250 | |
| 251 | -- post/pre-decrement operators |
| 252 | examples: i-- or --i |
| 253 | values: |
| 254 | i-- the value of i |
| 255 | --i the value of i reduced by 1 |
| 256 | explanation: like ++ except for subtraction |
| 257 | |
| 258 | == equality operator |
| 259 | example: x == 5 |
| 260 | value: true or false (not 0 or 0) |
| 261 | explanation: it does nothing to either value, but |
| 262 | it returns true if the 2 values are the same. |
| 263 | It returns false if they are not equal. |
| 264 | |
| 265 | != inequality operator |
| 266 | example: x != 5 |
| 267 | value: true or false |
| 268 | explanation returns true if the left expression is not equal to the right |
| 269 | expression. It returns fals if they are equal |
| 270 | |
| 271 | > greater than operator |
| 272 | example: x > 5 |
| 273 | value: true or false |
| 274 | explanation: true only if x has a value greater than 5 |
| 275 | false if the value is equal or less |
| 276 | |
| 277 | < less than operator |
| 278 | >= greater than or equal to operator |
| 279 | <= less than or equal to operator |
| 280 | examples: x < y x >= y x <= y |
| 281 | values: true or false |
| 282 | explanation: similar as to > except |
| 283 | < true if left is less than right |
| 284 | >= true if left is greater than *or equal to* right |
| 285 | <= true if the left is less than *or equal to* the right |
| 286 | |
| 287 | && logical and operator |
| 288 | || logical or operator |
| 289 | examples: x && y x || y |
| 290 | values: true or false |
| 291 | explanation: If the right value and left value are non-zero, && is true. |
| 292 | If either are false, then && is false. |
| 293 | For ||, only one of the values must be true for it to evaluate |
| 294 | as true. It is only false if both values indeed |
| 295 | are false |
| 296 | |
| 297 | ! negation operator |
| 298 | example: !x |
| 299 | value: true or false |
| 300 | explanation: If x is true, then !x is false |
| 301 | If x is false, !x is true. |
| 302 | |
| 303 | A pair of more complicated ones that are here just for the sake of being |
| 304 | here. Do not worry if they utterly confuse you. |
| 305 | |
| 306 | -> the call other operator |
| 307 | example: this_player()->query_name() |
| 308 | value: The value returned by the function being called |
| 309 | explanation: It calls the function which is on the right in the object |
| 310 | on the left side of the operator. The left expression *must* be |
| 311 | an object, and the right expression *must* be the name of a function. |
| 312 | If not such function exists in the object, it will return 0 (or |
| 313 | more correctly, undefined). |
| 314 | |
| 315 | ? : conditional operator |
| 316 | example: x ? y : z |
| 317 | values: in the above example, if x is try, the value is y |
| 318 | if x is false, the value of the expression is z |
| 319 | explanation: If the leftmost value is true, it will give the expression as |
| 320 | a whole the value of the middle expression. Else, it will give the |
| 321 | expression as a whole the value of the rightmost expression. |
| 322 | |
| 323 | A note on equality: A very nasty error people make that is VERY difficult |
| 324 | to debug is the error of placing = where you mean ==. Since |
| 325 | operators return values, they both make sense when being evaluated. |
| 326 | In other words, no error occurs. But they have very different values. For example: |
| 327 | if(x == 5) if(x = 5) |
| 328 | The value of x == 5 is true if the value of x is 5, false othewise. |
| 329 | The value of x = 5 is 5 (and therefore always true). |
| 330 | The if statement is looking for the expression in () to be either true or false, |
| 331 | so if you had = and meant ==, you would end up with an expression that is |
| 332 | always true. And you would pull your hair out trying to figure out |
| 333 | why things were not happening like they should :) |