home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume18 / ccr / part08 < prev    next >
Encoding:
Internet Message Format  |  1993-07-18  |  59.5 KB

  1. Path: uunet!news.tek.com!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v18i023:  ccr - colossal cave (adventure) implemented in TADS, Part08/11
  5. Date: 12 Jul 1993 19:29:05 GMT
  6. Organization: Tektronix, Inc, Redmond, OR, USA
  7. Lines: 1945
  8. Approved: billr@saab.CNA.TEK.COM
  9. Message-ID: <21se21$1d1@ying.cna.tek.com>
  10. NNTP-Posting-Host: saab.cna.tek.com
  11. Xref: uunet comp.sources.games:1823
  12.  
  13. Submitted-by: David Baggett <dmb@xbar.ai.mit.edu>
  14. Posting-number: Volume 18, Issue 23
  15. Archive-name: ccr/part08
  16. Environment: TADS
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 8 (of 11)."
  27. # Contents:  src/ccr-adv.t1 src/history.t
  28. # Wrapped by billr@saab on Mon Jul 12 12:02:44 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/ccr-adv.t1' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/ccr-adv.t1'\"
  32. else
  33. echo shar: Extracting \"'src/ccr-adv.t1'\" \(55312 characters\)
  34. sed "s/^X//" >'src/ccr-adv.t1' <<'END_OF_FILE'
  35. X/* $Header$ */
  36. X/* Copyright (c) 1988, 1991 by Michael J. Roberts.  All Rights Reserved. */
  37. X/*
  38. X   adv.t  - standard adventure definitions for TADS games
  39. X   Version 2.0
  40. X
  41. X   This file is part of TADS:  The Text Adventure Development System.
  42. X   Please see the file LICENSE.DOC (which should be part of the TADS
  43. X   distribution) for information on using this file, and for information
  44. X   on reaching High Energy Software, the developers of TADS.
  45. X
  46. X   This file defines the basic classes and functions used by most TADS
  47. X   adventure games.  It is generally #include'd at the start of each game
  48. X   source file.
  49. X*/
  50. X
  51. X/*
  52. X *   Define compound prepositions.  Since prepositions that appear in
  53. X *   parsed sentences must be single words, we must define any logical
  54. X *   prepositions that consist of two or more words here.  Note that
  55. X *   only two words can be pasted together at once; to paste more, use
  56. X *   a second step.  For example,  'out from under' must be defined in
  57. X *   two steps:
  58. X *
  59. X *     compoundWord 'out' 'from' 'outfrom';
  60. X *     compoundWord 'outfrom' 'under' 'outfromunder';
  61. X *
  62. X *   Listed below are the compound prepositions that were built in to
  63. X *   version 1.0 of the TADS run-time.
  64. X */
  65. XcompoundWord 'on' 'to' 'onto';           /* on to --> onto */
  66. XcompoundWord 'in' 'to' 'into';           /* in to --> into */
  67. XcompoundWord 'in' 'between' 'inbetween'; /* and so forth */
  68. XcompoundWord 'down' 'in' 'downin';
  69. XcompoundWord 'down' 'on' 'downon';
  70. XcompoundWord 'up' 'on' 'upon';
  71. XcompoundWord 'out' 'of' 'outof';
  72. XcompoundWord 'off' 'of' 'offof';
  73. X
  74. X/*
  75. X *   Format strings:  these associate keywords with properties.  When
  76. X *   a keyword appears in output between percent signs (%), the matching
  77. X *   property of the current command's actor is evaluated and substituted
  78. X *   for the keyword (and the percent signs).  For example, if you have:
  79. X *
  80. X *      formatstring 'you' fmtYou;
  81. X *
  82. X *   and the command being processed is:
  83. X *
  84. X *      fred, pick up the paper
  85. X *
  86. X *   and the "fred" actor has fmtYou = "he", and this string is output:
  87. X *
  88. X *      "%You% can't see that here."
  89. X *
  90. X *   Then the actual output is:  "He can't see that here."
  91. X *
  92. X *   The format strings are chosen to look like normal output (minus the
  93. X *   percent signs, of course) when the actor is Me.
  94. X */
  95. Xformatstring 'you' fmtYou;
  96. Xformatstring 'your' fmtYour;
  97. Xformatstring 'you\'re' fmtYoure;
  98. Xformatstring 'youm' fmtYoum;
  99. Xformatstring 'you\'ve' fmtYouve;
  100. Xformatstring 's' fmtS;
  101. Xformatstring 'es' fmtEs;
  102. Xformatstring 'have' fmtHave;
  103. Xformatstring 'do' fmtDo;
  104. Xformatstring 'are' fmtAre;
  105. X
  106. X/*
  107. X *   Forward-declare functions.  This is not required in most cases,
  108. X *   but it doesn't hurt.  Providing these forward declarations ensures
  109. X *   that the compiler knows that we want these symbols to refer to
  110. X *   functions rather than objects.
  111. X */
  112. XcheckDoor: function;
  113. XcheckReach: function;
  114. Xitemcnt: function;
  115. Xlistcont: function;
  116. Xlistcontcont: function;
  117. Xturncount: function;
  118. Xaddweight: function;
  119. Xaddbulk: function;
  120. Xincscore: function;
  121. Xsilent_incscore: function;    // DMB
  122. XdarkTravel: function;
  123. XscoreRank: function;
  124. Xterminate: function;
  125. Xdie: function;
  126. Xinit: function;
  127. Xpardon: function;
  128. Xpreinit: function;
  129. XinitSearch: function;
  130. X
  131. X/*
  132. X *   checkDoor:  if the door d is open, this function silently returns
  133. X *   the room r.  Otherwise, print a message ("The door is closed.") and
  134. X *   return nil.
  135. X */
  136. XcheckDoor: function( d, r )
  137. X{
  138. X    if ( d.isopen ) return( r );
  139. X    else
  140. X    {
  141. X        setit( d );
  142. X    caps(); d.thedesc; " is closed. ";
  143. X    return( nil );
  144. X    }
  145. X}
  146. X
  147. X/*
  148. X *   checkReach:  determines whether the object obj can be reached by
  149. X *   actor in location loc, using the verb v.  This routine returns true
  150. X *   if obj is a special object (numObj or strObj), if obj is in actor's
  151. X *   inventory or actor's location, or if it's in the 'reachable' list
  152. X *   for loc.
  153. X */
  154. XcheckReach: function( loc, actor, v, obj )
  155. X{
  156. X    if ( obj=numObj or obj=strObj ) return;
  157. X    if ( not ( actor.isCarrying( obj ) or obj.isIn( actor.location )))
  158. X    {
  159. X        if (find( loc.reachable, obj ) <> nil ) return;
  160. X        "%You% can't reach "; obj.thedesc; " from "; loc.thedesc; ". ";
  161. X        exit;
  162. X    }
  163. X}
  164. X
  165. X/*
  166. X@itemcnt: function( list )
  167. XReturns a count of the ``listable'' objects in \it list\.  An
  168. Xobject is listable (that is, it shows up in a room's description)
  169. Xif its \tt isListed\ property is \tt true\.  This function is
  170. Xuseful for determining how many objects (if any) will be listed
  171. Xin a room's description.
  172. X*/
  173. Xitemcnt: function( list )
  174. X{
  175. X    local cnt, tot, i;
  176. X    tot := length( list );
  177. X    cnt := 0;
  178. X    i := 1;
  179. X    while ( i <= tot )
  180. X    {
  181. X        if ( list[i].isListed ) cnt := cnt+1;
  182. X        i := i+1;
  183. X    }
  184. X    return( cnt );
  185. X}
  186. X
  187. X/*
  188. X@listcont: function( obj )
  189. XThis function displays the contents of an object, separated by
  190. Xcommas.  The \tt thedesc\ properties of the contents are used.
  191. XIt is up to the caller to provide the introduction to the list
  192. X(usually something to the effect of ``The box contains'' is
  193. Xdisplayed before calling \tt listcont\) and finishing the
  194. Xsentence (usually by displaying a period).  An object is listed
  195. Xonly if its \tt isListed\ property is \tt true\.
  196. X*/
  197. Xlistcont: function( obj )
  198. X{
  199. X    local i, count, tot, list, cur, disptot;
  200. X    count := 0;
  201. X    list := obj.contents;
  202. X    tot := length( list );
  203. X    disptot := itemcnt( list );
  204. X    i := 1;
  205. X    while ( i <= tot )
  206. X    {
  207. X        cur := list[i];
  208. X        if ( cur.isListed )
  209. X        {
  210. X            if ( count > 0 )
  211. X            {
  212. X                if ( count+1 < disptot )
  213. X                    ", ";
  214. X                else if (count = 1)
  215. X                    " and ";
  216. X                else
  217. X                    ", and ";
  218. X            }
  219. X            count := count + 1;
  220. X            cur.adesc;               // list this object
  221. X            if ( cur.isworn ) " (being worn)";
  222. X            else if ( cur.islamp and cur.islit ) " (providing light)";
  223. X        }
  224. X        i := i + 1;
  225. X    }
  226. X}
  227. X
  228. X/*
  229. X *   showcontcont:  list the contents of the object, plus the contents of
  230. X *   an fixeditem's contained by the object.  A complete sentence is shown.
  231. X *   This is an internal routine used by listcontcont and listfixedcontcont.
  232. X */
  233. X// DMB added print param and return value
  234. Xshowcontcont: function(obj, print)
  235. X{
  236. X    local cnt := 0;
  237. X    
  238. X    if (itemcnt( obj.contents ))
  239. X    {
  240. X        if ( obj.issurface and not obj.isqsurface )
  241. X        {
  242. X        cnt := cnt + itemcnt(obj.contents);
  243. X        if (print) {
  244. X            if (cnt > 1) {    // DMB added this check
  245. X                caps(); listcont(obj);
  246. X                " are sitting on "; obj.thedesc; ". ";
  247. X            }
  248. X            else {
  249. X                caps(); listcont(obj); " is sitting on ";
  250. X                obj.thedesc; ". ";
  251. X            }
  252. X        }
  253. X        }
  254. X        else if ( obj.contentsVisible and not obj.isqcontainer )
  255. X        {
  256. X        cnt := cnt + itemcnt(obj.contents);
  257. X        if (print) {
  258. X            caps();
  259. X            obj.thedesc; " seems to contain ";
  260. X            listcont( obj );
  261. X            ". ";
  262. X        }
  263. X        }
  264. X    }
  265. X    if ( obj.contentsVisible and not obj.isqcontainer )
  266. X        cnt := cnt + listfixedcontcont(obj, print);
  267. X
  268. X    return cnt;
  269. X}
  270. X
  271. X/*
  272. X@listfixedcontcont: function( obj )
  273. XList the contents of the contents of any \tt fixeditem\ objects
  274. Xin the \tt contents\ list of the object \it obj\.  This routine
  275. Xmakes sure that all objects that can be taken are listed somewhere
  276. Xin a room's description.  This routine recurses down the contents
  277. Xtree, following each branch until either something has been listed
  278. Xor the branch ends without anything being listable.  This routine
  279. Xdisplays a complete sentence, so no introductory or closing text
  280. Xis needed.
  281. X*/
  282. X// DMB added print param and return value
  283. Xlistfixedcontcont: function(obj, print)
  284. X{
  285. X    local list, i, tot, thisobj;
  286. X    local cnt := 0;
  287. X
  288. X    list := obj.contents;
  289. X    tot := length( list );
  290. X    i := 1;
  291. X    while ( i <= tot )
  292. X    {
  293. X        thisobj := list[i];
  294. X        if ( thisobj.isfixed and thisobj.contentsVisible and
  295. X      not thisobj.isqcontainer )
  296. X            cnt := cnt + showcontcont(thisobj, print);
  297. X    i := i + 1;
  298. X    }
  299. X    return cnt;
  300. X}
  301. X
  302. X/*
  303. X@listcontcont: function( obj )
  304. XThis function lists the contents of the contents of an object.
  305. XIt displays full sentences, so no introductory or closing text
  306. Xis required.  Any item in the \tt contents\ list of the object
  307. X\it obj\ whose \tt contentsVisible\ property is \tt true\ has
  308. Xits contents listed.  An Object whose \tt isqcontainer\ or
  309. X\tt isqsurface\ property is \tt true\ will not have its
  310. Xcontents listed.
  311. X*/
  312. X// DMB added print parameter and return value
  313. Xlistcontcont: function(obj, print)
  314. X{
  315. X    local list, i, tot;
  316. X    local cnt := 0;
  317. X    
  318. X    list := obj.contents;
  319. X    tot := length( list );
  320. X    i := 1;
  321. X    while ( i <= tot )
  322. X    {
  323. X        cnt := cnt + showcontcont(list[i], print);
  324. X    i := i + 1;
  325. X    }
  326. X    return cnt;
  327. X}
  328. X
  329. X/*
  330. X@turncount: function( parm )
  331. XThis function can be used as a daemon (normally set up in the \tt init\
  332. Xfunction) to update the turn counter after each turn.  This routine
  333. Xincrements \tt global.turnsofar\, and then calls \tt setscore\ to
  334. Xupdate the status line with the new turn count.
  335. X*/
  336. Xturncount: function( parm )
  337. X{
  338. X    incturn();
  339. X    global.turnsofar := global.turnsofar + 1;
  340. X    setscore( global.score, global.turnsofar );
  341. X}
  342. X                   
  343. X/*
  344. X@addweight: function( list )
  345. XAdds the weights of the objects in \it list\ and returns the sum.
  346. XThe weight of an object is given by its \tt weight\ property.  This
  347. Xroutine includes the weights of all of the contents of each object,
  348. Xand the weights of their contents, and so forth.
  349. X*/
  350. Xaddweight: function( l )
  351. X{
  352. X    local tot, i, c, totweight;
  353. X
  354. X    tot := length( l );
  355. X    i := 1;
  356. X    totweight := 0;
  357. X    while ( i <= tot )
  358. X    {
  359. X        c := l[i];
  360. X        totweight := totweight + c.weight;
  361. X        if (length( c.contents ))
  362. X            totweight := totweight + addweight( c.contents );
  363. X        i := i + 1;
  364. X    }
  365. X    return( totweight );
  366. X}
  367. X
  368. X/*
  369. X@addbulk: function( list )
  370. XThis function returns the sum of the bulks (given by the \tt bulk\
  371. Xproperty) of each object in \it list\.  The value returned includes
  372. Xonly the bulk of each object in the list, and \it not\ of the contents
  373. Xof the objects, as it is assumed that an object does not change in
  374. Xsize when something is put inside it.  You can easily change this
  375. Xassumption for special objects (such as a bag that stretches as
  376. Xthings are put inside) by writing an appropriate \tt bulk\ method
  377. Xfor that object.
  378. X*/
  379. Xaddbulk: function( list )
  380. X{
  381. X    local i, tot, totbulk, rem, cur;
  382. X
  383. X    tot := length( list );
  384. X    i := 1;
  385. X    totbulk := 0;
  386. X    while( i <= tot )
  387. X    {
  388. X        cur := list[i];
  389. X        if ( not cur.isworn )
  390. X            totbulk := totbulk + cur.bulk;
  391. X        i := i + 1;
  392. X    }
  393. X    return( totbulk );
  394. X}
  395. X
  396. X/*
  397. X@incscore: function( amount )
  398. XAdds \it amount\ to the total score, and updates the status line
  399. Xto reflect the new score.  The total score is kept in \tt global.score\.
  400. XAlways use this routine rather than changing \tt global.score\
  401. Xdirectly, since this routine ensures that the status line is
  402. Xupdated with the new value.
  403. X*/
  404. Xincscore: function( amount )    /* DMB */
  405. X{
  406. X    silent_incscore(amount);
  407. X
  408. X    "\b";
  409. X    if (amount = -1)
  410. X        "* Your score just went down by a point. *";
  411. X    else if (amount = 1)
  412. X        "* Your score just went up by a point. *";
  413. X    else if (amount < -1) {
  414. X        "* Your score just went down by ";
  415. X        say(-1 * amount); " points. *";
  416. X    }
  417. X    else if (amount > 1) {
  418. X        "* Your score just went up by "; say(amount); " points. *";
  419. X    }
  420. X    "\b";
  421. X}
  422. X// DMB: added the following:
  423. Xsilent_incscore: function( amount )
  424. X{
  425. X    global.score := global.score + amount;
  426. X    setscore( global.score, global.turnsofar );
  427. X}
  428. X
  429. X/*
  430. X@initSearch: function
  431. XInitializes the containers of objects with a \tt searchLoc\, \tt underLoc\,
  432. Xand \tt behindLoc\ by setting up \tt searchCont\, \tt underCont\, and
  433. X\tt behindCont\ lists, respectively.  You should call this function once in
  434. Xyour \tt preinit\ (or \tt init\, if you prefer) function to ensure that
  435. Xthe underable, behindable, and searchable objects are set up correctly.
  436. X*/
  437. XinitSearch: function
  438. X{
  439. X    local o;
  440. X    
  441. X    o := firstobj(hiddenItem);
  442. X    while (o <> nil)
  443. X    {
  444. X    if (o.searchLoc)
  445. X        o.searchLoc.searchCont := o.searchLoc.searchCont + o;
  446. X    else if (o.underLoc)
  447. X        o.underLoc.underCont := o.underLoc.underCont + o;
  448. X    else if (o.behindLoc)
  449. X        o.behindLoc.behindCont := o.behindLoc.behindCont + o;
  450. X    o := nextobj(o, hiddenItem);
  451. X    }
  452. X}
  453. X
  454. X/*
  455. X@nestedroom: room
  456. XA special kind of room that is inside another room; chairs and
  457. Xsome types of vehicles, such as inflatable rafts, fall into this
  458. Xcategory.  Note that a room can be within another room without
  459. Xbeing a \tt nestedroom\, simply by setting its \tt location\ property
  460. Xto another room.  The \tt nestedroom\ is different from an ordinary
  461. Xroom, though, in that it's an ``open'' room; that is, when inside it,
  462. Xthe actor is still really inside the enclosing room for purposes of
  463. Xdescriptions.  Hence, the player sees ``Laboratory, in the chair."
  464. XIn addition, a \tt nestedroom\ is an object in its own right,
  465. Xvisible to the player; for example, a chair is an object in a
  466. Xroom in addition to being a room itself.
  467. X*/
  468. Xclass nestedroom: NoNPC    // DMB room -> NoNPC for CCR
  469. X    islit =
  470. X    {
  471. X        if ( self.location ) return( self.location.islit );
  472. X        return( nil );
  473. X    }
  474. X    statusLine = {
  475. X             /* DMB onword */
  476. X           self.location.sdesc; ", ";
  477. X           self.onword; " "; 
  478. X           self.thedesc; "\n\t";
  479. X    }
  480. X    lookAround( verbosity ) =
  481. X    {
  482. X        self.statusLine;
  483. X    self.location.nrmLkAround( verbosity );
  484. X    }
  485. X    roomDrop( obj ) =
  486. X    {
  487. X        if ( self.location = nil or self.isdroploc ) pass roomDrop;
  488. X    else self.location.roomDrop( obj );
  489. X    }
  490. X;
  491. X
  492. X/*
  493. X@chairitem: fixeditem, nestedroom, surface
  494. XActs like a chair:  actors can sit on the object.  While sitting
  495. Xon the object, an actor can't go anywhere until standing up, and
  496. Xcan only reach objects that are on the chair and in the chair's
  497. X\tt reachable\ list.  By default, nothing is in the \tt reachable\
  498. Xlist.  Note that there is no real distinction made between chairs
  499. Xand beds, so you can sit or lie on either; the only difference is
  500. Xthe message displayed describing the situation.
  501. X*/
  502. Xclass chairitem: fixeditem, nestedroom, surface
  503. X    /* DMB onroom */
  504. X    onword = { if (self.onroom) "on"; else "in"; }
  505. X    offword = { if (self.onroom) "off"; else "out"; }
  506. X
  507. X    reachable = []          // list of all containers reachable from here;
  508. X                            //  normally, you can only reach carried items
  509. X                            //  from a chair, but this makes special allowances
  510. X    ischair = true          // it is a chair by default; for beds or other
  511. X                            //  things you lie down on, make it false
  512. X    roomAction( actor, v, dobj, prep, io ) =
  513. X    {
  514. X        if ( dobj<>nil and v<>inspectVerb )
  515. X            checkReach( self, actor, v, dobj );
  516. X        if ( io<>nil and v<>askVerb and v<>tellVerb )
  517. X            checkReach( self, actor, v, io );
  518. X    pass roomAction;
  519. X    }
  520. X    enterRoom( actor ) = {}
  521. X    noexit =
  522. X    {
  523. X        "%You're% not going anywhere until %you% get%s% ";
  524. X    self.offword; " of"; self.thedesc; ". ";
  525. X        return( nil );
  526. X    }
  527. X    verDoBoard( actor ) = { self.verDoSiton( actor ); }
  528. X    doBoard( actor ) = { self.doSiton( actor ); }
  529. X    verDoSiton( actor ) =
  530. X    {
  531. X        if ( actor.location = self )
  532. X        {
  533. X            "%You're% already "; self.onword; " ";
  534. X            self.thedesc; "! ";
  535. X        }
  536. X    }
  537. X    doSiton( actor ) =
  538. X    {
  539. X        "Okay, %you're% now sitting "; self.onword; " "; self.thedesc; ". ";
  540. X        actor.travelTo( self );
  541. X    }
  542. X    verDoLieon( actor ) =
  543. X    {
  544. X        self.verDoSiton( actor );
  545. X    }
  546. X    doLieon( actor ) =
  547. X    {
  548. X        // DMB changed so it says "lying"
  549. X        "Okay, %you're% now lying "; self.onword; " "; self.thedesc; ". ";
  550. X        actor.travelTo(self);
  551. X    }
  552. X    // DMB: added the following:
  553. X    doUnboard( actor ) =
  554. X    {
  555. X        if ( self.fastenitem )
  556. X    {
  557. X        "%You%'ll have to unfasten "; actor.location.fastenitem.thedesc;
  558. X        " first. ";
  559. X    }
  560. X    else
  561. X    {
  562. X            "Okay, %you're% no longer "; self.onword; " "; self.thedesc; ". ";
  563. X            self.leaveRoom( actor );
  564. X        actor.moveInto( self.location );
  565. X    }
  566. X    }
  567. X;
  568. X
  569. X/*
  570. X@beditem: chairitem
  571. XThis object is the same as a \tt chairitem\, except that the player
  572. Xis described as lying on, rather than sitting in, the object.
  573. X*/
  574. Xclass beditem: chairitem
  575. X    onroom = true
  576. X    ischair = nil
  577. X    isbed = true
  578. X    sdesc = "bed"
  579. X;
  580. X
  581. X/*
  582. X@thing: object
  583. XThe basic class for objects in a game.  The property \tt contents\
  584. Xis a list that specifies what is in the object; this property is
  585. Xautomatically set up by the system after the game is compiled to
  586. Xcontain a list of all objects that have this object as their
  587. X\tt location\ property.  The \tt contents\ property is kept
  588. Xconsistent with the \tt location\ properties of referenced objects
  589. Xby the \tt moveInto\ method; always use \tt moveInto\ rather than
  590. Xdirectly setting a \tt location\ property for this reason.  The
  591. X\tt adesc\ method displays the name of the object with an indefinite
  592. Xarticle; the default is to display ``a'' followed by the \tt sdesc\,
  593. Xbut objects that need a different indefinite article (such as ``an''
  594. Xor ``some'') should override this method.  Likewise, \tt thedesc\
  595. Xdisplays the name with a definite article; by default, \tt thedesc\
  596. Xdisplays ``the'' followed by the object's \tt sdesc\.  The \tt sdesc\
  597. Xsimply displays the object's name (``short description'') without
  598. Xany articles.  The \tt ldesc\ is the long description, normally
  599. Xdisplayed when the object is examined by the player; by default,
  600. Xthe \tt ldesc\ displays a ``It looks like an ordinary \tt sdesc\.''
  601. XThe \tt isIn( \it object\ )\ method returns \tt true\ if the
  602. Xobject's location is the specified \it object\ or the object's
  603. X\tt location\ is an object whose \tt contentsVisible\ property is
  604. X\tt true\ and that object's \tt isIn( \it object\ )\ method is
  605. X\tt true\.  Note that if \tt isIn\ is \tt true\, it doesn't
  606. Xnecessarily mean the object is reachable, because \tt isIn\ is
  607. X\tt true\ if the object is merely visible within the location.
  608. XThe \tt thrudesc\ method displays a message for when the
  609. Xplayer looks through the object (objects such as windows would
  610. Xuse this property).  The \tt moveInto( \it object\ )\ method
  611. Xmoves the object to be inside the specified \it object\; always use
  612. X\tt moveInto\ to move an object rather than setting its \tt location\
  613. Xdirectly, so that the appropriate \tt contents\ lists are updated.
  614. XTo make an object disappear, move it into \tt nil\.
  615. X*/
  616. Xclass thing: object
  617. X    isListed = true         // shows up in room/inventory listings
  618. X    contents = []           // set up automatically by system - do not set
  619. X    verGrab( obj ) = {}
  620. X    Grab( obj ) = {}
  621. X    adesc =
  622. X    {
  623. X        "a "; self.sdesc;   // default is "a <name>"; "self" is current object
  624. X    }
  625. X    thedesc =
  626. X    {
  627. X        "the "; self.sdesc; // default is "the <name>"
  628. X    }
  629. X    ldesc = { "It looks like an ordinary "; self.sdesc; " to me."; }
  630. X    readdesc = { "%You% can't read "; self.adesc; ". "; }
  631. X    actorAction( v, d, p, i ) =
  632. X    {
  633. X        "You have lost your mind. ";
  634. X        exit;
  635. X    }
  636. X    contentsVisible = { return( true ); }
  637. X    contentsReachable = { return( true ); }
  638. X    isIn( obj ) =
  639. X    {
  640. X        local myloc;
  641. X
  642. X        myloc := self.location;
  643. X        if ( myloc )
  644. X        {
  645. X            if ( myloc = obj ) return( true );
  646. X            if ( myloc.contentsVisible ) return( myloc.isIn( obj ));
  647. X        }
  648. X        return( nil );
  649. X    }
  650. X    thrudesc = { "%You% can't see much through "; self.thedesc; ".\n"; }
  651. X    moveInto( obj ) =
  652. X    {
  653. X        local loc;
  654. X
  655. X    /*
  656. X     *   For the object containing me, and its container, and so forth,
  657. X     *   tell it via a Grab message that I'm going away.
  658. X     */
  659. X    loc := self.location;
  660. X    while ( loc )
  661. X    {
  662. X        loc.Grab( self );
  663. X        loc := loc.location;
  664. X    }
  665. X
  666. X        if ( self.location )
  667. X            self.location.contents := self.location.contents - self;
  668. X        self.location := obj;
  669. X        if ( obj ) obj.contents := obj.contents + self;
  670. X    }
  671. X    verDoSave( actor ) =
  672. X    {
  673. X        "Please specify the name of the game to save in double quotes,
  674. X        for example, SAVE \"GAME1\". ";
  675. X    }
  676. X    verDoRestore( actor ) =
  677. X    {
  678. X        "Please specify the name of the game to restore in double quotes,
  679. X        for example, SAVE \"GAME1\". ";
  680. X    }
  681. X    verDoScript( actor ) =
  682. X    {
  683. X        "You should type the name of a file to write the transcript to
  684. X        in quotes, for example, SCRIPT \"LOG1\". ";
  685. X    }
  686. X    verDoSay( actor ) =
  687. X    {
  688. X        "You should say what you want to say in double quotes, for example,
  689. X        SAY \"HELLO\". ";
  690. X    }
  691. X    verDoPush( actor ) =
  692. X    {
  693. X        "Pushing "; self.thedesc; " doesn't do anything. ";
  694. X    }
  695. X    verDoWear( actor ) =
  696. X    {
  697. X        "%You% can't wear "; self.thedesc; ". ";
  698. X    }
  699. X    verDoTake( actor ) =
  700. X    {
  701. X        if ( self.location = actor )
  702. X        {
  703. X            "%You% already %have% "; self.thedesc; "! ";
  704. X        }
  705. X        else self.verifyRemove( actor );
  706. X    }
  707. X    verifyRemove( actor ) =
  708. X    {
  709. X      /*
  710. X     *   Check with each container to make sure that the container
  711. X     *   doesn't object to the object's removal.
  712. X     */
  713. X        local loc;
  714. X
  715. X        loc := self.location;
  716. X        while ( loc )
  717. X        {
  718. X            if ( loc <> actor ) loc.verGrab( self );
  719. X            loc := loc.location;
  720. X        }
  721. X    }
  722. X    isVisible( vantage ) =
  723. X    {
  724. X        local loc;
  725. X
  726. X        loc := self.location;
  727. X        if ( loc = nil ) return( nil );
  728. X
  729. X        /* if it's in the vantage, it's visible */
  730. X        if ( loc = vantage ) return( true );
  731. X
  732. X        /*
  733. X         *   if its location's contents are visible, and its location is
  734. X         *   itself visible, it's visible
  735. X         */
  736. X        if ( loc.contentsVisible and loc.isVisible( vantage )) return( true );
  737. X
  738. X        /*
  739. X         *   If the vantage has a location, and the vantage's location's
  740. X         *   contents are visible (if you can see me I can see you), and
  741. X         *   the object is visible from the vantage's location, the object
  742. X         *   is visible
  743. X         */
  744. X        if ( vantage.location <> nil and vantage.location.contentsVisible and
  745. X         self.isVisible( vantage.location ))
  746. X            return( true );
  747. X
  748. X        /* all tests failed:  it's not visible */
  749. X        return( nil );
  750. X    }
  751. X    cantReach( actor ) =
  752. X    {
  753. X        if ( self.location = nil )
  754. X        {
  755. X            if ( actor.location.location )
  756. X               "%You% can't reach that from << actor.location.thedesc >>. ";
  757. X            return;
  758. X        }
  759. X        if ( not self.location.isopenable or self.location.isopen )
  760. X            self.location.cantReach( actor );
  761. X        else "%You%'ll have to open << self.location.thedesc >> first. ";
  762. X    }
  763. X    isReachable( actor ) =
  764. X    {
  765. X        local loc;
  766. X
  767. X        /* if the object is in the room's 'reachable' list, it's reachable */
  768. X        if (find( actor.location.reachable, self ) <> nil )
  769. X            return( true );
  770. X
  771. X        /*
  772. X         *   If the object's container's contents are reachable, and the
  773. X         *   container is reachable, the object is reachable.
  774. X         */
  775. X        loc := self.location;
  776. X    if (find( actor.location.reachable, self ) <> nil )
  777. X        return( true );
  778. X    if ( loc = nil ) return( nil );
  779. X    if ( loc = actor or loc = actor.location ) return( true );
  780. X    if ( loc.contentsReachable )
  781. X        return( loc.isReachable( actor ));
  782. X    return( nil );
  783. X        return( nil );
  784. X    }
  785. X    doTake( actor ) =
  786. X    {
  787. X        local totbulk, totweight;
  788. X
  789. X        totbulk := addbulk( actor.contents ) + self.bulk;
  790. X        totweight := addweight( actor.contents );
  791. X        if ( not actor.isCarrying( self ))
  792. X            totweight := totweight + self.weight;
  793. X
  794. X        if ( totweight > actor.maxweight )
  795. X            "%Your% load is too heavy. ";
  796. X        else if ( totbulk > actor.maxbulk )
  797. X            "%You've% already got %your% hands full. ";
  798. X        else
  799. X        {
  800. X            self.moveInto( actor );
  801. X            "Taken. ";
  802. X        }
  803. X    }
  804. X    verDoDrop( actor ) =
  805. X    {
  806. X        if ( not actor.isCarrying( self ))
  807. X        {
  808. X            "%You're% not carrying "; self.thedesc; "! ";
  809. X        }
  810. X        else self.verifyRemove( actor );
  811. X    }
  812. X    doDrop( actor ) =
  813. X    {
  814. X        actor.location.roomDrop( self );
  815. X    }
  816. X    verDoUnwear( actor ) =
  817. X    {
  818. X        "%You're% not wearing "; self.thedesc; "! ";
  819. X    }
  820. X    verIoPutIn( actor ) =
  821. X    {
  822. X        "I don't know how to put anything into "; self.thedesc; ". ";
  823. X    }
  824. X    verDoPutIn( actor, io ) =
  825. X    {
  826. X        if ( io = nil ) return;
  827. X
  828. X        if ( self.location = io )
  829. X        {
  830. X            caps(); self.thedesc; " is already in "; io.thedesc; "! ";
  831. X        }
  832. X        else if ( io = self or io.isIn( self ))
  833. X        {
  834. X            "%You% can't put "; self.thedesc; " in itself! ";
  835. X        }
  836. X        else self.verifyRemove( actor );
  837. X    }
  838. X    doPutIn( actor, io ) =
  839. X    {
  840. X        self.moveInto( io );
  841. X        "Done. ";
  842. X    }
  843. X    verIoPutOn( actor ) =
  844. X    {
  845. X        "There's no good surface on "; self.thedesc; ". ";
  846. X    }
  847. X    verDoPutOn( actor, io ) =
  848. X    {
  849. X        if ( io = nil ) return;
  850. X
  851. X        if ( self.location = io )
  852. X        {
  853. X            caps(); self.thedesc; " is already on "; io.thedesc; "! ";
  854. X        }
  855. X        else if ( io = self or io.isIn( self ))
  856. X        {
  857. X            "%You% can't put "; self.thedesc; " on itself! ";
  858. X        }
  859. X        else self.verifyRemove( actor );
  860. X    }
  861. X    doPutOn( actor, io ) =
  862. X    {
  863. X        self.moveInto( io );
  864. X        "Done. ";
  865. X    }
  866. X    verIoTakeOut( actor ) = {}
  867. X    ioTakeOut( actor, dobj ) =
  868. X    {
  869. X        dobj.doTakeOut( actor, self );
  870. X    }
  871. X    verDoTakeOut( actor, io ) =
  872. X    {
  873. X        if ( io <> nil and not self.isIn( io ))
  874. X        {
  875. X            caps(); self.thedesc; " isn't in "; io.thedesc; ". ";
  876. X        }
  877. X    self.verDoTake(actor);         /* ensure object can be taken at all */
  878. X    }
  879. X    doTakeOut( actor, io ) =
  880. X    {
  881. X        self.doTake( actor );
  882. X    }
  883. X    verIoTakeOff( actor ) = {}
  884. X    ioTakeOff( actor, dobj ) =
  885. X    {
  886. X        dobj.doTakeOff( actor, self );
  887. X    }
  888. X    verDoTakeOff( actor, io ) =
  889. X    {
  890. X        if ( io <> nil and not self.isIn( io ))
  891. X        {
  892. X            caps(); self.thedesc; " isn't on "; io.thedesc; "! ";
  893. X        }
  894. X    self.verDoTake(actor);         /* ensure object can be taken at all */
  895. X    }
  896. X    doTakeOff( actor, io ) =
  897. X    {
  898. X        self.doTake( actor );
  899. X    }
  900. X    verIoPlugIn( actor ) =
  901. X    {
  902. X        "%You% can't plug anything into "; self.thedesc; ". ";
  903. X    }
  904. X    verDoPlugIn( actor, io ) =
  905. X    {
  906. X        "%You% can't plug "; self.thedesc; " into anything. ";
  907. X    }
  908. X    verIoUnplugFrom( actor ) =
  909. X    {
  910. X        "It's not plugged into "; self.thedesc; ". ";
  911. X    }
  912. X    verDoUnplugFrom( actor, io ) =
  913. X    {
  914. X        if ( io <> nil ) { "It's not plugged into "; io.thedesc; ". "; }
  915. X    }
  916. X    verDoLookin( actor ) =
  917. X    {
  918. X        "There's nothing in "; self.thedesc; ". ";
  919. X    }
  920. X    verDoLookthru( actor ) =
  921. X    {
  922. X        "%You% can't see anything through "; self.thedesc; ". ";
  923. X    }
  924. X    verDoLookunder( actor ) =
  925. X    {
  926. X        "There's nothing under "; self.thedesc; ". ";
  927. X    }
  928. X    verDoInspect( actor ) = {}
  929. X    doInspect( actor ) =
  930. X    {
  931. X        self.ldesc;
  932. X    }
  933. X    verDoRead( actor ) =
  934. X    {
  935. X        "I don't know how to read "; self.thedesc; ". ";
  936. X    }
  937. X    verDoLookbehind( actor ) =
  938. X    {
  939. X        "There's nothing behind "; self.thedesc; ". ";
  940. X    }
  941. X    verDoTurn( actor ) =
  942. X    {
  943. X        "Turning "; self.thedesc; " doesn't have any effect. ";
  944. X    }
  945. X    verDoTurnWith( actor, io ) =
  946. X    {
  947. X        "Turning "; self.thedesc; " doesn't have any effect. ";
  948. X    }
  949. X    verDoTurnTo( actor, io ) =
  950. X    {
  951. X        "Turning "; self.thedesc; " doesn't have any effect. ";
  952. X    }
  953. X    verIoTurnTo( actor ) =
  954. X    {
  955. X        "I don't know how to do that. ";
  956. X    }
  957. X    verDoTurnon( actor ) =
  958. X    {
  959. X        "I don't know how to turn "; self.thedesc; " on. ";
  960. X    }
  961. X    verDoTurnoff( actor ) =
  962. X    {
  963. X        "I don't know how to turn "; self.thedesc; " off. ";
  964. X    }
  965. X    verIoAskAbout( actor ) = {}
  966. X    ioAskAbout( actor, dobj ) =
  967. X    {
  968. X        dobj.doAskAbout( actor, self );
  969. X    }
  970. X    verDoAskAbout( actor, io ) =
  971. X    {
  972. X        "Surely, %you% can't think "; self.thedesc; " knows anything
  973. X        about it! ";
  974. X    }
  975. X    verIoTellAbout( actor ) = {}
  976. X    ioTellAbout( actor, dobj ) =
  977. X    {
  978. X        dobj.doTellAbout( actor, self );
  979. X    }
  980. X    verDoTellAbout( actor, io ) =
  981. X    {
  982. X        "It doesn't look as though "; self.thedesc; " is interested. ";
  983. X    }
  984. X    verDoUnboard( actor ) =
  985. X    {
  986. X        if ( actor.location <> self )
  987. X        {
  988. X            "%You're% not in "; self.thedesc; "! ";
  989. X        }
  990. X        else if ( self.location=nil )
  991. X        {
  992. X            "%You% can't get out of "; self.thedesc; "! ";
  993. X        }
  994. X    }
  995. X    doUnboard( actor ) =
  996. X    {
  997. X        if ( self.fastenitem )
  998. X    {
  999. X        "%You%'ll have to unfasten "; actor.location.fastenitem.thedesc;
  1000. X        " first. ";
  1001. X    }
  1002. X    else
  1003. X    {
  1004. X            "Okay, %you're% no longer in "; self.thedesc; ". ";
  1005. X            self.leaveRoom( actor );
  1006. X        actor.moveInto( self.location );
  1007. X    }
  1008. X    }
  1009. X    verDoAttackWith( actor, io ) =
  1010. X    {
  1011. X        "Attacking "; self.thedesc; " doesn't appear productive. ";
  1012. X    }
  1013. X    verIoAttackWith( actor ) =
  1014. X    {
  1015. X        "It's not very effective to attack with "; self.thedesc; ". ";
  1016. X    }
  1017. X    verDoEat( actor ) =
  1018. X    {
  1019. X        "I think I just lost my appetite.";        // DMB
  1020. X    }
  1021. X    verDoDrink( actor ) =
  1022. X    {
  1023. X        "Don't be ridiculous!";    // DMB
  1024. X    }
  1025. X    verDoGiveTo( actor, io ) =
  1026. X    {
  1027. X        if ( not actor.isCarrying( self ))
  1028. X        {
  1029. X            "%You're% not carrying "; self.thedesc; ". ";
  1030. X        }
  1031. X        else self.verifyRemove( actor );
  1032. X    }
  1033. X    doGiveTo( actor, io ) =
  1034. X    {
  1035. X        self.moveInto( io );
  1036. X        "Done. ";
  1037. X    }
  1038. X    verDoPull( actor ) =
  1039. X    {
  1040. X        "Pulling "; self.thedesc; " doesn't have any effect. ";
  1041. X    }
  1042. X    verDoThrowAt( actor, io ) =
  1043. X    {
  1044. X        if ( not actor.isCarrying( self ))
  1045. X        {
  1046. X            "%You're% not carrying "; self.thedesc; ". ";
  1047. X        }
  1048. X        else self.verifyRemove( actor );
  1049. X    }
  1050. X    doThrowAt( actor, io ) =
  1051. X    {
  1052. X        "%You% miss%es%. ";
  1053. X        self.moveInto( actor.location );
  1054. X    }
  1055. X    verIoThrowAt( actor ) =
  1056. X    {
  1057. X        if ( actor.isCarrying( self ))
  1058. X        {
  1059. X            "%You% could at least drop "; self.thedesc; " first. ";
  1060. X        }
  1061. X    }
  1062. X    ioThrowAt( actor, dobj ) =
  1063. X    {
  1064. X        dobj.doThrowAt( actor, self );
  1065. X    }
  1066. X    verDoThrowTo( actor, io ) =
  1067. X    {
  1068. X        if ( not actor.isCarrying( self ))
  1069. X        {
  1070. X            "%You're% not carrying "; self.thedesc; ". ";
  1071. X        }
  1072. X        else self.verifyRemove( actor );
  1073. X    }
  1074. X    doThrowTo( actor, io ) =
  1075. X    {
  1076. X        "%You% miss%es%. ";
  1077. X        self.moveInto( actor.location );
  1078. X    }
  1079. X    verDoThrow( actor ) =
  1080. X    {
  1081. X        if ( not actor.isCarrying( self ))
  1082. X        {
  1083. X            "%You're% not carrying "; self.thedesc; ". ";
  1084. X        }
  1085. X        else self.verifyRemove( actor );
  1086. X    }
  1087. X    doThrow( actor ) =
  1088. X    {
  1089. X        "Thrown. ";
  1090. X        self.moveInto( actor.location );
  1091. X    }
  1092. X    verDoShowTo( actor, io ) =
  1093. X    {
  1094. X    }
  1095. X    doShowTo( actor, io ) =
  1096. X    {
  1097. X        if ( io <> nil ) { caps(); io.thedesc; " isn't impressed. "; }
  1098. X    }
  1099. X    verIoShowTo( actor ) =
  1100. X    {
  1101. X        caps(); self.thedesc; " isn't impressed. ";
  1102. X    }
  1103. X    verDoClean( actor ) =
  1104. X    {
  1105. X        caps(); self.thedesc; " looks a bit cleaner now. ";
  1106. X    }
  1107. X    verDoCleanWith( actor, io ) = {}
  1108. X    doCleanWith( actor, io ) =
  1109. X    {
  1110. X        caps(); self.thedesc; " looks a bit cleaner now. ";
  1111. X    }
  1112. X    verDoMove( actor ) =
  1113. X    {
  1114. X        "Moving "; self.thedesc; " doesn't reveal anything. ";
  1115. X    }
  1116. X    verDoMoveTo( actor, io ) =
  1117. X    {
  1118. X        "Moving "; self.thedesc; " doesn't reveal anything. ";
  1119. X    }
  1120. X    verIoMoveTo( actor ) =
  1121. X    {
  1122. X        "That doesn't get us anywhere. ";
  1123. X    }
  1124. X    verDoMoveWith( actor, io ) =
  1125. X    {
  1126. X        "Moving "; self.thedesc; " doesn't reveal anything. ";
  1127. X    }
  1128. X    verIoMoveWith( actor ) =
  1129. X    {
  1130. X        caps(); self.thedesc; " doesn't seem to help. ";
  1131. X    }
  1132. X    verDoTypeOn( actor, io ) =
  1133. X    {
  1134. X        "You should say what you want to type in double quotes, for
  1135. X        example, TYPE \"HELLO\" ON KEYBOARD. ";
  1136. X    }
  1137. X    verDoTouch( actor ) =
  1138. X    {
  1139. X        "Touching "; self.thedesc; " doesn't seem to have any effect. ";
  1140. X    }
  1141. X    verDoPoke( actor ) =
  1142. X    {
  1143. X        "Poking "; self.thedesc; " doesn't seem to have any effect. ";
  1144. X    }
  1145. X    genMoveDir = { "%You% can't seem to do that. "; }
  1146. X    verDoMoveN( actor ) = { self.genMoveDir; }
  1147. X    verDoMoveS( actor ) = { self.genMoveDir; }
  1148. X    verDoMoveE( actor ) = { self.genMoveDir; }
  1149. X    verDoMoveW( actor ) = { self.genMoveDir; }
  1150. X    verDoMoveNE( actor ) = { self.genMoveDir; }
  1151. X    verDoMoveNW( actor ) = { self.genMoveDir; }
  1152. X    verDoMoveSE( actor ) = { self.genMoveDir; }
  1153. X    verDoMoveSW( actor ) = { self.genMoveDir; }
  1154. X    verDoSearch( actor ) =
  1155. X    {
  1156. X        "%You% find%s% nothing of interest. ";
  1157. X    }
  1158. X
  1159. X#include "thingext.t"    // DMB: include extensions to standard thing class
  1160. X;
  1161. X
  1162. X/*
  1163. X@item: thing
  1164. XA basic item which can be picked up by the player.  It has no weight
  1165. X(0) and minimal bulk (1).  The \tt weight\ property should be set
  1166. Xto a non-zero value for heavy objects.  The \tt bulk\ property
  1167. Xshould be set to a value greater than 1 for bulky objects, and to
  1168. Xzero for objects that are very small and take essentially no effort
  1169. Xto hold---or, more precisely, don't detract at all from the player's
  1170. Xability to hold other objects (for example, a piece of paper).
  1171. X*/
  1172. Xclass item: thing
  1173. X    weight = 0
  1174. X    bulk = 1
  1175. X;
  1176. X    
  1177. X/*
  1178. X@lightsource: item
  1179. XA portable lamp, candle, match, or other source of light.  The
  1180. Xlight source can be turned on and off with the \tt islit\ property.
  1181. XIf \tt islit\ is \tt true\, the object provides light, otherwise it's
  1182. Xjust an ordinary object.
  1183. X*/
  1184. Xclass lightsource: item
  1185. X    islamp = true
  1186. X;
  1187. X
  1188. X/*
  1189. X@hiddenItem: object
  1190. XThis is an object that is hidden with one of the \tt hider\ classes. 
  1191. XA \tt hiddenItem\ object doesn't have any special properties in its
  1192. Xown right, but all objects hidden with one of the \tt hider\ classes
  1193. Xmust be of class \tt hiddenItem\ so that \tt initSearch\ can find
  1194. Xthem.
  1195. X*/
  1196. Xclass hiddenItem: object
  1197. X;
  1198. X
  1199. X/*
  1200. X@hider: item
  1201. XThis is a basic class of object that can hide other objects in various
  1202. Xways.  The \tt underHider\, \tt behindHider\, and \tt searchHider\ classes
  1203. Xare examples of \tt hider\ subclasses.  The class defines
  1204. Xthe method \tt searchObj(\it actor, list\)\, which is given the list
  1205. Xof hidden items contained in the object (for example, this would be the
  1206. X\tt underCont\ property, in the case of a \tt underHider\), and ``finds''
  1207. Xthe object or objects. Its action is dependent upon a couple of other
  1208. Xproperties of the \tt hider\ object.  The \tt serialSearch\ property,
  1209. Xif \tt true\, indicates that items in the list are to be found one at
  1210. Xa time; if \tt nil\ (the default), the entire list is found on the
  1211. Xfirst try.  The \tt autoTake\ property, if \tt true\, indicates that
  1212. Xthe actor automatically takes the item or items found; if \tt nil\, the
  1213. Xitem or items are moved to the actor's location.  The \tt searchObj\ method
  1214. Xreturns the \it list\ with the found object or objects removed; the
  1215. Xcaller should assign this returned value back to the appropriate
  1216. Xproperty (for example, \tt underHider\ will assign the return value
  1217. Xto \tt underCont\).
  1218. X
  1219. XNote that because the \tt hider\ is hiding something, this class
  1220. Xoverrides the normal \tt verDoSearch\ method to display the
  1221. Xmessage, ``You'll have to be more specific about how you want
  1222. Xto search that.''  The reason is that the normal \tt verDoSearch\
  1223. Xmessage (``You find nothing of interest'') leads players to believe
  1224. Xthat the object was exhaustively searched, and we want to avoid
  1225. Xmisleading the player.  On the other hand, we don't want a general
  1226. Xsearch to be exhaustive for most \tt hider\ objects.  So, we just
  1227. Xdisplay a message letting the player know that the search was not
  1228. Xenough, but we don't give away what they have to do instead.
  1229. X
  1230. XThe objects hidden with one of the \tt hider\ classes must be
  1231. Xof class \tt hiddenItem\.
  1232. X*/
  1233. Xclass hider: item
  1234. X    verDoSearch(actor) =
  1235. X    {
  1236. X    "%You%'ll have to be more specific about how %you% want%s%
  1237. X    to search that. ";
  1238. X    }
  1239. X    searchObj(actor, list) =
  1240. X    {
  1241. X    local found, dest, i, tot;
  1242. X
  1243. X    /* see how much we get this time */
  1244. X    if (self.serialSearch)
  1245. X    {
  1246. X        found := [] + car(list);
  1247. X        list := cdr(list);
  1248. X    }
  1249. X    else
  1250. X    {
  1251. X        found := list;
  1252. X        list := nil;
  1253. X    }
  1254. X
  1255. X    /* figure destination */
  1256. X    dest := actor;
  1257. X    if (not self.autoTake) dest := dest.location;
  1258. X    
  1259. X    /* note what we found, and move it to destination */
  1260. X    "%You% find%s% ";
  1261. X    tot := length(found);
  1262. X    i := 1;
  1263. X    while (i <= tot)
  1264. X    {
  1265. X        found[i].adesc;
  1266. X        if (i+1 < tot) ", ";
  1267. X        else if (i = 1 and tot = 2) " and ";
  1268. X        else if (i+1 = tot and tot > 2) ", and ";
  1269. X        
  1270. X        found[i].moveInto(dest);
  1271. X        i := i + 1;
  1272. X    }
  1273. X
  1274. X    /* say what happened */
  1275. X    if (self.autoTake) ", which %you% take%s%. ";
  1276. X    else "! ";
  1277. X
  1278. X    if (list<>nil and length(list)=0) list := nil;
  1279. X    return(list);
  1280. X    }
  1281. X    serialSearch = nil             /* find everything in one try by default */
  1282. X    autoTake = true               /* actor takes item when found by default */
  1283. X;
  1284. X
  1285. X/*
  1286. X@underHider: hider
  1287. XThis is an object that can have other objects placed under it.  The
  1288. Xobjects placed under it can only be found by looking under the object;
  1289. Xsee the description of \tt hider\ for more information.  Note that you
  1290. Xshould set the \tt underLoc\ property of each hidden object to point
  1291. Xto the \tt underHider\.
  1292. X
  1293. XNote that an \tt underHider\ doesn't allow the \it player\ to put anything
  1294. Xunder the object during the game.  Instead, it's to make it easy for the
  1295. Xgame writer to set up hidden objects while implementing the game.  All you
  1296. Xneed to do to place an object under another object is declare the top
  1297. Xobject as an \tt underHider\, then declare the hidden object normally,
  1298. Xexcept use \tt underLoc\ rather than \tt location\ to specify the
  1299. Xlocation of the hidden object.  The \tt behindHider\ and \tt searchHider\
  1300. Xobjects work similarly.
  1301. X
  1302. XThe objects hidden with \tt underHider\ must be of class \tt hiddenItem\.
  1303. X*/
  1304. Xclass underHider: hider
  1305. X    underCont = []         /* list of items under me (set up by initSearch) */
  1306. X    verDoLookunder(actor) = {}
  1307. X    doLookunder(actor) =
  1308. X    {
  1309. X    if (self.underCont = nil)
  1310. X        "There's nothing else under <<self.thedesc>>. ";
  1311. X    else
  1312. X        self.underCont := self.searchObj(actor, self.underCont);
  1313. X    }
  1314. X;
  1315. X
  1316. X/*
  1317. X@behindHider: hider
  1318. XThis is just like an \tt underHider\, except that objects are hidden
  1319. Xbehind this object.  Objects to be behind this object should have their
  1320. X\tt behindLoc\ property set to point to this object.
  1321. X
  1322. XThe objects hidden with \tt behindHider\ must be of class \tt hiddenItem\.
  1323. X*/
  1324. Xclass behindHider: hider
  1325. X    behindCont = []
  1326. X    verDoLookbehind(actor) = {}
  1327. X    doLookbehind(actor) =
  1328. X    {
  1329. X    if (self.behindCont = nil)
  1330. X        "There's nothing else behind <<self.thedesc>>. ";
  1331. X    else
  1332. X        self.behindCont := self.searchObj(actor, self.behindCont);
  1333. X    }
  1334. X;
  1335. X    
  1336. X/*
  1337. X@searchHider: hider
  1338. XThis is just like an \tt underHider\, except that objects are hidden
  1339. Xwithin this object in such a way that the object must be looked in
  1340. Xor searched.  Objects to be hidden in this object should have their
  1341. X\tt searchLoc\ property set to point to this object.  Note that this
  1342. Xis different from a normal container, in that the objects hidden within
  1343. Xthis object will not show up until the object is explicitly looked in
  1344. Xor searched.
  1345. X
  1346. XThe items hidden with \tt searchHider\ must be of class \tt hiddenItem\.
  1347. X*/
  1348. Xclass searchHider: hider
  1349. X    searchCont = []
  1350. X    verDoSearch(actor) = {}
  1351. X    doSearch(actor) =
  1352. X    {
  1353. X    if (self.searchCont = nil)
  1354. X        "There's nothing else in <<self.thedesc>>. ";
  1355. X    else
  1356. X        self.searchCont := self.searchObj(actor, self.searchCont);
  1357. X    }
  1358. X    verDoLookin(actor) =
  1359. X    {
  1360. X    if (self.searchCont = nil)
  1361. X        pass verDoLookin;
  1362. X    }
  1363. X    doLookin(actor) =
  1364. X    {
  1365. X    if (self.searchCont = nil)
  1366. X        pass doLookin;
  1367. X    else
  1368. X        self.searchCont := self.searchObj(actor, self.searchCont);
  1369. X    }
  1370. X;
  1371. X    
  1372. X
  1373. X/*
  1374. X@fixeditem: thing
  1375. XAn object that cannot be taken or otherwise moved from its location.
  1376. XNote that a \tt fixeditem\ is sometimes part of a movable object;
  1377. Xthis can be done to make one object part of another, ensuring that
  1378. Xthey cannot be separated.  By default, the functions that list a room's
  1379. Xcontents do not automatically describe \tt fixeditem\ objects (because
  1380. Xthe \tt isListed\ property is set to \tt nil\).  Instead, the game author
  1381. Xwill generally describe the \tt fixeditem\ objects separately as part of
  1382. Xthe room's \tt ldesc\.  
  1383. X*/
  1384. Xclass fixeditem: thing      // An immovable object
  1385. X    isListed = nil          // not listed in room/inventory displays
  1386. X    isfixed = true          // Item can't be taken
  1387. X    weight = 0              // no actual weight
  1388. X    bulk = 0
  1389. X    verDoTake( actor ) =
  1390. X    {
  1391. X        "%You% can't have "; self.thedesc; ". ";
  1392. X    }
  1393. X    verDoTakeOut( actor, io ) =
  1394. X    {
  1395. X        self.verDoTake( actor );
  1396. X    }
  1397. X    verDoDrop( actor ) =
  1398. X    {
  1399. X        "%You% can't drop "; self.thedesc; ". ";
  1400. X    }
  1401. X    verDoTakeOff( actor, io ) =
  1402. X    {
  1403. X        self.verDoTake( actor );
  1404. X    }
  1405. X    verDoPutIn( actor, io ) =
  1406. X    {
  1407. X        "%You% can't put "; self.thedesc; " anywhere. ";
  1408. X    }
  1409. X    verDoPutOn( actor, io ) =
  1410. X    {
  1411. X        "%You% can't put "; self.thedesc; " anywhere. ";
  1412. X    }
  1413. X    verDoMove( actor ) =
  1414. X    {
  1415. X        "%You% can't move "; self.thedesc; ". ";
  1416. X    }
  1417. X;
  1418. X
  1419. X/*
  1420. X@readable: item
  1421. XAn item that can be read.  The \tt readdesc\ property is displayed
  1422. Xwhen the item is read.  By default, the \tt readdesc\ is the same
  1423. Xas the \tt ldesc\, but the \tt readdesc\ can be overridden to give
  1424. Xa different message.
  1425. X*/
  1426. Xclass readable: item
  1427. X    verDoRead( actor ) =
  1428. X    {
  1429. X    }
  1430. X    doRead( actor ) =
  1431. X    {
  1432. X        self.readdesc;
  1433. X    }
  1434. X    readdesc =
  1435. X    {
  1436. X        self.ldesc;
  1437. X    }
  1438. X;
  1439. X
  1440. X/*
  1441. X@fooditem: item
  1442. XAn object that can be eaten.  When eaten, the object is removed from
  1443. Xthe game, and \tt global.lastMealTime\ is decremented by the
  1444. X\tt foodvalue\ property.  By default, the \tt foodvalue\ property
  1445. Xis \tt global.eatTime\, which is the time between meals.  So, the
  1446. Xdefault \tt fooditem\ will last for one ``nourishment interval.''
  1447. X*/
  1448. Xclass fooditem: item
  1449. X    verDoEat( actor ) =
  1450. X    {
  1451. X        self.verifyRemove( actor );
  1452. X    }
  1453. X    doEat( actor ) =
  1454. X    {
  1455. X        "That was delicious! ";
  1456. X        // global.lastMealTime := global.lastMealTime - self.foodvalue;
  1457. X        self.moveInto( nil );
  1458. X    }
  1459. X    foodvalue = { return( global.eatTime ); }
  1460. X;
  1461. X
  1462. X/*
  1463. X@dialItem: fixeditem
  1464. XThis class is used for making ``dials,'' which are controls in
  1465. Xyour game that can be turned to a range of numbers.  You must
  1466. Xdefine the property \tt maxsetting\ as a number specifying the
  1467. Xhighest number to which the dial can be turned; the lowest number
  1468. Xon the dial is always 1.  The \tt setting\ property is the dial's
  1469. Xcurrent setting, and can be changed by the player by typing the
  1470. Xcommand ``turn dial to \it number\.''  By default, the \tt ldesc\
  1471. Xmethod displays the current setting.
  1472. X*/
  1473. Xclass dialItem: fixeditem
  1474. X    maxsetting = 10 // it has settings from 1 to this number
  1475. X    setting = 1     // the current setting
  1476. X    ldesc =
  1477. X    {
  1478. X        caps(); self.thedesc; " can be turned to settings
  1479. X        numbered from 1 to << self.maxsetting >>. It's
  1480. X        currently set to << self.setting >>. ";
  1481. X    }
  1482. X    verDoTurn( actor ) = {}
  1483. X    doTurn( actor ) =
  1484. X    {
  1485. X        askio( toPrep );
  1486. X    }
  1487. X    verDoTurnTo( actor, io ) = {}
  1488. X    doTurnTo( actor, io ) =
  1489. X    {
  1490. X        if ( io = numObj )
  1491. X        {
  1492. X            if ( numObj.value < 1 or numObj.value > self.maxsetting )
  1493. X            {
  1494. X                "There's no such setting! ";
  1495. X            }
  1496. X            else if ( numObj.value <> self.setting )
  1497. X            {
  1498. X                self.setting := numObj.value;
  1499. X                "Okay, it's now turned to "; say( self.setting ); ". ";
  1500. X            }
  1501. X            else
  1502. X            {
  1503. X                "It's already set to "; say( self.setting ); "! ";
  1504. X            }
  1505. X        }
  1506. X        else
  1507. X        {
  1508. X            "I don't know how to turn "; self.thedesc;
  1509. X            " to that. ";
  1510. X        }
  1511. X    }
  1512. X;
  1513. X
  1514. X/*
  1515. X@switchItem: fixeditem
  1516. XThis is a class for things that can be turned on and off by the
  1517. Xplayer.  The only special property is \tt isActive\, which is \tt nil\
  1518. Xif the switch is turned off and \tt true\ when turned on.  The object
  1519. Xaccepts the commands ``turn it on'' and ``turn it off,'' as well as
  1520. Xsynonymous constructions, and updates \tt isActive\ accordingly.
  1521. X*/
  1522. Xclass switchItem: fixeditem
  1523. X    verDoSwitch( actor ) = {}
  1524. X    doSwitch( actor ) =
  1525. X    {
  1526. X        self.isActive := not self.isActive;
  1527. X        "Okay, "; self.thedesc; " is now switched ";
  1528. X        if ( self.isActive ) "on"; else "off";
  1529. X        ". ";
  1530. X    }
  1531. X    verDoTurnon( actor ) =
  1532. X    {
  1533. X        if ( self.isActive ) "It's already turned on! ";
  1534. X    }
  1535. X    doTurnon( actor ) =
  1536. X    {
  1537. X        self.isActive := true;
  1538. X        "Okay, it's now turned on. ";
  1539. X    }
  1540. X    verDoTurnoff( actor ) =
  1541. X    {
  1542. X        if ( not self.isActive ) "It's already turned off! ";
  1543. X    }
  1544. X    doTurnoff( actor ) =
  1545. X    {
  1546. X        self.isActive := nil;
  1547. X        "Okay, it's now turned off. ";
  1548. X    }
  1549. X;
  1550. X
  1551. X/*
  1552. X@room: thing
  1553. XA location in the game.  By default, the \tt islit\ property is
  1554. X\tt true\, which means that the room is lit (no light source is
  1555. Xneeded while in the room).  You should create a \tt darkroom\
  1556. Xobject rather than a \tt room\ with \tt islit\ set to \tt nil\ if you
  1557. Xwant a dark room, because other methods are affected as well.
  1558. XThe \tt isseen\ property records whether the player has entered
  1559. Xthe room before; initially it's \tt nil\, and is set to \tt true\
  1560. Xthe first time the player enters.  The \tt roomAction( \it actor,
  1561. Xverb, directObject, preposition, indirectObject\ )\ method is
  1562. Xactivated for each player command; by default, all it does is
  1563. Xcall the room's location's \tt roomAction\ method if the room
  1564. Xis inside another room.  The \tt lookAround( \it verbosity\ )\
  1565. Xmethod displays the room's description for a given verbosity
  1566. Xlevel; \tt true\ means a full description, \tt nil\ means only
  1567. Xthe short description (just the room name plus a list of the
  1568. Xobjects present).  \tt roomDrop( \it object\ )\ is called when
  1569. Xan object is dropped within the room; normally, it just moves
  1570. Xthe object to the room and displays ``Dropped.''  The \tt firstseen\
  1571. Xmethod is called when \tt isseen\ is about to be set \tt true\
  1572. Xfor the first time (i.e., when the player first sees the room);
  1573. Xby default, this routine does nothing, but it's a convenient
  1574. Xplace to put any special code you want to execute when a room
  1575. Xis first entered.  The \tt firstseen\ method is called \it after\
  1576. Xthe room's description is displayed.
  1577. X*/
  1578. X
  1579. X/*
  1580. X *  room: thing
  1581. X *
  1582. X *  A location in the game.  By default, the islit property is
  1583. X *  true, which means that the room is lit (no light source is
  1584. X *  needed while in the room).  You should create a darkroom
  1585. X *  object rather than a room with islit set to nil if you
  1586. X *  want a dark room, because other methods are affected as well.
  1587. X *  The isseen property records whether the player has entered
  1588. X *  the room before; initially it's nil, and is set to true
  1589. X *  the first time the player enters.  The roomAction( actor,
  1590. X *  verb, directObject, preposition, indirectObject ) method is
  1591. X *  activated for each player command; by default, all it does is
  1592. X *  call the room's location's roomAction method if the room
  1593. X *  is inside another room.  The lookAround( verbosity )
  1594. X *  method displays the room's description for a given verbosity
  1595. X *  level; true means a full description, nil means only
  1596. X *  the short description (just the room name plus a list of the
  1597. X *  objects present).  roomDrop( object ) is called when
  1598. X *  an object is dropped within the room; normally, it just moves
  1599. X *  the object to the room and displays "Dropped."  The firstseen
  1600. X *  method is called when isseen is about to be set true
  1601. X *  for the first time (i.e., when the player first sees the room);
  1602. X *  by default, this routine does nothing, but it's a convenient
  1603. X *  place to put any special code you want to execute when a room
  1604. X *  is first entered.  The firstseen method is called after
  1605. X *  the room's description is displayed.
  1606. X*/
  1607. Xroom: thing
  1608. X    topline = true    // DMB -- see nestedroom
  1609. X    
  1610. X    /*
  1611. X     *   'reachable' is the list of explicitly reachable objects, over and
  1612. X     *   above the objects that are here.  This is mostly used in nested
  1613. X     *   rooms to make objects in the containing room accessible.  Most
  1614. X     *   normal rooms will leave this as an empty list.
  1615. X     */
  1616. X    reachable = []
  1617. X    
  1618. X    /*
  1619. X     *   roomCheck is true if the verb is valid in the room.  This
  1620. X     *   is a first pass; generally, its only function is to disallow
  1621. X     *   certain commands in a dark room.
  1622. X     */
  1623. X    roomCheck( v ) = { return( true ); }
  1624. X    islit = true            // rooms are lit unless otherwise specified
  1625. X    isseen = nil            // room has not been seen yet
  1626. X    enterRoom( actor ) =    // sent to room as actor is entering it
  1627. X    {
  1628. X        self.lookAround(( not self.isseen ) or global.verbose );
  1629. X        if ( self.islit )
  1630. X    {
  1631. X        if (not self.isseen) self.firstseen;
  1632. X        self.isseen := true;
  1633. X    }
  1634. X    }
  1635. X    roomAction( a, v, d, p, i ) =
  1636. X    {
  1637. X        if ( self.location ) self.location.roomAction( a, v, d, p, i );
  1638. X    }
  1639. X
  1640. X    /*
  1641. X     *   Whenever a normal object (i.e., one that does not override the
  1642. X     *   default doDrop provided by 'thing') is dropped, the actor's
  1643. X     *   location is sent roomDrop(object being dropped).  By default, 
  1644. X     *   we move the object into this room.
  1645. X     */
  1646. X    roomDrop( obj ) =
  1647. X    {
  1648. X        "Dropped. ";
  1649. X    obj.moveInto( self );
  1650. X    }
  1651. X
  1652. X    /*
  1653. X     *   Whenever an actor leaves this room, we run through the leaveList.
  1654. X     *   This is a list of objects that have registered themselves with us
  1655. X     *   via addLeaveList().  For each object in the leaveList, we send
  1656. X     *   a "leaving" message, with the actor as the parameter.  It should
  1657. X     *   return true if it wants to be removed from the leaveList, nil
  1658. X     *   if it wants to stay.
  1659. X     */
  1660. X    leaveList = []
  1661. X    addLeaveList( obj ) =
  1662. X    {
  1663. X        self.leaveList := self.leaveList + obj;
  1664. X    }
  1665. X    leaveRoom( actor ) =
  1666. X    {
  1667. X        local tmplist, thisobj, i, tot;
  1668. X
  1669. X        tmplist := self.leaveList;
  1670. X    tot := length( tmplist );
  1671. X    i := 1;
  1672. X        while ( i <= tot )
  1673. X        {
  1674. X        thisobj := tmplist[i];
  1675. X            if ( thisobj.leaving( actor ))
  1676. X                self.leaveList := self.leaveList - thisobj;
  1677. X            i := i + 1;
  1678. X        }
  1679. X    }
  1680. X    /*
  1681. X     *   lookAround describes the room.  If verbosity is true, the full
  1682. X     *   description is given, otherwise an abbreviated description (without
  1683. X     *   the room's ldesc) is displayed.
  1684. X     */
  1685. X    nrmLkAround( verbosity ) =      // lookAround without location status
  1686. X    {
  1687. X        local l, cur, i, tot;
  1688. X
  1689. X        if ( verbosity )
  1690. X        {
  1691. X            /* "\n\t"; self.ldesc; */
  1692. X        "\b"; self.ldesc;    /* DMB */
  1693. X
  1694. X            l := self.contents;
  1695. X        tot := length( l );
  1696. X        i := 1;
  1697. X            while ( i <= tot )
  1698. X            {
  1699. X            cur := l[i];
  1700. X                if ( cur.isfixed ) cur.heredesc;
  1701. X                i := i + 1;
  1702. X            }
  1703. X        }
  1704. X        /* "\n\t"; */
  1705. X        if (itemcnt( self.contents ))
  1706. X        {
  1707. X            P(); I();    /* DMB */
  1708. X            "You see "; listcont( self ); " here. ";
  1709. X       }
  1710. X        else {
  1711. X            "\n\t";
  1712. X        }
  1713. X
  1714. X    /*
  1715. X     * DMB add stuff to listcontcont so we can see if there's
  1716. X         * anything to print before putting the paragraph separator out.
  1717. X         */
  1718. X    if (listcontcont(self, nil)) {
  1719. X        P(); I();
  1720. X        listcontcont(self, true);
  1721. X    }
  1722. X
  1723. X    /*
  1724. X     * DMB: Hack for Colossal Cave: since the bear has a location
  1725. X     * that's a method, his actorDesc doesn't get printed by
  1726. X         * the code below.
  1727. X         */
  1728. X    if (Bear.isIn(self))
  1729. X        Bear.actorDesc;
  1730. X
  1731. X        l := self.contents;
  1732. X    tot := length( l );
  1733. X    i := 1;
  1734. X        while ( i <= tot )
  1735. X        {
  1736. X        cur := l[i];
  1737. X            if ( cur.isactor )
  1738. X            {
  1739. X                if ( cur <> Me )
  1740. X                {
  1741. X                    "\n\t";
  1742. X                    cur.actorDesc;
  1743. X                }
  1744. X            }
  1745. X            i := i + 1;
  1746. X        }
  1747. X    }
  1748. X    /* DMB: */
  1749. X    statusline = { self.sdesc; }
  1750. X    statusLine =
  1751. X    {
  1752. X        self.statusline;
  1753. X    }
  1754. X    lookAround( verbosity ) =
  1755. X    {
  1756. X        self.statusline; // DMB -- removed "\b";
  1757. X        self.nrmLkAround( verbosity );
  1758. X    }
  1759. X    
  1760. X    /*
  1761. X     *   Direction handlers.  The directions are all set up to
  1762. X     *   the default, which is no travel allowed.  To make travel
  1763. X     *   possible in a direction, just assign a room to the direction
  1764. X     *   property.
  1765. X     */
  1766. X    north = { return( self.noexit ); }
  1767. X    south = { return( self.noexit ); }
  1768. X    east  = { return( self.noexit ); }
  1769. X    west  = { return( self.noexit ); }
  1770. X    up    = { return( self.noexit ); }
  1771. X    down  = { return( self.noexit ); }
  1772. X    ne    = { return( self.noexit ); }
  1773. X    nw    = { return( self.noexit ); }
  1774. X    se    = { return( self.noexit ); }
  1775. X    sw    = { return( self.noexit ); }
  1776. X    in    = { return( self.noexit ); }
  1777. X    out   = { return( self.noexit ); }
  1778. X    
  1779. X    /*
  1780. X     *   noexit displays a message when the player attempts to travel
  1781. X     *   in a direction in which travel is not possible.
  1782. X     */
  1783. X    noexit = { "%You% can't go that way. "; return( nil ); }
  1784. X;
  1785. X
  1786. X/*
  1787. X@darkroom: room
  1788. XA dark room.  The player must have some object that can act as a
  1789. Xlight source in order to move about and perform most operations
  1790. Xwhile in this room.  Note that the room's lights can be turned
  1791. Xon by setting the room's \tt lightsOn\ property to \tt true\;
  1792. Xdo this instead of setting \tt islit\, because \tt islit\ is
  1793. Xa method which checks for the presence of a light source.
  1794. X*/
  1795. Xclass darkroom: room        // An enterable area which might be dark
  1796. X    islit =                 // true ONLY if something is lighting the room
  1797. X    {
  1798. X        local rem, cur, tot, i;
  1799. X
  1800. X    if ( self.lightsOn ) return( true );
  1801. X
  1802. X    rem := global.lamplist;
  1803. X    tot := length( rem );
  1804. X    i := 1;
  1805. X    while ( i <= tot )
  1806. X    {
  1807. X        cur := rem[i];
  1808. X        if ( cur.isIn( self ) and cur.islit ) return( true );
  1809. X        i := i + 1;
  1810. X    }
  1811. X    return( nil );
  1812. X    }
  1813. X    roomAction( actor, v, dobj, prep, io ) =
  1814. X    {
  1815. X        if ( not self.islit and not v.isTravelVerb and not v.issysverb )
  1816. X    {
  1817. X        "%You% can't see a thing. ";
  1818. X        exit;
  1819. X    }
  1820. X    else pass roomAction;
  1821. X    }
  1822. X    statusLine =
  1823. X    {
  1824. X        if ( self.islit ) pass statusLine;
  1825. X    else "In the dark.";
  1826. X    }
  1827. X    lookAround( verbosity ) =
  1828. X    {
  1829. X        // DMB: Changed pitch dark message
  1830. X        if ( self.islit ) pass lookAround;
  1831. X    else "It is now pitch dark.
  1832. X    If you proceed you will likely fall into a pit."; 
  1833. X
  1834. X    }
  1835. X    noexit =
  1836. X    {
  1837. X        if ( self.islit ) pass noexit;
  1838. X    else
  1839. X    {
  1840. X        darkTravel();
  1841. X        return( nil );
  1842. X    }
  1843. X    }
  1844. X    roomCheck( v ) =
  1845. X    {
  1846. X        if ( self.islit or v.issysverb or v.isTravelVerb ) return( true );
  1847. X    else
  1848. X    {
  1849. X        "It's pitch black.\n";
  1850. X        return( nil );
  1851. X    }
  1852. X    }
  1853. X;
  1854. X
  1855. X/*
  1856. X *  theFloor is a special item that appears in every room (hence
  1857. X *  the non-standard location property).  This object is included
  1858. X *  mostly for completeness, so that the player can refer to the
  1859. X *  floor; otherwise, it doesn't do much.  Dropping an item on the
  1860. X *  floor, for example, moves it to the current room.
  1861. X */
  1862. Xclass theFloor: beditem
  1863. X    onroom = true    // DMB so it won't say "in the ground"
  1864. X    noun = 'floor' 'ground'
  1865. X    sdesc = "ground"
  1866. X    adesc = "the ground"
  1867. X    location =
  1868. X    {
  1869. X        if ( Me.location = self )
  1870. X            return( self.sitloc );
  1871. X        else
  1872. X            return( Me.location );
  1873. X    }
  1874. X    locationOK = true        // suppress warning about location being a method
  1875. X    doSiton( actor ) =
  1876. X    {
  1877. X        "Okay, %you're% now sitting on "; self.thedesc; ". ";
  1878. X        self.sitloc := actor.location;
  1879. END_OF_FILE
  1880. if test 55312 -ne `wc -c <'src/ccr-adv.t1'`; then
  1881.     echo shar: \"'src/ccr-adv.t1'\" unpacked with wrong size!
  1882. fi
  1883. # end of 'src/ccr-adv.t1'
  1884. fi
  1885. if test -f 'src/history.t' -a "${1}" != "-c" ; then 
  1886.   echo shar: Will not clobber existing file \"'src/history.t'\"
  1887. else
  1888. echo shar: Extracting \"'src/history.t'\" \(1403 characters\)
  1889. sed "s/^X//" >'src/history.t' <<'END_OF_FILE'
  1890. X/*
  1891. X * Colossal Cave Revisited
  1892. X *
  1893. X * A remake of Willie Crowther and Don Woods' classic Adventure.
  1894. X * Converted from Donald Ekman's PC port of the original FORTRAN source.
  1895. X * TADS version by David M. Baggett for ADVENTIONS.
  1896. X *
  1897. X * Please document all changes in the history so we know who did what.
  1898. X *
  1899. X * This source code is copylefted under the terms of the GNU Public
  1900. X * License.  Essentially, this means that you are free to do whatever
  1901. X * you wish with this source code, provided you do not charge any
  1902. X * money for it or for any derivative works.
  1903. X *
  1904. X * ADVENTIONS distributes this game, but you are free to do what you will
  1905. X * with it, provided you adhere to the terms in the GNU Public License.
  1906. X * Send correspondence regarding this game or original works distributed
  1907. X * by ADVENTIONS to 
  1908. X *
  1909. X *    ADVENTIONS
  1910. X *    PO Box 851
  1911. X *    Columbia, MD 21044
  1912. X *
  1913. X * If you would like a catalog of releases, please enclose a SASE.  Thanks!
  1914. X *
  1915. X * Contributors
  1916. X *
  1917. X *    dmb    In real life:    David M. Baggett
  1918. X *        Internet:    <dmb@ai.mit.edu>
  1919. X *        Compu$erve:    76440,2671 (ADVENTIONS account)
  1920. X *        GEnie:        ADVENTIONS
  1921. X *
  1922. X * Modification History
  1923. X *
  1924. X * 1-Jan-93    dmb    rec.arts.int-fiction BETA release (source only)
  1925. X *                      For beta testing only -- not for general
  1926. X *            distribution.
  1927. X *
  1928. X * 20-Apr-93    dmb     Version 1.0 release.
  1929. X *
  1930. X *  9-Jul-93    dmb    Widespread version 1.0 release for all supported
  1931. X *            machines.
  1932. X *
  1933. X */
  1934. END_OF_FILE
  1935. if test 1403 -ne `wc -c <'src/history.t'`; then
  1936.     echo shar: \"'src/history.t'\" unpacked with wrong size!
  1937. fi
  1938. # end of 'src/history.t'
  1939. fi
  1940. echo shar: End of archive 8 \(of 11\).
  1941. cp /dev/null ark8isdone
  1942. MISSING=""
  1943. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  1944.     if test ! -f ark${I}isdone ; then
  1945.     MISSING="${MISSING} ${I}"
  1946.     fi
  1947. done
  1948. if test "${MISSING}" = "" ; then
  1949.     echo You have unpacked all 11 archives.
  1950.     echo "Now run buildit.sh to make gam file"
  1951.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1952. else
  1953.     echo You still need to unpack the following archives:
  1954.     echo "        " ${MISSING}
  1955. fi
  1956. ##  End of shell archive.
  1957. exit 0
  1958.