---------------------------------------------------------------------------- std_room.c -- The New Room Designed under 3.0, Lars (European) Created by Shard and Yakker, Cornucopia MUD Sept 12, 1991 Updated to match MudOS mudlib 0.9, Mobydick, 11-24-92 ---------------------------------------------------------------------------- Section One: Introduction ------------------------- This new std_room is designed in such a way as to make your room building experience much easier than any previous method, with additional options to give the wizard the versatility he needs with as few additions in the code as possible. As you continue through this documentation, you will see how each function is designed to make the coder do as little as possible. The idea behind this room format is to get the user to write more advanced rooms without doing any extra coding. After four weeks of work, this is the end result of the new room. We hope that it makes your life easier in some fashion, and that better rooms are produced as a result. ---------------------------------------------------------------------------- Section Two: Basic Rooms ------------------------ The first few things we need to talk about are the basic functions needed in a new room file. Certainly we will need to assign light to the room, as well as exits, short descriptions, and long descriptions. In those four functions, we can make an entire room. So let's do that: We'll call this file basic1.c. /* --------------- basic1.c -- The beginning basic room --------------- */ #include <mudlib.h> inherit ROOM ; void create() { set ("light", 1) ; set ("exits", ([ "north" : "/d/Fooland/hall" ]) ); set ("short", "a basic room") ; set ("long", "This is a basic room, without anything too fancy. Just some\n" + "very basic setup.\n\n"); } /* --------------------------- done basic1.c ---------------------------- */ There you have it! One complete room. Now, we need to analyze each line, so that we understand completely what each function does, and how it affects the room we have here. Note that everything between a /* and a */ is only a comment field, and we put them there to say things important to us. ******** create(): ******** void create() ----------------------- This is simply to declare our create function. We set the type of the return value to be void, which tells our function to return nothing. The function create() is where we put all of our initial information, and it is where we set all initial values. { ----------------------- This is a marker noting that we are beginning the code for our function. set("light",1) ; ----------------------- This function will set the light value in the room to be 1. If the value we assign to set_light is 0, then the room will be dark. If the value is 1, then the room is bright. set ("exits", ([ "north" : "/d/Fooland/hall" ]) ); ------------------------ This function will set the exits for our room. When we specify ([ and ]), we are setting up an mapping. Inside of the mapping, we have the string "north", which is the name of our first exit. The string "d/Fooland/hall.c" is the file which we want the player to go to if he moves north. You can give a room more than one exit by entering more than one element in the mapping, like this : set("exits", ([ "north" : "/d/Fooland/hall", "south" : "/d/Fooland/shop" ]) ); We can set as many exits from a room as we want. The only thing that we must be sure of is that there are the same number of exits as there are filenames to exit to. In other words, if there are 5 exits to other rooms, there must be five filenames in the second array to match those exits in the first array. set("short", "a basic room") ; ------------------------ This function will set the short description for the room. That way, if someone is in 'brief' mode when walking from room to room, they will see this description. set ("long", "This is a basic room, without anything too fancy. Just some\n" + "very basic setup.\n\n"); ------------------------ This function prints out the long description for the room. If a player or wizard is in 'verbose' mode, they will see this string. We can add strings in LPC, by using the + operator. For example, if I had the string: "This is a string.\n" it is the same as: "This " + "is a" + " string.\n" Note that the \n within the string represents a <RETURN> character on the line you are typing. So if I had: "This\nis\na\nstring.\n" then when printed out, it would look like: This is a string. } ------------------------ This is a marker noting that we are ending the code for our function. And that's it! There's a full description of how a room works. After writing a few rooms, you'll begin to get the idea on how to make rooms properly, using the correct syntax. ---------------------------------------------------------------------------- Section Three: Basic Rooms With Descriptions -------------------------------------------- Now that we know how to create basic rooms, let's concentrate on rooms that have item descriptions, or even better, item functions. When we add item descriptions and item functions to a room, we begin to add flavor to our rooms. Instead of just seeing a short and long description, we can actually look at items, note their appearances, and perhaps even discover something along the way. So, with that in mind, let's write two files, the first using item descriptions, and the second using both item descriptions and item functions. We'll call this file basic2.c. /* ---- basic2.c -- The beginning basic room with item descriptions ---- */ #include <mudlib.h> inherit ROOM ; void create() { set ("light",1) ; set ("exits", ([ "north" : "/d/Fooland/hall" ]) ); set ("short", "a basic room") ; set ("long", "This is another basic room, but you notice a chair in the room.\n\n"); set ("item_desc", ([ "chair" : "This is a very nice chair, with beautiful engravings.\n" ]) ); } /* --------------------------- done basic2.c ---------------------------- */ The most important thing we need to note about this room is that we are now setting a new property called "item_desc". This property will allow us to set up item descriptions in the room, so when a player looks at an item, and if it is in the mapping, it will write the string associated to the item in the mapping. For example, let's see what happens when we are in this room: ------------------------ This is another basic room, but you notice a chair in the room. The only obvious exit is north. > exa chair This is a very nice chair, with beautiful engravings. > ------------------------ So we notice how we are able to add a description to the room, simply by adding it to our "item_desc" property. If our mapping had the following information: set ("item_desc", ([ "chair" : "This is a very nice chair, with beautiful engravings.\n", "chairs" : "All very nice chairs, with beautiful engravings.\n", "A very big table, with lots of room for everyone.\n" ]) ); We would see the following results from this addition: ------------------------ This is another basic room, but you notice a chair in the room. The only obvious exit is north. > exa chair This is a very nice chair, with beautiful engravings. > exa chairs All very nice chairs, with beautiful engravings. > exa table A very big table, with lots of room for everyone. > ------------------------ So adding descriptions to a room is very easy, and this method is less of a headache for programmers who used to have to write long sections of code to do the same thing. Another way to spruce up the look of a room is to add item functions. What these do is call a function when an item is looked at. For example, let's take a look at our next example, which will use both item functions and item descriptions: /* -- basic3.c -- basic room with item descriptions / item functions -- */ inherit "std/room"; int callnum; void create() { set ("light", 1) ; set ("exits", ([ "north" : "/d/Fooland/hall" ]) ); set ("short", "a basic room") ; set ("long", "This is a basic room, with a table and chair inside.\n\n"); set ("item_desc", ([ "chair" : "This is a very nice chair, with beautiful engravings.\n" ]) ); set ("item_func", ([ "table" : "handle_table" ]) ); callnum = 0; } int handle_table() { callnum++; write("You have looked at the table " + callnum + " times.\n"); return 1; } /* -------------------------- done basic3.c ---------------------------- */ The first thing we need to do is explain what the set ("item_func") call does. We have taken the string "table", put it in the mapping's keys, and put the string "handle_table" in the mapping's values. We MUST have a function called handle_table() in our file for this to work properly. If the function does not exist, an error will occur. At this point, we can have this function do whatever we want. Another example of using item_func might be: set ("item_func", [( "table" : "handle_table", "desk" : "function_for_desk" ]) ); /* // Then after our create() function, we would have two additional // functions in our file, handle_table(), and function_for_desk(). // */ Let's take a look at the new code example a bit more closely. We have added a global integer, and another function, called handle_table(). We set callnum to 0 in the create() function, and from then on, every time we examine the table, we will add one to callnum. Let's break down the function into smaller pieces: (At this point, we will assume that the reader understands /* .. */, and { .. }.) **************** handle_table(): **************** int handle_table() ------------------------ This is the name of our function. When we set the string "handle_table" in our set_item_functions() call, we must make a function called the same thing. The function will return an int parameter to show that the look succeeded or failed. In the handle_table() function, we return a value of 1 to show that we have succeeded. If we had returned a value of 0 instead of 1, we would be saying that the function failed for some reason. callnum++; ------------------------ This increments the value of callnum by 1. It is the same as ++callnum, or callnum += 1, or even callnum = callnum + 1. We increment the callnum variable to show how many times we have called the function handle_table(). write("You have looked at the table " + callnum + " times.\n"); ------------------------ This statement will write out the number of times the person has gone into the room. We increment callnum by one everytime before printing this message out. Only the person who examines the table will see this message. return 1; ------------------------ This will return a successful value back to the caller. If this value were 0 instead of one, it would indicate an unsuccessful result to the caller. The output from this would look like: ------------------------ This is a basic room, with a table and chair inside. The only obvious exit is north. > exa chair This is a very nice chair, with beautiful engravings. > exa table You have looked at the table 1 times. > exa table You have looked at the table 2 times. > exa table You have looked at the table 3 times. > ------------------------ Now we've discussed standard exits, item descriptions, and item functions. Now let's take this a step further and discuss bad exits, bogus exits, and how to add and remove an exit from a room. --------------------------------------------------------------------------- Section Four: More Advanced Rooms With Additional Exits And Searching --------------------------------------------------------------------- We need to now discuss how to add and remove exits from rooms. One way to do this might be from someone examining an object, and finding an exit underneath. Let's jump right into the coding with a good example: /* ---- adv1.c -- advanced room with extra exits, and init actions ---- */ #include <mudlib.h> inherit ROOM ; void create() { set("light",1) ; set ("exits", ([ "north" : "/d/Fooland/hall" ]) ); set ("short", "an advanced room") ; set ("long", "This is an advanced room, with a table and chair inside.\n\n"); set ("item_func", ([ "chair" : "handle_chair", "table" : "handle_table" ]) ); } int handle_table() { write("You look at the table too closely, and lean too far!\n" + "You push it over the northern exit!\n"); delete ("exits/north") ; delete ("item_func/table") ; set ("item_desc/table" : "This is a neat table, blocking a door.\n"); return 1; } int handle_chair() { write("As you look under the chair, you notice a hole leading down!\n"); set ("exits/down", "/d/Fooland/inferno") ; delete ("item_func/chair") ; set ("item_desc/chair", "This is a chair with a hole underneath.\n") ; return 1; } /* --------------------------- done adv1.c ----------------------------- */ After finishing this topic, we need to stop and discuss all of the new functions we have introduced. Let's take a look at the functions we have now created, so that we understand exactly what the room does. **************** handle_table(): **************** write("You look at the table too closely, and lean too far!\n" + "You push it over the northern exit!\n"); ------------------------ Inform the user of the removal of the northern exit. You might also want to use say() or tell_room() to inform the other users in the room. delete ("exits/north") ; ------------------------ This will remove the exit from the room. Note we only need to give the direction of the exit. The rest of it will be handled automatically by the room code. delete ("item_func/table") ; ------------------------ This will remove the item function handle_table() from the list of possible item functions. From then on, whenever anyone tries to examine the table, the table will not be an examinable item. set ("item_desc/table", "This is a neat table, blocking a door.\n"); ------------------------ At this point, we then add a new table description. Now, whenever someone looks over the table, they will see the description added. return 1; ------------------------ This returns a successful value to the caller of the function. *************** handle_chair(): *************** write("As you look at the chair, you notice a hole leading down!\n"); ------------------------ Write a cute message to the user, telling him that a new exit has appeared in the room. You can also use say(), or tell_room(), to let the rest of the people in the room know that a new exit exists. set ("exit/down", "/d/Fooland/inferno") ; ------------------------ Now we add an exit to the room. Essentially, what we are doing is adding another exit name to our list of exit names, and specifying the filename to go to. We do not need a mapping here like we used in set ("exits"), because we are only setting one exit. The first argument is always the direction, and the second the filename. delete ("item_func/chair") ; ------------------------ This will remove the item function handle_chair() from the list of possible item functions. From then on, whenever anyone tries to examine the chair, the chair will not be an examinable item. set ("item_desc/chair", "This is a real neat chair.\n") ; ------------------------ At this point, we then add a new chair description. Now, whenever someone looks over the chair, they will see the description added. return 1; ------------------------ This returns a successful value to the caller of the function. If you've survived all of that, then let's run a sample output of what the room does: ------------------------ This is an advanced room, with a table and chair inside. The only obvious exit is north. > examine chair As you look at the chair, you notice a hole leading down! > look This is an advanced room, with a table and chair inside. There are two obvious exits: north, down. > examine table You look at the table too closely, and shut it over the northern exit! > look This is an advanced room, with a table and chair inside. The only obvious exit is down. > examine chair This is a chair with a hole underneath. > examine table This is a neat table, blocking a door. ------------------------ Note that as we look at the exits, either an exit appeared or disappeared depending on the way the function was written. If we looked at the table, the northern exit disappeared, while if we looked at the chair, the down exit appeared. You can use these types of examples to add lots of color to your room. Secret exits and room descriptions (which also detail the objects in the room) will make your castle shine. Now let's cover how to search for items. The basics behind searching is that a person searches an item or a room for something hidden. Now, what the programmer decides to hide is up to them, but the way that they hide it in the code can be simple, and elegant. Let's take a look at our second advanced example: OK, well, let's not do, then.