phone.t -- a TADS module for implementing telephones

by Amir Karger (karger@post.harvard.edu)

Last check-in: $Date: 1999/12/26 23:27:02 $ 

********************
Pre-Introduction
********************

Feel free to copy and use this module. I would be happier if you would make
changes by using modify or replace within your files rather than changing
phont.t. I would be even happier if you let me know about it, so that I could
make the module better and rerelease it. If you must make changes, please mark
them as such, for clarity's sake. In other words, it's public domain, but
please play nice.

Note: This module is alpha, which means the docs are alpha squared. 

********************
Introduction
********************

phone.t is a module for creating and using telephones in TADS.

This module requires Suzanne Britton's chatter.t. If you're implementing a
phone, it makes sense to use more sophisticated talking techniques than are
standard in TADS.

phone.t needs TADS 2.5.1 or higher.

The mini-game test.t has some phones in it. test.scr is a test input script,
and test.out is the corresponding output.

In this doc, "caller" and "receiver" will be used to describe an actor (e.g.,
Me) who calls another actor.

********************
Game Play
********************

There are three ways to call someone. You can dial a number (DIAL 333) or a
string (DIAL "555-1212"). If you know their phone number, you can dial an
actor by name (DIAL JOE). Note that TADS can only handle integers up to
2147483647, which means 18005551212 will (silently!) fail. In that case, you
can use a string.

If you call someone on the phone, then you can speak to them as if they were
in the same room. That is, you can use ASK, TELL, HELLO, and SAY. You can also
use the new verbs added by chatter.t, like GOODBYE, APOLOGIZE, and YES and NO.
But something like "show book to Joe" will still yield "I see no joe here."

If the phone rings, you can pick it up with GET THE PHONE or ANSWER THE PHONE.
At the end of the conversation, HANG UP.

********************
Global Variables
********************
The function init_phone creates global.actorList, which is just a list of
the actors in the game. That way, you can say CALL MARY without getting
a "I don't see any mary here" error.

********************
New verbs
********************
The verbs "answer" and "hang up" have been added. Answer will answer the phone
when it's ringing. Hang up will hang up the phone when you're using it
(whether or not you're currently talking to someone on it.)

takeVerb and dropVerb have (hopefully) been modified correctly so that PICK UP
PHONE and PUT DOWN PHONE will do what you expect.

At least in theory, the verbs work for NPCs, so you can have an NPC pick up
the phone, or hang up the phone if the PC gets them angry, say.

********************
Coding with phone.t
********************

The basic things you'll need to do to use phone.t are:
- call init_phone from your init function
- define some fixed_phone or mobile_phone objects. See the Classes section
  below)
- set a few properties like (phone and Actor) phone_number, and actors'
  phone_hello properties. See the Actor and Phone properties sections below.

There are a bunch of other things you can change to customize your game, as
shown below. You'll probably also want to modify lots of the properties
described in the chatter.t manual.

********************
Classes
********************

phone: the base class for telephones. It handles things like the
verbs for calling or answering phones.

fixed_phone: A fixed phone is a phone you can't carry around.
CALL JOE will pick up the receiver and call. PICK UP PHONE will just pick up
the phone, which means you'll get a dial tone. (Of course, if the phone was
ringing when you picked it up, you'll be connected with whoever was calling).
You can't leave the room when you're holding a fixed_phone. HANG UP and PUT
DOWN PHONE are equivalent

(Incidentally, fixed_phone is implemented using a single fixed item. There's no
receiver item you can pick up, for example.)

mobile_phone: (Warning! Mostly Untested!) You can carry a mobile phone around.
If the phone is ringing and you're not holding it, ANSWER PHONE or PICK UP
PHONE will take the phone before answering it. If the phone isn't ringing,
PICK UP PHONE will just take it like a normal object, and ANSWER PHONE
will give an error.

********************
Phone properties
********************

Properties you have to set/override:

    phone_number
        this phone's phone number
    
    valid_phone_num(actor, num)
	Valid phone numbers for this actor to call from this phone. E.g.
	checking for the number of digits in the number. Returns true for a
	valid number.  Note that if you say "call joe" and you know joe's
	number is 333, the the number 333 has to pass this test. (This
	could, e.g., disallow making long-distance calls from a given phone.)

	Default: print "Invalid number. " and return nil
    
    valid_phone_str(actor, str)
        Valid phone numbers (in string form) to call from this phone. See
	comments about valid_phone_num above

	Default: print "Invalid number. " and return nil
    
Properties you might want to set:

    wrong_number
	what will be printed out if the caller calls a valid number or string
	which doesn't have a corresponding phone. Note that you may or may not
	want to make this equal to the default phone.no_answer.
	Default: "There's no answer. "

    no_answer
        message when someone calls this phone and there's noone there
	Default: "There's no answer. "

    busy_signal
        message when someone calls this phone and it's being used
        Default: "The phone's busy. "

    dial_tone_daemon
        This daemon says "You hear a dial tone. " if you're on the phone and
	aren't connected with anyone.

Properties used by the code that you might want to refer to:

    off_hook
        is this phone currently being used?
	Default: nil

    ringing
        phone object that's trying to connect to this phone, if any
	(Note: this is *not* just a boolean "is the phone ringing?")
	Default: nil

    speaker
        who's speaking on this phone?
	Default: nil

    partner
        which phone is this phone currently connected with?
	Default: nil

(Be careful about *setting* these properties, as there are methods, like
set_speaker and unset_speaker, which do that.)

Note that every phone needs to have a location, because an actor only knows
they're being called if a phone rings at their location.  If you have an actor
that the character never sees, but only speaks to on the phone, you need to
make the phone a mobile_phone whose location is the actor.

********************
Actor properties
********************

Here are the new Actor properties. Most of them are nil e.g. when you're not
on the phone.

Properties you have to set:

    phone_number
	What's my (current) phone number, if any. This will often be set equal
	to the phone_number of the phone in my current location.

Properties you might want to set:

    phone_known
	A list of Actors whose phone numbers you know. (Obviously, this is most
	important to set for the Me object.) You can only CALL JOE if Joe is in
	your phone_known list. Of course, you could reach Joe by randomly
	guessing (trying "dial 111", "dial 112"...) even if you don't know
	it.

    phone_hello
	What do I say when I pick up the phone?
        Default: "Someone picks up the phone. \"Hello?\" "

    phone_will_answer
        Will I pick up the phone if it rings in my location?
	Default: true

Properties used by the code that you might want to refer to:

    my_phone
	What phone am I currently speaking on?
	Default: nil

    phone_partner 
        Whom am I currently talking to on the phone?
	(= my_phone.partner.speaker)
	Default: nil

(These properties, like phone.speaker, are set by methods, so be careful
about changing them by hand.)

By default, receiver.phone_answer calls receive_phone.doPhoneAnswer(self) and
then outputs phone_hello. You could override phone_answer to say "Someone
picks up the phone, says, \"Don't bother me!\n" and hangs up." and not
connect.

