TADS: attempt at writing a game


9 Sep 1995 10:11:44 -0400

I just started trying to write text adventures a while ago - here's the
prolougue for a game I'm working on in TADS...
Could someone help me with various things in here that could be done more
efficiently or generally better? (I don't really like the way the sleeping
guard works...)

I would appreciate greatly any comments or suggestions... I really want to
get better at writing i-f... (since I suck so bad at playing it... ;)

Here's the code:

/* _Lucid Dreaming_ v.1 (c) 1995 Jason Reed all rights reserved*/

#include <adv.t>
die: function;
win: function;
scoreRank: function;
init: function;
terminate: function;
pardon: function;
darkTravel: function;

/*
* The die() function is called when the player dies. It tells the
* player how well he has done (with his score), and asks if he'd
* like to start over (the alternative being quitting the game).
*/
die: function
{
"\b*** You have died ***\b";
scoreRank();
"\bYou may restore a saved game, start over, quit, or undo
the current command.\n";
while ( 1 )
{
local resp;

"\nPlease enter RESTORE, RESTART, QUIT, or UNDO: >";
resp := upper(input());
if ( resp = 'RESTORE' )
{
resp := askfile( 'File to restore' );
if ( resp = nil ) "Restore failed. ";
else if ( restore( resp )) "Restore failed. ";
else
{
Me.location.lookAround(true);
scoreStatus( global.score, global.turnsofar );
abort;
}
}
else if ( resp = 'RESTART' )
{
scoreStatus( 0, 0 );
restart();
}
else if ( resp = 'QUIT' )
{
terminate();
quit();
abort;
}
else if (resp = 'UNDO')
{
if (undo())
{
"(Undoing one command)\b";
Me.location.lookAround(true);
scoreStatus(global.score, global.turnsofar);
abort;
}
else
"Sorry, no undo information is available. ";
}
}
}

win: function
{
"\n\n\n*** You have won! ***\n\n\n";
scoreRank(); terminate();quit(); abort;
}

/*
* The scoreRank() function displays how well the player is doing.
* This default definition doesn't do anything aside from displaying
* the current and maximum scores. Some game designers like to
* provide a ranking that goes with various scores ("Novice Adventurer,"
* "Expert," and so forth); this is the place to do so if desired.
*
* Note that "global.maxscore" defines the maximum number of points
* possible in the game; change the property in the "global" object
* if necessary.
*/
scoreRank: function
{
"In a total of "; say( global.turnsofar );
" turns, you have achieved a score of ";
say( global.score ); " points out of a possible ";
say( global.maxscore ); ".\n";
}

/*
* The init() function is run at the very beginning of the game.
* It should display the introductory text for the game, start
* any needed daemons and fuses, and move the player's actor ("Me")
* to the initial room, which defaults here to "startroom".
*/
init: function
{
version.sdesc;

"\n\n\nYou exist somewhere, without memory, without any sensation
save
pure, undiluted, unassociated pain. Your head (at least you think it's
your
head) has a sensation not entirely unlike being torn off and jumped upon
repeatedly. You contract
reflexively, blinded by the pain, trying to move around in desperate hope
of
relief when suddenly everything grows blurry and dark... within moments,
you
lose conciousness.\n\n\n
After an indeterminate amount of time passes, you find...\n\n";

setdaemon( turncount, nil );
Me.location := beach;
beach.lookAround( true );
beach.isseen := true;
scoreStatus(0, 0);
}

preinit: function
{
local o;

global.lamplist := [];
o := firstobj();
while( o <> nil )
{
if ( o.islamp ) global.lamplist := global.lamplist + o;
o := nextobj( o );
}
initSearch();
}

terminate: function
{
}

pardon: function
{
"I beg your pardon? ";
}

numObj: basicNumObj ;
strObj: basicStrObj ;

global: object
turnsofar = 0

score = 0

maxscore = 25

verbose = nil

lamplist = []

;

version: object
sdesc = "Lucid Dreaming v.1 (c) 1995 Jason Reed all rights reserved.
\n Developed with TADS, the Text Adventure Development System.\n"
;

Me: basicMe;

