Does anyone have any knowledge of how to implement a tape recorder or a
telephone in TADS? If you could post some source code relating to
either item, I'd be grateful.
A lot of it depends on what you want done with either item. For example,
will players be able to dial out on your phone? Will they receive calls
on the phone? Will the tape recorder be used for recording, or playback,
If you further refine your requests, I'm sure someone here can help.
Sorry about the vagueness of the last post. I'm trying to implement a
telephone on which you can place and receive calls--I've seen this done
in Inform but never in TADS. As for the tape recorder, I'd like it to
be fully featured, meaning that you can record, play, rewind, and
I'd appreciate any help,
IMHO a proper tape recorder is much more difficult to implement than a phone.
With a recorder it actually has to record any sounds, things you say and
things the NPCs say. It also has to play them back with appropriate spaces
Andy Leighton => an...@azaal.dircon.co.uk
"... January is your third most common month for madness" - _Sarah Canary_
What is it you're trying to do with them? Chances are that if someone else
has coded one or both of these items, they don't do what you're looking
For the phone, you probably want to be able to
> say "hello" into phone
Do you need a play-only tape recorder (that doesn't make sense, but you
know what I mean)? Is the tape recorder going to be recording with the
player is present? (If not, it makes it *much* easier).
Have you tried doing it yourself? If so, waht difficulties have you run
-=- Mark -=-
This is still far too vague. Try to describe the situations you'll be
using the phone in. What commands do you want the player to issue in
order to place a call? I'm presuming you want the player to "dial
<number> on phone" to place a call, and "answer phone" to receive a
call. That's easy enough, but how do you want to carry on a
As for a tape recorder, *what* are you trying to record? Are you
going to use it to tap into a phone line and record everything that
is said? Or do you want to bring it to a leture hall and record
what goes on there? Or are you slipping it under the bed in order
to capture a private conversation?
Here's a reality check: authors typically implement the *minimum*
necessary for any device. More code means more bugs. Neil deMause
in "Frenetic Five", for example, has the following situation: the
player answers the phone, listens for a bit, and then it's over
-- the player never says anything, nor does s/he have to hang up.
Try to think of how you're going to have the players use your
devices, and then restrict them to that. But you have to do it in
a way that doesn't seem restricted, or it feels too contrived.
-=- Mark -=-
It's one of those old-fashioned, black rotary phones that are blunt
enough to serve as a murder weapon. The receiver is currently seated in
>PICK UP RECEIVER
The phone rings three times before a bright and chipper voice answers,
"Sears Customer Service, Deborah speaking, how may I help you?"
>DEBORAH, SEND BINOCULARS TO 217 OVERLOOK ROAD
"Thank you, sir. Have a nice day!"
>DEBORAH, THANK YOU. HANG UP.
A bit unrealistic, I admit, but that's what I'm attempting to do. Is it
> As for a tape recorder, *what* are you trying to record? Are you
> going to use it to tap into a phone line and record everything that
> is said? Or do you want to bring it to a leture hall and record
> what goes on there? Or are you slipping it under the bed in order
> to capture a private conversation?
Another little sample transcript(Again, not from my game).
You're standing in the basement. Cobwebs and dust are everywhere.
Suddenly, you hear footsteps above you, and a muffled voice.
"Leroy, what the heck do you think you're doing?" The voice may be
muffled but you'd recognize it anywhere--it's the evil crime boss Mr.
>TURN ON TAPE RECORDER. PUSH RECORD BUTTON.
You should put a cassette in first.
>OPEN TAPE RECORDER. PUT CASSETTE IN TAPE RECORDER. PUSH RECORD BUTTON.
The tape recorder begins to whirr as it records.
"Waddya mean Krieger wasn't killed? Those were my strict orders--kill
him! Which part of "kill Joe Krieger" don't you understand?" There is
a reply but you can't quite hear it. Mr. Small snorts and continues.
"Well, Leroy, that's just not good enough. Good-bye."
You cringe. There's the loud crack of a rifle and then the mailsack
thud of a body hitting the floorboards.
"Harry, get this body out of here, and get Whisker in here." You hear
Mr. Small say.
>TURN OFF TAPE RECORDER
Okay, the tape recorder is now off.
That's what I'm trying to do.
> Here's a reality check: authors typically implement the *minimum*
> necessary for any device. More code means more bugs. Neil deMause
> in "Frenetic Five", for example, has the following situation: the
> player answers the phone, listens for a bit, and then it's over
> -- the player never says anything, nor does s/he have to hang up.
> Try to think of how you're going to have the players use your
> devices, and then restrict them to that. But you have to do it in
> a way that doesn't seem restricted, or it feels too contrived.
> -=- Mark -=-
I have been keeping that in mind, thank you. Again, sorry about the
vagueness of my first two posts; I was worried that I might make the
post *too* long if I posted a sample transcript of what I'm trying to
do. I would appreciate any help, thank you.
> >X PHONE
> It's one of those old-fashioned, black rotary phones that are blunt
> enough to serve as a murder weapon. The receiver is currently seated in
> its cradle.
Easy enough. :)
> >PICK UP RECEIVER
This is actually a little trickier than you might think, actually. You'd
need to make the receiver a takeable object, not a fixed item. But it
should also be attached to the phone by a cord. So you'd need to call
addLeaveList() for the current room to make sure the player is forced to
drop it if he or she tries to wander away from the phone while holding the
receiver. Unless, of course, the phone is also being carried. This kind of
thing can get pretty ugly to code. That's why I simply coded a phone in my
game as a one-piece unit sans separate receiver. :)
> >DIAL 123-4567
> The phone rings three times before a bright and chipper voice answers,
> "Sears Customer Service, Deborah speaking, how may I help you?"
This bit is also a tiny bit tricky. Minor thing first - TADS expects an
indirect object when referring to text. The full form would be DIAL 123 ON
THE PHONE. However, if you've set up your verify methods correctly, TADS
will automatically supply the phone object if the phone is the only
dialable item in the room.
Tricky bit: TADS will not normally permit the player to type in a hyphen,
as used in North American phone numbers. So you could do what I did, which
is to take the easy way out. I simply decreed that henceforth all phone
numbers in my game universe are 5 digits long, as in some smaller UK
cities. And no area codes allowed! However, if you had your heart set on
permitting hyphens you'd need to write a preparse() function that loops
through the current input line and toasts any offending hyphens. You could
have it truly fussy and only remove hyphens bracketed by numerals, but
that shouldn't be necessary if you set up your adjectives properly. (ie:
you don't have the artificial situation where there are disambiguation
cases in which two words are identical unless they have a hyphen) If you
want to permit long distance calls with area codes in brackets (and maybe
dialling 9 to get out of a PBX :) then you're on your own. It'd be doable,
but would likely involve a lot of ugly hardcoded hacks.
Of course, you could take the simple approach and simply move your game
backwards in time, to the years prior to the introduction of automated
telephone exchanges. Then you could simply permit:
OPERATOR, GET ME PINEWOOD 3020
:) Has a nice Humphrey Bogart playing Philip Marlowe in the 1930s, don't
you think? Admittedly, I doubt the Sears Catalogue accepted phone orders
back then, but my knowledge of American mercantile consumer distribution
systems is admittedly rather feeble.
> >DEBORAH, SEND BINOCULARS TO 217 OVERLOOK ROAD
> "Thank you, sir. Have a nice day!"
Cool! Without even having to give a credit card number? :) Anyway, to
implement this you'd have to create a dummy actor and make it accessible
to the player when the phone is answered. You'd have this actor object
respond to a certain subset of commands, but of course its ldesc would
simply be something like "The disembodied voice of the Sears sales rep is
not visible." or whatever. Other than that you'd have your standard TADS
directed actor. This could be a moderately believable NPC, of course, as
telephone reps are unlikely to want to engage in meaningful conversations
about the state of world affairs or whatever. ("I'm sorry ma'am, but my
job is to take your order.")
> >DEBORAH, THANK YOU. HANG UP.
> A bit unrealistic, I admit, but that's what I'm attempting to do. Is it
Same as above. Plus you'd have a new verb called "hang up." Naturally
you'd need to specify the direct object, unless you hardcoded the verb's
action() method to check for the special case of the phone being present
and the receiver being off the hook.
The limited set of commands that you've outlined is certainly doable. The
trick is to implement it in such a way that there are sensible responses
for all the other things the player tries to do. This can be a real can of
proverbial worms, so most people writing text adventures tend to cop out
and simplify the operational behaviour of the telephone to an easily
written subset of behaviours. At least, that's what I did. :)
> The tape recorder begins to whirr as it records.
> "Waddya mean Krieger wasn't killed? Those were my strict orders--kill
> him! Which part of "kill Joe Krieger" don't you understand?" There is
> a reply but you can't quite hear it. Mr. Small snorts and continues.
This isn't impossible to implement, but would require a lot of complex
code to cover the various possibilities. A lot. You'll have to make a lot
of decisions about how realistic you want your recorder to be. For
example, do you permit the cassette to be rewound and erased? To be
rewound partway and recorded over? If so, you'll need to write in a form
of time-based counter that's incremented each turn. Not hard, just fiddly.
As for recording events you'll probably want to write a set of routines
for outputting all bits of text related to sound. You'll then need to
write two pieces of text for each bit of sound - for example "You hear the
angry voice of Mr. Small coming through the floorboards above your head."
and "You hear the angry voice of Mr. Small emerging tinnily from the
loudspeaker of the cassette recorder." Then, when a sound event occurred
you would need to display the former to the player and store the latter as
a single-quoted string into a list associated with the cassette. This
would be done each turn by a recording daemon, triggered by pressing the
record button. Something like:
if ( cassettePlayer.location = hiddenBasement )
cassette.recording[ cassette.counter ] :=
'You hear a recording of Mr. Small conveniently explaining his evil
"You hear Mr. Small's voice above you... ";
cassette.counter += 1;
Not a very good code example, as it's hardcoded and not very flexible -
you'd want to have a list of arrays, really. But you get the idea.
Of course you'll want the check for the location to be a bit smarter than
that - what if the cassette player is sitting on a table in the room? Or
in a bag on the table? You could use the uberloc() function from Stephen
Granade's TADS libraries to do this, but what if you had a cassette player
inside a soundproof box? Ouch. The easy solution would be to ensure the
complete absence of soundproof boxes in your game, :) but you could also
consider looking at WorldClass, which contains a more complex model for
dealing with this kind of thing, at the expense of additional complexity.
However, since the cassette recorder is portable there are still more
additional complications. What if the player puts the player down, then
walks away? Of course it'll keep recording. This can obviously be useful
(record Mr. Small's fiendish and dastardly plotting while the player is
hidden next door) but can also be hellishly complicated. What if the
player leaves the player on a street corner? Surely it should then record
street noise. What if the player sings? You'll need code that records the
effect. ("You hear yourself singing. Don't quit your day job.") What if
the player speaks out loud? Will other players be able to hear the
cassette? ("You hear your own voice saying 'If anyone hears this recording
- it was Mr. Small! He did it!'") What if there's a radio in the room?
("You can't hear anything Mr. Small has to say - the sound of
easy-listening music oozing from the radio drowns him out.") You have to
code for every reasonable eventuality that the player will expect, or else
come up with good workarounds. Or make damn sure that really complex
situations won't arise by omitting radios from the game, not allowing the
player to speak, whatever.
For this reason, I have a recording device in my game that doesn't permit
the player to record anything more. Too much work for too little return,
given the way my game is set up. Of course in your game it may well be
worth the effort, if recording Mr. Small's murderous orders is the most
critical point of the whole thing.
Once you have your list of sounds it's fairly easy to code something like:
say( cassette.recording[ cassette.counter ] );
and have it called once per turn by a daemon. Take a look at the source
to Ditch Day Drifter - it has a pre-recorded diary that works this way.
So. Sorry to be a bit discouraging. This sort of thing could make for a
very interesting game, but you'll have to be extremely careful as to how
complex your code will be, and what possibilities you will allow.
- Neil K.
Thanks for the correction and your help. BTW, I found a way to simplify
the enormous amount of code needed to implement a tape recorder by
adding a "recorddesc" to any object you might want to try and record.
Just thought you would be interested.
> [...] BTW, I found a way to simplify
> the enormous amount of code needed to implement a tape recorder by
> adding a "recorddesc" to any object you might want to try and record.
Yep - that could be a useful tool in many cases. Although it wouldn't
necessarily make things much easier in the case of devices that don't
always produce the same noise. To be realistic, the recorder should
capture the sound emitted by a particular item at a particular moment in
time, and if that noise changes all the time then a simple recorddesc
property may not be sufficient. Particularly if it were a double-quoted