!\--------------------------------------------------------------------------- Following is a fairly nifty telephone class for users of Hugo v.2.2 that will allow you to implement any number of telephones in a game without having to write a mountain of code for each one. I'm providing step-by-step instructions, but they're pretty brief. You may find everything difficult to understand at first. It's really not that difficult, considering what a bitch telephones can be to code, but the best thing would probably be to slap my code into a fresh SHELL.HUG file, change "emptyroom" to "apartment," take care of whatever other minor details need to be taken care of, and then compile and play around with the thing. You won't hear any actual conversations, of course, since you won't have written them yet, but you'll at least have some idea what kind of beast you're dealing with when it comes time to write them. Anyway, without further ado: The first thing you need to do is type in some new verb definitions particular to telephone usage: ---------------------------------------------------------------------------\! verb "dial", "call" * DoVague * object DoDial verb "answer" * DoVague * object DoAnswer verb "hang" * "up" DoHangup * "up" object DoHangup \!-------------------------------------------------------------------------- Then, before you forget, provide the default verbroutines corresponding to the verbs you just defined. (If you're new to Hugo, or don't already have some set place in your source where you like to put these, put 'em at the end). --------------------------------------------------------------------------\! routine DoAnswer { "Sure. Ok, buddy. Whatever." } routine DoDial { "You can't dial that." } routine DoHangup { if phone_obj in location : Perform(&DoHangup, phone_obj) elseif not object : "There's nothing here to hang up." else : "You can't hang that up." } !\-------------------------------------------------------------------------- Next, back up toward the beginning of your code, type or paste in the following new variables and attribute. (If you're not sure where to put these, put 'em right after the lines that link in the Hugo library.) Here's what these new critters are for: "someone_on_line" is a variable intended to be used as a true/false switch. In your own code, when you write your actual phone call events, you will want to set this switch to true to signify that someone is actually on the other end of the phone. If you fail to set this switch, when the player answers or picks up the phone, he will be told that there's no one there. Also, you will need to manually set it to false in the case where the player stays on the line throughout the entire conversation so that the other party finishes and hangs up first. In the case where the player hangs up in the middle of a conversation, my code sets it to false automatically. "phone_number" holds the object number of the phone number being dialed. I've implemented telephone numbers as actual game objects, since that's so much easier than trying to parse input strings of numbers and dashes. This method has its drawbacks, but all in all it's not so bad. More about this later. "phone_obj" holds the object number of the particular telephone being used. This is necessary because there is only one handset object, which must be passed around from phone to phone as needed. We'll see how to do this in a moment. Finally, "off_hook" means just what it says: it indicates whether the handset is currently on or off the telephone's hook. Generally speaking, unless you really start fiddling with the phone class code, it's not one you need to worry about. You will, however, want to check this attribute when you do your "ring" events, since phones that are off the hook shouldn't ring (and the call shouldn't come through at all). NOTE: It is not possible with this code for a player to walk away and leave a receiver off the hook. If a phone is not hung up (i.e. if it is off_hook), it's because the player is standing there holding it. ---------------------------------------------------------------------------/! global someone_on_line global phone_number global phone_obj attribute off_hook !\-------------------------------------------------------------------------- Ok. Remember how I just said you need to set "phone_obj" so that the handset object gets moved around properly? How you do this will depend upon your story. If you have more than one phone in a room, it'll be up to you to figure it out. However, if you're not going to have more than a single phone in any given room, put lines like the following in the main() routine, so that your phones are checked and handled every turn (you should end up with one "if" or "elseif" line for each location that has a phone in it, with phone_obj set to the phone that's in it): ---------------------------------------------------------------------------\! if location = apartment phone_obj = red_phone ! elseif location = airport ! phone_obj = white_phone ! etc... move hook to phone_obj ! don't change these three lines if receiver not in player move receiver to hook !\-------------------------------------------------------------------------- Wow. Now you get to see the actual class definition. Aren't you excited? ---------------------------------------------------------------------------\! class phone "telephone_class" { is open, platform nouns "telephone", "phone" article "a" long_desc { "It's just an ordinary telephone. "; if self is off_hook "The receiver is off the hook." else : "" } before { object DoAnswer { if self is off_hook "The phone is already off the hook." elseif not someone_on_line { self is off_hook move receiver to player receiver is not hidden "You pick up the phone, but there's no one on the line." } else { self is off_hook move receiver to player receiver is not hidden AnswerThePhone() } } object DoGet { if self is off_hook "The phone is already off the hook." elseif not someone_on_line { self is off_hook move receiver to player receiver is not hidden "You pick up the phone." } else Perform(&DoAnswer, self) } object DoListen { if self is not off_hook and someone_on_line "The phone is ringing." elseif self is not off_hook "The phone is silent." elseif someone_on_line "The other party is speaking to you." else "You hear a dial tone." } object DoHangup { if self is not off_hook "The phone is already hung up." else { self is not off_hook move receiver to hook receiver is hidden someone_on_line = false "You hang up the phone." } } object DoDial { if self is not off_hook "You'd better pick up the phone first." elseif someone_on_line "That would be rude." else { if phone_number = glorias_number ! AN EXAMPLE "You dial 555-1212." else "You dial randomly until an operator comes on the line telling you to cut it out." } } xobject DoPutIn { if object = receiver Perform(&DoPutIn, receiver, hook) else : return false } xobject DoGet { if object = receiver Perform(&DoGet, receiver, hook) else : return false } } } !\-------------------------------------------------------------------------- Next come the receiver and hook. Note that the receiver is of the attachable class. This will prevent the player from moving off to another location while he's holding it. He'll also get a nice little inventory description telling him that the receiver he's holding is attached to the telephone, which impresses the hell out of people from Estonia. ---------------------------------------------------------------------------\! attachable receiver "telephone receiver" { is hidden in_scope { if phone_obj in location : return player else : return 0 } nouns "receiver", "handset" article "a" attached_to { return phone_obj } attached_desc "attached to" long_desc { if phone_obj is not off_hook: "The receiver is on the hook." else : "The receiver is off the hook." } before { object DoGet { Perform(&DoGet, phone_obj) } object DoDrop, DoHangup { Perform(&DoHangup, phone_obj) } object DoListen { Perform(&DoListen, phone_obj) } } } scenery hook "phone hook" { is open, platform nouns "hook", "cradle" article "the" long_desc { if phone_obj is not off_hook: "There's a receiver on the hook." else : "The hook is empty." } before { xobject DoPutIn { if object = receiver Perform(&DoDrop, receiver) else : "You can't put that on the hook." } xobject DoGet { if object = receiver Perform(&DoGet, receiver) else : "That's not on the hook." } object DoPush { if phone_obj is off_hook { if someone_on_line { someone_on_line = false "You press the cradle, breaking the connection." } else : "You press the cradle." } else : "The receiver is in the way." } } } !\-------------------------------------------------------------------------- Finally, an actual telephone object which inherits from the phone class defined above. If you want sixteen phones in your game just make sixteen objects similar to this one and put 'em where you want 'em (remembering, of course, to do the necessary housekeeping in the main() routine for each one). ---------------------------------------------------------------------------\! phone red_phone "red telephone" { in apartment adjectives "red" short_desc { "A red telephone hangs beside your bed." } } !\-------------------------------------------------------------------------- The following has been broken out of the phone class before() routine for convenience's sake. If you go back up and look, it is simply called whenever a phone is successfully answered (i.e. when a phone is picked up and there's someone on the line). How you code up all your telephone conversations will depend upon the number and nature of them, so I can't give any detailed guidance here, but in any case it will be easier to keep track of everything if you don't try to do it in the before() routine. ---------------------------------------------------------------------------\! routine AnswerThePhone { "You answer the phone." } !\-------------------------------------------------------------------------- Lastly, phone numbers. Following is a rough example showing how to implement them as game objects. Again, if you're into pain, feel free to dump this approach and parse the input strings yourself. Oh? You're still here? Well, then, throw this little guy into your code, compile it, and run your game. Type "call 555-1212 " and you'll see quickly enough what you need to do to make it fit your own story. Remember the "phone_number" variable I talked about before? Look at DoDial below and you'll see what it's good for. We want the phone to be checked first to see if it can be dialed, so we're going to call the phone class' DoDial routine where all that is done. But we also need to pass the phone number (object). The simplest, least confusing way to "pass" the number in this case is to use a global variable, and so that's the reason for "phone_number". This method also gives us access to the number (object) at any time we might need it in other routines, so all in all its not a bad use of a global. --------------------------------------------------------------------------\! object glorias_number "Gloria's number" { is known in_scope { return player } nouns "555-1212", "5551212", "number" adjectives "gloria's" before { object DoDial { phone_number = self Perform(&DoDial, phone_obj) } object DoLook { "Gloria's number is 555-1212." } object { "You can't do that with Gloria's phone number." } } } !\--------------------------------------------------------------------------- That's it! Enjoy! This document is provided as-is, with no warranty whatsoever express or implied, by Cardinal Teulbachs, Archbishop of Frith. It is also copyright (c) 1996. ---------------------------------------------------------------------------\!