darkTravel: function
{
"You stumble around in the dark, and don't get anywhere. ";
}

goToSleep: function
{
"***\bYou wake up some time later, feeling refreshed. ";
global.awakeTime := 0;
}

beach: room
sdesc = "Beach"
ldesc = "You are in a small beach, surrounded by forest to the north and
east, and the ocean to the south and west. You can just make out the top
of a
building to the east. The sun, strangely oversized and red-orange,
penetrates
through your clothes, warming your skin just beyond a comfortable level.
Paths lead both northeast and east into relatively dense forest."
ne = {if (theguard1.alive) return guard1path; else return clearing;}
east = path
;

path: room
sdesc = "Path"
ldesc = "A path cut through the forest which runs east-west. All around
you
are innumerable species of flowers, insects, and birds. To the northeast
you
can see the top of a strangely built structure poking above impossibly
steep
cliffs."
west = beach
east = guard2
;

guard1path: room
sdesc = "Path"
ldesc = "The path that comes from the southwest ends abruptly
before a large bush. From where you stand, you can see a clearing in the
forest to the east and a giant metal wall that connects two cliffs, with a
small doorway at the base. Just next to the door you see an extremely
alert
guard, brandishing a painfully sharp sword and eyeing the native fauna
just a
little bit too suspiciously. Fortunately for you however, the guard can't
see
you from behind the bush."
east={ "You rush the guard, and he, in response, casually holds his sword
pointed in your general direction, thus forcibly and successively impaling
and removing somewhat handy vital organs from your abdomen. Despite the
fact
that it kind of goes without saying, you die."; die();}
sw=beach
;

clearing: room
sdesc = "Clearing"
ldesc = "The path that comes from the southwest from here ends abruptly
before a large bush. To the north of it is the clearing in which you
stand.
To the east is the giant facade of a building that you are sure is
stationary
yet somehow manages to look like it's moving. The wall has a small doorway
at its base, through which you could enter. "
in = building
east = building
sw=beach
;

building: room
sdesc = "Building"
ldesc = "The walls here are quite unsettling. Unable to decide on any
particular color or shape,
they twist and bend throughout the spectrum and visible space. There is a
small socket in one wall, which doesn't seem to be moving quite as much.
A doorway leads out, to the west. "
out = self.tessexit
west = self.tessexit
tessexit = {
if (length(socket.contents) >0)
return socket.contents[1].dest;
else
{"An invisible force prevents you from leaving. ";
return(nil);}
}
;

socket: container, fixeditem
sdesc = "socket"
location = building
noun = 'socket'
ioPutIn (actor, dobj) = {
if (length(self.contents) > 0)
{"You can't seem to fit anything else into the socket while ";
self.contents[1].thedesc; " is in there. ";}
else if (isclass(dobj,chip))
{caps(); dobj.thedesc; " fits neatly into the socket. As it slides
into place, you feel a slight sensation of movement. ";
dobj.moveInto(self);}
else {caps(); dobj.thedesc; " doesn't fit into the socket. ";}
}
;

theguard1: fixeditem
sdesc = "guard"
noun = 'guard'
adjective = 'alert'
ldesc = "This guy looks serious... I wouldn't go near him without some
sort
of protection."
location = guard1path
alive = 1
verDoAttackWith( actor, io ) ={}
;

guard2: room
sdesc = "Base of mountains"
ldesc = "You stand at the foot of unclimbable cliffs stretching from
northwest to east, just to the north of which stands an unusually shaped
building. Sleeping slumped the northern rock wall is a guard, evidently
not
doing his job. A path leads west into the forest and a rough cave is
carved
out of the mountains to the northeast."
west=path
ne = cave
in = cave
;

theguard2: fixeditem, searchHider
sdesc = "guard"
noun = 'guard'
adjective = 'sleeping'
ldesc = "You used to think the idea of guarding something was making sure
no-one got near it who wasn't supposed to. Even though you have no idea
what
he is supposed to be guarding, you deduce from his definite lack of
alertness
(not to mention conciousness) that he interpereted the job description
just a
little bit differently."
location = guard2
serialSearch = 1
autoTake=nil
;

cheese: hiddenItem, item, treasure
sdesc = "cheese"
adesc = "some cheese"
ldesc = "Unusually enough, this piece of cheese looks mostly natural, in
contrast to some other cheese-like products that you have seen elsewhere."
noun = 'cheese'
searchLoc=theguard2
;

sword: hiddenItem, item, treasure
sdesc = "sword"
ldesc = "A generic-looking sword. The guard you stole it from didn't
appear
in need of it, so you figured you might as well take it off his hands."
noun = 'sword'
searchLoc=theguard2
verIoAttackWith(actor)={}
ioAttackWith(actor,dobj) = {
if (dobj = theguard1)
{"You rush the guard, and take him by suprise. You thrust the sword into
hus
chest and, instead of dying normally, he disappears in a brilliant flash
of
white light, and with him the sword. You venture out into the now
unguarded
clearing... \n\n\n ";
self.moveInto(nil);
theguard1.moveInto(nil);
theguard1.alive := nil;
Me.moveInto(clearing);
Me.location.lookAround(true);
incscore(5);
}
else
{"I don't think it would be a good idea to attack "; dobj.thedesc; ". ";}
}
;

cave: room
sdesc = "Cave"
ldesc = {
"You are in a rather typically dank and dark cave, with light streaming in
from the exit to the southwest. It reminds you of another one you explored
aeons ago.... a fairly colossal cave, in fact, in contrast to this one.
Just
as your fit of deja vu subsides, you notice hundreds of rats lounging in
the
myriad crevices and pits, and scampering across the rough cave floor. ";

if (rat.location = self)
"To the north you notice a rat-sized hole guarded by a dirty grey rat the
size of your head, who stares expectantly at you.";
else
"To the north you notice a rat-sized hole. ";
}
out = guard2
sw = guard2
;
rat: fixeditem
sdesc = "large rat"
ldesc = "Judging by its general level of apperance and evident health,
this
is probably a direct descendent of the rat that started the black plague.
It
seems hungry."
noun='rat' 'mouse' 'packrat'
adjective='diseased' 'large' 'ugly' 'plague' 'mickey' 'pack'
location = cave
verIoGiveTo ( actor)= {}
ioGiveTo ( actor, dobj) = {
if (dobj = cheese)
{"The rat looks ravenously at the cheese and devours it, leaving behind a
not-so-small puddle of syrupy saliva. It raises its head and front legs
and
stares at you momentarily then dashes off to the little hole, retrieves a
small microchip, and places it at your feet before disappearing into
another
small hole. You realize that this is one damn good packrat. ";
cheese.moveInto(nil);
chip2.moveInto(self.location);
self.moveInto(nil);
incscore(4);}
else
{"The rat doesn't seem to want "; dobj.thedesc; ". ";}
}
;
class chip: item
sdesc = {self.color; " microchip";}
ldesc = {"It looks like something taken right out of a computer; it's a
little "; self.color; " rectangle with pins sticking out on both ends, 8
to a side. On
its surface you can see the letters '"; self.chipname; "' inscribed on it.
";}
noun = 'chip' 'microchip' 'IC'
adjective = 'silicon' 'micro'
chipname = ""
dest = nil
;

chip1: chip
location = socket
color = "red"
adjective = 'red'
chipname = "World1"
dest = clearing
;

chip2: chip, treasure
takevalue = 1
color = "black"
adjective = 'black'
chipname = "World2"
dest = basement
;

basement: room
sdesc = "Basement hallway."
ldesc = {incscore(5); "Congratulations! you figured out how to get off
the island, thus
completing the prologue of this game. Due to the fact that I haven't
written
the rest of it yet, this is the temporary ending."; win();
}
east = building
;

/* here's the treasure class, lifted and modified from ditch day -
which I beat using only _1_ hint, which is quite good for me :) */

class treasure: item
istreasure = true
takevalue = 5
hasScored = nil
doTake( actor ) =
{
if ( not self.hasScored ) // have we scored yet?
{
incscore( self.takevalue ); // add our "takevalue" to the
score
self.hasScored := true; // note that we have scored
}
pass doTake; // continue with the normal doTake from "item"
}
;

---Jason