home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume18
/
ccr
/
part09
< prev
next >
Wrap
Internet Message Format
|
1993-07-19
|
62KB
Path: uunet!news.tek.com!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v18i024: ccr - colossal cave (adventure) implemented in TADS, Part09/11
Date: 12 Jul 1993 19:29:11 GMT
Organization: Tektronix, Inc, Redmond, OR, USA
Lines: 2427
Approved: billr@saab.CNA.TEK.COM
Message-ID: <21se27$1d2@ying.cna.tek.com>
NNTP-Posting-Host: saab.cna.tek.com
Xref: uunet comp.sources.games:1824
Submitted-by: David Baggett <dmb@xbar.ai.mit.edu>
Posting-number: Volume 18, Issue 24
Archive-name: ccr/part09
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 9 (of 11)."
# Contents: src/ccr-item.t src/ccr-npc.t src/ccr.t src/makefile
# Wrapped by billr@saab on Mon Jul 12 12:02:45 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/ccr-item.t' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/ccr-item.t'\"
else
echo shar: Extracting \"'src/ccr-item.t'\" \(26875 characters\)
sed "s/^X//" >'src/ccr-item.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 USA
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 * 20-Apr-93 dmb Fixed a bug with the treasures: you could
X * get points for a treasure without being able
X * to carry it.
X */
X
X/*
X * This file defines all carryable items in the game.
X */
Xclass CCR_item: item;
X
X/*
X * Important notes about treasures:
X *
X * If you want to add treasures, use the CCR_treasure_item class. Take
X * care to call the original doDrop and pass doTake if you override the
X * doDrop or doTake methods, because it is in these methods that we
X * handle the scoring.
X *
X * Each treasure is worth self.takepoints points when taken for the
X * first time, and an additional self.depositpoints when deposited
X * in the bulding. Be sure to update global.maxscore and scoreRank
X * if you add treasures (or anything else that gives the player points,
X * for that matter).
X *
X * The proper way to check if an object is a treasure is:
X *
X * if (isclass(obj, CCR_treasure_item))
X * ...
X *
X */
Xclass CCR_treasure_item: CCR_item
X plural = 'treasures' 'goodies' 'loot'
X
X takepoints = 2 // points for taking this treasure
X depositpoints = 12 // points for putting in building
X
X awardedpointsfortaking = nil
X awardedpointsfordepositing = nil
X
X doTake(actor) = {
X inherited.doTake(actor);
X
X //
X // If we didn't get the object (e.g., if the actor's carrying
X // too much), don't give points.
X //
X if (not self.isIn(actor))
X return;
X
X //
X // Give the player some points for taking the treasure
X // the first time.
X //
X // If the player removes a treasure from the bulding
X // floor, reduce his score by the value of that
X // treasure. (This is to prevent him from dropping
X // a treasure off, getting the points, and then giving
X // it to the troll or otherwise losing it.)
X //
X if (not self.awardedpointsfortaking) {
X incscore(self.takepoints);
X self.awardedpointsfortaking := true;
X }
X if (self.awardedpointsfordepositing) {
X if (self.isIn(Inside_Building)) {
X incscore(-1 * self.depositpoints);
X self.awardedpointsfordepositing := nil;
X
X // That's one more treasure to deposit.
X global.treasures := global.treasures + 1;
X }
X }
X }
X doDrop(actor) = {
X self.checkpoints;
X pass doDrop;
X }
X
X checkpoints = {
X //
X // Award points for putting treasure in building (unless
X // we've already awarded the points for depositing this
X // treasure).
X //
X if (Me.isIn(Inside_Building)) {
X if (not self.awardedpointsfortaking) {
X //
X // This shouldn't happen, but just in case...
X //
X incscore(self.takepoints);
X self.awardedpointsfortaking := true;
X }
X else if (not self.awardedpointsfordepositing) {
X incscore(self.depositpoints);
X self.awardedpointsfordepositing := true;
X
X // That's one less treasure to deposit.
X global.treasures := global.treasures - 1;
X }
X }
X }
X;
X
Xset_of_keys: CCR_item, keyItem
X sdesc = "set of keys"
X ldesc = "It's just a normal-looking set of keys."
X location = Inside_Building
X noun = 'keys' 'key' 'keyring' 'set'
X adjective = 'key'
X;
X
Xbrass_lantern: CCR_item, lightsource
X turnsleft = 330 // expert mode (default)
X sdesc = "brass lantern"
X ldesc = {
X "It is a shiny brass lamp";
X
X if (self.islit) {
X if (self.turnsleft <= 30)
X ", glowing dimly.";
X else
X ", glowing brightly.";
X }
X else
X ". It is not currently lit.";
X }
X location = Inside_Building
X noun = 'lamp' 'headlamp' 'headlight' 'lantern' 'light'
X
X ison = nil
X islit = {
X if (self.ison and self.turnsleft > 0)
X return true;
X else
X return nil;
X }
X
X verDoRub(actor) = {}
X doRub(actor) = {
X "Rubbing the electric lamp is not particularly
X rewarding. Anyway, nothing exciting happens.";
X }
X
X verDoTurnon(actor) = {
X if (self.ison)
X "It's already on.";
X }
X doTurnon(actor) = {
X "The lamp is now on.";
X self.ison := true;
X
X if (self.turnsleft > 0)
X notify(self, &wearbatteries, 0);
X else
X " Unfortunately, the batteries seem to
X be dead.";
X }
X verDoTurnoff(actor) = {
X if (not self.ison)
X "It's already off.";
X }
X doTurnoff(actor) = {
X "The lamp is now off.";
X self.turnoff;
X }
X verDoLight(actor) = { self.verDoTurnon(actor); }
X doLight(actor) = { self.doTurnon(actor); }
X
X verIoPutIn(actor) = {}
X ioPutIn(actor, dobj) = {
X if (dobj = old_batteries)
X "Those batteries are dead; they won't
X do any good at all.";
X else if (dobj = fresh_batteries)
X self.do_replace;
X else
X "The only thing you might successfully put in
X the lamp is a fresh pair of batteries.";
X }
X
X // The following method is called when the player gets resurrected.
X turnoff = {
X if (self.ison) {
X self.ison := nil;
X unnotify(self, &wearbatteries);
X }
X }
X
X wearbatteries = {
X self.turnsleft := self.turnsleft - 1;
X
X if (self.turnsleft < 1) {
X P(); I();
X "Your lamp has run out of power. ";
X
X if (self.replace_batteries) {
X // do nothing
X }
X else if (Me.location.isoutside) {
X "There's not much point in wandering
X around out here, and you can't
X explore the cave without a lamp. So
X let's just call it a day.";
X
X call_it_a_day();
X }
X }
X else if (self.turnsleft = 30) {
X P(); I();
X "Your lamp is getting dim. ";
X
X if (self.replace_batteries) {
X // do nothing.
X }
X else if (fresh_batteries.used) {
X // DMB: changed the wording of this
X // slightly for convenience.
X "You're also out of spare batteries.
X You'd best start wrapping this up.";
X }
X else if (fresh_batteries.location <> nil) {
X "You'd best go back for those
X batteries.";
X }
X else {
X "You'd best start wrapping this up,
X unless you can find some fresh
X batteries. I seem to recall there's a
X vending machine in the maze. Bring
X some coins with you.";
X }
X }
X }
X
X replace_batteries = {
X if (fresh_batteries.isIn(Me.location)) {
X " I'm taking the liberty of replacing the
X batteries.";
X
X self.do_replace;
X
X return true;
X }
X else
X return nil;
X }
X
X do_replace = {
X fresh_batteries.used := true;
X fresh_batteries.moveInto(nil);
X old_batteries.moveInto(Me.location);
X self.turnsleft := 2500;
X }
X;
X
Xblack_rod: CCR_item
X sdesc = "black rod"
X ldesc = "It's a three foot black rod with a rusty star on an end."
X location = In_Debris_Room
X noun = 'rod' 'star'
X adjective = 'black' 'rusty' 'star'
X
X verDoWave(actor) = {}
X doWave(actor) = {
X if (self.isIn(West_Side_Of_Fissure) or
X self.isIn(On_East_Bank_Of_Fissure)) {
X
X if (global.closed) {
X "Peculiar. Nothing happens.";
X }
X else {
X if (CrystalBridge.exists) {
X "The crystal bridge has
X vanished!";
X CrystalBridge.exists := nil;
X }
X else {
X "A crystal bridge now spans
X the fissure.";
X CrystalBridge.exists := true;
X }
X }
X }
X else
X "Nothing happens.";
X }
X;
X
Xwicker_cage: CCR_item, container
X sdesc = "wicker cage"
X ldesc = {
X "It's a small wicker cage.";
X }
X location = In_Cobble_Crawl
X noun = 'cage'
X adjective = 'small' 'wicker' 'bird'
X
X verDoPutIn(actor) = {}
X doPutIn(actor, io) = {
X if (io <> little_bird) {
X caps(); self.thedesc; " isn't big enough
X to hold "; io.thedesc; ".";
X }
X else
X pass doPutIn;
X }
X;
X
X/*
X * The following rod is actually an explosive. Don't ask ME how anyone
X * is supposed to figure this out from the description. I've left it
X * the way it was even though I think it's pretty bogus.
X *
X * I've added the words 'explosive' and 'dynamite' as nouns and adjectives,
X * and 'blast' as an adjective. Perhaps this will give some lucky soul
X * a clue.
X */
Xblack_mark_rod: CCR_item
X sdesc = "marked rod"
X ldesc = {
X "It's a three foot black rod with a rusty mark on an end.";
X }
X location = At_Sw_End
X noun = 'rod' 'mark' 'explosive' 'dynamite'
X adjective = 'black' 'rusty' 'mark' 'blast' 'explosive' 'dynamite'
X
X verDoWave(actor) = {}
X doWave(actor) = { "Nothing happens."; }
X
X verDoBlastWith(actor) = {}
X doBlastWith(actor) = { endpuzzle(); }
X;
X
Xlittle_bird: CCR_item
X sdesc = {
X if (not self.isIn(wicker_cage))
X "cheerful ";
X
X "little bird";
X }
X ldesc = {
X if (self.isIn(wicker_cage))
X "The little bird looks unhappy in the cage.";
X else
X "The cheerful little bird is sitting here singing.";
X }
X location = In_Bird_Chamber
X noun = 'bird'
X
X verDoFeed(actor) = {}
X doFeed(actor) = {
X "It's not hungry. (It's merely pinin' for the fjords).
X Besides, you have no bird seed.";
X }
X verIoGiveTo(actor) = {
X "I suspect it would prefer bird seed.";
X }
X
X /*
X * Catch any attempt to remove the bird. It won't cooperate
X * When the player has the rod with the star on the end.
X */
X verifyRemove(actor) = {
X if (self.isIn(Me)) {
X "You already have the little bird. If
X you take it out of the cage it will likely
X fly away from you.";
X }
X else if (black_rod.isIn(Me)) {
X "The bird was unafraid when you entered, but
X as you approach it becomes disturbed and you
X cannot catch it.";
X }
X else
X pass verifyRemove;
X }
X
X verDoTake(actor) = {
X if (not wicker_cage.isIn(Me))
X "You can catch the bird, but you cannot carry it.";
X else
X pass verDoTake;
X }
X doTake(actor) = {
X self.doPutIn(Me, wicker_cage);
X }
X
X verDoPutIn(actor) = {}
X doPutIn(actor, io) = {
X if (io <> wicker_cage) {
X "Don't put the poor bird in "; io.thedesc; "!";
X }
X else
X pass doPutIn;
X }
X
X verDoAttack(actor) = {
X if (self.isIn(wicker_cage))
X "Oh, leave the poor unhappy bird alone.";
X else {
X "The little bird is now dead. Its body disappears.";
X self.moveInto(nil);
X }
X }
X
X verDoDrop(actor) = {}
X doDrop(actor) = {
X if (self.isIn(Snake.location)) {
X "The little bird attacks the green snake, and
X in an astounding flurry drives the snake
X away.";
X
X Snake.moveInto(nil);
X self.moveInto(Me.location);
X }
X else if (self.isIn(Dragon.location)) {
X "The little bird attacks the green dragon,
X and in an astounding flurry gets burnt to a
X cinder. The ashes blow away.";
X
X self.moveInto(nil);
X }
X else
X pass doDrop;
X }
X
X doTakeOut(actor, io) = {
X // Drop ourselves automatically. (The bird flies away
X // when taken out of a container.)
X self.doDrop(actor);
X }
X;
X
Xvelvet_pillow: CCR_item
X sdesc = "velvet pillow"
X ldesc = "It's just a small velvet pillow."
X location = In_Soft_Room
X noun = 'pillow'
X adjective = 'velvet' 'small'
X;
X
Xgiant_bivalve: CCR_item
X opened = nil
X
X sdesc = {
X if (self.opened)
X "giant oyster";
X else
X "giant clam";
X
X if (self.isIn(Me))
X " >grunt!<";
X }
X thedesc = {
X if (self.opened)
X "the giant oyster";
X else
X "the giant clam";
X }
X
X ldesc = {
X "It's an enormous clam with its shell tightly closed.";
X
X // During the endgame, the oyster has something
X // written on it.
X if (self.isIn(At_Ne_End) or self.isIn(At_Sw_End)) {
X "Interesting. There seems to be something
X written on the underside of the oyster.";
X }
X }
X location = In_Shell_Room
X noun = 'clam' 'oyster' 'bivalve' 'shell'
X adjective = 'giant' 'enormous' 'massive' 'big' 'huge' 'tightly'
X 'closed' 'five' 'foot' 'five-foot' '5-foot'
X
X verDoOpen(actor) = { self.verDoOpenWith(actor, nil); }
X doOpen(actor) = {
X if (trident.isIn(Me)) {
X //
X // In the original, "open clam" would work
X // ask long as you were carrying the trident,
X // but this seems very prone to accidental
X // solving, and since we aren't limited to
X // two word parsing, I've just taken the
X // liberty of forcing the player to type
X // "open clam with trident."
X //
X "You'll need to be a bit more specific that
X that, I'm afraid.";
X }
X else {
X "You don't have anything strong enough to
X open "; self.thedesc; ".";
X }
X }
X verDoOpenWith(actor, io) = {
X if (self.isIn(Me)) {
X "I advise you to put down "; self.thedesc;
X " before opening it. >Strain!<";
X }
X }
X doOpenWith(actor, io) = {
X if (io = trident) {
X if (self.opened) {
X "The oyster creaks open, revealing nothing
X but oyster inside. It promptly snaps shut
X again.";
X }
X else {
X "A glistening pearl falls out of the clam and
X rolls away. Goodness, this must really be an
X oyster. (I never was very good at
X identifying bivalves.) Whatever it is, it
X has now snapped shut again.";
X
X self.opened := true;
X pearl.moveInto(In_A_Cul_De_Sac);
X }
X }
X else {
X caps(); io.thedesc; " isn't strong enough to
X open "; self.thedesc; ".";
X }
X }
X verDoBreak(actor) = {
X "The shell is very strong and is impervious to
X attack.";
X }
X verDoAttack(actor) = { self.verDoBreak(actor); }
X verDoAttackWith(actor, io) = { self.verDoBreak(actor); }
X
X //
X // The oyster has a hint written on its underside once
X // the cave's closed. (Look, don't ask me, I'm just
X // porting this game!)
X //
X verDoRead(actor) = {
X if (not self.isIn(At_Ne_End) and not self.isIn(At_Sw_End))
X "You're babbling -- snap out of it!";
X }
X doRead(actor) = {
X //
X // This is supposed to be a hint (i.e., it's supposed
X // to cost points), but I've put it in as a freebie
X // because I think the final puzzle is absurdly
X // difficult even with the free hint.
X //
X "It says, \"There is something strange about this
X place, such that one of the words I've always known
X now has a new effect.\"";
X }
X;
X
Xspelunker_today: CCR_item, readable
X sdesc = "recent issues of \"Spelunker Today\""
X adesc = { self.sdesc; }
X ldesc = { self.readdesc; }
X readdesc = {
X // This said "magazine is written" in the original,
X // which is obviously wrong given the sdesc.
X
X "I'm afraid the magazines are written in Dwarvish.";
X }
X
X location = In_Anteroom
X plural = 'magazines'
X noun = 'magazine' 'issue' 'issue' 'spelunker'
X 'today' 'dwarvish'
X adjective = 'spelunker' 'today' 'dwarvish'
X
X doDrop(actor) = {
X if (Me.isIn(At_Witts_End))
X silent_incscore(global.wittpoints);
X
X pass doDrop;
X }
X doTake(actor) = {
X if (Me.isIn(At_Witts_End))
X silent_incscore(-1 * global.wittpoints);
X
X pass doTake;
X }
X;
X
Xtasty_food: CCR_item, fooditem
X sdesc = "some tasty food"
X adesc = { self.sdesc; }
X thedesc = "the tasty food"
X ldesc = "Sure looks yummy!"
X location = Inside_Building
X noun = 'food' 'ration' 'rations' 'tripe'
X adjective = 'yummy' 'tasty' 'delicious' 'scrumptious'
X;
X
Xbottle: CCR_item
X haswater = true
X hasoil = nil
X
X sdesc = {
X if (self.haswater)
X "small bottle of water";
X else if (self.hasoil)
X "small bottle of oil";
X else
X "small empty bottle";
X }
X location = Inside_Building
X noun = 'bottle' 'jar' 'flask'
X
X verIoPutIn(actor) = {}
X ioPutIn(actor, dobj) = {
X if (self.haswater)
X "The bottle is already full of water.";
X else if (self.hasoil)
X "The bottle is already full of oil.";
X else if (dobj = Stream) {
X "The bottle is now full of water.";
X self.haswater := true;
X }
X else if (dobj = Oil) {
X "The bottle is now full of oil.";
X self.hasoil := true;
X }
X else {
X "I'm not sure how to do that.";
X }
X }
X
X verDoFill(actor) = {}
X doFill(actor) = {
X if (self.isIn(Stream.location))
X self.ioPutIn(actor, Stream);
X else if (self.isIn(Oil.location))
X self.ioPutIn(actor, Oil);
X else
X "There is nothing here with which to fill the
X bottle.";
X }
X
X verDoEmpty(actor) = {}
X doEmpty(actor) = {
X if (self.haswater or self.hasoil)
X "Your bottle is now empty and the ground is
X now wet.";
X else
X "The bottle is already empty!";
X
X self.empty;
X }
X
X verDoPourOn(actor, io) = {}
X doPourOn(actor, io) = {
X if (io = RustyDoor) {
X if (self.hasoil) {
X "The oil has freed up the hinges so that the
X door will now move, although it requires some
X effort.";
X
X RustyDoor.isoiled := true;
X }
X else if (self.haswater) {
X "The hinges are quite thoroughly
X rusted now and won't budge.";
X }
X else {
X "The bottle is empty.";
X }
X
X self.empty;
X }
X else if (io = Plant) {
X if (self.haswater) {
X Plant.water;
X }
X else if (self.hasoil) {
X "The plant indignantly shakes the oil
X off its leaves and asks, \"Water?\"";
X }
X else {
X "The bottle is empty.";
X }
X
X self.empty;
X }
X else if (io = theFloor)
X self.doEmpty(actor);
X else
X "That doesn't seem productive.";
X }
X
X verDoDrink(actor) = {
X if (not self.hasoil and not self.haswater)
X "The bottle is empty.";
X
X if (self.hasoil)
X "Don't drink the oil, you fool!";
X }
X doDrink(actor) = {
X "The bottle is now empty.";
X self.empty;
X }
X
X empty = {
X self.haswater := nil;
X self.hasoil := nil;
X }
X;
Xwater_in_the_bottle: CCR_decoration
X sdesc = "water in the bottle"
X adesc = "water"
X ldesc = "It looks like ordinary water to me."
X locationOK = true // tell compiler OK for location to be method
X location = {
X if (bottle.haswater)
X return bottle.location;
X else
X return nil;
X }
X noun = 'water' 'h2o'
X
X verDoPourOn(actor, io) = {}
X doPourOn(actor, io) = { bottle.doPourOn(actor, io); }
X verDoDrink(actor) = { bottle.verDoDrink(actor); }
X doDrink(actor) = { bottle.doDrink(actor); }
X;
Xoil_in_the_bottle: CCR_decoration
X sdesc = "oil in the bottle"
X adesc = "oil"
X ldesc = "It looks like ordinary oil to me."
X locationOK = true // tell compiler OK for location to be method
X location = {
X if (bottle.hasoil)
X return bottle.location;
X else
X return nil;
X }
X noun = 'oil' 'lubricant' 'grease'
X
X verDoPourOn(actor, io) = {}
X doPourOn(actor, io) = { bottle.doPourOn(actor, io); }
X verDoDrink(actor) = { bottle.verDoDrink(actor); }
X doDrink(actor) = { bottle.doDrink(actor); }
X;
X
Xaxe: CCR_item
X nograb = nil // hack for when you attack the bear with it
X
X sdesc = "dwarf's axe"
X ldesc = {
X if (self.nograb)
X "It's lying beside the bear.";
X else
X "It's just a little axe.";
X }
X location = nil // created when first dwarf attacks
X noun = 'axe'
X adjective = 'little' 'dwarf' 'dwarvish' 'dwarven' 'dwarf\'s'
X
X verifyRemove(actor) = {
X if (self.nograb)
X "No chance. It's lying beside the ferocious
X bear, quite within harm's way.";
X }
X;
X
Xfresh_batteries: CCR_item
X used = nil // used in lamp yet?
X
X sdesc = "fresh batteries"
X ldesc = {
X "They look like ordinary batteries. (A sepulchral
X voice says, \"Still going!\")";
X }
X noun = 'batteries' 'battery' 'duracel' 'duracell' 'duracels'
X 'duracells' 'energizer' 'energizers' 'everready'
X 'everreadies' 'eveready' 'evereadies'
X adjective = 'fresh'
X
X location = nil
X;
X
Xold_batteries: CCR_item
X sdesc = "worn-out batteries"
X ldesc = {
X "They look like ordinary batteries.";
X }
X noun = 'batteries' 'battery' 'duracel' 'duracell' 'duracels'
X 'duracells' 'energizer' 'energizers' 'everready'
X 'everreadies' 'eveready' 'evereadies'
X adjective = 'worn' 'out' 'worn-out' 'dead' 'empty' 'dry' 'old'
X
X location = nil
X;
X
X/*
X * Treasures
X */
Xlarge_gold_nugget: CCR_treasure_item
X depositpoints = 10
X sdesc = "large gold nugget"
X ldesc = "It's a large sparkling nugget of gold!"
X location = In_Nugget_Of_Gold_Room
X noun = 'gold' 'nugget'
X adjective = 'gold' 'large'
X;
Xseveral_diamonds: CCR_treasure_item
X depositpoints = 10
X sdesc = "several diamonds"
X adesc = { self.sdesc; }
X thedesc = "the diamonds"
X ldesc = "They look to be of the highest quality!"
X location = West_Side_Of_Fissure
X noun = 'diamond' 'diamonds'
X adjective = 'several' 'high' 'quality' 'high-quality'
X;
Xbars_of_silver: CCR_treasure_item
X depositpoints = 10
X sdesc = "bars of silver"
X adesc = { self.sdesc; }
X ldesc = "They're probably worth a fortune!"
X location = Low_N_S_Passage
X noun = 'silver' 'bars'
X adjective = 'silver'
X;
Xprecious_jewelry: CCR_treasure_item
X depositpoints = 10
X sdesc = "precious jewelry"
X adesc = { self.sdesc; }
X ldesc = "It's all quite exquisite!"
X location = In_South_Side_Chamber
X noun = 'jewel' 'jewels' 'jewelry'
X adjective = 'precious' 'exquisite'
X;
Xrare_coins: CCR_treasure_item
X depositpoints = 10
X sdesc = "rare coins"
X adesc = { self.sdesc; }
X ldesc = "They're a numismatist's dream!"
X location = In_West_Side_Chamber
X noun = 'coins'
X adjective = 'rare'
X;
Xtreasure_chest: CCR_treasure_item
X spotted = nil // found yet? See also Dead_End_13 in ccr-room.t
X
X depositpoints = 12
X sdesc = "treasure chest"
X ldesc = {
X "It's the pirate's treasure chest, filled with
X riches of all kinds!";
X }
X location = nil
X noun = 'chest' 'box' 'treasure' 'riches'
X adjective = 'pirate' 'pirate\'s' 'treasure'
X;
Xgolden_eggs: CCR_treasure_item
X depositpoints = 14
X sdesc = "nest of golden eggs"
X ldesc = "The nest is filled with beautiful golden eggs!"
X location = In_Giant_Room
X noun = 'eggs' 'egg' 'nest'
X adjective = 'golden' 'beautiful'
X;
Xtrident: CCR_treasure_item
X depositpoints = 14
X sdesc = "jeweled trident"
X ldesc = "The trident is covered with fabulous jewels!"
X location = In_Cavern_With_Waterfall
X noun = 'trident'
X adjective = 'jeweled' 'jewel-encrusted' 'encrusted' 'fabulous'
X
X verIoOpenWith(actor) = {}
X ioOpenWith(actor, dobj) = {
X dobj.doOpenWith(actor, self);
X }
X;
Xming_vase: CCR_treasure_item
X depositpoints = 14
X sdesc = "ming vase"
X ldesc = {
X "It's a delicate, previous, ming vase!";
X }
X location = In_Oriental_Room
X noun = 'vase' 'ming' 'shards' 'pottery'
X
X doDrop(actor) = {
X if (velvet_pillow.isIn(Me.location)) {
X "The vase is now resting, delicately, on a
X velvet pillow.";
X
X self.moveInto(Me.location);
X
X self.checkpoints; // make sure we count points
X // for putting this in building
X }
X else {
X "The ming vase drops with a delicate crash.";
X self.shatter;
X }
X }
X
X verIoPutIn(actor) = {}
X ioPutIn(actor, dobj) = {
X if (dobj = Stream or dobj = Oil) {
X "The sudden change in temperature has
X delicately shattered the vase.";
X
X self.shatter;
X }
X else {
X "I'm not sure how to do that.";
X }
X }
X
X verDoFill(actor) = {}
X doFill(actor) = {
X if (self.isIn(Stream.location))
X self.ioPutIn(actor, Stream);
X else if (self.isIn(Oil.location))
X self.ioPutIn(actor, Oil);
X else
X "There is nothing here with which to fill the
X vase.";
X }
X
X verDoBreak(actor) = {}
X doBreak(actor) = {
X "You have taken the vase and hurled it delicately to
X the ground.";
X
X self.shatter;
X }
X
X shatter = {
X self.moveInto(nil);
X shards.moveInto(Me.location);
X }
X;
Xshards: CCR_item
X sdesc = "some worthless shards of pottery"
X adesc = { self.sdesc; }
X ldesc = {
X "They're just worthless shards of pottery";
X
X if (self.location = Me.location) // not in a container
X ", littered everywhere.";
X else
X ".";
X
X " They look to be the remains of what was once a
X beautiful vase. I guess some oaf must have dropped it.";
X }
X
X noun = 'pottery' 'shards'
X adjective = 'worthless'
X;
X
Xegg_sized_emerald: CCR_treasure_item
X depositpoints = 14
X sdesc = "emerald the size of a plover's egg"
X adesc = { "an "; self.sdesc; }
X ldesc = "Plover's eggs, by the way, are quite large."
X location = In_Plover_Room
X noun = 'emerald'
X adjective = 'egg-sized'
X;
Xplatinum_pyramid: CCR_treasure_item
X depositpoints = 14
X sdesc = "platinum pyramid"
X ldesc = "The platinum pyramid is 8 inches on a side!"
X location = In_Dark_Room
X noun = 'platinum' 'pyramid'
X adjective = 'platinum' 'pyramidal'
X;
Xpearl: CCR_treasure_item
X depositpoints = 14
X sdesc = "glistening pearl"
X ldesc = "It's incredibly large!"
X location = nil
X noun = 'pearl'
X adjective = 'glistening' 'incredible' 'incredibly' 'large'
X;
Xpersian_rug: CCR_treasure_item
X depositpoints = 14
X sdesc = {
X "Persian rug";
X
X if (self.isIn(Dragon.location))
X " (upon which the dragon is sprawled out)";
X }
X adesc = {
X "a "; self.sdesc;
X }
X ldesc = {
X if (self.isIn(Dragon.location))
X "The dragon is sprawled out on the Persian rug!!";
X else if (not self.isIn(Me))
X "The Persian rug is spread out on the floor here.";
X else
X "The Persian rug is the finest you've ever seen!";
X }
X location = In_Secret_Canyon
X noun = 'rug' 'persian'
X adjective = 'persian' 'fine' 'finest' 'dragon\'s'
X
X verifyRemove(actor) = {
X if (self.isIn(Dragon.location))
X "You'll need to get the dragon to move first!";
X }
X;
Xrare_spices: CCR_treasure_item
X depositpoints = 14
X sdesc = "rare spices"
X adesc = { self.sdesc; }
X ldesc = "They smell wonderfully exotic!"
X location = In_Chamber_Of_Boulders
X noun = 'spices' 'spice'
X adjective = 'rare' 'exotic'
X
X verDoSmell(actor) = {}
X doSmell(actor) = { self.ldesc; }
X;
Xgolden_chain: CCR_treasure_item, keyedLockable
X depositpoints = 14
X isfixed = {
X if (self.islocked)
X return true;
X else
X return nil;
X }
X isListed = { return not self.isfixed; }
X
X mykey = set_of_keys // pretty handy, those!
X islocked = true // locked meaning "locked to the wall."
X isopen = nil // need this since we're keyedLockable
X
X sdesc = "golden chain"
X ldesc = {
X "The chain has thick links of solid gold!";
X
X if (self.islocked) {
X if (Bear.wasreleased)
X "It's locked to the wall!";
X else
X " The bear is chained to the wall with it!";
X }
X }
X heredesc = {
X if (self.isfixed) {
X P(); I();
X if (Bear.wasreleased)
X "There is a golden chain here, locked
X to the wall.";
X else
X "There is a golden chain here, and a
X large cave bear is locked to the wall
X with it!";
X }
X }
X
X location = In_Barren_Room
X noun = 'chain' 'links' 'shackles'
X adjective = 'solid' 'gold' 'golden' 'thick'
X
X verDoLock(actor) = {
X if (not self.isIn(In_Barren_Room)) {
X "There is nothing here to which the chain can
X be locked.";
X }
X else
X pass verDoLock;
X }
X verDoLockWith(actor, io) = {
X self.verDoLock(actor); // -> pass verDoLock (OK?)
X pass verDoLockWith;
X }
X
X verDoUnlock(actor) = {
X if (not Bear.wasreleased and not Bear.istame) {
X "There is no way to get past the bear to
X unlock the chain, which is probably just as
X well.";
X }
X else
X pass verDoUnlock;
X }
X verDoUnlockWith(actor, io) = {
X self.verDoUnlock(actor);
X pass verDoUnlockWith;
X }
X
X // inherit proper doUnlock from keyedLockable
X doUnlockWith(actor, io) = {
X Bear.wasreleased := true;
X pass doUnlockWith;
X }
X
X verifyRemove(actor) = {
X if (not Bear.wasreleased) {
X if (Bear.istame)
X "It's locked to the friendly bear.";
X else
X "It's locked to the ferocious bear!";
X }
X else if (self.islocked)
X "The chain is still locked to the wall.";
X }
X;
END_OF_FILE
if test 26875 -ne `wc -c <'src/ccr-item.t'`; then
echo shar: \"'src/ccr-item.t'\" unpacked with wrong size!
fi
# end of 'src/ccr-item.t'
fi
if test -f 'src/ccr-npc.t' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/ccr-npc.t'\"
else
echo shar: Extracting \"'src/ccr-npc.t'\" \(25988 characters\)
sed "s/^X//" >'src/ccr-npc.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 * 20-Apr-93 dmb Incorporated Mike Roberts' changes to make
X * this a lot faster. Uses the new intersect
X * built-in, so CCR must now be built with TADS
X * >= 2.0.13.
X *
X */
X
X/*
X * This file handles non-player character (dwarves and pirate) movement.
X *
X * Be sure to update exitlist and/or npclist if you add any new travel
X * verbs to CCR_Room.
X */
XinitNPC: function
X{
X local o;
X
X //
X // Construct list of NPC exits for each room
X //
X o := firstobj(CCR_room);
X while (o <> nil) {
X if (not o.noNPCs) {
X //
X // Add this room to the global list of rooms
X // the NPC's can be in.
X //
X global.NPCrooms := global.NPCrooms + o;
X
X do_exitlist(o);
X do_npclist(o);
X }
X else if (global.debug) {
X //
X // Debugging info:
X //
X "\b\"<< o.sdesc >>\" is off limits to NPC's.";
X }
X
X o := nextobj(o, CCR_room);
X }
X}
X
X/*
X * Add standard exits to the list of exits that NPC's should check
X * when they're wandering about randomly.
X */
Xdo_exitlist: function(o)
X{
X local exitlist, i, j, gotit;
X local tot1, tot2;
X
X //
X // List of all exit property names that NPC's will consider.
X // Note that magic words are left out because NPC's don't
X // know them.
X //
X exitlist := [
X &north &south &east &west
X &ne &nw &se &sw
X &up &down &in &out
X
X &jump &upstream &downstream &forwards &outdoors
X &left &right &cross &over &across &road &forest
X &valley &stairs &building &gully &stream &rock &bed
X &crawl &cobble &tosurface &dark &passage &low &canyon
X &awkward &giant &view &pit &crack &steps &dome &hall
X &barren &debris &hole &wall &broken &floor &toroom
X &slit &slab &depression &entrance &secret &cave
X &bedquilt &oriental &cavern &shell &reservoir &main
X &office &fork
X ];
X tot1 := length(exitlist);
X
X for (i := 1; i <= tot1; i++) {
X //
X // If this exit property is a simple
X // object (prop 2), NPC's can use it, so
X // add it to the room's NPC exit list.
X //
X // Make sure we don't add the same
X // desination room twice. Just because
X // there are multiple travel verbs from
X // one place to another doesn't mean the
X // destination should be more likely.
X //
X if (proptype(o, exitlist[i]) = 2
X and not o.(exitlist[i]).noNPCs) {
X
X //
X // Search current exitlist for
X // this exit's destination.
X //
X gotit := (find(o.NPCexits, o.(exitlist[i])) <> nil);
X if (not gotit)
X o.NPCexits := o.NPCexits + exitlist[i];
X }
X }
X}
X
X/*
X * Add NPC special exits to the list of exits that NPC's should check
X * when they're wandering about randomly.
X */
Xdo_npclist: function(o)
X{
X local npclist, i, tot;
X
X //
X // NPC exits. These get considered if even if they're methods.
X // The only way they won't be added to the list of exits to
X // try is if they're = nil and not methods.
X //
X npclist := [
X &NPCexit1 &NPCexit2 &NPCexit3 &NPCexit4
X &NPCexit5 &NPCexit6 &NPCexit7 &NPCexit8
X ];
X
X tot := length(npclist);
X for (i := 1; i <= tot; i++) {
X //
X // If this NPC exit property is anything but
X // nil (i.e., just nil, and not a method
X // that returns nil). then NPC's can use it.
X // Methods that return nil are fine because
X // they might be conditional on some game
X // events, like the crystal bridge having
X // been created, etc.
X //
X if (proptype(o, npclist[i]) <> 5) // not = nil
X o.NPCexits := o.NPCexits + npclist[i];
X }
X}
X
X/*
X * Make sure NPC room connections are sound.
X */
Xcheck_connections: function
X{
X local o;
X
X o := firstobj(CCR_room);
X while (o <> nil) {
X if (not o.noNPCs)
X do_debug(o);
X
X o := nextobj(o, CCR_room);
X }
X}
X
Xdo_debug: function(o)
X{
X local i, tot;
X
X if (length(o.NPCexits) = 0) {
X P(); I();
X "Oh dear, someone seems to have damaged one of my
X room connections. The room \"";
X
X o.sdesc;
X
X "\" has no exits for NPC's to follow, but it's not
X listed as off limits to NPC's. Please notify the
X cave management as soon as possible!";
X }
X else if (global.debug) {
X //
X // Debugging info:
X //
X "\b\""; o.sdesc; "\" has "; say(length(o.NPCexits));
X if (length(o.NPCexits) > 1)
X " NPC exits:";
X else
X " NPC exit:";
X
X tot := length(o.NPCexits);
X for (i := 1; i <= tot; i++) {
X "\b\t-> ";
X if (o.(o.NPCexits[i]))
X o.(o.NPCexits[i]).sdesc;
X else
X "(nil)";
X }
X }
X}
X
X/*
X * A class defining some common things for NPC's.
X */
Xclass NPC: object
X //
X // List of currect pirate locations.
X //
X loclist = [] // where they are
X newloclist = [] // where they're going
X
X //
X // Scatter any NPC's that are currently in
X // the room to random rooms in the cave. (We
X // have to make sure the new rooms aren't off
X // limits to dwarves, though.)
X //
X scatter = {
X local i, dest, len, r, tot;
X local melocs;
X
X for (melocs := [], i := Me.location ; i ; i := i.location)
X melocs += i;
X if (length(intersect(melocs, self.loclist))) return;
X
X self.newloclist := [];
X tot := length(self.loclist);
X len := length(global.NPCrooms);
X for (i := 1; i <= tot; i++) {
X if (find(melocs, self.loclist[i])) {
X //
X // Make sure we get a real location.
X //
X dest := nil;
X while (dest = nil) {
X r := rand(len);
X dest := global.NPCrooms[r];
X }
X
X self.newloclist += dest;
X }
X else {
X self.newloclist += self.loclist[i];
X }
X
X }
X self.loclist := self.newloclist;
X }
X
X //
X // Returns true if any NPC's of this type are in locations
X // adjacent to the player. (I.e., if any NPC's could take
X // any exit that would bring them to the player's current
X // location.)
X //
X anyadjacent = {
X local adjacent, i, j, len, dir, dest, melocs;
X local tot1;
X local cur;
X
X//"\nanyadjacent(enter)\n";
X for (melocs := [], i := Me.location ; i ; i := i.location)
X melocs += i;
X
X adjacent := nil;
X tot1 := length(self.loclist);
X for (i := 1; i <= tot1; i++) {
X len := length(self.loclist[i].NPCexits);
X cur := self.loclist[i];
X for (j := 1; j <= len; j++) {
X dest := cur.(cur.NPCexits[j]);
X
X //
X // We need to check the destination
X // to be sure it exists. It may be
X // nil if we called an NPCexit method.
X //
X if (dest) if (find(melocs, dest)) {
X adjacent := true;
X break;
X }
X }
X
X //
X // If we've found an adjacent pirate we
X // can stop looking.
X //
X if (adjacent)
X break;
X }
X
X//"\nanyadjacent(exit)\n";
X return adjacent;
X }
X;
X
X/*
X * Move the dwarves. See the global object in ccr-std.t for paramters.
X */
XDwarves: NPC, Actor
X rhetoricalturn = -999 // hack -- see yesVerb in ccr-verbs.t
X attackers = 0 // number of dwarves that attack this turn
X
X sdesc = "threatening little dwarf"
X ldesc = {
X "It's probably not a good idea to get too close. Suffice
X it to say the little guy's pretty aggressive.";
X }
X
X noun = 'dwarf' 'dwarves' 'guy'
X adjective = 'threatening' 'nasty' 'little' 'mean'
X
X //
X // We don't use actorDesc for the dwarves because it gets printed
X // too early. (We want to let the player know that a dwarf is
X // in the room as soon as the dwarf moves into the room, not at
X // the start of the next turn.)
X //
X actorDesc = {}
X
X locationOK = true // tell compiler OK for location to be method
X location = {
X local i, melocs;
X
X for (melocs := [], i := Me.location ; i ; i := i.location)
X melocs += i;
X if (length(intersect(melocs, self.loclist)) = 0)
X return(nil);
X
X //
X // Check each dwarf's location. If at least one dwarf
X // is in the same location as the player, make our
X // location the same as the player's.
X //
X for (i := 1; i <= length(self.loclist); i++)
X if (find(melocs, self.loclist[i]))
X return self.loclist[i];
X
X return nil;
X }
X
X verDoKick(actor) = {}
X doKick(actor) = {
X "You boot the dwarf across the room. He curses, then
X gets up and brushes himself off. Now he's madder
X than ever!";
X }
X verDoAttack(actor) = {
X if (not axe.isIn(Me)) {
X "With what? Your bare hands?";
X self.rhetoricalturn := global.turnsofar;
X }
X }
X doAttack(actor) = { self.doAttackWith(actor, axe); }
X
X //
X // The following method is called when the player responds, "yes"
X // to "With what? Your bare hands?"
X //
X nicetry = { "You wish."; }
X
X verDoAttackWith(actor, io) = {}
X doAttackWith(actor, io) = {
X //
X // If the player throws the axe at the dwarf, he
X // might reduce the dwarf to a cloud of greasy
X // black smoke.
X //
X if (io = axe) {
X if (rand(100) <= global.dwarfhit) {
X "You killed a little dwarf. The body
X vanishes in a cloud of greasy black
X smoke.";
X
X //
X // Remove this location from our list
X // of locations where dwarves are.
X //
X self.loclist -= self.location;
X }
X else {
X "You attack a little dwarf, but he
X dodges out of the way.";
X }
X
X axe.moveInto(Me.location);
X }
X else if (io = Hands)
X self.nicetry;
X else
X "Somehow I doubt that'll be very effective.";
X }
X
X verIoGiveTo(actor) = {}
X ioGiveTo(actor, dobj) = {
X if (dobj = tasty_food) {
X self.doFeed(Me);
X }
X else {
X "The dwarf is not at all interested in your
X offer. (The reason being, perhaps, that if
X he kills you he gets everything you have
X anyway.)";
X }
X }
X
X verIoThrowAt(actor) = { self.verIoGiveTo(actor); }
X ioThrowAt(actor, dobj) = {
X if (dobj = axe)
X self.doAttackWith(actor, dobj);
X else
X self.ioGiveTo(actor, dobj);
X }
X verIoThrowTo(actor) = { self.verIoGiveTo(actor); }
X ioThrowTo(actor, dobj) = {
X if (dobj = axe)
X self.doAttackWith(actor, dobj);
X else
X self.ioGiveTo(actor, dobj);
X }
X
X verDoFeed(actor) = {}
X doFeed(actor) = {
X if (tasty_food.isIn(Me)) {
X "You fool, dwarves eat only coal! Now you've
X made him *really* mad!!";
X }
X else {
X "You have no food to give the dwarf.";
X }
X }
X
X //
X // Place dwarves in starting locations.
X //
X place = {
X local i, loc, r;
X
X self.loclist := [];
X for (i := 1; i <= global.dwarves; i++) {
X //
X // If there are any fixed starting locations
X // for dwarves left, put this dwarf in the
X // next one. Otherwise place him randomly.
X //
X loc := nil;
X if (length(global.dwarfloc) >= i)
X loc := global.dwarfloc[i];
X
X //
X // Invalidate initial location if it's off limits
X // to NPC's.
X //
X if (loc)
X if (loc.noNPCs)
X loc := nil;
X
X //
X // Make sure we get a real location.
X //
X while (loc = nil) {
X r := rand(length(global.NPCrooms));
X loc := global.NPCrooms[r];
X }
X
X //
X // Add this dwarf's location to the list.
X //
X self.loclist := self.loclist + loc;
X }
X }
X
X //
X // Move dwarves.
X //
X move = {
X local i, j, len, r, dest, done, dir, loc;
X local melocs;
X//"\ndwarves.move(enter)\n";
X
X //
X // Move each remaining dwarf.
X //
X // If the dwarf is currently in the player's location,
X // he stays where he is.
X //
X // If a dwarf is in a location adjacent to the player's
X // current location, he moves into the player's location
X // if he can. (We check his possible exits to see if
X // any of them go the player's location.) A consequence
X // of this is that dwarves will follow the player
X // relentlessly once they've spotted him. (But the global
X // value dwarftenacity can be set to prevent dwarves
X // from *always following*, of course.)
X //
X // If a dwarf isn't adjacent to the player, he just moves
X // around randomly.
X //
X
X for (melocs := [], i := Me.location ; i ; i := i.location)
X melocs += i;
X
X self.newloclist := [];
X self.attackers := 0; // assume no dwarves attack this turn
X for (i := length(self.loclist); i > 0; i--) {
X //
X // Get a copy of this dwarf's location for speed.
X //
X loc := self.loclist[i];
X
X //
X // Haven't found a new location yet.
X //
X done := nil;
X
X //
X // In player's current location?
X //
X if (find(melocs, loc)) {
X dest := loc; // stay put
X done := true;
X }
X
X //
X // Try each exit and see if we can reach the
X // player. If we have an exit that leads to
X // the player, we know it's an OK destination
X // location, since we pruned off all the noNPCs
X // rooms when we constructed the exit lists.
X //
X len := length(loc.NPCexits);
X if (not done) for (j := len; j > 0; j--) {
X dir := loc.NPCexits[j];
X dest := loc.(dir);
X
X //
X // We need to check the destination
X // to be sure it exists. It may be
X // nil if we called an NPCexit method.
X //
X if (dest <> nil and find(melocs, dest) <> nil)
X {
X //
X // Is this dwarf tenacious enough
X // to follow the player?
X //
X if (rand(100) <= global.dtenacity)
X done := true;
X break;
X }
X }
X
X //
X // Have we found a destination yet? If not,
X // move dwarf to a randomly selected adjacent
X // location.
X //
X // We need to check the destination because
X // the NPCexit methods in the rooms can sometimes
X // return nil. (For example, when the crystal
X // bridge doesn't exist yet, the giant's door
X // has not been opened, etc.)
X //
X while (not done) {
X dir := loc.NPCexits[rand(len)];
X dest := loc.(dir);
X
X if (dest)
X done := true;
X }
X
X //
X // Set new destination.
X //
X self.newloclist += dest;
X
X //
X // If the dwarf didn't move, he has an opportunity
X // to attack.
X //
X if (loc = dest) {
X if (find(melocs, loc))
X if (rand(100) <= global.dwarfattack)
X self.attackers++;
X
X //
X // Print some debugging info if in debug mode
X //
X if (global.debug) {
X P();
X "Dwarf stays \""; dest.sdesc; ".\"\n";
X }
X }
X else {
X //
X // Print some debugging info if in debug mode
X //
X if (global.debug) {
X P();
X "Dwarf moves from \"";
X self.loclist[i].sdesc; "\" to \"";
X dest.sdesc; ".\"\n";
X }
X }
X }
X
X //
X // Replace old locations with destinations.
X //
X self.loclist := self.newloclist;
X
X self.tell;
X//"\ndwarves.move(exit)\n";
X }
X
X //
X // Tell the player what's going on with the dwarves.
X //
X tell = {
X local i, j, len, r, dest, done, dir, count, adjacent;
X local melocs;
X//"\ntell(enter)\n";
X //
X // Count how many dwarves are in the room with the player.
X //
X for (melocs := [], i := Me.location ; i ; i := i.location)
X melocs += i;
X count := length(intersect(melocs, self.loclist));
X
X //
X // If any dwarves are in the room with the player and
X // the axe hasn't been thrown yet, throw the axe and
X // scatter the dwarves.
X //
X if (count > 0 and axe.location = nil) {
X P(); I();
X
X "A little dwarf just walked around a corner,
X saw you, threw a little axe at you which
X missed, cursed, and ran away.";
X
X axe.moveInto(self.location);
X
X //
X // Scatter any dwarves in the room.
X //
X self.scatter;
X
X //
X // No dwarves in the room. Be sure we take back
X // those attacks too...
X //
X count := 0;
X self.attackers := 0;
X }
X
X //
X // Tell the player if any dwarves are in the room with him,
X // or if any are nearby.
X //
X if (count = 0) {
X //
X // If no dwarves are in the room, but at least
X // one dwarf is in an adjacent location, tell
X // the player he hears something.
X //
X // (Only the pirate makes noise in the original,
X // which seem a bit strange and not as much fun.)
X //
X if (self.anyadjacent) {
X P(); I(); "You hear the pitter-patter
X of little feet.";
X }
X }
X else if (count = 1) {
X P(); I();
X "There is a threatening little dwarf in the
X room with you.";
X }
X else if (count > 1) {
X P(); I();
X "There are "; say(count); " threatening
X little dwarves in the room with you.";
X }
X
X //
X // Handle dwarf attacks.
X //
X if (self.attackers > 0) {
X if (self.attackers = 1) {
X if (count = 1)
X " He throws a knife at you!";
X else
X " One of them throws a knife
X at you!";
X }
X else {
X if (self.attackers = count) {
X if (count = 2)
X " Both of them throw
X knives at you!";
X else
X " All of them throw
X knives at you!";
X }
X else {
X say(self.attackers); " of them throw
X knives at you!";
X }
X }
X
X //
X // Curtains for our hero?!
X //
X count := 0;
X for (i := 1; i <= self.attackers; i++) {
X if (rand(100) <= global.dwarfaccuracy)
X count++;
X }
X
X P(); I();
X if (count > 0) {
X if (count = self.attackers) {
X if (count = 1)
X "It gets you!";
X else if (count = 2)
X "Both of them get you!";
X else
X "All of them get you!";
X }
X else if (count = 1) {
X "One of them gets you!";
X }
X else {
X say(count); " of them get
X you!";
X }
X
X die();
X }
X else {
X if (self.attackers = 1)
X "It misses you!";
X else if (self.attackers = 2)
X "Both of them miss you!";
X else
X "They all miss you!";
X }
X }
X//"\ntell(exit)\n";
X }
X;
X/*
X * The player can never get the dwarves' knives (that would be too easy),
X * but we'll let him examine them anyway.
X */
XDwarfKnives: decoration
X sdesc = "dwarf's knife"
X ldesc = { self.verifyRemove(Me); }
X noun = 'knife' 'knives'
X adjective = 'sharp' 'nasty' 'dwarf\'s' 'dwarvish' 'dwarven'
X 'dwarfish'
X
X locationOK = true // tell compiler OK for location to be method
X location = {
X return Dwarves.location;
X }
X
X verifyRemove(actor) = {
X "The dwarves' knives vanish as they strike the walls
X of the cave.";
X }
X
X verIoAttackWith(actor) = {
X "You don't have the dwarf's knife!";
X }
X;
X
X/*
X * Move the pirate(s). See the global object in ccr-std.t for paramters.
X *
X * This code is quite similar to the Dwarves code, but is simple because
X * there's never any interaction between the player and the pirates. (The
X * pirates just come in, do their stuff, and vanish.)
X *
X * Note that even if there's more than one pirate, the text printed in
X * in this object will treat all the pirates as a single one. So the
X * only difference having multiple pirates makes is that the more you
X * have, the more likely the player is to run into "him."
X */
XPirates: NPC, Actor
X location = nil // not a real actor, so pretend we don't exist
X
X seen = nil // has the player seen (one of) us?
X
X //
X // Place pirates in starting locations.
X //
X place = {
X local i, loc, r;
X
X self.loclist := [];
X for (i := 1; i <= global.pirates; i++) {
X //
X // If there are any fixed starting locations
X // for pirates left, put this pirate in the
X // next one. Otherwise place him randomly.
X //
X loc := nil;
X if (length(global.pirateloc) >= i)
X loc := global.pirateloc[i];
X
X //
X // Invalidate initial location if it's off limits
X // to NPC's.
X //
X if (loc)
X if (loc.noNPCs)
X loc := nil;
X
X //
X // Make sure we get a real location.
X //
X while (loc = nil) {
X r := rand(length(global.NPCrooms));
X loc := global.NPCrooms[r];
X }
X
X //
X // Add this pirate's location to the list.
X //
X self.loclist := self.loclist + loc;
X }
X }
X
X //
X // Move pirates.
X //
X move = {
X local i, j, len, r, dest, done, dir, melocs;
X
X//"\npirates.move(enter)\n";
X //
X // Move each remaining pirate.
X //
X // If the pirate is currently in the player's location,
X // he stays where he is.
X //
X // If a pirate is in a location adjacent to the player's
X // current location, he moves into the player's location
X // if he can. We limit this with the ptenacity global.
X //
X // If a pirate isn't adjacent to the player, he just moves
X // around randomly.
X //
X self.newloclist := [];
X for (melocs := [], i := Me.location ; i ; i := i.location)
X melocs += i;
X
X for (i := 1; i <= length(self.loclist); i++) {
X //
X // Haven't found a new location yet.
X //
X done := nil;
X
X //
X // In player's current location?
X //
X if (find(melocs, self.loclist[i])) {
X dest := self.loclist[i]; // stay put
X done := true;
X }
X
X //
X // Try each exit and see if we can reach the
X // player. If we have an exit that leads to
X // the player, we know it's an OK destination
X // location, since we pruned off all the noNPCs
X // rooms when we constructed the exit lists.
X //
X len := length(self.loclist[i].NPCexits);
X if (not done) for (j := 1; j <= len; j++) {
X dir := self.loclist[i].NPCexits[j];
X dest := self.loclist[i].(dir);
X
X //
X // We need to check the destination
X // to be sure it exists. It may be
X // nil if we called an NPCexit method.
X //
X if (dest) if (find(melocs, dest)) {
X //
X // Is this pirate tenacious enough
X // to follow the player?
X //
X if (rand(100) <= global.ptenacity)
X done := true;
X break;
X }
X }
X
X //
X // Have we found a destination yet? If not,
X // move pirate to a randomly selected adjacent
X // location.
X //
X // We need to check the destination because
X // the NPCexit methods in the rooms can sometimes
X // return nil. (For example, when the crystal
X // bridge doesn't exist yet, the giant's door
X // has not been opened, etc.)
X //
X while (not done) {
X dir := self.loclist[i].NPCexits[rand(len)];
X dest := self.loclist[i].(dir);
X
X if (dest)
X done := true;
X }
X
X //
X // Set new destination.
X //
X self.newloclist += dest;
X
X //
X // Print some debugging info if in debug mode
X //
X if (self.loclist[i] = dest) {
X if (global.debug) {
X P();
X "Pirate stays \""; dest.sdesc; ".\"\n";
X }
X }
X else {
X if (global.debug) {
X P();
X "Pirate moves from \"";
X self.loclist[i].sdesc; "\" to \"";
X dest.sdesc; ".\"\n";
X }
X }
X }
X
X //
X // Replace old locations with destinations.
X //
X self.loclist := self.newloclist;
X
X self.tell;
X//"\npirates.move(exit)\n";
X }
X
X //
X // Tell the player what's going on with the pirates.
X //
X tell = {
X local i, t, count, snagged, melocs;
X//"\npirates.tell(enter)\n";
X
X //
X // Count how many pirates are in the room with the player.
X // (We really only need to know if there are any at all,
X // but this is just as easy.)
X //
X for (melocs := [], i := Me.location ; i ; i := i.location)
X melocs += i;
X count := length(intersect(melocs, self.loclist));
X
X //
X // Tell the player if any pirates are nearby.
X //
X if (count = 0) {
X //
X // If no pirates are in the room, but at least
X // one pirate is in an adjacent location, tell
X // the player he hears something.
X //
X if (self.anyadjacent) {
X P(); I();
X "There are faint rustling noises from
X the darkness behind you.";
X }
X }
X else if (count > 0) {
X //
X // A pirate has snagged the player.
X // Move any treasures the player is carring
X // to the pirate's repository, currently
X // hard-coded as Dead_End_13 because there's
X // code in that room that can't easily be
X // made general.
X //
X // Since the player may be keeping his treasures
X // in containers, it's actually easier just
X // to search through the global list of
X // treasures and check each one's location to
X // see if it's in the player, rather than
X // recursively checking all the player's belongings
X // and seeing if they're treasures. (Also, we want
X // to get treasures that are just lying around in
X // the room too.)
X //
X snagged := 0;
X for (i := 1; i <= length(global.treasurelist); i++) {
X t := global.treasurelist[i] ;
X if (t.isIn(Me.location)) {
X t.moveInto(Dead_End_13);
X snagged++;
X }
X }
X
X //
X // Print a message telling the player what happened.
X //
X if (snagged > 0) {
X P();
X I(); "Out from the shadows behind you
X pounces a bearded pirate! \"Har,
X har,\" he chortles. \"I'll just take
X all this booty and hide it away with
X me chest deep in the maze!\" He
X snatches your treasure and vanishes
X into the gloom.";
X }
X else {
X //
X // In the original code, if you weren't
X // holding the lamp, you just wouldn't
X // see the pirate when you weren't
X // carrying any treasures. This seems
X // bogus, so I've added a conditional here.
X //
X P();
X I(); "There are faint rustling noises
X from the darkness behind you. As you
X turn toward them, ";
X
X if (brass_lantern.isIn(Me))
X "the beam of your lamp falls
X across";
X else
X "you spot";
X
X " a bearded pirate. He is carrying a
X large chest. \"Shiver me timbers!\"
X He cries, \"I've been spotted! I'd
X best hie meself off to the maze to
X hide me chest!\" With that, he
X vanishes into the gloom.";
X }
X
X //
X // Install the treasure chest if it hasn't
X // already been installed. No worries about
X // the chest appearing out of nowhere when
X // the player's at Dead_End_13, because the
X // pirate can't go there. (It's off limits
X // to NPC's.)
X //
X if (not self.seen) {
X treasure_chest.moveInto(Dead_End_13);
X self.seen := true;
X }
X
X //
X // Scatter any pirates in the room.
X //
X self.scatter;
X }
X//"\npirates.tell(enter)\n";
X }
X;
END_OF_FILE
if test 25988 -ne `wc -c <'src/ccr-npc.t'`; then
echo shar: \"'src/ccr-npc.t'\" unpacked with wrong size!
fi
# end of 'src/ccr-npc.t'
fi
if test -f 'src/ccr.t' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/ccr.t'\"
else
echo shar: Extracting \"'src/ccr.t'\" \(2419 characters\)
sed "s/^X//" >'src/ccr.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 * Colossal Cave Revisited and its accompanying source code are
X * Copyright (C) 1993 David M. Baggett.
X *
X *---------------------------------------------------------------------------
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of version 2 of the GNU General Public License as
X * published by the Free Software Foundation.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X *---------------------------------------------------------------------------
X *
X * Please document all changes in the history (here as well as in the
X * appropriate source files) so we know who did what.
X *
X *---------------------------------------------------------------------------
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 */
X#include "history.t"
X
X#include "ccr-adv.t"
X#include "format.t"
X#include "preparse.t"
X#include "ccr-std.t"
X#include "ccr-room.t"
X#include "ccr-item.t"
X#include "ccr-verb.t"
X#include "ccr-npc.t"
X#include "help.t"
X#include "close.t"
END_OF_FILE
if test 2419 -ne `wc -c <'src/ccr.t'`; then
echo shar: \"'src/ccr.t'\" unpacked with wrong size!
fi
# end of 'src/ccr.t'
fi
if test -f 'src/makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/makefile'\"
else
echo shar: Extracting \"'src/makefile'\" \(884 characters\)
sed "s/^X//" >'src/makefile' <<'END_OF_FILE'
X#
X# Makefile for Colossal Cave Revisited
X# Requires TADS compiler 2.1.0 or greater.
X#
X# Note that some of the Unix versions of the compilers return error
X# codes when everything's actually fine.
X#
X
X#
X# Set TC and TR to point to your TADS compiler and run-time.
X#
XTC= tadsc
XTR= tadsr
X
XPROGNAME= ccr
XDEBUG= -ds
XSWAPTIONS=
XOOPTIONS= -s -mp32000
XOPTIONS= $(OOPTIONS) $(SWAPTIONS) $(DEBUG)
X
X# Production version options
XPOPTIONS= $(OOPTIONS) $(SWAPTIONS)
X
X.PRECIOUS= $(PROGNAME).gam # do not delete game file on errors
X
XHEADERS= ccr-adv.t ccr-std.t
XROOMS= ccr-room.t
XOBJECTS= ccr-item.t
XMISC= close.t ccr-verb.t format.t help.t ccr-npc.t preparse.t thingext.t
X
X$(PROGNAME).gam: makefile $(PROGNAME).t $(HEADERS) $(ROOMS) $(OBJECTS) $(MISC)
X $(TC) $(OPTIONS) $(PROGNAME).t
X
Xproduction: makefile $(PROGNAME).t $(HEADERS) $(ROOMS) $(OBJECTS) $(MISC)
X $(TC) $(POPTIONS) $(PROGNAME).t
END_OF_FILE
if test 884 -ne `wc -c <'src/makefile'`; then
echo shar: \"'src/makefile'\" unpacked with wrong size!
fi
# end of 'src/makefile'
fi
echo shar: End of archive 9 \(of 11\).
cp /dev/null ark9isdone
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