home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!news.tek.com!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v18i023: ccr - colossal cave (adventure) implemented in TADS, Part08/11
- Date: 12 Jul 1993 19:29:05 GMT
- Organization: Tektronix, Inc, Redmond, OR, USA
- Lines: 1945
- Approved: billr@saab.CNA.TEK.COM
- Message-ID: <21se21$1d1@ying.cna.tek.com>
- NNTP-Posting-Host: saab.cna.tek.com
- Xref: uunet comp.sources.games:1823
-
- Submitted-by: David Baggett <dmb@xbar.ai.mit.edu>
- Posting-number: Volume 18, Issue 23
- Archive-name: ccr/part08
- Environment: TADS
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 8 (of 11)."
- # Contents: src/ccr-adv.t1 src/history.t
- # Wrapped by billr@saab on Mon Jul 12 12:02:44 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/ccr-adv.t1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/ccr-adv.t1'\"
- else
- echo shar: Extracting \"'src/ccr-adv.t1'\" \(55312 characters\)
- sed "s/^X//" >'src/ccr-adv.t1' <<'END_OF_FILE'
- X/* $Header$ */
- X/* Copyright (c) 1988, 1991 by Michael J. Roberts. All Rights Reserved. */
- X/*
- X adv.t - standard adventure definitions for TADS games
- X Version 2.0
- X
- X This file is part of TADS: The Text Adventure Development System.
- X Please see the file LICENSE.DOC (which should be part of the TADS
- X distribution) for information on using this file, and for information
- X on reaching High Energy Software, the developers of TADS.
- X
- X This file defines the basic classes and functions used by most TADS
- X adventure games. It is generally #include'd at the start of each game
- X source file.
- X*/
- X
- X/*
- X * Define compound prepositions. Since prepositions that appear in
- X * parsed sentences must be single words, we must define any logical
- X * prepositions that consist of two or more words here. Note that
- X * only two words can be pasted together at once; to paste more, use
- X * a second step. For example, 'out from under' must be defined in
- X * two steps:
- X *
- X * compoundWord 'out' 'from' 'outfrom';
- X * compoundWord 'outfrom' 'under' 'outfromunder';
- X *
- X * Listed below are the compound prepositions that were built in to
- X * version 1.0 of the TADS run-time.
- X */
- XcompoundWord 'on' 'to' 'onto'; /* on to --> onto */
- XcompoundWord 'in' 'to' 'into'; /* in to --> into */
- XcompoundWord 'in' 'between' 'inbetween'; /* and so forth */
- XcompoundWord 'down' 'in' 'downin';
- XcompoundWord 'down' 'on' 'downon';
- XcompoundWord 'up' 'on' 'upon';
- XcompoundWord 'out' 'of' 'outof';
- XcompoundWord 'off' 'of' 'offof';
- X
- X/*
- X * Format strings: these associate keywords with properties. When
- X * a keyword appears in output between percent signs (%), the matching
- X * property of the current command's actor is evaluated and substituted
- X * for the keyword (and the percent signs). For example, if you have:
- X *
- X * formatstring 'you' fmtYou;
- X *
- X * and the command being processed is:
- X *
- X * fred, pick up the paper
- X *
- X * and the "fred" actor has fmtYou = "he", and this string is output:
- X *
- X * "%You% can't see that here."
- X *
- X * Then the actual output is: "He can't see that here."
- X *
- X * The format strings are chosen to look like normal output (minus the
- X * percent signs, of course) when the actor is Me.
- X */
- Xformatstring 'you' fmtYou;
- Xformatstring 'your' fmtYour;
- Xformatstring 'you\'re' fmtYoure;
- Xformatstring 'youm' fmtYoum;
- Xformatstring 'you\'ve' fmtYouve;
- Xformatstring 's' fmtS;
- Xformatstring 'es' fmtEs;
- Xformatstring 'have' fmtHave;
- Xformatstring 'do' fmtDo;
- Xformatstring 'are' fmtAre;
- X
- X/*
- X * Forward-declare functions. This is not required in most cases,
- X * but it doesn't hurt. Providing these forward declarations ensures
- X * that the compiler knows that we want these symbols to refer to
- X * functions rather than objects.
- X */
- XcheckDoor: function;
- XcheckReach: function;
- Xitemcnt: function;
- Xlistcont: function;
- Xlistcontcont: function;
- Xturncount: function;
- Xaddweight: function;
- Xaddbulk: function;
- Xincscore: function;
- Xsilent_incscore: function; // DMB
- XdarkTravel: function;
- XscoreRank: function;
- Xterminate: function;
- Xdie: function;
- Xinit: function;
- Xpardon: function;
- Xpreinit: function;
- XinitSearch: function;
- X
- X/*
- X * checkDoor: if the door d is open, this function silently returns
- X * the room r. Otherwise, print a message ("The door is closed.") and
- X * return nil.
- X */
- XcheckDoor: function( d, r )
- X{
- X if ( d.isopen ) return( r );
- X else
- X {
- X setit( d );
- X caps(); d.thedesc; " is closed. ";
- X return( nil );
- X }
- X}
- X
- X/*
- X * checkReach: determines whether the object obj can be reached by
- X * actor in location loc, using the verb v. This routine returns true
- X * if obj is a special object (numObj or strObj), if obj is in actor's
- X * inventory or actor's location, or if it's in the 'reachable' list
- X * for loc.
- X */
- XcheckReach: function( loc, actor, v, obj )
- X{
- X if ( obj=numObj or obj=strObj ) return;
- X if ( not ( actor.isCarrying( obj ) or obj.isIn( actor.location )))
- X {
- X if (find( loc.reachable, obj ) <> nil ) return;
- X "%You% can't reach "; obj.thedesc; " from "; loc.thedesc; ". ";
- X exit;
- X }
- X}
- X
- X/*
- X@itemcnt: function( list )
- XReturns a count of the ``listable'' objects in \it list\. An
- Xobject is listable (that is, it shows up in a room's description)
- Xif its \tt isListed\ property is \tt true\. This function is
- Xuseful for determining how many objects (if any) will be listed
- Xin a room's description.
- X*/
- Xitemcnt: function( list )
- X{
- X local cnt, tot, i;
- X tot := length( list );
- X cnt := 0;
- X i := 1;
- X while ( i <= tot )
- X {
- X if ( list[i].isListed ) cnt := cnt+1;
- X i := i+1;
- X }
- X return( cnt );
- X}
- X
- X/*
- X@listcont: function( obj )
- XThis function displays the contents of an object, separated by
- Xcommas. The \tt thedesc\ properties of the contents are used.
- XIt is up to the caller to provide the introduction to the list
- X(usually something to the effect of ``The box contains'' is
- Xdisplayed before calling \tt listcont\) and finishing the
- Xsentence (usually by displaying a period). An object is listed
- Xonly if its \tt isListed\ property is \tt true\.
- X*/
- Xlistcont: function( obj )
- X{
- X local i, count, tot, list, cur, disptot;
- X count := 0;
- X list := obj.contents;
- X tot := length( list );
- X disptot := itemcnt( list );
- X i := 1;
- X while ( i <= tot )
- X {
- X cur := list[i];
- X if ( cur.isListed )
- X {
- X if ( count > 0 )
- X {
- X if ( count+1 < disptot )
- X ", ";
- X else if (count = 1)
- X " and ";
- X else
- X ", and ";
- X }
- X count := count + 1;
- X cur.adesc; // list this object
- X if ( cur.isworn ) " (being worn)";
- X else if ( cur.islamp and cur.islit ) " (providing light)";
- X }
- X i := i + 1;
- X }
- X}
- X
- X/*
- X * showcontcont: list the contents of the object, plus the contents of
- X * an fixeditem's contained by the object. A complete sentence is shown.
- X * This is an internal routine used by listcontcont and listfixedcontcont.
- X */
- X// DMB added print param and return value
- Xshowcontcont: function(obj, print)
- X{
- X local cnt := 0;
- X
- X if (itemcnt( obj.contents ))
- X {
- X if ( obj.issurface and not obj.isqsurface )
- X {
- X cnt := cnt + itemcnt(obj.contents);
- X if (print) {
- X if (cnt > 1) { // DMB added this check
- X caps(); listcont(obj);
- X " are sitting on "; obj.thedesc; ". ";
- X }
- X else {
- X caps(); listcont(obj); " is sitting on ";
- X obj.thedesc; ". ";
- X }
- X }
- X }
- X else if ( obj.contentsVisible and not obj.isqcontainer )
- X {
- X cnt := cnt + itemcnt(obj.contents);
- X if (print) {
- X caps();
- X obj.thedesc; " seems to contain ";
- X listcont( obj );
- X ". ";
- X }
- X }
- X }
- X if ( obj.contentsVisible and not obj.isqcontainer )
- X cnt := cnt + listfixedcontcont(obj, print);
- X
- X return cnt;
- X}
- X
- X/*
- X@listfixedcontcont: function( obj )
- XList the contents of the contents of any \tt fixeditem\ objects
- Xin the \tt contents\ list of the object \it obj\. This routine
- Xmakes sure that all objects that can be taken are listed somewhere
- Xin a room's description. This routine recurses down the contents
- Xtree, following each branch until either something has been listed
- Xor the branch ends without anything being listable. This routine
- Xdisplays a complete sentence, so no introductory or closing text
- Xis needed.
- X*/
- X// DMB added print param and return value
- Xlistfixedcontcont: function(obj, print)
- X{
- X local list, i, tot, thisobj;
- X local cnt := 0;
- X
- X list := obj.contents;
- X tot := length( list );
- X i := 1;
- X while ( i <= tot )
- X {
- X thisobj := list[i];
- X if ( thisobj.isfixed and thisobj.contentsVisible and
- X not thisobj.isqcontainer )
- X cnt := cnt + showcontcont(thisobj, print);
- X i := i + 1;
- X }
- X return cnt;
- X}
- X
- X/*
- X@listcontcont: function( obj )
- XThis function lists the contents of the contents of an object.
- XIt displays full sentences, so no introductory or closing text
- Xis required. Any item in the \tt contents\ list of the object
- X\it obj\ whose \tt contentsVisible\ property is \tt true\ has
- Xits contents listed. An Object whose \tt isqcontainer\ or
- X\tt isqsurface\ property is \tt true\ will not have its
- Xcontents listed.
- X*/
- X// DMB added print parameter and return value
- Xlistcontcont: function(obj, print)
- X{
- X local list, i, tot;
- X local cnt := 0;
- X
- X list := obj.contents;
- X tot := length( list );
- X i := 1;
- X while ( i <= tot )
- X {
- X cnt := cnt + showcontcont(list[i], print);
- X i := i + 1;
- X }
- X return cnt;
- X}
- X
- X/*
- X@turncount: function( parm )
- XThis function can be used as a daemon (normally set up in the \tt init\
- Xfunction) to update the turn counter after each turn. This routine
- Xincrements \tt global.turnsofar\, and then calls \tt setscore\ to
- Xupdate the status line with the new turn count.
- X*/
- Xturncount: function( parm )
- X{
- X incturn();
- X global.turnsofar := global.turnsofar + 1;
- X setscore( global.score, global.turnsofar );
- X}
- X
- X/*
- X@addweight: function( list )
- XAdds the weights of the objects in \it list\ and returns the sum.
- XThe weight of an object is given by its \tt weight\ property. This
- Xroutine includes the weights of all of the contents of each object,
- Xand the weights of their contents, and so forth.
- X*/
- Xaddweight: function( l )
- X{
- X local tot, i, c, totweight;
- X
- X tot := length( l );
- X i := 1;
- X totweight := 0;
- X while ( i <= tot )
- X {
- X c := l[i];
- X totweight := totweight + c.weight;
- X if (length( c.contents ))
- X totweight := totweight + addweight( c.contents );
- X i := i + 1;
- X }
- X return( totweight );
- X}
- X
- X/*
- X@addbulk: function( list )
- XThis function returns the sum of the bulks (given by the \tt bulk\
- Xproperty) of each object in \it list\. The value returned includes
- Xonly the bulk of each object in the list, and \it not\ of the contents
- Xof the objects, as it is assumed that an object does not change in
- Xsize when something is put inside it. You can easily change this
- Xassumption for special objects (such as a bag that stretches as
- Xthings are put inside) by writing an appropriate \tt bulk\ method
- Xfor that object.
- X*/
- Xaddbulk: function( list )
- X{
- X local i, tot, totbulk, rem, cur;
- X
- X tot := length( list );
- X i := 1;
- X totbulk := 0;
- X while( i <= tot )
- X {
- X cur := list[i];
- X if ( not cur.isworn )
- X totbulk := totbulk + cur.bulk;
- X i := i + 1;
- X }
- X return( totbulk );
- X}
- X
- X/*
- X@incscore: function( amount )
- XAdds \it amount\ to the total score, and updates the status line
- Xto reflect the new score. The total score is kept in \tt global.score\.
- XAlways use this routine rather than changing \tt global.score\
- Xdirectly, since this routine ensures that the status line is
- Xupdated with the new value.
- X*/
- Xincscore: function( amount ) /* DMB */
- X{
- X silent_incscore(amount);
- X
- X "\b";
- X if (amount = -1)
- X "* Your score just went down by a point. *";
- X else if (amount = 1)
- X "* Your score just went up by a point. *";
- X else if (amount < -1) {
- X "* Your score just went down by ";
- X say(-1 * amount); " points. *";
- X }
- X else if (amount > 1) {
- X "* Your score just went up by "; say(amount); " points. *";
- X }
- X "\b";
- X}
- X// DMB: added the following:
- Xsilent_incscore: function( amount )
- X{
- X global.score := global.score + amount;
- X setscore( global.score, global.turnsofar );
- X}
- X
- X/*
- X@initSearch: function
- XInitializes the containers of objects with a \tt searchLoc\, \tt underLoc\,
- Xand \tt behindLoc\ by setting up \tt searchCont\, \tt underCont\, and
- X\tt behindCont\ lists, respectively. You should call this function once in
- Xyour \tt preinit\ (or \tt init\, if you prefer) function to ensure that
- Xthe underable, behindable, and searchable objects are set up correctly.
- X*/
- XinitSearch: function
- X{
- X local o;
- X
- X o := firstobj(hiddenItem);
- X while (o <> nil)
- X {
- X if (o.searchLoc)
- X o.searchLoc.searchCont := o.searchLoc.searchCont + o;
- X else if (o.underLoc)
- X o.underLoc.underCont := o.underLoc.underCont + o;
- X else if (o.behindLoc)
- X o.behindLoc.behindCont := o.behindLoc.behindCont + o;
- X o := nextobj(o, hiddenItem);
- X }
- X}
- X
- X/*
- X@nestedroom: room
- XA special kind of room that is inside another room; chairs and
- Xsome types of vehicles, such as inflatable rafts, fall into this
- Xcategory. Note that a room can be within another room without
- Xbeing a \tt nestedroom\, simply by setting its \tt location\ property
- Xto another room. The \tt nestedroom\ is different from an ordinary
- Xroom, though, in that it's an ``open'' room; that is, when inside it,
- Xthe actor is still really inside the enclosing room for purposes of
- Xdescriptions. Hence, the player sees ``Laboratory, in the chair."
- XIn addition, a \tt nestedroom\ is an object in its own right,
- Xvisible to the player; for example, a chair is an object in a
- Xroom in addition to being a room itself.
- X*/
- Xclass nestedroom: NoNPC // DMB room -> NoNPC for CCR
- X islit =
- X {
- X if ( self.location ) return( self.location.islit );
- X return( nil );
- X }
- X statusLine = {
- X /* DMB onword */
- X self.location.sdesc; ", ";
- X self.onword; " ";
- X self.thedesc; "\n\t";
- X }
- X lookAround( verbosity ) =
- X {
- X self.statusLine;
- X self.location.nrmLkAround( verbosity );
- X }
- X roomDrop( obj ) =
- X {
- X if ( self.location = nil or self.isdroploc ) pass roomDrop;
- X else self.location.roomDrop( obj );
- X }
- X;
- X
- X/*
- X@chairitem: fixeditem, nestedroom, surface
- XActs like a chair: actors can sit on the object. While sitting
- Xon the object, an actor can't go anywhere until standing up, and
- Xcan only reach objects that are on the chair and in the chair's
- X\tt reachable\ list. By default, nothing is in the \tt reachable\
- Xlist. Note that there is no real distinction made between chairs
- Xand beds, so you can sit or lie on either; the only difference is
- Xthe message displayed describing the situation.
- X*/
- Xclass chairitem: fixeditem, nestedroom, surface
- X /* DMB onroom */
- X onword = { if (self.onroom) "on"; else "in"; }
- X offword = { if (self.onroom) "off"; else "out"; }
- X
- X reachable = [] // list of all containers reachable from here;
- X // normally, you can only reach carried items
- X // from a chair, but this makes special allowances
- X ischair = true // it is a chair by default; for beds or other
- X // things you lie down on, make it false
- X roomAction( actor, v, dobj, prep, io ) =
- X {
- X if ( dobj<>nil and v<>inspectVerb )
- X checkReach( self, actor, v, dobj );
- X if ( io<>nil and v<>askVerb and v<>tellVerb )
- X checkReach( self, actor, v, io );
- X pass roomAction;
- X }
- X enterRoom( actor ) = {}
- X noexit =
- X {
- X "%You're% not going anywhere until %you% get%s% ";
- X self.offword; " of"; self.thedesc; ". ";
- X return( nil );
- X }
- X verDoBoard( actor ) = { self.verDoSiton( actor ); }
- X doBoard( actor ) = { self.doSiton( actor ); }
- X verDoSiton( actor ) =
- X {
- X if ( actor.location = self )
- X {
- X "%You're% already "; self.onword; " ";
- X self.thedesc; "! ";
- X }
- X }
- X doSiton( actor ) =
- X {
- X "Okay, %you're% now sitting "; self.onword; " "; self.thedesc; ". ";
- X actor.travelTo( self );
- X }
- X verDoLieon( actor ) =
- X {
- X self.verDoSiton( actor );
- X }
- X doLieon( actor ) =
- X {
- X // DMB changed so it says "lying"
- X "Okay, %you're% now lying "; self.onword; " "; self.thedesc; ". ";
- X actor.travelTo(self);
- X }
- X // DMB: added the following:
- X doUnboard( actor ) =
- X {
- X if ( self.fastenitem )
- X {
- X "%You%'ll have to unfasten "; actor.location.fastenitem.thedesc;
- X " first. ";
- X }
- X else
- X {
- X "Okay, %you're% no longer "; self.onword; " "; self.thedesc; ". ";
- X self.leaveRoom( actor );
- X actor.moveInto( self.location );
- X }
- X }
- X;
- X
- X/*
- X@beditem: chairitem
- XThis object is the same as a \tt chairitem\, except that the player
- Xis described as lying on, rather than sitting in, the object.
- X*/
- Xclass beditem: chairitem
- X onroom = true
- X ischair = nil
- X isbed = true
- X sdesc = "bed"
- X;
- X
- X/*
- X@thing: object
- XThe basic class for objects in a game. The property \tt contents\
- Xis a list that specifies what is in the object; this property is
- Xautomatically set up by the system after the game is compiled to
- Xcontain a list of all objects that have this object as their
- X\tt location\ property. The \tt contents\ property is kept
- Xconsistent with the \tt location\ properties of referenced objects
- Xby the \tt moveInto\ method; always use \tt moveInto\ rather than
- Xdirectly setting a \tt location\ property for this reason. The
- X\tt adesc\ method displays the name of the object with an indefinite
- Xarticle; the default is to display ``a'' followed by the \tt sdesc\,
- Xbut objects that need a different indefinite article (such as ``an''
- Xor ``some'') should override this method. Likewise, \tt thedesc\
- Xdisplays the name with a definite article; by default, \tt thedesc\
- Xdisplays ``the'' followed by the object's \tt sdesc\. The \tt sdesc\
- Xsimply displays the object's name (``short description'') without
- Xany articles. The \tt ldesc\ is the long description, normally
- Xdisplayed when the object is examined by the player; by default,
- Xthe \tt ldesc\ displays a ``It looks like an ordinary \tt sdesc\.''
- XThe \tt isIn( \it object\ )\ method returns \tt true\ if the
- Xobject's location is the specified \it object\ or the object's
- X\tt location\ is an object whose \tt contentsVisible\ property is
- X\tt true\ and that object's \tt isIn( \it object\ )\ method is
- X\tt true\. Note that if \tt isIn\ is \tt true\, it doesn't
- Xnecessarily mean the object is reachable, because \tt isIn\ is
- X\tt true\ if the object is merely visible within the location.
- XThe \tt thrudesc\ method displays a message for when the
- Xplayer looks through the object (objects such as windows would
- Xuse this property). The \tt moveInto( \it object\ )\ method
- Xmoves the object to be inside the specified \it object\; always use
- X\tt moveInto\ to move an object rather than setting its \tt location\
- Xdirectly, so that the appropriate \tt contents\ lists are updated.
- XTo make an object disappear, move it into \tt nil\.
- X*/
- Xclass thing: object
- X isListed = true // shows up in room/inventory listings
- X contents = [] // set up automatically by system - do not set
- X verGrab( obj ) = {}
- X Grab( obj ) = {}
- X adesc =
- X {
- X "a "; self.sdesc; // default is "a <name>"; "self" is current object
- X }
- X thedesc =
- X {
- X "the "; self.sdesc; // default is "the <name>"
- X }
- X ldesc = { "It looks like an ordinary "; self.sdesc; " to me."; }
- X readdesc = { "%You% can't read "; self.adesc; ". "; }
- X actorAction( v, d, p, i ) =
- X {
- X "You have lost your mind. ";
- X exit;
- X }
- X contentsVisible = { return( true ); }
- X contentsReachable = { return( true ); }
- X isIn( obj ) =
- X {
- X local myloc;
- X
- X myloc := self.location;
- X if ( myloc )
- X {
- X if ( myloc = obj ) return( true );
- X if ( myloc.contentsVisible ) return( myloc.isIn( obj ));
- X }
- X return( nil );
- X }
- X thrudesc = { "%You% can't see much through "; self.thedesc; ".\n"; }
- X moveInto( obj ) =
- X {
- X local loc;
- X
- X /*
- X * For the object containing me, and its container, and so forth,
- X * tell it via a Grab message that I'm going away.
- X */
- X loc := self.location;
- X while ( loc )
- X {
- X loc.Grab( self );
- X loc := loc.location;
- X }
- X
- X if ( self.location )
- X self.location.contents := self.location.contents - self;
- X self.location := obj;
- X if ( obj ) obj.contents := obj.contents + self;
- X }
- X verDoSave( actor ) =
- X {
- X "Please specify the name of the game to save in double quotes,
- X for example, SAVE \"GAME1\". ";
- X }
- X verDoRestore( actor ) =
- X {
- X "Please specify the name of the game to restore in double quotes,
- X for example, SAVE \"GAME1\". ";
- X }
- X verDoScript( actor ) =
- X {
- X "You should type the name of a file to write the transcript to
- X in quotes, for example, SCRIPT \"LOG1\". ";
- X }
- X verDoSay( actor ) =
- X {
- X "You should say what you want to say in double quotes, for example,
- X SAY \"HELLO\". ";
- X }
- X verDoPush( actor ) =
- X {
- X "Pushing "; self.thedesc; " doesn't do anything. ";
- X }
- X verDoWear( actor ) =
- X {
- X "%You% can't wear "; self.thedesc; ". ";
- X }
- X verDoTake( actor ) =
- X {
- X if ( self.location = actor )
- X {
- X "%You% already %have% "; self.thedesc; "! ";
- X }
- X else self.verifyRemove( actor );
- X }
- X verifyRemove( actor ) =
- X {
- X /*
- X * Check with each container to make sure that the container
- X * doesn't object to the object's removal.
- X */
- X local loc;
- X
- X loc := self.location;
- X while ( loc )
- X {
- X if ( loc <> actor ) loc.verGrab( self );
- X loc := loc.location;
- X }
- X }
- X isVisible( vantage ) =
- X {
- X local loc;
- X
- X loc := self.location;
- X if ( loc = nil ) return( nil );
- X
- X /* if it's in the vantage, it's visible */
- X if ( loc = vantage ) return( true );
- X
- X /*
- X * if its location's contents are visible, and its location is
- X * itself visible, it's visible
- X */
- X if ( loc.contentsVisible and loc.isVisible( vantage )) return( true );
- X
- X /*
- X * If the vantage has a location, and the vantage's location's
- X * contents are visible (if you can see me I can see you), and
- X * the object is visible from the vantage's location, the object
- X * is visible
- X */
- X if ( vantage.location <> nil and vantage.location.contentsVisible and
- X self.isVisible( vantage.location ))
- X return( true );
- X
- X /* all tests failed: it's not visible */
- X return( nil );
- X }
- X cantReach( actor ) =
- X {
- X if ( self.location = nil )
- X {
- X if ( actor.location.location )
- X "%You% can't reach that from << actor.location.thedesc >>. ";
- X return;
- X }
- X if ( not self.location.isopenable or self.location.isopen )
- X self.location.cantReach( actor );
- X else "%You%'ll have to open << self.location.thedesc >> first. ";
- X }
- X isReachable( actor ) =
- X {
- X local loc;
- X
- X /* if the object is in the room's 'reachable' list, it's reachable */
- X if (find( actor.location.reachable, self ) <> nil )
- X return( true );
- X
- X /*
- X * If the object's container's contents are reachable, and the
- X * container is reachable, the object is reachable.
- X */
- X loc := self.location;
- X if (find( actor.location.reachable, self ) <> nil )
- X return( true );
- X if ( loc = nil ) return( nil );
- X if ( loc = actor or loc = actor.location ) return( true );
- X if ( loc.contentsReachable )
- X return( loc.isReachable( actor ));
- X return( nil );
- X return( nil );
- X }
- X doTake( actor ) =
- X {
- X local totbulk, totweight;
- X
- X totbulk := addbulk( actor.contents ) + self.bulk;
- X totweight := addweight( actor.contents );
- X if ( not actor.isCarrying( self ))
- X totweight := totweight + self.weight;
- X
- X if ( totweight > actor.maxweight )
- X "%Your% load is too heavy. ";
- X else if ( totbulk > actor.maxbulk )
- X "%You've% already got %your% hands full. ";
- X else
- X {
- X self.moveInto( actor );
- X "Taken. ";
- X }
- X }
- X verDoDrop( actor ) =
- X {
- X if ( not actor.isCarrying( self ))
- X {
- X "%You're% not carrying "; self.thedesc; "! ";
- X }
- X else self.verifyRemove( actor );
- X }
- X doDrop( actor ) =
- X {
- X actor.location.roomDrop( self );
- X }
- X verDoUnwear( actor ) =
- X {
- X "%You're% not wearing "; self.thedesc; "! ";
- X }
- X verIoPutIn( actor ) =
- X {
- X "I don't know how to put anything into "; self.thedesc; ". ";
- X }
- X verDoPutIn( actor, io ) =
- X {
- X if ( io = nil ) return;
- X
- X if ( self.location = io )
- X {
- X caps(); self.thedesc; " is already in "; io.thedesc; "! ";
- X }
- X else if ( io = self or io.isIn( self ))
- X {
- X "%You% can't put "; self.thedesc; " in itself! ";
- X }
- X else self.verifyRemove( actor );
- X }
- X doPutIn( actor, io ) =
- X {
- X self.moveInto( io );
- X "Done. ";
- X }
- X verIoPutOn( actor ) =
- X {
- X "There's no good surface on "; self.thedesc; ". ";
- X }
- X verDoPutOn( actor, io ) =
- X {
- X if ( io = nil ) return;
- X
- X if ( self.location = io )
- X {
- X caps(); self.thedesc; " is already on "; io.thedesc; "! ";
- X }
- X else if ( io = self or io.isIn( self ))
- X {
- X "%You% can't put "; self.thedesc; " on itself! ";
- X }
- X else self.verifyRemove( actor );
- X }
- X doPutOn( actor, io ) =
- X {
- X self.moveInto( io );
- X "Done. ";
- X }
- X verIoTakeOut( actor ) = {}
- X ioTakeOut( actor, dobj ) =
- X {
- X dobj.doTakeOut( actor, self );
- X }
- X verDoTakeOut( actor, io ) =
- X {
- X if ( io <> nil and not self.isIn( io ))
- X {
- X caps(); self.thedesc; " isn't in "; io.thedesc; ". ";
- X }
- X self.verDoTake(actor); /* ensure object can be taken at all */
- X }
- X doTakeOut( actor, io ) =
- X {
- X self.doTake( actor );
- X }
- X verIoTakeOff( actor ) = {}
- X ioTakeOff( actor, dobj ) =
- X {
- X dobj.doTakeOff( actor, self );
- X }
- X verDoTakeOff( actor, io ) =
- X {
- X if ( io <> nil and not self.isIn( io ))
- X {
- X caps(); self.thedesc; " isn't on "; io.thedesc; "! ";
- X }
- X self.verDoTake(actor); /* ensure object can be taken at all */
- X }
- X doTakeOff( actor, io ) =
- X {
- X self.doTake( actor );
- X }
- X verIoPlugIn( actor ) =
- X {
- X "%You% can't plug anything into "; self.thedesc; ". ";
- X }
- X verDoPlugIn( actor, io ) =
- X {
- X "%You% can't plug "; self.thedesc; " into anything. ";
- X }
- X verIoUnplugFrom( actor ) =
- X {
- X "It's not plugged into "; self.thedesc; ". ";
- X }
- X verDoUnplugFrom( actor, io ) =
- X {
- X if ( io <> nil ) { "It's not plugged into "; io.thedesc; ". "; }
- X }
- X verDoLookin( actor ) =
- X {
- X "There's nothing in "; self.thedesc; ". ";
- X }
- X verDoLookthru( actor ) =
- X {
- X "%You% can't see anything through "; self.thedesc; ". ";
- X }
- X verDoLookunder( actor ) =
- X {
- X "There's nothing under "; self.thedesc; ". ";
- X }
- X verDoInspect( actor ) = {}
- X doInspect( actor ) =
- X {
- X self.ldesc;
- X }
- X verDoRead( actor ) =
- X {
- X "I don't know how to read "; self.thedesc; ". ";
- X }
- X verDoLookbehind( actor ) =
- X {
- X "There's nothing behind "; self.thedesc; ". ";
- X }
- X verDoTurn( actor ) =
- X {
- X "Turning "; self.thedesc; " doesn't have any effect. ";
- X }
- X verDoTurnWith( actor, io ) =
- X {
- X "Turning "; self.thedesc; " doesn't have any effect. ";
- X }
- X verDoTurnTo( actor, io ) =
- X {
- X "Turning "; self.thedesc; " doesn't have any effect. ";
- X }
- X verIoTurnTo( actor ) =
- X {
- X "I don't know how to do that. ";
- X }
- X verDoTurnon( actor ) =
- X {
- X "I don't know how to turn "; self.thedesc; " on. ";
- X }
- X verDoTurnoff( actor ) =
- X {
- X "I don't know how to turn "; self.thedesc; " off. ";
- X }
- X verIoAskAbout( actor ) = {}
- X ioAskAbout( actor, dobj ) =
- X {
- X dobj.doAskAbout( actor, self );
- X }
- X verDoAskAbout( actor, io ) =
- X {
- X "Surely, %you% can't think "; self.thedesc; " knows anything
- X about it! ";
- X }
- X verIoTellAbout( actor ) = {}
- X ioTellAbout( actor, dobj ) =
- X {
- X dobj.doTellAbout( actor, self );
- X }
- X verDoTellAbout( actor, io ) =
- X {
- X "It doesn't look as though "; self.thedesc; " is interested. ";
- X }
- X verDoUnboard( actor ) =
- X {
- X if ( actor.location <> self )
- X {
- X "%You're% not in "; self.thedesc; "! ";
- X }
- X else if ( self.location=nil )
- X {
- X "%You% can't get out of "; self.thedesc; "! ";
- X }
- X }
- X doUnboard( actor ) =
- X {
- X if ( self.fastenitem )
- X {
- X "%You%'ll have to unfasten "; actor.location.fastenitem.thedesc;
- X " first. ";
- X }
- X else
- X {
- X "Okay, %you're% no longer in "; self.thedesc; ". ";
- X self.leaveRoom( actor );
- X actor.moveInto( self.location );
- X }
- X }
- X verDoAttackWith( actor, io ) =
- X {
- X "Attacking "; self.thedesc; " doesn't appear productive. ";
- X }
- X verIoAttackWith( actor ) =
- X {
- X "It's not very effective to attack with "; self.thedesc; ". ";
- X }
- X verDoEat( actor ) =
- X {
- X "I think I just lost my appetite."; // DMB
- X }
- X verDoDrink( actor ) =
- X {
- X "Don't be ridiculous!"; // DMB
- X }
- X verDoGiveTo( actor, io ) =
- X {
- X if ( not actor.isCarrying( self ))
- X {
- X "%You're% not carrying "; self.thedesc; ". ";
- X }
- X else self.verifyRemove( actor );
- X }
- X doGiveTo( actor, io ) =
- X {
- X self.moveInto( io );
- X "Done. ";
- X }
- X verDoPull( actor ) =
- X {
- X "Pulling "; self.thedesc; " doesn't have any effect. ";
- X }
- X verDoThrowAt( actor, io ) =
- X {
- X if ( not actor.isCarrying( self ))
- X {
- X "%You're% not carrying "; self.thedesc; ". ";
- X }
- X else self.verifyRemove( actor );
- X }
- X doThrowAt( actor, io ) =
- X {
- X "%You% miss%es%. ";
- X self.moveInto( actor.location );
- X }
- X verIoThrowAt( actor ) =
- X {
- X if ( actor.isCarrying( self ))
- X {
- X "%You% could at least drop "; self.thedesc; " first. ";
- X }
- X }
- X ioThrowAt( actor, dobj ) =
- X {
- X dobj.doThrowAt( actor, self );
- X }
- X verDoThrowTo( actor, io ) =
- X {
- X if ( not actor.isCarrying( self ))
- X {
- X "%You're% not carrying "; self.thedesc; ". ";
- X }
- X else self.verifyRemove( actor );
- X }
- X doThrowTo( actor, io ) =
- X {
- X "%You% miss%es%. ";
- X self.moveInto( actor.location );
- X }
- X verDoThrow( actor ) =
- X {
- X if ( not actor.isCarrying( self ))
- X {
- X "%You're% not carrying "; self.thedesc; ". ";
- X }
- X else self.verifyRemove( actor );
- X }
- X doThrow( actor ) =
- X {
- X "Thrown. ";
- X self.moveInto( actor.location );
- X }
- X verDoShowTo( actor, io ) =
- X {
- X }
- X doShowTo( actor, io ) =
- X {
- X if ( io <> nil ) { caps(); io.thedesc; " isn't impressed. "; }
- X }
- X verIoShowTo( actor ) =
- X {
- X caps(); self.thedesc; " isn't impressed. ";
- X }
- X verDoClean( actor ) =
- X {
- X caps(); self.thedesc; " looks a bit cleaner now. ";
- X }
- X verDoCleanWith( actor, io ) = {}
- X doCleanWith( actor, io ) =
- X {
- X caps(); self.thedesc; " looks a bit cleaner now. ";
- X }
- X verDoMove( actor ) =
- X {
- X "Moving "; self.thedesc; " doesn't reveal anything. ";
- X }
- X verDoMoveTo( actor, io ) =
- X {
- X "Moving "; self.thedesc; " doesn't reveal anything. ";
- X }
- X verIoMoveTo( actor ) =
- X {
- X "That doesn't get us anywhere. ";
- X }
- X verDoMoveWith( actor, io ) =
- X {
- X "Moving "; self.thedesc; " doesn't reveal anything. ";
- X }
- X verIoMoveWith( actor ) =
- X {
- X caps(); self.thedesc; " doesn't seem to help. ";
- X }
- X verDoTypeOn( actor, io ) =
- X {
- X "You should say what you want to type in double quotes, for
- X example, TYPE \"HELLO\" ON KEYBOARD. ";
- X }
- X verDoTouch( actor ) =
- X {
- X "Touching "; self.thedesc; " doesn't seem to have any effect. ";
- X }
- X verDoPoke( actor ) =
- X {
- X "Poking "; self.thedesc; " doesn't seem to have any effect. ";
- X }
- X genMoveDir = { "%You% can't seem to do that. "; }
- X verDoMoveN( actor ) = { self.genMoveDir; }
- X verDoMoveS( actor ) = { self.genMoveDir; }
- X verDoMoveE( actor ) = { self.genMoveDir; }
- X verDoMoveW( actor ) = { self.genMoveDir; }
- X verDoMoveNE( actor ) = { self.genMoveDir; }
- X verDoMoveNW( actor ) = { self.genMoveDir; }
- X verDoMoveSE( actor ) = { self.genMoveDir; }
- X verDoMoveSW( actor ) = { self.genMoveDir; }
- X verDoSearch( actor ) =
- X {
- X "%You% find%s% nothing of interest. ";
- X }
- X
- X#include "thingext.t" // DMB: include extensions to standard thing class
- X;
- X
- X/*
- X@item: thing
- XA basic item which can be picked up by the player. It has no weight
- X(0) and minimal bulk (1). The \tt weight\ property should be set
- Xto a non-zero value for heavy objects. The \tt bulk\ property
- Xshould be set to a value greater than 1 for bulky objects, and to
- Xzero for objects that are very small and take essentially no effort
- Xto hold---or, more precisely, don't detract at all from the player's
- Xability to hold other objects (for example, a piece of paper).
- X*/
- Xclass item: thing
- X weight = 0
- X bulk = 1
- X;
- X
- X/*
- X@lightsource: item
- XA portable lamp, candle, match, or other source of light. The
- Xlight source can be turned on and off with the \tt islit\ property.
- XIf \tt islit\ is \tt true\, the object provides light, otherwise it's
- Xjust an ordinary object.
- X*/
- Xclass lightsource: item
- X islamp = true
- X;
- X
- X/*
- X@hiddenItem: object
- XThis is an object that is hidden with one of the \tt hider\ classes.
- XA \tt hiddenItem\ object doesn't have any special properties in its
- Xown right, but all objects hidden with one of the \tt hider\ classes
- Xmust be of class \tt hiddenItem\ so that \tt initSearch\ can find
- Xthem.
- X*/
- Xclass hiddenItem: object
- X;
- X
- X/*
- X@hider: item
- XThis is a basic class of object that can hide other objects in various
- Xways. The \tt underHider\, \tt behindHider\, and \tt searchHider\ classes
- Xare examples of \tt hider\ subclasses. The class defines
- Xthe method \tt searchObj(\it actor, list\)\, which is given the list
- Xof hidden items contained in the object (for example, this would be the
- X\tt underCont\ property, in the case of a \tt underHider\), and ``finds''
- Xthe object or objects. Its action is dependent upon a couple of other
- Xproperties of the \tt hider\ object. The \tt serialSearch\ property,
- Xif \tt true\, indicates that items in the list are to be found one at
- Xa time; if \tt nil\ (the default), the entire list is found on the
- Xfirst try. The \tt autoTake\ property, if \tt true\, indicates that
- Xthe actor automatically takes the item or items found; if \tt nil\, the
- Xitem or items are moved to the actor's location. The \tt searchObj\ method
- Xreturns the \it list\ with the found object or objects removed; the
- Xcaller should assign this returned value back to the appropriate
- Xproperty (for example, \tt underHider\ will assign the return value
- Xto \tt underCont\).
- X
- XNote that because the \tt hider\ is hiding something, this class
- Xoverrides the normal \tt verDoSearch\ method to display the
- Xmessage, ``You'll have to be more specific about how you want
- Xto search that.'' The reason is that the normal \tt verDoSearch\
- Xmessage (``You find nothing of interest'') leads players to believe
- Xthat the object was exhaustively searched, and we want to avoid
- Xmisleading the player. On the other hand, we don't want a general
- Xsearch to be exhaustive for most \tt hider\ objects. So, we just
- Xdisplay a message letting the player know that the search was not
- Xenough, but we don't give away what they have to do instead.
- X
- XThe objects hidden with one of the \tt hider\ classes must be
- Xof class \tt hiddenItem\.
- X*/
- Xclass hider: item
- X verDoSearch(actor) =
- X {
- X "%You%'ll have to be more specific about how %you% want%s%
- X to search that. ";
- X }
- X searchObj(actor, list) =
- X {
- X local found, dest, i, tot;
- X
- X /* see how much we get this time */
- X if (self.serialSearch)
- X {
- X found := [] + car(list);
- X list := cdr(list);
- X }
- X else
- X {
- X found := list;
- X list := nil;
- X }
- X
- X /* figure destination */
- X dest := actor;
- X if (not self.autoTake) dest := dest.location;
- X
- X /* note what we found, and move it to destination */
- X "%You% find%s% ";
- X tot := length(found);
- X i := 1;
- X while (i <= tot)
- X {
- X found[i].adesc;
- X if (i+1 < tot) ", ";
- X else if (i = 1 and tot = 2) " and ";
- X else if (i+1 = tot and tot > 2) ", and ";
- X
- X found[i].moveInto(dest);
- X i := i + 1;
- X }
- X
- X /* say what happened */
- X if (self.autoTake) ", which %you% take%s%. ";
- X else "! ";
- X
- X if (list<>nil and length(list)=0) list := nil;
- X return(list);
- X }
- X serialSearch = nil /* find everything in one try by default */
- X autoTake = true /* actor takes item when found by default */
- X;
- X
- X/*
- X@underHider: hider
- XThis is an object that can have other objects placed under it. The
- Xobjects placed under it can only be found by looking under the object;
- Xsee the description of \tt hider\ for more information. Note that you
- Xshould set the \tt underLoc\ property of each hidden object to point
- Xto the \tt underHider\.
- X
- XNote that an \tt underHider\ doesn't allow the \it player\ to put anything
- Xunder the object during the game. Instead, it's to make it easy for the
- Xgame writer to set up hidden objects while implementing the game. All you
- Xneed to do to place an object under another object is declare the top
- Xobject as an \tt underHider\, then declare the hidden object normally,
- Xexcept use \tt underLoc\ rather than \tt location\ to specify the
- Xlocation of the hidden object. The \tt behindHider\ and \tt searchHider\
- Xobjects work similarly.
- X
- XThe objects hidden with \tt underHider\ must be of class \tt hiddenItem\.
- X*/
- Xclass underHider: hider
- X underCont = [] /* list of items under me (set up by initSearch) */
- X verDoLookunder(actor) = {}
- X doLookunder(actor) =
- X {
- X if (self.underCont = nil)
- X "There's nothing else under <<self.thedesc>>. ";
- X else
- X self.underCont := self.searchObj(actor, self.underCont);
- X }
- X;
- X
- X/*
- X@behindHider: hider
- XThis is just like an \tt underHider\, except that objects are hidden
- Xbehind this object. Objects to be behind this object should have their
- X\tt behindLoc\ property set to point to this object.
- X
- XThe objects hidden with \tt behindHider\ must be of class \tt hiddenItem\.
- X*/
- Xclass behindHider: hider
- X behindCont = []
- X verDoLookbehind(actor) = {}
- X doLookbehind(actor) =
- X {
- X if (self.behindCont = nil)
- X "There's nothing else behind <<self.thedesc>>. ";
- X else
- X self.behindCont := self.searchObj(actor, self.behindCont);
- X }
- X;
- X
- X/*
- X@searchHider: hider
- XThis is just like an \tt underHider\, except that objects are hidden
- Xwithin this object in such a way that the object must be looked in
- Xor searched. Objects to be hidden in this object should have their
- X\tt searchLoc\ property set to point to this object. Note that this
- Xis different from a normal container, in that the objects hidden within
- Xthis object will not show up until the object is explicitly looked in
- Xor searched.
- X
- XThe items hidden with \tt searchHider\ must be of class \tt hiddenItem\.
- X*/
- Xclass searchHider: hider
- X searchCont = []
- X verDoSearch(actor) = {}
- X doSearch(actor) =
- X {
- X if (self.searchCont = nil)
- X "There's nothing else in <<self.thedesc>>. ";
- X else
- X self.searchCont := self.searchObj(actor, self.searchCont);
- X }
- X verDoLookin(actor) =
- X {
- X if (self.searchCont = nil)
- X pass verDoLookin;
- X }
- X doLookin(actor) =
- X {
- X if (self.searchCont = nil)
- X pass doLookin;
- X else
- X self.searchCont := self.searchObj(actor, self.searchCont);
- X }
- X;
- X
- X
- X/*
- X@fixeditem: thing
- XAn object that cannot be taken or otherwise moved from its location.
- XNote that a \tt fixeditem\ is sometimes part of a movable object;
- Xthis can be done to make one object part of another, ensuring that
- Xthey cannot be separated. By default, the functions that list a room's
- Xcontents do not automatically describe \tt fixeditem\ objects (because
- Xthe \tt isListed\ property is set to \tt nil\). Instead, the game author
- Xwill generally describe the \tt fixeditem\ objects separately as part of
- Xthe room's \tt ldesc\.
- X*/
- Xclass fixeditem: thing // An immovable object
- X isListed = nil // not listed in room/inventory displays
- X isfixed = true // Item can't be taken
- X weight = 0 // no actual weight
- X bulk = 0
- X verDoTake( actor ) =
- X {
- X "%You% can't have "; self.thedesc; ". ";
- X }
- X verDoTakeOut( actor, io ) =
- X {
- X self.verDoTake( actor );
- X }
- X verDoDrop( actor ) =
- X {
- X "%You% can't drop "; self.thedesc; ". ";
- X }
- X verDoTakeOff( actor, io ) =
- X {
- X self.verDoTake( actor );
- X }
- X verDoPutIn( actor, io ) =
- X {
- X "%You% can't put "; self.thedesc; " anywhere. ";
- X }
- X verDoPutOn( actor, io ) =
- X {
- X "%You% can't put "; self.thedesc; " anywhere. ";
- X }
- X verDoMove( actor ) =
- X {
- X "%You% can't move "; self.thedesc; ". ";
- X }
- X;
- X
- X/*
- X@readable: item
- XAn item that can be read. The \tt readdesc\ property is displayed
- Xwhen the item is read. By default, the \tt readdesc\ is the same
- Xas the \tt ldesc\, but the \tt readdesc\ can be overridden to give
- Xa different message.
- X*/
- Xclass readable: item
- X verDoRead( actor ) =
- X {
- X }
- X doRead( actor ) =
- X {
- X self.readdesc;
- X }
- X readdesc =
- X {
- X self.ldesc;
- X }
- X;
- X
- X/*
- X@fooditem: item
- XAn object that can be eaten. When eaten, the object is removed from
- Xthe game, and \tt global.lastMealTime\ is decremented by the
- X\tt foodvalue\ property. By default, the \tt foodvalue\ property
- Xis \tt global.eatTime\, which is the time between meals. So, the
- Xdefault \tt fooditem\ will last for one ``nourishment interval.''
- X*/
- Xclass fooditem: item
- X verDoEat( actor ) =
- X {
- X self.verifyRemove( actor );
- X }
- X doEat( actor ) =
- X {
- X "That was delicious! ";
- X // global.lastMealTime := global.lastMealTime - self.foodvalue;
- X self.moveInto( nil );
- X }
- X foodvalue = { return( global.eatTime ); }
- X;
- X
- X/*
- X@dialItem: fixeditem
- XThis class is used for making ``dials,'' which are controls in
- Xyour game that can be turned to a range of numbers. You must
- Xdefine the property \tt maxsetting\ as a number specifying the
- Xhighest number to which the dial can be turned; the lowest number
- Xon the dial is always 1. The \tt setting\ property is the dial's
- Xcurrent setting, and can be changed by the player by typing the
- Xcommand ``turn dial to \it number\.'' By default, the \tt ldesc\
- Xmethod displays the current setting.
- X*/
- Xclass dialItem: fixeditem
- X maxsetting = 10 // it has settings from 1 to this number
- X setting = 1 // the current setting
- X ldesc =
- X {
- X caps(); self.thedesc; " can be turned to settings
- X numbered from 1 to << self.maxsetting >>. It's
- X currently set to << self.setting >>. ";
- X }
- X verDoTurn( actor ) = {}
- X doTurn( actor ) =
- X {
- X askio( toPrep );
- X }
- X verDoTurnTo( actor, io ) = {}
- X doTurnTo( actor, io ) =
- X {
- X if ( io = numObj )
- X {
- X if ( numObj.value < 1 or numObj.value > self.maxsetting )
- X {
- X "There's no such setting! ";
- X }
- X else if ( numObj.value <> self.setting )
- X {
- X self.setting := numObj.value;
- X "Okay, it's now turned to "; say( self.setting ); ". ";
- X }
- X else
- X {
- X "It's already set to "; say( self.setting ); "! ";
- X }
- X }
- X else
- X {
- X "I don't know how to turn "; self.thedesc;
- X " to that. ";
- X }
- X }
- X;
- X
- X/*
- X@switchItem: fixeditem
- XThis is a class for things that can be turned on and off by the
- Xplayer. The only special property is \tt isActive\, which is \tt nil\
- Xif the switch is turned off and \tt true\ when turned on. The object
- Xaccepts the commands ``turn it on'' and ``turn it off,'' as well as
- Xsynonymous constructions, and updates \tt isActive\ accordingly.
- X*/
- Xclass switchItem: fixeditem
- X verDoSwitch( actor ) = {}
- X doSwitch( actor ) =
- X {
- X self.isActive := not self.isActive;
- X "Okay, "; self.thedesc; " is now switched ";
- X if ( self.isActive ) "on"; else "off";
- X ". ";
- X }
- X verDoTurnon( actor ) =
- X {
- X if ( self.isActive ) "It's already turned on! ";
- X }
- X doTurnon( actor ) =
- X {
- X self.isActive := true;
- X "Okay, it's now turned on. ";
- X }
- X verDoTurnoff( actor ) =
- X {
- X if ( not self.isActive ) "It's already turned off! ";
- X }
- X doTurnoff( actor ) =
- X {
- X self.isActive := nil;
- X "Okay, it's now turned off. ";
- X }
- X;
- X
- X/*
- X@room: thing
- XA location in the game. By default, the \tt islit\ property is
- X\tt true\, which means that the room is lit (no light source is
- Xneeded while in the room). You should create a \tt darkroom\
- Xobject rather than a \tt room\ with \tt islit\ set to \tt nil\ if you
- Xwant a dark room, because other methods are affected as well.
- XThe \tt isseen\ property records whether the player has entered
- Xthe room before; initially it's \tt nil\, and is set to \tt true\
- Xthe first time the player enters. The \tt roomAction( \it actor,
- Xverb, directObject, preposition, indirectObject\ )\ method is
- Xactivated for each player command; by default, all it does is
- Xcall the room's location's \tt roomAction\ method if the room
- Xis inside another room. The \tt lookAround( \it verbosity\ )\
- Xmethod displays the room's description for a given verbosity
- Xlevel; \tt true\ means a full description, \tt nil\ means only
- Xthe short description (just the room name plus a list of the
- Xobjects present). \tt roomDrop( \it object\ )\ is called when
- Xan object is dropped within the room; normally, it just moves
- Xthe object to the room and displays ``Dropped.'' The \tt firstseen\
- Xmethod is called when \tt isseen\ is about to be set \tt true\
- Xfor the first time (i.e., when the player first sees the room);
- Xby default, this routine does nothing, but it's a convenient
- Xplace to put any special code you want to execute when a room
- Xis first entered. The \tt firstseen\ method is called \it after\
- Xthe room's description is displayed.
- X*/
- X
- X/*
- X * room: thing
- X *
- X * A location in the game. By default, the islit property is
- X * true, which means that the room is lit (no light source is
- X * needed while in the room). You should create a darkroom
- X * object rather than a room with islit set to nil if you
- X * want a dark room, because other methods are affected as well.
- X * The isseen property records whether the player has entered
- X * the room before; initially it's nil, and is set to true
- X * the first time the player enters. The roomAction( actor,
- X * verb, directObject, preposition, indirectObject ) method is
- X * activated for each player command; by default, all it does is
- X * call the room's location's roomAction method if the room
- X * is inside another room. The lookAround( verbosity )
- X * method displays the room's description for a given verbosity
- X * level; true means a full description, nil means only
- X * the short description (just the room name plus a list of the
- X * objects present). roomDrop( object ) is called when
- X * an object is dropped within the room; normally, it just moves
- X * the object to the room and displays "Dropped." The firstseen
- X * method is called when isseen is about to be set true
- X * for the first time (i.e., when the player first sees the room);
- X * by default, this routine does nothing, but it's a convenient
- X * place to put any special code you want to execute when a room
- X * is first entered. The firstseen method is called after
- X * the room's description is displayed.
- X*/
- Xroom: thing
- X topline = true // DMB -- see nestedroom
- X
- X /*
- X * 'reachable' is the list of explicitly reachable objects, over and
- X * above the objects that are here. This is mostly used in nested
- X * rooms to make objects in the containing room accessible. Most
- X * normal rooms will leave this as an empty list.
- X */
- X reachable = []
- X
- X /*
- X * roomCheck is true if the verb is valid in the room. This
- X * is a first pass; generally, its only function is to disallow
- X * certain commands in a dark room.
- X */
- X roomCheck( v ) = { return( true ); }
- X islit = true // rooms are lit unless otherwise specified
- X isseen = nil // room has not been seen yet
- X enterRoom( actor ) = // sent to room as actor is entering it
- X {
- X self.lookAround(( not self.isseen ) or global.verbose );
- X if ( self.islit )
- X {
- X if (not self.isseen) self.firstseen;
- X self.isseen := true;
- X }
- X }
- X roomAction( a, v, d, p, i ) =
- X {
- X if ( self.location ) self.location.roomAction( a, v, d, p, i );
- X }
- X
- X /*
- X * Whenever a normal object (i.e., one that does not override the
- X * default doDrop provided by 'thing') is dropped, the actor's
- X * location is sent roomDrop(object being dropped). By default,
- X * we move the object into this room.
- X */
- X roomDrop( obj ) =
- X {
- X "Dropped. ";
- X obj.moveInto( self );
- X }
- X
- X /*
- X * Whenever an actor leaves this room, we run through the leaveList.
- X * This is a list of objects that have registered themselves with us
- X * via addLeaveList(). For each object in the leaveList, we send
- X * a "leaving" message, with the actor as the parameter. It should
- X * return true if it wants to be removed from the leaveList, nil
- X * if it wants to stay.
- X */
- X leaveList = []
- X addLeaveList( obj ) =
- X {
- X self.leaveList := self.leaveList + obj;
- X }
- X leaveRoom( actor ) =
- X {
- X local tmplist, thisobj, i, tot;
- X
- X tmplist := self.leaveList;
- X tot := length( tmplist );
- X i := 1;
- X while ( i <= tot )
- X {
- X thisobj := tmplist[i];
- X if ( thisobj.leaving( actor ))
- X self.leaveList := self.leaveList - thisobj;
- X i := i + 1;
- X }
- X }
- X /*
- X * lookAround describes the room. If verbosity is true, the full
- X * description is given, otherwise an abbreviated description (without
- X * the room's ldesc) is displayed.
- X */
- X nrmLkAround( verbosity ) = // lookAround without location status
- X {
- X local l, cur, i, tot;
- X
- X if ( verbosity )
- X {
- X /* "\n\t"; self.ldesc; */
- X "\b"; self.ldesc; /* DMB */
- X
- X l := self.contents;
- X tot := length( l );
- X i := 1;
- X while ( i <= tot )
- X {
- X cur := l[i];
- X if ( cur.isfixed ) cur.heredesc;
- X i := i + 1;
- X }
- X }
- X /* "\n\t"; */
- X if (itemcnt( self.contents ))
- X {
- X P(); I(); /* DMB */
- X "You see "; listcont( self ); " here. ";
- X }
- X else {
- X "\n\t";
- X }
- X
- X /*
- X * DMB add stuff to listcontcont so we can see if there's
- X * anything to print before putting the paragraph separator out.
- X */
- X if (listcontcont(self, nil)) {
- X P(); I();
- X listcontcont(self, true);
- X }
- X
- X /*
- X * DMB: Hack for Colossal Cave: since the bear has a location
- X * that's a method, his actorDesc doesn't get printed by
- X * the code below.
- X */
- X if (Bear.isIn(self))
- X Bear.actorDesc;
- X
- X l := self.contents;
- X tot := length( l );
- X i := 1;
- X while ( i <= tot )
- X {
- X cur := l[i];
- X if ( cur.isactor )
- X {
- X if ( cur <> Me )
- X {
- X "\n\t";
- X cur.actorDesc;
- X }
- X }
- X i := i + 1;
- X }
- X }
- X /* DMB: */
- X statusline = { self.sdesc; }
- X statusLine =
- X {
- X self.statusline;
- X }
- X lookAround( verbosity ) =
- X {
- X self.statusline; // DMB -- removed "\b";
- X self.nrmLkAround( verbosity );
- X }
- X
- X /*
- X * Direction handlers. The directions are all set up to
- X * the default, which is no travel allowed. To make travel
- X * possible in a direction, just assign a room to the direction
- X * property.
- X */
- X north = { return( self.noexit ); }
- X south = { return( self.noexit ); }
- X east = { return( self.noexit ); }
- X west = { return( self.noexit ); }
- X up = { return( self.noexit ); }
- X down = { return( self.noexit ); }
- X ne = { return( self.noexit ); }
- X nw = { return( self.noexit ); }
- X se = { return( self.noexit ); }
- X sw = { return( self.noexit ); }
- X in = { return( self.noexit ); }
- X out = { return( self.noexit ); }
- X
- X /*
- X * noexit displays a message when the player attempts to travel
- X * in a direction in which travel is not possible.
- X */
- X noexit = { "%You% can't go that way. "; return( nil ); }
- X;
- X
- X/*
- X@darkroom: room
- XA dark room. The player must have some object that can act as a
- Xlight source in order to move about and perform most operations
- Xwhile in this room. Note that the room's lights can be turned
- Xon by setting the room's \tt lightsOn\ property to \tt true\;
- Xdo this instead of setting \tt islit\, because \tt islit\ is
- Xa method which checks for the presence of a light source.
- X*/
- Xclass darkroom: room // An enterable area which might be dark
- X islit = // true ONLY if something is lighting the room
- X {
- X local rem, cur, tot, i;
- X
- X if ( self.lightsOn ) return( true );
- X
- X rem := global.lamplist;
- X tot := length( rem );
- X i := 1;
- X while ( i <= tot )
- X {
- X cur := rem[i];
- X if ( cur.isIn( self ) and cur.islit ) return( true );
- X i := i + 1;
- X }
- X return( nil );
- X }
- X roomAction( actor, v, dobj, prep, io ) =
- X {
- X if ( not self.islit and not v.isTravelVerb and not v.issysverb )
- X {
- X "%You% can't see a thing. ";
- X exit;
- X }
- X else pass roomAction;
- X }
- X statusLine =
- X {
- X if ( self.islit ) pass statusLine;
- X else "In the dark.";
- X }
- X lookAround( verbosity ) =
- X {
- X // DMB: Changed pitch dark message
- X if ( self.islit ) pass lookAround;
- X else "It is now pitch dark.
- X If you proceed you will likely fall into a pit.";
- X
- X }
- X noexit =
- X {
- X if ( self.islit ) pass noexit;
- X else
- X {
- X darkTravel();
- X return( nil );
- X }
- X }
- X roomCheck( v ) =
- X {
- X if ( self.islit or v.issysverb or v.isTravelVerb ) return( true );
- X else
- X {
- X "It's pitch black.\n";
- X return( nil );
- X }
- X }
- X;
- X
- X/*
- X * theFloor is a special item that appears in every room (hence
- X * the non-standard location property). This object is included
- X * mostly for completeness, so that the player can refer to the
- X * floor; otherwise, it doesn't do much. Dropping an item on the
- X * floor, for example, moves it to the current room.
- X */
- Xclass theFloor: beditem
- X onroom = true // DMB so it won't say "in the ground"
- X noun = 'floor' 'ground'
- X sdesc = "ground"
- X adesc = "the ground"
- X location =
- X {
- X if ( Me.location = self )
- X return( self.sitloc );
- X else
- X return( Me.location );
- X }
- X locationOK = true // suppress warning about location being a method
- X doSiton( actor ) =
- X {
- X "Okay, %you're% now sitting on "; self.thedesc; ". ";
- X self.sitloc := actor.location;
- END_OF_FILE
- if test 55312 -ne `wc -c <'src/ccr-adv.t1'`; then
- echo shar: \"'src/ccr-adv.t1'\" unpacked with wrong size!
- fi
- # end of 'src/ccr-adv.t1'
- fi
- if test -f 'src/history.t' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/history.t'\"
- else
- echo shar: Extracting \"'src/history.t'\" \(1403 characters\)
- sed "s/^X//" >'src/history.t' <<'END_OF_FILE'
- X/*
- X * Colossal Cave Revisited
- X *
- X * A remake of Willie Crowther and Don Woods' classic Adventure.
- X * Converted from Donald Ekman's PC port of the original FORTRAN source.
- X * TADS version by David M. Baggett for ADVENTIONS.
- X *
- X * Please document all changes in the history so we know who did what.
- X *
- X * This source code is copylefted under the terms of the GNU Public
- X * License. Essentially, this means that you are free to do whatever
- X * you wish with this source code, provided you do not charge any
- X * money for it or for any derivative works.
- X *
- X * ADVENTIONS distributes this game, but you are free to do what you will
- X * with it, provided you adhere to the terms in the GNU Public License.
- X * Send correspondence regarding this game or original works distributed
- X * by ADVENTIONS to
- X *
- X * ADVENTIONS
- X * PO Box 851
- X * Columbia, MD 21044
- X *
- X * If you would like a catalog of releases, please enclose a SASE. Thanks!
- X *
- X * Contributors
- X *
- X * dmb In real life: David M. Baggett
- X * Internet: <dmb@ai.mit.edu>
- X * Compu$erve: 76440,2671 (ADVENTIONS account)
- X * GEnie: ADVENTIONS
- X *
- X * Modification History
- X *
- X * 1-Jan-93 dmb rec.arts.int-fiction BETA release (source only)
- X * For beta testing only -- not for general
- X * distribution.
- X *
- X * 20-Apr-93 dmb Version 1.0 release.
- X *
- X * 9-Jul-93 dmb Widespread version 1.0 release for all supported
- X * machines.
- X *
- X */
- END_OF_FILE
- if test 1403 -ne `wc -c <'src/history.t'`; then
- echo shar: \"'src/history.t'\" unpacked with wrong size!
- fi
- # end of 'src/history.t'
- fi
- echo shar: End of archive 8 \(of 11\).
- cp /dev/null ark8isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 11 archives.
- echo "Now run buildit.sh to make gam file"
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-