From mipos3!intelca!oliveb!ames!ll-xn!husc6!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games-request Thu Jan 14 17:52:45 PST 1988 Article 42 of net.sources.games: Path: td2cad!mipos3!intelca!oliveb!ames!ll-xn!husc6!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games-request From: games-request@tekred.TEK.COM Newsgroups: net.sources.games Subject: v03i036: crystal - another adventure game, Part04/05 Message-ID: <2032@tekred.TEK.COM> Date: 12 Jan 88 18:19:30 GMT Sender: billr@tekred.TEK.COM Lines: 2140 Approved: billr@tekred.TEK.COM Submitted by: nrcvax!kosman!kevin Comp.sources.games: Volume 3, Issue 36 Archive-name: crystal/Part04 #! /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 MAKEflop <<'END_OF_MAKEflop' Xecho "you must be root for this one ... crystal is 111 owned by bin ..\c" Xread xyzzy Xcat Files | cpio -ocBv > /dev/rfp021 END_OF_MAKEflop if test 122 -ne `wc -c cvatt.c <<'END_OF_cvatt.c' X/* cvatt.c X * attacks, droping things, feeding and other such stuff X ************************************************************************/ X X#include X#include "cvobj.h" X#include "cvocab.h" X#include "cvlocs.h" X#include "cvmisc.h" X#include "cvorcs.h" X#include "cvcode.h" X#include "random.h" X Xextern int actspk[]; /* cvocab.c */ Xextern char *oword; Xextern void cvsave(); Xextern void putcode(); Xextern int mutilate(); Xextern void newcon(); Xextern int drunkbear(); Xextern int wakeking(); X X#define OKAY(msg) {rspeak(msg); return S_okay;} X#define DEFMSG OKAY(actspk[verb%1000]) X#define BREAKIT {register int i; if (i = mutilate(object)) {\ X newloc = &(cvloc[i]); return S_move;\ X } else return S_okay; } X#define FILLIT(object,liquid) {(object)->prop = (liquid) - _WATER + 1;} X#define INTRANS X#define TRANS 10000 + X Xstatic int Xdropit(verb,object) register struct cvobj *object; X{ X if ((object == ROPE) X && TOTING(ROPE2) X && !TOTING(ROPE)) object = ROPE2; X X if (TOTING(BOTTLE) && (OBJ(LIQ(BOTTLE))==object)) object = BOTTLE; X X if (TOTING(CUP) && (OBJ(LIQ(CUP))==object)) object = CUP; X X if (!TOTING(object)) DEFMSG; X X if ((object == WALLET) && (HERE(VEND)) && (VEND->prop == 0)) X { if (object->prop == 4) X { pspeak(object,4); X rspeak(54); X } else { X object->prop++; X VEND->prop = 1; X move(BOTTLE,loc); X pspeak(BOTTLE,BOTTLE->prop); X return S_okay; X } X } else if (object == RUG) X { register int k; X k = RUG->prop; X RUG->prop = 0; X if (k) { X if ((loc - cvloc) > 30) X { if (drownch()) { X return S_move; X } else { X rspeak(54); X } X } else { X destry(RUG); X pspeak(RUG,2); X return S_okay; X } X } else { X rspeak(54); X } X } else if (object == BOAT) X { object->prop -= 2; X if (loc->flags & DROWN) X { rspeak(120); X oldlc2 = loc; X die(); X return S_move; X } X rspeak(54); X } else if ((object == SEARS) X && (((loc - cvloc) == SEARS->iloc) X || ((loc - cvloc) == 78) ) ) X { object->prop = 1; X move2(SEARS,&(cvloc[78 + (SEARS->iloc) - (loc - cvloc)])); X pspeak(object,1); X } else if (object == FOOD && HERE(DRAGON)) { X rspeak(166); /* tell him the dragon doesn't eat that */ X } else { X rspeak(54); /* okay */ X } X X move(object,loc); X if (HERE(ORCS) && ORCS->prop) X { if (((object == CUP) || (object == BOTTLE)) X && (LIQ(object) == _COLA)) X { didorc(); X return S_okay; X } X pspeak(ORCS,2); /* the orcs don't like that */ X } X X if ((object == CHEST) && (SKELTN->prop == 1)) X { SKELTN->prop = 2; X rspeak(97); /* skeleton crumples */ X } X X return S_okay; X} X Xint Xcvatt(verb,obj,object) register int verb,obj; Xregister struct cvobj *object; X{ register int k; X X switch ((!!obj*10000) + verb) { X X case TRANS DROP: X return dropit(verb,object); X X case TRANS THROW: X/* throw is like pour for liquids. For axe, something might get killed. X Otherwise, it is the same as "drop". X The axe is the only way to deal with some things, and is special for X the bugbear (as is the keg, food, keys.) X Sand is special for the Balrog. X Spice is special for the dragon. X*/ X if ((object == WATER) || (object == WINE) ||(object == COLA)) X { goto L9130; X } X X if ((object == ROPE) && TOTING(ROPE2) && !TOTING(object)) { X object = ROPE2; X } X X if (!TOTING(object)) DEFMSG; X X if (BEAR->prop && HERE(BEAR)) { X if ((object == KEY) && (CHAIN->prop == 2)) { X move(KEY,loc); X CHAIN->prop = 0; X destr2(CHAIN); X rspeak(151); /* the bugbear is no slouch */ X BEAR->prop -= 2; X YOGI->dseen = TRUE; X YOGI->dloc = loc; X return S_show; X } X if ((object == KEG) X || (((object == CUP) || (object == BOTTLE)) X && (LIQ(object) == _WINE))) { X return drunkbear(object); X } X } X X if ((object == HAMMER) && HERE(SKELTN) && (SKELTN->prop == 1)) { X HAMMER->prop = SKELTN->prop = 0; X pspeak(HAMMER,2); X move(HAMMER,loc); X /* let's not be annoyed with curses or odd things about X "take" when pirate is really inactive */ X PIRATE->dloc = PIRATE->oloc = DEAD; X PIRATE->dseen = FALSE; X newloc = loc; X return S_move; X } X X if ((object == SPICE) && HERE(DRAGON)) { X destry(SPICE); X destry(DRAGON); X DRAGON->prop = 0; X X PUFF->dseen = TRUE; /* now for the really annoying dragon */ X PUFF->dloc = loc; X OKAY(148); /* the bad news */ X } X X if ((object == SAND) && (BALLY->dloc = loc)) { X pspeak(SAND,1); X destry(SAND); X pspeak(BALROG,1); X BALROG->prop = 0; X move(BALROG,&(cvloc[62])); X BALLY->dseen = FALSE; X BALLY->dloc = DEAD; X return S_okay; X } X X if (object == FOOD) { X goto L8210; /* treat as FEED */ X } X X /* non-weapons just get dropped here and that's it */ X if ((object != AXE) /* note: AXE is not among weapons */ X && ((object <= MINWPN) || (object >= MAXWPN))) { X return dropit(verb,object); X } X X move(object,loc); /* weapons also end up here */ X/* he may kill any dwarf, the kobold, or sometimes even the giant */ X/* but with multiple targets, we hit the easy ones first */ X if (SLASHER->dloc == loc) { X KOBOLD->prop = 3; X move(KOBOLD,loc); X KOBOLD->conn2.where = FIXED; X SLASHER->dseen = FALSE; X SLASHER->dloc = DEAD; X rspeak(150); X newloc = loc; X return S_move; X } X X { register struct monster *cre; X for (cre = MINDWR; cre <= MAXDWR; cre++) { X if (cre->dloc == loc) { X if (PCT(67) && (saved == -1)) { X cre->dseen = FALSE; X cre->dloc = DEAD; X dflag++; /* annoy them some more */ X rspeak(++dkill == 1 ? 149 : 47); X } else { X rspeak(48); X } X newloc = loc; X return S_move; X } X } X } X X if (HERE(GIANT) && GIANT->prop) { X pspeak(GIANT,3); X oldlc2 = loc; X die(); X return S_show; X } X X if (HERE(BEAR) && BEAR->prop) { X move2(AXE,FIXED); X AXE->prop = 1; X if (HERE(CHAIN) && !TOTING(CHAIN)) juggle(CHAIN); X juggle(BEAR); X OKAY(164); X } X X if (SKELTN->prop == 1) { X rspeak(141); X newloc = loc; X return S_show; X } X X if (ME->dloc == loc) return suicide(); X X { register struct monster *cre; X for (cre = orcs; cre->iloc >= 0; ++cre) { X if (cre->dloc == loc) { X rspeak(141); X newloc = loc; X return S_show; X } X } X } X X carry(object); /* well, pick it up again */ X return dropit(verb,object); /* and just drop the damned thing */ X X case INTRANS FEED: XL8210: obj = 0; X if (HERE(BEAR) X && (BEAR->prop == 2 || BEAR->prop == 4)) obj = _BEAR; X if (dflag >= 2) { X register struct monster *cre; X if (HERE(UNICRN) X && (UNICRN->prop) X && (!obj || PCT(75))) obj = _UNICRN; X for (cre = MINDWR; cre <= MAXDWR; ++cre) { X if ((cre->dloc == loc) && ( !obj || PCT(50))) obj = _DWARF; X } X } X if (!obj) { /* nobody here to feed */ X if (verb != THROW) return S_what; /* normally, just complain */ X obj = _FOOD; /* but if he said "throw food" */ X object = OBJ(obj); /* we instead . . . */ X return dropit(verb,object); /* just drop it */ X } X object = OBJ(obj); X case TRANS FEED: X if (!HERE(FOOD)) DEFMSG; X if (object == DWARF) { X dflag += 8; /* get them mad */ X OKAY(103); X } X if (object == UNICRN && UNICRN->prop) return unicorn(); X if (object == BEAR X && (BEAR->prop == 2 || BEAR->prop == 4)) { X pspeak(BEAR, --(BEAR->prop)); X destry(FOOD); X return S_okay; X } X OKAY(14); X X case INTRANS POUR: X obj = 0; X if (TOTING(BOTTLE) && LIQ(BOTTLE)) obj = LIQ(BOTTLE); X if (TOTING(CUP) && LIQ(CUP)) obj = (obj << 10) + LIQ(CUP); X if (!obj || (obj > 2000)) return S_what; X object = OBJ(obj); X case TRANS POUR: XL9130: k = 0; /* from THROW (indirectly from FEED, too) */ X if (TOTING(BOTTLE) && LIQ(BOTTLE) == obj) k = _BOTTLE; X if (TOTING(CUP) && LIQ(CUP) == obj) k = (k << 10) + _CUP; X if (k > 2000) OKAY(143); /* from what? */ X if (k) object = OBJ(obj=k); X if (!TOTING(object)) DEFMSG; X if (object != CUP && object != BOTTLE) OKAY(78); /* cannot */ X k = LIQ(object); X if (!k) { X pspeak(object,11); /* but it's empty */ X return S_okay; X } X if (verb == THROW) { X if (k == _WINE && HERE(BEAR) && BEAR->prop) { X return drunkbear(object); X } else { X rspeak(k == _WATER ? 77 : 79); X } X } else { X obj = object - cvobj; X obj = _CUP + _BOTTLE - obj; X if (OBJ(obj)->prop == 0 && HERE(OBJ(obj))) { X OBJ(obj)->prop = object->prop; X pspeak(OBJ(obj),object->prop + 7); X } else { X rspeak(k == _WATER ? 77 : 79); X } X } X object->prop = 0; X newcon(object,7,k); X return S_show; X X case INTRANS FILL: X obj = 0; X if (TOTING(CUP)) { X if (TOTING(BOTTLE)) { X if (!(BOTTLE->prop) && !(CUP->prop)) { X return S_what; /* can't tell which one */ X } else { X obj = CUP->prop ? _BOTTLE : _CUP; X } X } else obj = _CUP; X } else if (TOTING(BOTTLE)) obj = _BOTTLE; X if (!obj) return S_what; X object = OBJ(obj); X case TRANS FILL: X if (object != BOTTLE && object != CUP) DEFMSG; X if (!TOTING(object)) OKAY(29); X if (object->prop) {pspeak(object,12); return S_show; } X if (!(k = LIQLOC(loc))) { X obj = _CUP + _BOTTLE - obj; X if (HERE(OBJ(obj))) k = LIQ(OBJ(obj)); X if (!k) OKAY(106); X pspeak(OBJ(obj),7); /* announce source is now empty */ X OBJ(obj)->prop = 0; X } X newcon(object,(object->prop=k-_WATER+1)+7, k); /* announce result */ X return S_show; X X default: X fputs("Unknown verb in cvatt.\n",stdout); X return S_okay; X } X} X END_OF_cvatt.c if test 9165 -ne `wc -c cvdie.c <<'END_OF_cvdie.c' X/* cvdie.c X ************************************************************************/ X X#include X#include X#include "cvobj.h" X#include "cvorcs.h" X#include "cvocab.h" X#include "cvlocs.h" X#include "cvmisc.h" X X/* "You're dead, Jim." You got yourself killed somehow, clown. The X * easiest way is to go to location DEAD, which is the destination of X * some entries in travel structures. We allow this 'maxdie' times, X * where maxdie is automatically initialized based on the number of X * snide messages we have available (and how much orange smoke...) in X * messages around rmsg[81]. Each death results in a message (81,83,...) X * which offers reincarnation; if accepted, this results in message 82, 84, X * etc. The last time, if he wants another chance, he gets a snide X * remark (what else? so what's new?) as we exit. When reincarnated, X * all objects being carried get moved to 'oldlc2' (presumably the last X * place prior to getting killed) without change of prop number. The lamp X * is turned off and left outside the building (only if he was carrying X * it, of course). He himself is left outside the privy (and heaven help X * him if he tries to "hope" back into the cave without the lamp!). X * X * 'oldlc2' is zapped so he can't just "retreat". X */ X Xvoid Xdie() X{ X register int yea; X register struct cvobj *curobj ; X X blklin = TRUE ; X if ( (UNICRN->conn1.where == oldlc2) X && (loc == oldlc2) X && (UNICRN->prop) ) { X pspeak(UNICRN,5); /* very lucky! */ X UNICRN->prop = 1 ; X loc = oldlc2; X } else { X if (closing || demo) { X rspeak(131); X ++numdie; X finish = TRUE; X return ; X } X yea = yes(81+numdie*2,82+numdie*2,54) ; X ++numdie; X if ((numdie == maxdie) || !yea) {finish = TRUE; return; } X if (TOTING(LAMP)) { X move(LAMP,LAMPLOC); X LAMP->prop = 0 ; X } X loc = LAMPLOC; X move(COMPASS,LAMPLOC); X /* the following may be confusing. GIANT and PRIEST X * represent the same thing to the adventurer, but X * here they are represented by an 'object' and a X * 'monster'. X */ X if ((GIANT->prop == 1) && PRIEST->dseen) destry(GIANT); X } /* may or may not be dead; objects still get dropped */ X /* drop all objects (still) being carried. X Throw away if over water. */ X newloc = (oldlc2->flags & DROWN) ? LOST : oldlc2 ; X for (curobj = cvobj; curobj->desc != NULL; ++curobj) X if (TOTING(curobj)) move(curobj,newloc); /* drop them */ X if (RUG->prop == 1) RUG->prop = 0 ; /* get off the rug */ X if ((BOAT->prop/2) == 1) BOAT->prop -= 2; /* leave the boat */ X if ( ( LNUM(SCROLL->conn1.where) == 91) X || INMAZE(SCROLL->conn1.where)) X move(SCROLL,&(cvloc[SCROLL->iloc])); X if ( (LNUM(MEDAL->conn1.where) == CAPE->iloc) X || (LNUM(MEDAL->conn1.where) == SPICE->iloc) ) X move(MEDAL,&(cvloc[MEDAL->iloc])); X if (SKELTN->prop == 1) SKELTN->prop = 2; X newloc = oldloc = loc ; X} END_OF_cvdie.c if test 2825 -ne `wc -c cvdwrf.c <<'END_OF_cvdwrf.c' X/* cvdwrf.c X * performs dwarf-motion stuff once per turn. Considers all moving X * creatures except the adventurer to be "dwarves" in some sense, X * because their motion rules are all very similar. X * As long as they are not dead, all dwarves move about randomly in X * much the same way that adventurers do, but the dwarves are smart X * enough to skip the usual hazards -- they never go to fatal X * places. X *************************************************************************/ X X#include X#include X X#include "cvobj.h" X#include "cvlocs.h" X#include "cvocab.h" X#include "cvorcs.h" X#include "cvmisc.h" X#include "random.h" X Xextern struct rtr rtrav[]; /* rug and rope travel array */ Xextern int maxloc; /* test for legal locs */ X Xextern void carry(); /* pick up object */ Xextern void destry(); /* destroy an object (at first location) */ Xextern void mkill(); /* kill monster */ Xextern void move(); /* place an object at a location */ Xextern void move2(); /* place an object at a second location, X or make it unmoveable */ Xextern void pspeak(); /* announce a property message of an object */ Xextern void rspeak(); /* utter one of the random messages */ Xextern void putcode(); /* used in debugging */ X Xextern int tally, tally2; /* counts of objects seen */ X Xint Xdodwarf() X{ register struct cvobj *curobj; X register struct cvtrav *curtrv; X register struct monster *cre; X register int i; X X if (closing && ( (newloc - cvloc) < 31 || newloc == DEAD) ) { X rspeak(130); /* you can't get out */ X newloc = loc; /* make him stay put */ X if (!panic) clock2 = 15; /* if this is his first attempt */ X panic = TRUE; /* remember he has paniced already */ X } X X/* If monsters are following, the adventurer is not allowed to back up, X * because there's a monster in the way. X */ X X if (loc != newloc /* he's moving */ X && (loc - cvloc) >=62 /* he's moving inside the cave */ X && dflag >= 2 /* dwarf stuff going */ X && !FORCED(loc) ) { /* he could be coming from there */ X for (cre = MINDWR; cre->dw; ++cre) { X if ( cre->dseen X && (newloc == cre->oloc || newloc == oldloc) ) { X newloc = loc; /* prevent him */ X rspeak(2); /* tell him why */ X break; /* skip checking other dwarves */ X } /* end if dseen */ X } /* end dwarf check */ X } /* end of backup loop */ X X loc = newloc; /* assign the possibly new place */ X X/* If he gets as far as the pool hall, start up the dwarf stuff. Things X * then stay quiet for a random amount of time. At some point a (fake) X * dwarf spots him, and misses him with an axe. This encounter just X * scares him, and provides the axe he will need, but never does any harm. X * At this point, the dwarves all start moving from their (hard-wired) X * starting points. X * X * Some dwarves (those awakened by a special encounter: the King, the X * dragon, the bugbear), plus all those below the throne start later at X * the time they are called for. X * X * No dwarf starts where the axe is thrown, because a dwarf who might X * otherwise start there is assigned an alternate starting point. X * X */ X if (loc != DEAD X && (loc - cvloc) >= 62 X && !FORCED(loc) ) X switch (dflag) { X auto int dtotal, attack, stick, destj; X#define MAXDEST 20 X auto struct cvloc *ddest[MAXDEST]; X X case 0: dflag = 1; break; /* allow things to start */ X case 1: if ( !HERE(IDOL) /* could start orcs? */ X && !HERE(CHAIN) /* could start bugbear? */ X && !HERE(ORB) /* could start Grendl? */ X && !HERE(CROWN) /* could start king? */ X && !HERE(SCEPT) /* could start dragon? */ X && (PCT(85) || DARK) ) X break; /* Don't start in the dark unless he's sneaking X up on one of the vital encounters */ X dflag = 2; /* Go into full swing now */ X for ( i = 0; i < 3; ++i ) { X cre = MINDWR + RAN(MAXDWR-MINDWR+1); /* pick a real dwarf */ X if (PCT(50) && saved == -1) X cre->dloc = DEAD; /* may kill it off */ X } /* end of dwarf-killing loop */ X X for (cre = MINDWR; cre->dw; ++cre) { X if (loc == cre->dloc) X cre->dloc = DALTLC; /* start no real dwarf here */ X cre->oloc = cre->dloc; X } X X rspeak(3); /* Throw the axe */ X move(AXE,loc); X break; X X default: X/* Things are in full swing now. Move each dwarf at random, except that X * if he's seen the adventurer, he follows. Dwarves never go to locations X * outside the cave. If wandering at random, they don't back up unless X * that's the only way to go. If they don't have to move, they attack. X * Of course, dead dwarves don't do much of anything. X */ X dtotal = attack = stick = 0; X if ( PIRATE->dloc != DEAD /* Is Pirate still alive? */ X && loc != CHLOC /* But we're not at chest loc */ X && CHEST->prop < 0 /* And never saw chest */ X && tally == tally2+1) /* And that's the last one */ X PIRATE->dseen = TRUE; /* Give adventurer a hand */ X for (cre = orcs; cre->iloc >= 0; ++cre) { X if (cre->dloc == DEAD || cre->dloc == cvloc) continue; /*dead*/ X destj = 0; X ddest[destj] = cre->oloc; /* pad the list (could back up) */ X for (curtrv = cre->dloc->travel; curtrv->word != -1; ++curtrv){ X if (curtrv->s) { X for ( ;curtrv->s; curtrv++) ; /* skip sequence */ X continue; /* then go try the next entry */ X } X i = curtrv->l; X if ( i >= 62 /* in the cave */ X && i <= maxloc /* not message or magic */ X && ((newloc = &(cvloc[i])) != cre->oloc || cre->dseen) X /* don't back up when wandering */ X && ( ! destj || newloc != ddest[destj - 1] ) X && destj < MAXDEST /* room in array */ X && newloc != cre->dloc X && !FORCED(&(cvloc[i])) /* don't enter danger */ X && ( cre != PIRATE || !BADPLC(newloc)) ) { X ddest[destj++] = newloc; /* enter possible move */ X } X } /* end of testing travel array */ X i = destj; /* remember how many */ X if (destj) destj = RAN(destj); else i++; /* make a selection */ X cre->oloc = cre->dloc; X cre->dloc = ddest[destj]; X X if (loc == cre->oloc) { X cre->dloc = loc; /* pass in the hall */ X destj = 0; /* flag that he's following */ X } else { X for (destj = 0; destj < i; ++destj) { X if (ddest[destj] == loc) { X destj = 0; /* flag that he could follow */ X break; X } X } X } X#ifdef DEBUG X if (cre == BALLY) { X printf("\nBALLY to loc %d: ",cre->dloc - cvloc); X putcode(cre->dloc->ldesc); X putchar('\n'); X } X#endif X if ( loc == cre->dloc /* it's here, or */ X || (cre->dseen /* it's following, and */ X && ((destj < i) /* it could follow (priest special ) */ X || ( cre == PRIEST && LNUM(loc) == 134 ) ) ) ) { X cre->dloc = loc; X cre->dseen = TRUE; X switch (cre - orcs) { X case IPIRAT: X#ifdef DEBUG X puts("\nThe pirate is here."); X#endif X if (loc == CHLOC || FOUND(CHEST)) break; X for (i = 0, curobj = MINTRS; X curobj != ENDTRS; ++curobj) { X if (TOTING(curobj)) break; X if (HERE(curobj)) i=1; X } X if (curobj == ENDTRS) { X /* nothing to steal, but we'll hear from him anyway */ X if (tally == (tally2 + 1) X && i == 0 X && CHEST->conn1.where == LOST X && HERE(LAMP) X && LAMP->prop == 0 ) { X rspeak(186); X move(CHEST,CHLOC); X } else { X if (cre->oloc != cre->dloc X && PCT(20)) X rspeak(127); X break; X } X } else { /* he's gonna get something */ X rspeak(128); X if (CHEST->conn1.where == LOST) X move(CHEST,CHLOC); X for (curobj = MINTRS; curobj != ENDTRS; ++curobj) { X if (HERE(curobj)) { X if (curobj == ORB && INMAZE(loc)) { X if (LNUM(loc) != 92 X && curobj->conn2.where == LOST) X move(curobj,&(cvloc[92])); X } else { X if (curobj->conn2.where == LOST) X move(curobj,CHLOC); X } X } /* end handling toted treasure */ X } /* end of stealing loop */ X PIRATE->dloc = PIRATE->oloc = CHLOC; X PIRATE->dseen = FALSE; X } /* end of any-treasure-here case */ X /* end of the pirate's wickedness (for now) */ X break; /* switch break */ X X case IGRENDL: X pspeak(SPIDER,1); /* he's after you */ X if (PCT(50)) break; /* half the time he does no more */ X if (TOTING(SWORD)) { X rspeak(137); /* sorry about that, Grendl */ X mkill(&(orcs[IGRENDL]),SPIDER); X } else { X rspeak(135); X oldlc2 = loc; X goto dead; X } X break; X X case IDRAGON: X pspeak(DRAGON,2+RAN(8)); /* just keep bitchin' */ X break; X X case IKING: X pspeak(HELM,1); /* he's after you! */ X if (cre->dloc == PUFF->dloc) { X pspeak(HELM,3); /* can't stand complaints */ X mkill(PUFF,DRAGON); X } else { X if (( loc == oldloc || loc == oldlc2) && PCT(40)) { X pspeak(HELM,5); /* sorry 'bout that */ X oldlc2 = loc; X goto dead; X } X } X break; X X case IDJINN: X pspeak(DJINN,0); /* he's here */ X break; X X case IKOBOLD: X pspeak(KOBOLD,0); /* he's here */ X if (( loc == oldloc || loc == oldlc2) && PCT(25)) { X pspeak(KOBOLD,2); X oldlc2 = loc; X goto dead; X } else { X pspeak(KOBOLD,1); X } X break; X X case IBEAR: X move(BEAR,loc); X if (( loc == oldloc || loc == oldlc2) && PCT(25)) { X rspeak(196); X oldlc2 = loc; X goto dead; X } X break; X X case IUNICRN: X move(UNICRN,loc); X break; X X case IPRIEST: X move(GIANT,loc); X if (( loc == oldloc || loc == oldlc2) && PCT(50)) { X rspeak(223); X oldlc2 = loc; X goto dead; X } else { X if (LNUM(loc) == 134) { X pspeak(GIANT,4); /* bye, bye priest */ X mkill(PRIEST,GIANT); X } X } X break; X X case IBALROG: X pspeak(BALROG,2); X if (PCT(50)) { X pspeak(BALROG,3); X if (( loc == oldloc || loc == oldlc2 )==PCT(85) X && RAN(limit+2) >= 10 ) { X pspeak(BALROG,4); X limit = (limit+9)/10; X } X } X break; X X case ISELF: X pspeak(SELF,0); X if (PCT(17)) pspeak(SELF,RAN(3)+2); X break; X X default: /* normal dwarves are the rest */ X if (!cre->dw) break; /* in case I goofed */ X ++dtotal; /* count him in the room */ X if (cre->dloc == cre->oloc) { /* if he can */ X ++attack; X if (knfloc != FIXED) knfloc = loc; X if (PCT((dflag-2)*5)) ++stick; X } X X } /* end of switch */ X } /* end of processing for being followed */ X else { X#ifdef DEBUG X if (cre->dseen) { X printf("Creature %d cannot follow.\n", cre - orcs); X } X#endif X cre->dseen = FALSE; X switch (cre - orcs) { X case IBEAR: X destry(BEAR); X if (AXE->prop == 1 && AXE->conn2.where == FIXED) { X AXE->prop = 0; X AXE->conn2.where = NULL; X } X break; X X case IPRIEST: X destry(GIANT); X break; X X case IUNICRN: X if (UNICRN->prop != -1) UNICRN->prop = 2; X destry(UNICRN); X break; X } X } X } /* end of creature scan */ X X if (dtotal) { X if (dtotal > 1) { X (void) printf( X"\nThere are %d threatening little dwarves in the room with you.\n",dtotal); X } else rspeak(4); X if (attack) { X if (dflag == 2) ++dflag; /* After the first time */ X if (saved != -1) dflag = 20;/* Catch copyists */ X blklin = FALSE; X if (attack > 1) { X (void) printf( X"%d of them throw knives at you!\n",attack); X i = 6; X } else { X rspeak(5); X i = 52; X } X if (stick <= 1) X rspeak(i+stick); X else (void) printf( X"%d of them get you!\n",stick); X if (stick) { X oldlc2 = loc; X goto dead; X } X } X } X } /* end of switch for dwarf state */ X return (FALSE); X Xdead: return(TRUE); X} END_OF_cvdwrf.c if test 11495 -ne `wc -c cvgo.c <<'END_OF_cvgo.c' X/* cvgo.c X * adventurer motion routine moveme() X *************************************************************************/ X X#include X#include "cvobj.h" X#include "cvocab.h" X#include "cvlocs.h" X#include "cvmisc.h" X#include "cvorcs.h" X#include "random.h" X Xextern struct cvobj *lastobj; /* cvmain.c */ X Xstatic void Xwrongway(verb) int verb ; X{ if ((verb == FIND) || (verb == INVENT)) {rspeak(59); return; } X if (verb <= ENTER) {rspeak(9); return; } X if ((verb == HOPE) X || (verb == BANIS) X || (verb == MISFO)) {rspeak(42); return; } X rspeak(12); X return; X} X Xstatic struct cvloc * Xleave(tr) register struct cvtrav *tr; X{ X if (tr->l <= 300) return &(cvloc[tr->l]) ; X if (tr->l <= 500) X switch (tr->l) X { X case 301: /* wrong magic word ! */ X newloc = loc; X switch (SHELF->prop) { X case 0: Xshakeit: if (loc - cvloc == SHELF->iloc || loc - cvloc == SHELF->iloc+1) X rspeak(214); X else X rspeak(162); X SHELF->prop ++ ; X return loc; X case 1: X if (PCT(25)) goto shakeit; X if (PCT(33)) { X rspeak(42); X return loc; X } X SHELF->prop++; X { register struct cvobj *ob; X register struct cvloc *shloc; X shloc = &(cvloc[SHELF->iloc]); X X /* dump everything off of shelf */ X for (ob = lastobj; ob != cvobj; ob--) { X if (ob->conn1.where == shloc) move(ob,shloc+1); X } X move2(SHELF,shloc); /* shelf stays, though */ X if (!AT(SHELF)) { X rspeak(162); X return loc; X } X loc = shloc + 1; X newloc = &(cvloc[25]); X rspeak(163); X return loc; X } X case 3: /* already destroyed */ X rspeak(42); X return loc; X } X case 302: /* down a clean column */ X loc = COLUMN->conn1.where; X if (COLUMN->prop == 0) { X COLUMN->prop = 1; X if (DAM->prop == 0) { X loc = &(cvloc[getrick()]); X } X } X return loc; X case 303: /* out of maze .. activate grendl if carrying orb */ X newloc = loc - 1; X SPIDER->prop = 0; X pspeak(SPIDER,2); X GRENDL->dseen = TRUE; X GRENDL->dloc = newloc; X return newloc; X case 305: /* jumped into bottomless fissure */ X rspeak(224); X { register struct cvobj *ob; X register int co; X co = 0; X for (ob = cvobj; ob->desc != NULL; ob++) { X if (TOTING(ob)) {co++; destry(ob);} X } X if (RUG->prop == 1) RUG->prop = 0; X rspeak(co ? 134 : 133); X } X loc = newloc = oldlc2 = &(cvloc[62]); X return loc; X case 306: /* leave repository */ X newloc = &(cvloc[146]); X if (MIRROR->prop == 1) { X MIRROR->prop = 0; X pspeak(MIRROR,2); X ME->dloc = loc; X ME->dseen = TRUE; X } X return loc; X default: bug(20); X } X rspeak((int)(tr->l - 500)) ; X return loc ; X} X X#define SKIP {ctrav = skip(ctrav); continue; } X#define DOIT { register struct cvloc *temp; temp = leave(ctrav) ;\ X if (ctrav->s) continue ; else return temp; } Xstatic struct cvtrav * Xskip(tr) register struct cvtrav *tr; X{ while (tr->s) {++tr;} ; X return tr ; X} X X/* given the current location in parameter "where" and a verb in parameter X * "verb", put the new location into the result. The current loc is saved X * in "oldloc" in case he wants to retreat. The current "oldloc" is saved X * in "oldlc2", in case he dies. (If he does, "newloc" will be limbo, and X * "oldloc" will be what killed him, so we need "oldlc2", which is the X * last place he was safe.) X * X * Each location (struct cvloc) has a travel array (struct cvtrav *travel) X * of entries, each of which contains a word-number (or -1 to end the X * array for this location) and maybe some other stuff. If the location X * and continue parts are both zero, subsequent entries are examined until X * a useable one is found (this makes several motion words synonyms in the X * location). The continue flag makes for concatenated decisions, or for X * messages then motions, all in one entry, without the need for fake X * forced-motion locations. (e.g. AHHHHHHHHH...You are at the bottom with X * a broken neck). X */ X Xstruct cvloc * Xmoveme(where,verb) struct cvloc *where; int verb; X{ X register struct cvtrav *ctrav; X auto int rugrop; X X /* if he tries to use the compass, make sure this makes sense */ X if ( (verb >= NORTH) && (verb <= NW)) X { if (where > (&(cvloc[30])) && !TOTING(COMPASS) ) X { rspeak(58); return where; } /* need compass */ X X if (DARK) X { rspeak(74) ; return where; } /* can't read compass */ X } X X if (verb == WAIT) { return where; } X X if (verb == BACK) X { X /* look for a verb which goes from where to oldloc, X or if oldloc has forced motion, to oldlc2. If one is found, X and the verb is not magic, and does not involve random motion, X he can go back. */ X X register struct cvloc *backto; X register struct cvtrav *forceto ; X register int fword; X X backto = FORCED(oldloc) ? oldlc2 : oldloc ; X oldlc2 = oldloc ; oldloc = where ; X X if ( (backto == where) || PCT(5) ) X { rspeak(91); return where; } X X for (forceto = NULL, X ctrav = where->travel; ctrav->word >= 0; ++ctrav) X { if ((&(cvloc[ctrav->l])) == backto) {forceto = ctrav; break ; } X if (ctrav->l < 300) X { register struct cvloc *through; X through = &(cvloc[ctrav->l]) ; X if (FORCED(through) X && ((&(cvloc[through->travel->l])) == backto)) X forceto = ctrav ; X } X } X X if (forceto == NULL) X { rspeak(140); /* you can't get there from here */ X return where; X } X X fword = forceto->word ; X /* make him find his own magic words */ X if ( (fword == HOPE) X || (fword == BANIS) X || (fword == MISFO) ) X { rspeak(91); return where; } X X /* don't go back through probabilities, or other conditions */ X for (ctrav = where->travel; ctrav->word >= 0; ++ctrav) X { if ( (ctrav->word == fword) && (ctrav->n)) X { rspeak(91); return where; } X } X verb = fword ; /* change verb to the one that does it */ X } X X oldlc2 = oldloc; oldloc = where; X X switch (verb) X { X case DOWN: rugrop = 1 ; break ; X case UP: rugrop = 2 ; break ; X case CLIMB: rugrop = 3 ; break ; X default: rugrop = 0 ; break ; X } X X /* find an entry with this motion verb */ X for (ctrav = where->travel; ctrav->word >= 0; ++ctrav) X { if ((ctrav->word == 1) || (ctrav->word == verb)) break ; X } X X if (ctrav->word < 0) X { /* no such motion -- unless we can find a way to do it with the X rug or the rope */ X if (rugrop) { X register int l, len; X register struct rtr *rtrp; X l = loc - cvloc; X len = 0; X for (rtrp = rtrav; rtrp->top > 0; rtrp++) { X switch (rugrop) { X case 3: /* he said "CLIMB" */ X if (rtrp->top == l) goto down; X if (rtrp->bot == l) goto up; X if (rtrp->mid == l) goto up; X case 1: /* he said "DOWN" */ Xdown: X if (rtrp->mid == l) { X if (rtrp->bot) { X l = rtrp->bot; X len = 1; X } X } else if (rtrp->top == l) { X if (rtrp->mid) { X l = rtrp->mid; X len = 1; X } else { X l = rtrp->bot; X len = 2; X } X } X break; X case 2: /* he said "UP" */ Xup: X if (rtrp->mid == l) { X l = rtrp->top; X len = 1; X } else if (rtrp->bot == l) { X if (rtrp->mid) { X l = rtrp->mid; X len = 1; X } else { X l = rtrp->top; X len = 2; X } X } X break; X } /* end switch */ X /* l = possible destination number */ X /* len = # of 60-foot rope segments needed */ X if (len) break; X } /* end for to find destination */ X if (len) { X newloc = &(cvloc[l]); X if (RUG->prop == 1 && rugrop != 3) { /* flying? */ X if (rtrp->rug) { X rspeak(199); /* flying where he shouldn't */ X move(RUG, &(cvloc[RUG->iloc])); X oldlc2 = &(cvloc[rtrp->drop]); X die(); X } X return newloc; X } /* end of flying */ X if (ROPE->conn1.where - cvloc == rtrp->top) { X l = ROPE->prop; X if (l % 2) goto L6345; X } X if (ROPE2->conn1.where - cvloc == rtrp->top) { X l = ROPE2->prop; X if (l == 3) goto L6345; X } X /* check that you have the rope or carpet set up */ XL6340: if (rtrp == rtrav) { X if (PCT(20)) return loc; X loc = DEAD; X newloc = &(cvloc[24]); X return newloc; X } X newloc = loc; X if (RUG->prop == 0 && PCT(67)) rspeak(198); X else rspeak(14); X return newloc; XL6345: X switch (l) { X case 3: /* 60 foot rope */ X if (len > 1) { X rspeak(153); X return loc; X } X case 1: /* 120 foot rope, uncut */ X case 7: /* 120 foot rope, spliced and tested */ XL6350: if (RUG->prop == 1) { X newloc = loc; X rspeak(117); X } X return newloc; X case 5: /* 120 foot rope with a dangerous knot */ X if (RUG->prop == 1) { X rspeak(117); X return loc; X } X if (loc == &(cvloc[rtrp->bot]) || X newloc == &(cvloc[rtrp->bot])) { X rspeak(208); X ROPE->prop = 3; /* broken rope */ X EROPE->prop = 0; X destry(EROPE2); X move(ROPE2,&(cvloc[rtrp->drop])); X ROPE2->prop = 2; X oldlc2 = &(cvloc[rtrp->drop]); X die(); X return newloc; X } X goto L6350; X default: X bug(55); X } /* end of rope-state switch */ X } else { X newloc = loc; X } X } /* end of rug/rope possibilities */ X wrongway(verb); return where; X } X X do X { X for (;!(ctrav->s) && !(ctrav->l) && !(ctrav->n);++ctrav) ; X X switch (ctrav->m) X { X case 0: X if ((ctrav->n) && !PCT(ctrav->n)) SKIP ; X DOIT ; X case IF_HAVE: X if (!TOTING(OBJ(ctrav->n))) SKIP ; X DOIT ; X case IF_NHAVE: X if (TOTING(OBJ(ctrav->n))) SKIP ; X DOIT ; X case IF_WITH: X if (!HERE(OBJ(ctrav->n))) SKIP ; X DOIT ; X case IF_NWITH: X if (HERE(OBJ(ctrav->n))) SKIP ; X DOIT ; X case IF_PROP: X if (OBJ(ctrav->n)->prop != ctrav->v) SKIP ; X DOIT ; X case IF_NPROP: X if (OBJ(ctrav->n)->prop == ctrav->v) SKIP ; X DOIT ; X } X bug(29) ; X } while ((++ctrav)->word >= 0) ; X X bug(25) ; X return where; X} END_OF_cvgo.c if test 9558 -ne `wc -c cvmove.c <<'END_OF_cvmove.c' X/* cvmove.c X * various object motion subroutines X *************************************************************************/ X X#include X#include "cvobj.h" X#include "cvlocs.h" X Xextern void bug() ; Xextern int holding ; X X/* start toting an object, removing it from the list of things at its X * former location. Increment 'holding' unless it was already being X * toted. X * Primarily used by move(). X */ Xvoid Xcarry(obj) register struct cvobj *obj; X{ register struct cvloc *from; X register struct conn *this; X X from = obj->conn1.where ; X obj->conn1.where = TAKEN ; X if (from == TAKEN) return ; X ++holding ; X if (from != (struct cvloc *) NULL) X { for ( this = &(from->atloc); X this->link != &(obj->conn1); this = this->link) X if (this->link == NULL) bug(30); X this->link = obj->conn1.link ; X } X obj->conn1.link = NULL ; X return; X} X X/* pick up an object by its second location, removing it from the list X * of things at its former location. X * Primarily used by move2(). X */ Xstatic void Xcarry2(obj) register struct cvobj *obj; X{ register struct cvloc *from; X register struct conn *this; X X from = obj->conn2.where ; X obj->conn2.where = TAKEN ; X if (from == TAKEN) return ; X if (from != (struct cvloc *) NULL) X { for ( this = &(from->atloc); X this->link != &(obj->conn2); this = this->link) X if (this->link == NULL) bug(30); X this->link = obj->conn2.link ; X } X obj->conn2.link = NULL ; X return; X} X X/* place any object anywhere by picking it up and dropping it. X * may already be toting it, in which case the carry is a no-op. X * X * to move the second place of an object, use the object's number plus X * OBJSIZ as the object. X * X * 'move' may be called regardless of where the object was, whether X * it's being carried, is lost, is destroyed, or whatever. X */ Xvoid Xmove(obj,toloc) X register struct cvobj *obj; X register struct cvloc *toloc; X{ X register struct cvloc *from; X X from = obj->conn1.where ; X if ((from != LOST) && (from != TAKEN)) carry(obj); X X if (obj->conn1.where == TAKEN) --holding ; X obj->conn1.where = toloc ; X if (toloc == LOST) return ; X obj->conn1.link = toloc->atloc.link ; X toloc->atloc.link = &(obj->conn1) ; X return; X} X X/* place any object anywhere by picking it up and dropping it by its X * second location. May already be toting it, in which case the carry X * is a no-op. X * X * 'move2' may be called regardless of where the object was, whether X * it's being carried, is lost, is destroyed, or whatever. X */ Xvoid Xmove2(obj,toloc) X register struct cvobj *obj; X register struct cvloc *toloc; X{ X register struct cvloc *from; X X from = obj->conn2.where ; X if ((from != LOST) && (from != TAKEN)) carry2(obj); X X if (obj->conn2.where == TAKEN) --holding ; X obj->conn2.where = toloc ; X if (toloc == LOST) return ; X obj->conn2.link = toloc->atloc.link ; X toloc->atloc.link = &(obj->conn2) ; X return; X} X X X/* juggle an object by picking it up and putting it down again, the X * purpose being to get the object to the front of the chain of things X * at its location. X */ Xvoid Xjuggle(obj) register struct cvobj *obj; X{ X register struct cvloc *where; X X where = obj->conn1.where ; X if (where == NULL) bug(33); X move(obj,where); X return; X} X Xvoid Xjuggl2(obj) register struct cvobj *obj; X{ register struct cvloc *where; X X where = obj->conn2.where ; X if (where == NULL) bug(33); X move2(obj,where); X return; X} X X X/* destroy the object by dropping at an inaccessable place X */ Xvoid Xdestry(obj) register struct cvobj *obj; X{ move(obj,LOST); X} X Xvoid Xdestr2(obj) register struct cvobj *obj ; X{ move2(obj,LOST); X} END_OF_cvmove.c if test 3523 -ne `wc -c cvocab.c <<'END_OF_cvocab.c' X/* cvocab.c X * the crystal cave vocabulary X ************************************************************************/ X X#include "cvocab.h" X X/************************************************************************* X * action defaults: X * each line contains the message number of the default error X * message for one of the action verbs. X *************************************************************************/ Xint actspk[] = { X 0, X 24, /* carry */ X 29, /* drop */ X 38, /* on */ X 38, /* off */ X 28, /* open */ X 28, /* lock */ X 0, /* say */ X 75, /* rub */ X 59, /* find */ X 59, /* inventory */ X 13, /* quit */ X 13, /* score */ X 0, /* nothing */ X 13, /* suspend */ X 155, /* brief */ X 13, /* hours */ X 29, /* throw */ X 43, /* go */ X 8, /* pay */ X 146, /* break */ X 110, /* drink */ X 110, /* eat */ X 195, /* read */ X 12, /* tie */ X 147, /* untie */ X 174, /* feed */ X 29, /* pour */ X 110, /* kill/attack */ X 110, /* rig */ X 207, /* cut */ X 109, /* fill */ X 38, /* test */ X 67, /* blast */ X 42, /* wave */ X 191, /* sit */ X 14, /* calm */ X 14, /* fly */ X 110, /* wake */ X 0, /* describe */ X 0, /* touch */ X 221, /* play */ X 0, /* restore */ X 13}; /* help */ X X/************************************************************************* X * vocabulary: X * each entry contains a code and a word. The codes in uppercase X * are defined in cvocab.h, and are used in common with other X * parts of the program. The thousands-position of the code X * indicates what "part of speech" we have here: X * 0: the word is a motion verb or location reference for X * use in travelling. See cvlocs.c. X * 1: the word is an object. X * 2: the word is an action verb (such as "carry", "attack") X * 3: the word is a special case verb (such as "dig") and X * the low-order part of the code is an index into the X * message array. These words may duplicate objects. X *************************************************************************/ Xstruct cvocab vtab [] = { X{NORTH, "north"}, X{NORTH, "n"}, X{NE, "northeast"}, X{NE, "ne"}, X{EAST, "east"}, X{EAST, "e"}, X{SE, "southeast"}, X{SE, "se"}, X{SOUTH, "south"}, X{SOUTH, "s"}, X{SW, "southwest"}, X{SW, "sw"}, X{WEST, "west"}, X{WEST, "w"}, X{NW, "northwest"}, X{NW, "nw"}, X{UP, "up"}, X{UP, "upward"}, X{UP, "u"}, X{UP, "above"}, X{UP, "ascend"}, X{DOWN, "down"}, X{DOWN, "downward"}, X{DOWN, "d"}, X{DOWN, "descend"}, X{OUT, "out"}, X{OUT, "outside"}, X{OUT, "exit"}, X{OUT, "leave"}, X{IN, "in"}, X{ENTER, "enter"}, X{JUMP, "jump"}, X{BARN, "barn"}, X{BARN, "building"}, X{PRIVY, "privy"}, X{PRIVY, "outhouse"}, X{SHAFT, "shaft"}, X{SINKH, "sink"}, X{SINKH, "sinkhole"}, X{PIGPE, "pig"}, X{PIGPE, "pigs"}, X{PIGPE, "pigpen"}, X{BLUFF, "bluff"}, X{HEADQ, "park"}, X{HEADQ, "headquarters"}, X{M_GATE, "gate"}, /* also appears as an object word as a rnager X synonym 1060 */ X{M_GATE, "mouth"}, X{M_GATE, "entrance"}, X{LAKE, "lake"}, X{LAKE, "rapids"}, X{FIELD, "field"}, X{FIELD, "pasture"}, X{FIELD, "meadow"}, X{BACK, "back"}, X{BACK, "return"}, X{BACK, "retreat"}, X{WAIT, "null"}, X{WAIT, "wait"}, X{WAIT, "nowhere"}, X{CROSS, "cross"}, X{HOPE, "hope"}, X{UPSTR, "upstream"}, X{DOWNS, "downstream"}, X{CLIMB, "climb"}, X{CLIMB, "scale"}, X{PATH, "path"}, X{PAST, "p"}, X{PAST, "past"}, X{FUTUR, "f"}, X{FUTUR, "future"}, X{BANIS, "banish"}, X{MISFO, "misfortune"}, X X/* start of object section */ X X{1001, "diamonds"}, X{1002, "silver"}, X{1002, "sack"}, X{_JEWLRY, "jewelry"}, X{1004, "coins"}, X{_CHEST, "chest"}, X{_CHEST, "box"}, X{_CHEST, "treasure"}, X{_CAPE, "ermine"}, X{_CAPE, "cape"}, X{_CAPE, "cloak"}, X{_CROWN, "crown"}, X{_SCEPT, "scepter"}, X{1009, "sapphire"}, X{_ORB, "platinum"}, X{_ORB, "orb"}, X{_IDOL, "jade"}, X{_IDOL, "idol"}, X{_RUG, "rug"}, X{_RUG, "persian"}, X{_RUG, "carpet"}, X{_UNICRN, "unicorn"}, /* also as special verb, 3226 */ X{_UNICRN, "collar"}, /* also as special verb, 3226 */ X{_CHAIN, "chain"}, X{_RING, "ring"}, X{_RING, "adamant"}, X{_HELM, "helm"}, X{_HELM, "helmet"}, X{_HELM, "mithril"}, X{1017, "gold"}, X{1017, "nugget"}, X{_THRONE, "throne"}, X{_THRONE, "seat"}, X{_THRONE, "chair"}, X{_SWORD, "sword"}, X{_HAMMER, "hammer"}, X{_CUP, "cup"}, X{_MEDAL, "ruby"}, X{_MEDAL, "medallion"}, X{_SCROLL, "parchment"}, /* also so special verb, 3126 */ X{_SCROLL, "scroll"}, /* also as special verb, 3126 */ X{_HARP, "harp"}, X{_HARP, "ivory"}, X{_STONE, "arkenstone"}, X{_STONE, "stone"}, X{_KEG, "keg"}, X{_KEG, "beer"}, X{1027, "long"}, X{1027, "longsword"}, X{1028, "broad"}, X{1028, "broadsword"}, X{1029, "spear"}, X{1030, "short"}, X{1030, "shortsword"}, X{1031, "bow"}, X{1032, "dagger"}, X{1033, "quarterstaff"}, X{1033, "staff"}, X{1034, "halberd"}, X{1035, "armor"}, X{1035, "armour"}, X{1036, "heater"}, X{1037, "round shield"}, X{1038, "tall"}, X{1039, "cuirass"}, X{_COLUMN, "column"}, X{1041, "pearls"}, X{1042, "helictites"}, X{1043, "gypsum"}, X{1043, "flowers"}, X{1044, "bat"}, X{1044, "bats"}, X{1046, "crystal"}, X{1046, "butterfly"}, X{1046, "butterflies"}, X{1046, "soda-straws"}, X{1046, "soda"}, X{1046, "sodastraws"}, X{1046, "straw"}, X{1046, "straws"}, X{1046, "stalactites"}, X{1047, "indian"}, X{1047, "pot"}, X X{_COMPASS, "compass"}, X{_KEY, "key"}, X{_KEY, "keys"}, X{_LAMP, "lamp"}, X{_LAMP, "headlamp"}, X{_RICK, "rick"}, /* the ranger? */ X{_SEARS, "sears"}, X{_SEARS, "catalog"}, X{_WALLET, "change"}, X{_WALLET, "wallet"}, X{_DOOR, "door"}, X{_BRIDGE, "bridge"}, X{_BOAT, "boat"}, X{_DAM, "rimstone"}, X{_DAM, "dam"}, X{_O_GATE, "gate"}, /* name of location -- only available to X program -- see word 23 */ X{_O_GATE, "ranger"}, X{_ROPE, "rope"}, /* objects 61 to 64 are various rope parts */ X{_ROPE, "knot"}, X X{1065, "guano"}, X X{_SPICE, "spices"}, X{_KNIFE, "knife"}, X{_KNIFE, "knives"}, X{_FOOD, "food"}, X{_FOOD, "rations"}, X{_BOTTLE, "bottle"}, X{_BOTTLE, "jar"}, X{_WATER, "water"}, X{_WATER, "h2o"}, X{_WINE, "wine"}, X{_COLA, "coke"}, X{_COLA, "cola"}, X{_COLA, "orca"}, X{_MIRROR, "mirror"}, X{_GIANT, "priest"}, X{_GIANT, "giant"}, X{_GIANT, "orc"}, X{_ORCS, "orcs"}, X{_TOMB, "tomb"}, X{_TOMB, "figure"}, X{_AXE, "axe"}, X{_TOAD, "toad"}, X{_SAND, "sand"}, X{_SAND, "turquoise"}, X{_SHELF, "shelf"}, X{_HANG, "hangings"}, X{_HANG, "silk"}, X X{_CRAP, "droppings"}, X{_CRAP, "shit"}, X{_CRAP, "crap"}, X{_CRAP, "poo"}, X{_SHOWER, "shower"}, X{_VEND, "machine"}, X{_VEND, "vending"}, X{_BATTER, "batteries"}, X{_DWARF, "dwarf"}, X{_DWARF, "dwarves"}, X{_BEAR, "bear"}, /* also action word 3095 */ X{_BEAR, "bugbear"}, /* also action word 3095 */ X{_BEAR, "bug"}, /* also action word 3095 */ X{_SKELTN, "skeleton"}, X{_SPIDER, "spider"}, X{_SPIDER, "grendl"}, X{_DRAGON, "dragon"}, X{_DJINN, "djinni"}, /* also action word 3193 */ X{_KOBOLD, "cobol"}, /* also action word 3194 */ X{_KOBOLD, "kobold"}, /* also action word 3194 */ X{_BALROG, "balrog"}, /* also action word 3160 */ X{_SELF, "*you*"}, X{_SELF, "*yourself*"}, X{_SELF, "self"}, X{_SELF, "me"}, X X/* verb section */ X X{TAKE, "carry"}, X{TAKE, "take"}, X{TAKE, "keep"}, X{TAKE, "catch"}, X{TAKE, "steal"}, X{TAKE, "capture"}, X{TAKE, "get"}, X{TAKE, "tote"}, X{DROP, "drop"}, X{DROP, "release"}, X{DROP, "free"}, X{DROP, "discard"}, X{DROP, "dump"}, X{DROP, "offer"}, X{DROP, "abandon"}, X{ON, "light"}, X{ON, "on"}, X{OFF, "off"}, X{OFF, "extinguish"}, X{UNLOC, "open"}, X{UNLOC, "unlock"}, X{LOCK, "close"}, X{LOCK, "lock"}, X{SAY, "say"}, X{SAY, "chant"}, X{SAY, "sing"}, X{SAY, "utter"}, X{SAY, "mumble"}, X{RUB, "rub"}, X{FIND, "find"}, X{INVENT, "inventory"}, X{QUIT, "quit"}, X{QUIT, "qui"}, X{QUIT, "qu"}, X{QUIT, "q"}, X{SCORE, "score"}, X{NOTHI, "nothing"}, X{SAVE, "save"}, X{BRIEF, "brief"}, X{THROW, "throw"}, X{THROW, "toss"}, X{THROW, "fling"}, X{WALK, "walk"}, X{WALK, "run"}, X{WALK, "travel"}, X{WALK, "go"}, X{WALK, "proceed"}, X{WALK, "continue"}, X{WALK, "explore"}, X{WALK, "goto"}, X{WALK, "follow"}, X{WALK, "turn"}, X{PAY, "pay"}, X{BREAK, "break"}, X{BREAK, "smash"}, X{BREAK, "destroy"}, X{DRINK, "drink"}, X{EAT, "eat"}, X{READ, "read"}, X{TIE, "tie"}, X{UNTIE, "untie"}, X{FEED, "feed"}, X{POUR, "pour"}, X{KILL, "kill"}, X{KILL, "fight"}, X{KILL, "hit"}, X{KILL, "strike"}, X{KILL, "attack"}, X{RIG, "rig"}, X{RIG, "anchor"}, X{CUT, "cut"}, X{CUT, "divide"}, X{FILL, "fill"}, X{TEST, "test"}, X{BLAST, "blast"}, X{WAVE, "wave"}, X{WAVE, "shake"}, X{WAVE, "swing"}, X{SIT, "sit"}, X{CALM, "calm"}, X{CALM, "placate"}, X{CALM, "tame"}, X{FLY, "fly"}, X{FLY, "rise"}, X{WAKE, "wake"}, X{WAKE, "disturb"}, X{DESCRB, "look"}, X{DESCRB, "examine"}, X{DESCRB, "describe"}, X{TOUCH, "touch"}, X{PLAY, "play"}, X{PLAY, "strum"}, X{PLAY, "finger"}, X{PLAY, "tune"}, X{RESTOR, "restore"}, X{RESTOR, "resume"}, X{HELP, "help"}, X{HELP, "?"}, X X/* special action words */ X X{3010, "left"}, X{3010, "right"}, X{3010, "forward"}, X{3010, "backward"}, X X{3050, "fee"}, X{3050, "fie"}, X{3050, "foe"}, X{3050, "foo"}, X{3050, "fum"}, X{3050, "xyzzy"}, X{3050, "plugh"}, X{3050, "sesame"}, X{3050, "opensesame"}, X{3050, "abra"}, X{3050, "abracadabra"}, X{3050, "shazam"}, X{3050, "hocus"}, X{3050, "pocus"}, X X{3064, "tree"}, X{3064, "trees"}, X{3064, "wood"}, X{3064, "woods"}, X{3064, "forest"}, X X{3066, "dig"}, X{3066, "excavate"}, X{3068, "lost"}, X X{3069, "mist"}, X X{3095, "bugbear"}, /* also object 1091 */ X{3095, "bug"}, /* also object 1091 */ X{3095, "bear"}, /* also object 1091 */ X X{3123, "time"}, X{3123, "timemaze"}, X X{3126, "parchment"}, /* also object 1023 */ X{3126, "scroll"}, /* also object 1023 */ X X{3139, "stop"}, X X{3142, "info"}, X{3142, "information"}, X X{3147, "swim"}, X X{3152, "y"}, X{3152, "yes"}, X{3152, "ye"}, X{3152, "no"}, X{3152, "okay"}, X{3152, "ok"}, X X{3160, "balrog"}, /* also object 1097 */ X X{3190, "siege"}, X{3190, "perilous"}, X X{3193, "djinni"}, /* also object 1095 */ X{3194, "kobold"}, /* also object 1096 */ X{3194, "cobol"}, /* also object 1096 */ X X{3225, "fuck"}, X X{3226, "unicorn"}, /* also object 1013 */ X X X{0} /************* mark the end ***************/ X}; END_OF_cvocab.c if test 9543 -ne `wc -c cvsave.c <<'END_OF_cvsave.c' X/* cvsave.c X * routine to save or restore the user's game X * only one game per user name is allowed in this version X * what is saved: X * a time-stamp of the program version (not the game) X * all non-stack variables from cvmain.c X * all variable info from cvlocs.c, cvobj.c X *************************************************************************/ X X#include X#include X#include X#include X#include X#include "cvobj.h" X#include "cvlocs.h" X X#define DIRNAME "/usr/games/lib/crystal/" X#define DIRLEN (sizeof DIRNAME) Xextern char *cuserid(); Xextern char emain, datastart; Xextern int saved; Xstatic char savename[DIRLEN+L_cuserid] = DIRNAME; Xstatic unsigned datalen ; Xstatic unsigned conlen = sizeof(struct cvloc *) + sizeof(struct conn *); X Xlong ptime = -1; /* program time-stamp */ X Xvoid Xcvsave() X{ register struct cvloc *curloc; X register struct cvobj *curobj; X auto char userid[L_cuserid]; X auto struct stat buf; X auto int save; X X datalen = &emain-&datastart; X X if (cuserid(userid) == NULL) { X puts("\nCannot save because I don't know who you are!"); X return; X } X X (void) strcpy(savename+DIRLEN-1, userid); X if (stat(savename,&buf) == -1) { X if (errno != ENOENT) { X puts("\nCannot save because of directory trouble\n"); X return; X } X } else { X if (yes(93,0,0)) { X if (unlink(savename) == -1) { X printf("\nCannot unlink %s\n",savename); X return; X } X } else { return; } X } X if ((save = open(savename,O_WRONLY|O_EXCL|O_CREAT,0600)) == -1) { X printf("\nCannot create %s\n",savename); X return; X } X if (write(save,&ptime,sizeof(long)) == -1 X || write(save,&datastart,datalen) == -1) { X perror("Saving cave:"); X close(save); X unlink(savename); X return; X } X for (curobj = cvobj; curobj->desc != NULL; curobj++) { X if (write(save, &(curobj->prop), sizeof(int)) == -1 X || write(save, &(curobj->conn1.where),conlen) == -1 X || write(save, &(curobj->conn2.where),conlen) == -1) { X perror("Saving cave objects"); X close(save); X unlink(savename); X return; X } X } X for (curloc = cvloc; curloc->travel != NULL; curloc++) { X if (write(save, &(curloc->abb), sizeof(int)) == -1 X || write(save, &(curloc->atloc.where),conlen) == -1) { X perror("Saving cave places"); X close(save); X unlink(savename); X return; X } X } X (void) close(save); X return; X} X Xvoid Xcvrest() X{ register struct cvloc *curloc; X register struct cvobj *curobj; X auto char userid[L_cuserid]; X auto int save; X auto long ftime = -1; X X datalen = &emain-&datastart; X X if (cuserid(userid) == NULL) { X puts("\nCannot restore because I don't know who you are!"); X return; X } X X (void) strcpy(savename+DIRLEN-1, userid); X X if ((save = open(savename,O_RDONLY)) == -1) { X printf("\nCannot find %s\n",savename); X return; X } X if (read(save,&ftime,sizeof(long)) != sizeof(long) X#ifdef XVERSION X || ftime != ptime X#endif X || read(save,&datastart,datalen) != datalen) { X if (ftime == -1) { X perror("Restoring cave:"); X } else { X puts("\nSave file not created by this version"); X } X close(save); X unlink(savename); X return; X } X for (curobj = cvobj; curobj->desc != NULL; curobj++) { X if (read(save, &(curobj->prop), sizeof(int)) != sizeof(int) X || read(save, &(curobj->conn1.where),conlen) != conlen X || read(save, &(curobj->conn2.where),conlen) != conlen) { X perror("Restoring cave objects"); X close(save); X unlink(savename); X return; X } X } X for (curloc = cvloc; curloc->travel != NULL; curloc++) { X if (read(save, &(curloc->abb), sizeof(int)) != sizeof(int) X || read(save, &(curloc->atloc.where),conlen) != conlen) { X perror("Restoring cave places"); X close(save); X unlink(savename); X return; X } X } X if (read(save, &ftime, 1) != 0) { X puts("\nNot end of file"); X close (save); X unlink(savename); X exit(1); X } X (void) close(save); X if (saved == 1) saved = -1; X return; X} END_OF_cvsave.c if test 3854 -ne `wc -c