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: 12 july 1993 |
| 5 | |
| 6 | CHAPTER 8: The data type "object" |
| 7 | |
| 8 | 8.1 Review |
| 9 | You should now be able to do anything so long as you stick to calling |
| 10 | functions within your own object. You should also know, that at the |
| 11 | bare minimum you can get the create() (or reset()) function in your object |
| 12 | called to start just by loading it into memory, and that your reset() |
| 13 | function will be called every now and then so that you may write the |
| 14 | code necessary to refresh your room. Note that neither of these |
| 15 | functions MUST be in your object. The driver checks to see if the |
| 16 | function exists in your object first. If it does not, then it does not |
| 17 | bother. You are also acquainted with the data types void, int, and string. |
| 18 | |
| 19 | 7.2 Objects as data types |
| 20 | In this chapter you will be acquainted with a more complex data type, |
| 21 | object. An object variable points to a real object loaded into the |
| 22 | driver's memory. You declare it in the same manner as other data types: |
| 23 | object ob; |
| 24 | It differs in that you cannot use +, -, +=, -=, *, or / (what would it |
| 25 | mean to divide a monster by another monster?). And since efuns like |
| 26 | say() and write() only want strings or ints, you cannot write() or |
| 27 | say() them (again, what would it mean to say a monster?). |
| 28 | But you can use them with some other of the most important efuns on any |
| 29 | LPMud. |
| 30 | |
| 31 | 8.3 The efun: this_object() |
| 32 | This is an efun which returns an object in which the function being executed |
| 33 | exists. In other words, in a file, this_object() refers to the object your |
| 34 | file is in whether the file gets cloned itself or inherted by another file. |
| 35 | It is often useful when you are writing a file which is getting inherited |
| 36 | by another file. Say you are writing your own living.c which gets |
| 37 | inherited by user.c and monster.c, but never used alone. You want to log |
| 38 | the function set_level() it is a player's level being set (but you do not |
| 39 | care if it is a monster. |
| 40 | You might do this: |
| 41 | |
| 42 | void set_level(int x) { |
| 43 | if(this_object()->is_player()) log_file("levels", "foo\n"); |
| 44 | level = x; |
| 45 | } |
| 46 | |
| 47 | Since is_player() is not defined in living.c or anything it inherits, |
| 48 | just saying if(is_player()) will result in an error since the driver |
| 49 | does not find that function in your file or anything it inherits. |
| 50 | this_object() allows you to access functions which may or may not be |
| 51 | present in any final products because your file is inherited by others |
| 52 | without resulting in an error. |
| 53 | |
| 54 | 8.4 Calling functions in other objects |
| 55 | This of course introduces us to the most important characteristic of |
| 56 | the object data type. It allows us to access functions in other objects. |
| 57 | In previous examples you have been able to find out about a player's level, |
| 58 | reduce the money they have, and how much hp they have. |
| 59 | Calls to functions in other objects may be done in two ways: |
| 60 | |
| 61 | object->function(parameters) |
| 62 | call_other(object, "function", parameters); |
| 63 | |
| 64 | example: |
| 65 | this_player()->add_money("silver", -5); |
| 66 | call_other(this_player(), "add_money", "silver", -5); |
| 67 | |
| 68 | In some (very loose sense), the game is just a chain reaction of function |
| 69 | calls initiated by player commands. When a player initiates a chain of |
| 70 | function calls, that player is the object which is returned by |
| 71 | the efun this_player(). So, since this_player() can change depending |
| 72 | on who initiated the sequence of events, you want to be very careful |
| 73 | as to where you place calls to functions in this_player(). The most common |
| 74 | place you do this is through the last important lfun (we have mentioned |
| 75 | create() and reset()) init(). |
| 76 | |
| 77 | 8.5 The lfun: init() |
| 78 | Any time a living thing encounters an object (enters a new room, or enters |
| 79 | the same room as a certain other object), init() is called in all of |
| 80 | the objects the living being newly encounters. It is at this point |
| 81 | that you can add commands the player can issue in order to act. |
| 82 | Here is a sample init() function in a flower. |
| 83 | |
| 84 | void init() { |
| 85 | ::init(); |
| 86 | add_action("smell_flower", "smell"); |
| 87 | } |
| 88 | |
| 89 | Ito smell_flower(). So you should have smell_flower() look like this: |
| 90 | |
| 91 | 1 int smell_flower(string str); /* action functions are type int */ |
| 92 | 2 |
| 93 | 3 int smell_flower(string str) { |
| 94 | 4 if(str != "flower") return 0; /* it is not the flower being smelled */ |
| 95 | 5 write("You sniff the flower.\n"); |
| 96 | 6 say((string)this_player()->query_cap_name()+" smells the flower.\n"); |
| 97 | 7 this_player()->add_hp(random(5)); |
| 98 | 8 return 1; |
| 99 | 9 } |
| 100 | |
| 101 | In line 1, we have our function declared. |
| 102 | In line 3, smell_flower() begins. str becomes whatever comes after the |
| 103 | players command (not including the first white space). |
| 104 | In line 4, it checks to see if the player had typed "smell flower". If |
| 105 | the player had typed "smell cheese", then str would be "cheese". If |
| 106 | it is not in fact "flower" which is being smelled, then 0 is returned, |
| 107 | letting the driver know that this was not the function which should |
| 108 | have been called. If in fact the player had a piece of cheese as well |
| 109 | which had a smell command to it, the driver would then call the function |
| 110 | for smelling in that object. The driver will keep calling all functions |
| 111 | tied to smell commands until one of them returns 1. If they all return |
| 112 | 0, then the player sees "What?" |
| 113 | In line 5, the efun write() is called. write() prints the string which |
| 114 | is passed to it to this_player(). So whoever typed the command here |
| 115 | sees "You sniff the flower." |
| 116 | In line 6, the efun say() is called. say() prints the string which is |
| 117 | doing the sniffing, we have to call the query_cap_name() function |
| 118 | in this_player(). That way if the player is invis, it will say |
| 119 | "Someone" (or something like that), and it will also be properly |
| 120 | capitalized. |
| 121 | In line 7, we call the add_hp() function in the this_player() object, |
| 122 | since we want to do a little healing for the sniff (Note: do not |
| 123 | code this object on your mud, whoever balances your mud will shoot you). |
| 124 | In line 8, we return control of the game to the driver, returning 1 to |
| 125 | let it know that this was in fact the right function to call. |
| 126 | |
| 127 | 8.6 Adding objects to your rooms |
| 128 | And now, using the data type object, you can add monsters to your rooms: |
| 129 | |
| 130 | void create() { |
| 131 | ::create(); |
| 132 | set_property("light", 3); |
| 133 | set("short", "Krasna Square"); |
| 134 | set("long", "Welcome to the Central Square of the town of Praxis.\n"); |
| 135 | set_exits( ({ "d/standard/hall" }), ({ "east" }) ); |
| 136 | } |
| 137 | |
| 138 | void reset() { |
| 139 | object ob; |
| 140 | |
| 141 | ::reset(); |
| 142 | if(present("guard")) return; /* Do not want to add a guard if */ |
| 143 | ob = new("/std/monster"); /* one is already here */ |
| 144 | ob->set_name("guard"); |
| 145 | ob->set("id", ({ "guard", "town guard" }) ); |
| 146 | ob->set("short", "Town guard"); |
| 147 | ob->set("long", "He guards Praxis from nothingness.\n"); |
| 148 | ob->set_gender("male"); |
| 149 | ob->set_race("human"); |
| 150 | ob->set_level(10); |
| 151 | ob->set_alignment(200); |
| 152 | ob->set_humanoid(); |
| 153 | ob->set_hp(150); |
| 154 | ob->set_wielding_limbs( ({ "right hand", "left hand" }) ); |
| 155 | ob->move(this_object()); |
| 156 | } |
| 157 | |
| 158 | Now, this will be wildly different on most muds. Some, as noted before, |
| 159 | in that object so you have a uniquely configured monster object. The |
| 160 | last act in native muds is to call move() in the monster object to move |
| 161 | it to this room (this_object()). In compat muds, you call the efun |
| 162 | move_object() which takes two parameters, the object to be moved, and the |
| 163 | object into which it is being moved. |
| 164 | |
| 165 | 8.7 Chapter summary |
| 166 | At this point, you now have enough knowledge to code some really nice |
| 167 | stuff. Of course, as I have been stressing all along, you really need |
| 168 | to read the documents on building for your mud, as they detail which |
| 169 | functions exist in which types of objects for you to call. No matter |
| 170 | what your knowledge of the mudlib is, you have enough know-how to |
| 171 | give a player extra things to do like sniffing flowers or glue or whatever. |
| 172 | At this point you should get busy coding stuff. But the moment things |
| 173 | even look to become tedious, that means it is time for you to move to |
| 174 | the next level and do more. Right now code yourself a small area. |
| 175 | Make extensive use of the special functions coded in your mud's |
| 176 | room.c (search the docs for obscure ones no one else seems to use). |
| 177 | Add lots o' neat actions. Create weapons which have magic powers which |
| 178 | gradually fade away. All of this you should be able to do now. Once |
| 179 | this becomes routine for you, it will be time to move on to intermediate |
| 180 | stuff. Note that few people actually get to the intermediate stuff. |
| 181 | If you have played at all, you notice there are few areas on the mud |
| 182 | which do what I just told you you should be able to do. It is not |
| 183 | because it is hard, but because there is a lot of arrogance out there |
| 184 | on the part of people who have gotten beyond this point, and very little |
| 185 | communicating of that knowledge. The trick is to push yourself and |
| 186 | think of something you want to do that is impossible. If you ask someone |
| 187 | in the know how to do X, and they say that is impossible, find out |
| 188 | youself how to code it by experimenting. |
| 189 | |
| 190 | George Reese |
| 191 | Descartes of Borg |
| 192 | 12 july 1993 |
| 193 | borg@hebron.connected.com |
| 194 | Descartes@Nightmare (intermud) |
| 195 | Descartes@Igor (not intermud) |